diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3e2945b..3f48ba3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,7 +36,7 @@ on: env: SHOREBIRD_TOKEN: ${{ secrets.SHOREBIRD_TOKEN }} - FLUTTER_VERSION: 3.38.5 + FLUTTER_VERSION: 3.38.4 jobs: build: @@ -348,13 +348,13 @@ jobs: name: Releases path: | build/windows/x64/runner/Release/bike_control.windows.zip - build/windows/x64/runner/Release/bike_control.windows.msix + build/windows/x64/runner/Release/bike_control.msix - name: Update Release uses: ncipollo/release-action@v1 with: allowUpdates: true - artifacts: "build/windows/x64/runner/Release/bike_control.windows.msix" + artifacts: "build/windows/x64/runner/Release/bike_control.msix" prerelease: true tag: v${{ env.VERSION }} token: ${{ secrets.TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fb8887..db04f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,15 @@ BikeControl now offers a free trial period of 5 days for all features, so you can test everything before deciding to purchase a license. Please contact the support if you experience any issues! +### 4.1.0 (16-12-2025) + **Features**: - control your trainer manually without requiring a controller - just like a Companion app - support for Wahoo KICKR HEADWIND: control the fan via your controller **Fixes**: - Gamepads: handle analog values correctly on Windows -- MyWhoosh: updated default keymap to use steering instead of navigating +- MyWhoosh: updated default keymap to use the new A+D keys for steering ### 4.0.0 (07-12-2025) diff --git a/INSTRUCTIONS_ROUVY.md b/INSTRUCTIONS_ROUVY.md index e69de29..47d20c8 100644 --- a/INSTRUCTIONS_ROUVY.md +++ b/INSTRUCTIONS_ROUVY.md @@ -0,0 +1,4 @@ +## Local Connection method +* +The local connection method (avalable on Android, Windows and macOS) allows BikeControl to directly control Rouvy either using touch or keyboard keys. This way you don't need to select any "Controllers" at all in Rouvy. +Make sure the "Virtual Shifting Controls" are enabled: https://support.rouvy.com/hc/en-us/articles/32452137189393-Virtual-Shifting#h_01K9SWGWYMAVQV108SQ9KWQAKC diff --git a/WINDOWS_STORE_VERSION.txt b/WINDOWS_STORE_VERSION.txt index fcdb2e1..ee74734 100644 --- a/WINDOWS_STORE_VERSION.txt +++ b/WINDOWS_STORE_VERSION.txt @@ -1 +1 @@ -4.0.0 +4.1.0 diff --git a/lib/bluetooth/devices/base_device.dart b/lib/bluetooth/devices/base_device.dart index 7d05b69..10f22b3 100644 --- a/lib/bluetooth/devices/base_device.dart +++ b/lib/bluetooth/devices/base_device.dart @@ -128,10 +128,10 @@ abstract class BaseDevice { // For repeated actions, don't trigger key down/up events (useful for long press) final result = await core.actionHandler.performAction(action, isKeyDown: true, isKeyUp: false); - actionStreamInternal.add(LogNotification(result.message)); // Increment command count after successful execution await IAPManager.instance.incrementCommandCount(); + actionStreamInternal.add(ActionNotification(result)); } } @@ -160,10 +160,10 @@ abstract class BaseDevice { } final result = await core.actionHandler.performAction(action, isKeyDown: false, isKeyUp: true); - actionStreamInternal.add(ActionNotification(result)); // Increment command count after successful execution await IAPManager.instance.incrementCommandCount(); + actionStreamInternal.add(LogNotification(result.message)); } } diff --git a/lib/bluetooth/devices/mywhoosh/link.dart b/lib/bluetooth/devices/mywhoosh/link.dart index 740dd2f..e9073cf 100644 --- a/lib/bluetooth/devices/mywhoosh/link.dart +++ b/lib/bluetooth/devices/mywhoosh/link.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'dart:io'; -import 'package:flutter/foundation.dart'; import 'package:bike_control/bluetooth/devices/trainer_connection.dart'; import 'package:bike_control/bluetooth/devices/zwift/protocol/zp.pb.dart'; import 'package:bike_control/bluetooth/messages/notification.dart'; @@ -11,6 +10,7 @@ import 'package:bike_control/utils/core.dart'; import 'package:bike_control/utils/keymap/buttons.dart'; import 'package:bike_control/utils/keymap/keymap.dart'; import 'package:bike_control/utils/requirements/multi.dart'; +import 'package:flutter/foundation.dart'; class WhooshLink extends TrainerConnection { Socket? _socket; @@ -155,7 +155,7 @@ class WhooshLink extends TrainerConnection { InGameAction.steerRight, ]; if (jsonObject != null && !isKeyDown && !supportsIsKeyUpActions.contains(keyPair.inGameAction)) { - return Success('No Action sent on key down for action: ${keyPair.inGameAction}'); + return Ignored('No Action sent on key down for action: ${keyPair.inGameAction}'); } else if (jsonObject != null) { final jsonString = jsonEncode(jsonObject); _socket?.writeln(jsonString); diff --git a/lib/utils/actions/base_actions.dart b/lib/utils/actions/base_actions.dart index 9c9bf25..386a2e3 100644 --- a/lib/utils/actions/base_actions.dart +++ b/lib/utils/actions/base_actions.dart @@ -32,6 +32,10 @@ class NotHandled extends ActionResult { const NotHandled(super.message); } +class Ignored extends ActionResult { + const Ignored(super.message); +} + class Error extends ActionResult { const Error(super.message); } diff --git a/lib/utils/keymap/apps/my_whoosh.dart b/lib/utils/keymap/apps/my_whoosh.dart index c01e99b..77dbf99 100644 --- a/lib/utils/keymap/apps/my_whoosh.dart +++ b/lib/utils/keymap/apps/my_whoosh.dart @@ -1,8 +1,8 @@ -import 'package:dartx/dartx.dart'; -import 'package:flutter/services.dart'; import 'package:bike_control/main.dart'; import 'package:bike_control/utils/keymap/apps/supported_app.dart'; import 'package:bike_control/utils/requirements/multi.dart'; +import 'package:dartx/dartx.dart'; +import 'package:flutter/services.dart'; import '../buttons.dart'; import '../keymap.dart'; @@ -44,8 +44,8 @@ class MyWhoosh extends SupportedApp { .map( (b) => KeyPair( buttons: [b], - physicalKey: PhysicalKeyboardKey.arrowRight, - logicalKey: LogicalKeyboardKey.arrowRight, + physicalKey: PhysicalKeyboardKey.keyD, + logicalKey: LogicalKeyboardKey.keyD, touchPosition: Offset(60, 80), isLongPress: true, inGameAction: InGameAction.steerRight, @@ -53,6 +53,18 @@ class MyWhoosh extends SupportedApp { ), ...ControllerButton.values .filter((e) => e.action == InGameAction.steerLeft) + .map( + (b) => KeyPair( + buttons: [b], + physicalKey: PhysicalKeyboardKey.keyA, + logicalKey: LogicalKeyboardKey.keyA, + touchPosition: Offset(32, 80), + isLongPress: true, + inGameAction: InGameAction.steerLeft, + ), + ), + ...ControllerButton.values + .filter((e) => e.action == InGameAction.navigateLeft) .map( (b) => KeyPair( buttons: [b], @@ -63,6 +75,18 @@ class MyWhoosh extends SupportedApp { inGameAction: InGameAction.steerLeft, ), ), + ...ControllerButton.values + .filter((e) => e.action == InGameAction.navigateRight) + .map( + (b) => KeyPair( + buttons: [b], + physicalKey: PhysicalKeyboardKey.arrowRight, + logicalKey: LogicalKeyboardKey.arrowRight, + touchPosition: Offset(32, 80), + isLongPress: true, + inGameAction: InGameAction.steerLeft, + ), + ), ...ControllerButton.values .filter((e) => e.action == InGameAction.toggleUi) .map( diff --git a/lib/widgets/testbed.dart b/lib/widgets/testbed.dart index 2c06c2c..ba98b38 100644 --- a/lib/widgets/testbed.dart +++ b/lib/widgets/testbed.dart @@ -2,9 +2,6 @@ import 'dart:async'; import 'dart:math' as math; import 'dart:ui'; -import 'package:flutter/scheduler.dart'; -import 'package:flutter/services.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:bike_control/bluetooth/devices/zwift/protocol/zp.pb.dart'; import 'package:bike_control/utils/actions/base_actions.dart' as actions; import 'package:bike_control/utils/core.dart'; @@ -13,6 +10,9 @@ import 'package:bike_control/utils/keymap/apps/custom_app.dart'; import 'package:bike_control/utils/keymap/buttons.dart'; import 'package:bike_control/widgets/ui/button_widget.dart'; import 'package:bike_control/widgets/ui/toast.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:flutter/services.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; import '../bluetooth/messages/notification.dart'; @@ -125,7 +125,7 @@ class _TestbedState extends State with SingleTickerProviderStateMixin { } } } - } else if (data is ActionNotification) { + } else if (data is ActionNotification && data.result is! actions.Ignored) { buildToast( context, location: ToastLocation.bottomLeft, diff --git a/pubspec.yaml b/pubspec.yaml index 0521809..2af2502 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: bike_control description: "BikeControl - Control your virtual riding" publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 4.2.0+51 +version: 4.2.0+53 environment: sdk: ^3.9.0