mirror of
https://github.com/jonasbark/swiftcontrol.git
synced 2026-02-18 00:17:40 +01:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8649203cf | ||
|
|
765b0c3d6d | ||
|
|
248c40731c | ||
|
|
cde01a4863 | ||
|
|
1ee8a0188b | ||
|
|
32e8fc9bf5 | ||
|
|
3c87d895c5 | ||
|
|
82dd8a9b48 |
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@@ -71,6 +71,11 @@ jobs:
|
||||
env:
|
||||
DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY: ${{ secrets.DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY }}
|
||||
|
||||
- name: Decode Keystore
|
||||
run: |
|
||||
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > android/android.keystore;
|
||||
echo "${{ secrets.KEYSTORE_PROPERTIES }}" > android/keystore.properties;
|
||||
|
||||
#6 Building APK
|
||||
- name: Build APK
|
||||
run: flutter build apk --release
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -12,6 +12,8 @@
|
||||
.swiftpm/
|
||||
migrate_working_dir/
|
||||
|
||||
android/keystore.properties
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
### 1.0.5 (2025-03-29)
|
||||
- Zwift Ride: remap the shifter buttons to the correct values
|
||||
|
||||
### 1.0.0+4 (2025-03-29)
|
||||
- Zwift Ride: attempt to fix button parsing
|
||||
- Android: fix missing permissions
|
||||
- Windows: potential fix for key press issues
|
||||
|
||||
### 1.0.0+3 (2025-03-29)
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@ import android.os.Build
|
||||
import android.util.Log
|
||||
import android.view.ViewConfiguration
|
||||
import android.view.accessibility.AccessibilityEvent
|
||||
import android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED
|
||||
import android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED
|
||||
import android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
||||
|
||||
|
||||
@@ -30,7 +28,6 @@ class AccessibilityService : AccessibilityService(), Listener {
|
||||
private val ignorePackages = listOf("com.android.systemui", "com.android.launcher", "com.android.settings")
|
||||
|
||||
override fun onAccessibilityEvent(event: AccessibilityEvent) {
|
||||
Log.w("Acc", "onAccessibilityEvent: ${event.packageName} ${event.eventType} ${event.contentChangeTypes}")
|
||||
if (event.packageName == null || rootInActiveWindow == null) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import java.io.FileInputStream
|
||||
import java.util.*
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
@@ -5,6 +8,11 @@ plugins {
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
}
|
||||
|
||||
|
||||
val keystorePropertiesFile = rootProject.file("keystore.properties")
|
||||
val keystoreProperties = Properties()
|
||||
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||||
|
||||
android {
|
||||
namespace = "de.jonasbark.swift_play"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
@@ -33,11 +41,18 @@ android {
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
create("config") {
|
||||
keyAlias = keystoreProperties["keyAlias"] as String
|
||||
keyPassword = keystoreProperties["keyPassword"] as String
|
||||
storeFile = file("../${keystoreProperties["storeFile"] as String}")
|
||||
storePassword = keystoreProperties["storePassword"] as String
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
signingConfig = signingConfigs.getByName("config")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,16 @@ import 'package:swift_control/utils/keymap/keymap.dart';
|
||||
class AndroidActions extends BaseActions {
|
||||
static const MYWHOOSH_APP_PACKAGE = "com.mywhoosh.whooshgame";
|
||||
static const TRAININGPEAKS_APP_PACKAGE = "com.indieVelo.client";
|
||||
static const validPackageNames = [MYWHOOSH_APP_PACKAGE, TRAININGPEAKS_APP_PACKAGE];
|
||||
|
||||
WindowEvent? windowInfo;
|
||||
|
||||
@override
|
||||
void init(Keymap? keymap) {
|
||||
streamEvents().listen((windowEvent) {
|
||||
windowInfo = windowEvent;
|
||||
if (validPackageNames.contains(windowEvent.packageName)) {
|
||||
windowInfo = windowEvent;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,9 @@ class DesktopActions extends BaseActions {
|
||||
if (keymap == null) {
|
||||
throw Exception('Keymap is not set');
|
||||
}
|
||||
keyPressSimulator.simulateKeyDown(_keymap!.decrease);
|
||||
keyPressSimulator.simulateKeyDown(_keymap!.decrease).then((_) {
|
||||
keyPressSimulator.simulateKeyUp(_keymap!.decrease);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -27,6 +29,8 @@ class DesktopActions extends BaseActions {
|
||||
if (keymap == null) {
|
||||
throw Exception('Keymap is not set');
|
||||
}
|
||||
keyPressSimulator.simulateKeyDown(_keymap!.increase);
|
||||
keyPressSimulator.simulateKeyDown(_keymap!.increase).then((_) {
|
||||
keyPressSimulator.simulateKeyUp(_keymap!.increase);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:accessibility/accessibility.dart';
|
||||
import 'package:swift_control/main.dart';
|
||||
import 'package:swift_control/utils/devices/zwift_click.dart';
|
||||
import 'package:swift_control/utils/messages/ride_notification.dart';
|
||||
@@ -25,12 +24,15 @@ class ZwiftRide extends ZwiftClick {
|
||||
_lastControllerNotification = clickNotification;
|
||||
actionStreamInternal.add(clickNotification);
|
||||
|
||||
if (clickNotification.analogLR.abs() == 100) {
|
||||
actionHandler.increaseGear();
|
||||
} else if (clickNotification.analogUD.abs() == 100) {
|
||||
if (clickNotification.buttonShiftDownLeft || clickNotification.buttonShiftUpLeft || clickNotification.buttonZ) {
|
||||
actionHandler.decreaseGear();
|
||||
} else if (clickNotification.buttonShiftUpRight ||
|
||||
clickNotification.buttonShiftDownRight ||
|
||||
clickNotification.buttonOnOffLeft) {
|
||||
// TODO remove buttonZ once the assignment is fixed for real
|
||||
actionHandler.increaseGear();
|
||||
}
|
||||
if (clickNotification.buttonA) {
|
||||
/*if (clickNotification.buttonA) {
|
||||
actionHandler.controlMedia(MediaAction.next);
|
||||
} else if (clickNotification.buttonY) {
|
||||
actionHandler.controlMedia(MediaAction.volumeUp);
|
||||
@@ -38,7 +40,7 @@ class ZwiftRide extends ZwiftClick {
|
||||
actionHandler.controlMedia(MediaAction.volumeDown);
|
||||
} else if (clickNotification.buttonZ) {
|
||||
actionHandler.controlMedia(MediaAction.playPause);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class RideNotification extends BaseNotification {
|
||||
late bool buttonPowerUpLeft, buttonPowerDownLeft;
|
||||
late bool buttonOnOffLeft, buttonOnOffRight;
|
||||
|
||||
late int analogLR, analogUD;
|
||||
int analogLR = 0, analogUD = 0;
|
||||
|
||||
RideNotification(Uint8List message) {
|
||||
final status = RideKeyPadStatus.fromBuffer(message);
|
||||
@@ -62,9 +62,9 @@ class RideNotification extends BaseNotification {
|
||||
buttonOnOffRight = status.buttonMap & _RideButtonMask.ONOFF_R_BTN.mask == BTN_PRESSED;
|
||||
|
||||
for (final analogue in status.analogButtons.groupStatus) {
|
||||
if (analogue.location == RideAnalogLocation.LEFT) {
|
||||
if (analogue.location == RideAnalogLocation.LEFT || analogue.location == RideAnalogLocation.RIGHT) {
|
||||
analogLR = analogue.analogValue;
|
||||
} else if (analogue.location == RideAnalogLocation.DOWN) {
|
||||
} else if (analogue.location == RideAnalogLocation.DOWN || analogue.location == RideAnalogLocation.UP) {
|
||||
analogUD = analogue.analogValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:swift_control/main.dart';
|
||||
import 'package:swift_control/utils/requirements/platform.dart';
|
||||
|
||||
@@ -18,6 +19,36 @@ class AccessibilityRequirement extends PlatformRequirement {
|
||||
}
|
||||
}
|
||||
|
||||
class BluetoothScanRequirement extends PlatformRequirement {
|
||||
BluetoothScanRequirement() : super('Allow Bluetooth Scan');
|
||||
|
||||
@override
|
||||
Future<void> call() async {
|
||||
await Permission.bluetoothScan.request();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> getStatus() async {
|
||||
final state = await Permission.bluetoothScan.status;
|
||||
status = state.isGranted || state.isLimited;
|
||||
}
|
||||
}
|
||||
|
||||
class BluetoothConnectRequirement extends PlatformRequirement {
|
||||
BluetoothConnectRequirement() : super('Allow Bluetooth Connections');
|
||||
|
||||
@override
|
||||
Future<void> call() async {
|
||||
await Permission.bluetoothConnect.request();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> getStatus() async {
|
||||
final state = await Permission.bluetoothConnect.status;
|
||||
status = state.isGranted || state.isLimited;
|
||||
}
|
||||
}
|
||||
|
||||
class NotificationRequirement extends PlatformRequirement {
|
||||
NotificationRequirement() : super('Allow adding persistent Notification');
|
||||
|
||||
|
||||
@@ -29,7 +29,14 @@ Future<List<PlatformRequirement>> getRequirements() async {
|
||||
} else if (Platform.isWindows) {
|
||||
list = [BluetoothTurnedOn(), KeyboardRequirement(), KeymapRequirement(), BluetoothScanning()];
|
||||
} else if (Platform.isAndroid) {
|
||||
list = [BluetoothTurnedOn(), AccessibilityRequirement(), NotificationRequirement(), BluetoothScanning()];
|
||||
list = [
|
||||
BluetoothTurnedOn(),
|
||||
AccessibilityRequirement(),
|
||||
NotificationRequirement(),
|
||||
BluetoothScanRequirement(),
|
||||
BluetoothConnectRequirement(),
|
||||
BluetoothScanning(),
|
||||
];
|
||||
} else {
|
||||
list = [UnsupportedPlatform()];
|
||||
}
|
||||
|
||||
48
pubspec.lock
48
pubspec.lock
@@ -367,6 +367,54 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
permission_handler:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: permission_handler
|
||||
sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.4.0"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_android
|
||||
sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "12.1.0"
|
||||
permission_handler_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: f84a188e79a35c687c132a0a0556c254747a08561e99ab933f12f6ca71ef3c98
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.4.6"
|
||||
permission_handler_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_html
|
||||
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.3+5"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.3.0"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_windows
|
||||
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: swift_control
|
||||
description: "SwiftControl - Control your virtual riding"
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
version: 1.0.0+4
|
||||
version: 1.0.5+0
|
||||
|
||||
environment:
|
||||
sdk: ^3.7.0
|
||||
@@ -14,6 +14,7 @@ dependencies:
|
||||
flutter_local_notifications: ^19.0.0
|
||||
universal_ble: any
|
||||
protobuf: ^3.1.0
|
||||
permission_handler: ^11.4.0
|
||||
dartx: any
|
||||
pointycastle: any
|
||||
keypress_simulator: ^0.2.0
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <keypress_simulator_windows/keypress_simulator_windows_plugin_c_api.h>
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
#include <universal_ble/universal_ble_plugin_c_api.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
KeypressSimulatorWindowsPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("KeypressSimulatorWindowsPluginCApi"));
|
||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||
UniversalBlePluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UniversalBlePluginCApi"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
keypress_simulator_windows
|
||||
permission_handler_windows
|
||||
universal_ble
|
||||
url_launcher_windows
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user