Compare commits

..

737 Commits
v ... v4.4.0+77

Author SHA1 Message Date
Jonas Bark
41a3a8f14d update changelog 2026-01-16 00:21:01 +01:00
Jonas Bark
a883abcd1c Merge remote-tracking branch 'origin/main' 2026-01-16 00:20:40 +01:00
Jonas Bark
ab37de8f40 fix issue #258 2026-01-16 00:20:30 +01:00
jonasbark
ac0e15eaa7 Update instructions for MyWhoosh Link connectivity 2026-01-15 17:06:46 +01:00
Jonas Bark
a6a7e7f0c2 show logs file path 2026-01-15 14:35:18 +01:00
Jonas Bark
3cacdf9a3a update changelog 2026-01-15 14:25:36 +01:00
Jonas Bark
3ebbda3690 kickr headwind: write without response to potentially fix #11 2026-01-15 08:55:03 +01:00
Jonas Bark
74abb13acf skip powermeters from connecting 2026-01-14 12:12:19 +01:00
Jonas Bark
86addc00fd Merge remote-tracking branch 'origin/win' 2026-01-13 18:42:52 +01:00
jonas.bark@gmx.de
9cebea225c fix import 2026-01-13 18:42:42 +01:00
jonasbark
59bdb30321 Merge pull request #255 from jonasbark/win
Win
2026-01-13 18:20:52 +01:00
Jonas Bark
d51fb7dfa2 update translations 2026-01-13 18:20:25 +01:00
jonas.bark@gmx.de
b955c51a91 cleanup 2026-01-13 18:07:35 +01:00
Jonas Bark
86ecd1ad20 check win package format 2026-01-13 17:57:01 +01:00
jonas.bark@gmx.de
c089b3bdbd fix test phase logic 2026-01-13 17:49:17 +01:00
Jonas Bark
9612b213aa adjust instructions 2026-01-13 11:49:27 +01:00
Jonas Bark
83c9b52708 Merge branch 'copilot/fix-bluetooth-keyboard-issue' 2026-01-12 18:43:46 +01:00
Jonas Bark
a7bde7c08a UI fix 2026-01-12 18:43:10 +01:00
Jonas Bark
c8613b5975 fix implementation 2026-01-12 18:42:54 +01:00
jonasbark
87bb728601 Merge pull request #253 from jonasbark/copilot/add-support-thinkrider-vs200
Add support for Thinkrider VS200 virtual shifter
2026-01-12 17:55:47 +01:00
copilot-swe-agent[bot]
e1f9d4fb08 Add debug logging for all received hexValues while in beta
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2026-01-12 16:55:12 +00:00
copilot-swe-agent[bot]
14e6c1186c Address code review feedback: memory leak and thread safety
- Store keymap update subscription to allow cancellation on re-init
- Fix List<String?> to List<String> in setHandledKeys signature
- Use ConcurrentHashMap.newKeySet() for thread-safe handledKeys access
- Clear and update the set instead of replacing it

Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2026-01-12 16:52:22 +00:00
copilot-swe-agent[bot]
abeb142f0b Fix case-insensitive pattern matching for VS200
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2026-01-12 16:50:52 +00:00
copilot-swe-agent[bot]
d416756614 Update VS200 logic: use only FEA0 service with specific byte patterns
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2026-01-12 16:49:48 +00:00
copilot-swe-agent[bot]
823eb9e9a4 Change approach: Use keymap-based filtering for HID key events
- Add setHandledKeys API to pass list of keys with keymaps to Android side
- Android AccessibilityService checks if key is in handled keys set before swallowing
- Dart side updates handled keys list whenever keymap changes
- Remove hardcoded media/volume key filtering
- This allows keyboards to work for typing while still capturing mapped keys

Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2026-01-12 16:49:19 +00:00
copilot-swe-agent[bot]
6579092f4a Update README with Thinkrider VS200 support
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2026-01-12 16:37:23 +00:00
copilot-swe-agent[bot]
c242c09025 Add support for Thinkrider VS200 virtual shifter
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2026-01-12 16:36:53 +00:00
copilot-swe-agent[bot]
89c9ed598c Fix Android accessibility service to only intercept media/volume keys
- Add isMediaOrVolumeKey() helper to filter key events by key code
- Only swallow media and volume keys (play/pause, next, volume up/down, etc.)
- Let all other keys (typing keys, navigation, etc.) pass through to the system
- This fixes Bluetooth keyboard interference when BikeControl is running

Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2026-01-12 16:36:18 +00:00
copilot-swe-agent[bot]
a3a592bd16 Initial plan 2026-01-12 16:31:49 +00:00
copilot-swe-agent[bot]
a161829913 Initial plan 2026-01-12 16:31:43 +00:00
Jonas Bark
b4473ad067 patch it 2026-01-11 15:48:57 +01:00
jonas.bark@gmx.de
4752f99fcf fix windows issue 2026-01-11 15:47:29 +01:00
Jonas Bark
6e757cf15c list supported actions of connection method 2026-01-11 13:01:10 +01:00
Jonas Bark
a87810db88 list supported actions of connection method 2026-01-11 13:00:43 +01:00
Jonas Bark
0ddb3e8081 clenaup 2026-01-11 12:11:28 +01:00
Jonas Bark
e29aed8bcf version++ 2026-01-11 11:28:43 +01:00
Jonas Bark
d99a3257af optional notification permission on macOS 2026-01-11 11:28:29 +01:00
Jonas Bark
a772b210cd don't connect to both Zwift Ride instances 2026-01-11 11:25:20 +01:00
Jonas Bark
860700ab91 version++ 2026-01-08 10:37:51 +01:00
Jonas Bark
ff5d90d468 fix Apple full version detection 2026-01-08 10:37:36 +01:00
Jonas Bark
43773310d5 ui fix, sync purchases once, Zwift Ride adjustment 2026-01-08 09:43:52 +01:00
jonasbark
2da65645b0 Update Windows Store version to 4.3.0 2026-01-07 14:04:51 +01:00
Jonas Bark
0c62d64987 version++ 2026-01-07 11:21:22 +01:00
Jonas Bark
546f6c2f8f version++ 2026-01-07 11:03:03 +01:00
Jonas Bark
a6ee15e3ba changelog adjustment 2026-01-07 10:37:46 +01:00
Jonas Bark
51793847cf performance & ui fixes 2026-01-07 10:36:41 +01:00
Jonas Bark
f308aa3847 performance & ui fixes 2026-01-07 10:19:21 +01:00
Jonas Bark
695b994577 fix shorebird logic 2026-01-06 18:08:56 +01:00
Jonas Bark
2301d04c61 refactor update UI 2026-01-06 09:10:27 +01:00
Jonas Bark
e46ec5172c OBC adjustments 2026-01-05 13:23:33 +01:00
Jonas Bark
691e108c82 OBC adjustments 2026-01-05 13:22:23 +01:00
Jonas Bark
166146a8f8 Web fixes 2026-01-03 20:50:06 +01:00
Jonas Bark
2a42cfc80f make notifications optional on macOS & iOS 2026-01-03 09:42:03 +01:00
Jonas Bark
aff1f20ebe Merge branch '4.2.4'
# Conflicts:
#	CHANGELOG.md
#	lib/utils/iap/revenuecat_service.dart
2026-01-02 21:02:54 +01:00
Jonas Bark
804fed799d fix logic 2026-01-02 21:02:02 +01:00
Jonas Bark
b6450ba47c restore button 2026-01-02 20:42:23 +01:00
Jonas Bark
14a4234583 instructions UI change 2026-01-02 15:03:46 +01:00
Jonas Bark
72cd165992 instructions for local connection method 2026-01-02 14:03:08 +01:00
Jonas Bark
239aec2083 onboarding UI 2026-01-01 13:50:02 +01:00
Jonas Bark
a43ab60dcb onboarding UI 2026-01-01 13:47:17 +01:00
Jonas Bark
484b7f74e6 onboarding UI 2026-01-01 13:44:45 +01:00
Jonas Bark
8c1ddcb019 ui adjustments 2026-01-01 12:40:45 +01:00
Jonas Bark
306a5badef onboarding for new users 2025-12-31 16:26:40 +01:00
Jonas Bark
e82003cd57 onboarding for new users 2025-12-31 16:16:37 +01:00
Jonas Bark
6a6aafe0a9 onboarding for new users 2025-12-31 15:52:30 +01:00
Jonas Bark
4bd440e167 ui adjustments 2025-12-31 13:51:47 +01:00
Jonas Bark
80d198787f ui adjustments 2025-12-31 12:26:34 +01:00
Jonas Bark
7f7bae477b debug text adjustments 2025-12-31 12:11:06 +01:00
Jonas Bark
2917814ecc alternative title during button editor 2025-12-30 17:45:06 +01:00
Jonas Bark
e268a86f20 fix media key icons 2025-12-30 14:12:55 +01:00
jonasbark
9a13831e91 Merge pull request #240 from jonasbark/copilot/enable-media-key-dispatching
Add media key dispatching for Desktop platforms
2025-12-30 14:04:12 +01:00
copilot-swe-agent[bot]
9f6e57b9ff Fix Windows compilation error: Cast UINT to WORD for wVk field
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-30 12:57:32 +00:00
Jonas Bark
86cf7491c3 Revert "issue"
This reverts commit 681ec710a1.
2025-12-30 13:55:30 +01:00
jonas.bark@gmx.de
681ec710a1 issue 2025-12-30 13:54:34 +01:00
Jonas Bark
dc40d61766 fix dart 2025-12-30 13:46:30 +01:00
copilot-swe-agent[bot]
326ff4ce24 Style: Fix code formatting and remove trailing comma in C++
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-30 12:43:50 +00:00
copilot-swe-agent[bot]
ca81642c5c Optimize: Make key maps static const for better performance
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-30 12:42:38 +00:00
copilot-swe-agent[bot]
32e4b9762b Refactor: Use maps instead of if-else chains for key mappings
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-30 12:41:13 +00:00
copilot-swe-agent[bot]
0c94852246 Use string identifiers instead of keyCode for media keys
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-30 12:39:26 +00:00
copilot-swe-agent[bot]
d2f67e402b Complete media key dispatching implementation
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-30 12:36:10 +00:00
copilot-swe-agent[bot]
145e55fe68 Add proper error handling for media key dispatch
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-30 12:34:41 +00:00
copilot-swe-agent[bot]
fd6358c233 Fix command count increment order for media keys
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-30 12:33:21 +00:00
copilot-swe-agent[bot]
1d047ce9ef Fix code review issues: error message and type mismatch
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-30 12:31:44 +00:00
copilot-swe-agent[bot]
a27a0b8872 Improve documentation for macOS media stop key behavior
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-30 12:30:10 +00:00
copilot-swe-agent[bot]
0e98a9d500 Add media key dispatching support for Desktop platforms
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-30 12:27:55 +00:00
copilot-swe-agent[bot]
728b2e0b53 Initial plan 2025-12-30 12:21:42 +00:00
jonas.bark@gmx.de
220ffa49c6 fix windows notifications 2025-12-30 13:19:56 +01:00
jonas.bark@gmx.de
74d1ec58de fix a companion mode issue with delayed dispatches 2025-12-30 12:44:02 +01:00
Jonas Bark
b2d19f7e70 ignore messages when in background 2025-12-30 09:44:27 +01:00
Jonas Bark
7db8dfec62 message permission fix 2025-12-29 15:08:46 +01:00
Jonas Bark
b0c0767dc7 obp adjustments 2025-12-29 10:15:36 +01:00
Jonas Bark
2e880869f3 restore purchase 2025-12-29 09:19:06 +01:00
Jonas Bark
1edf949a7a Merge branch 'revenuecat' 2025-12-28 13:14:16 +01:00
Jonas Bark
04c85668fe Merge branch 'main' of github.com:jonasbark/swiftcontrol 2025-12-28 13:14:13 +01:00
Jonas Bark
fcefd863cd version++ 2025-12-28 13:13:57 +01:00
Jonas Bark
64bac7e50f revenue cat changes, italian translation 2025-12-28 13:12:20 +01:00
Jonas Bark
f94c1b1851 check original app version 2025-12-27 09:08:29 +01:00
Jonas Bark
3a013db311 Merge remote-tracking branch 'origin/main' into revenuecat 2025-12-27 09:04:13 +01:00
jonasbark
0fd141316e Revise MyWhoosh Link connection instructions
Updated instructions for using MyWhoosh Link connection method to clarify optional steps and improve readability.
2025-12-27 00:23:16 +01:00
Jonas Bark
2ed4f389c9 Merge branch 'main' into revenuecat 2025-12-26 23:15:47 +01:00
Jonas Bark
9a1a25ed17 unlock for now 2025-12-26 23:15:24 +01:00
Jonas Bark
173fae7472 handle old migrated purchases 2025-12-26 22:57:43 +01:00
Jonas Bark
82c9df2214 fix podfile 2025-12-26 20:35:59 +01:00
Jonas Bark
a49b6b81ae fix podfile 2025-12-26 20:35:53 +01:00
Jonas Bark
dffa7003bc Merge branch 'copilot/integrate-revenuecat-sdk' 2025-12-26 19:44:12 +01:00
Jonas Bark
818ff4909a implement logic 2025-12-26 19:36:20 +01:00
Jonas Bark
d1e054d5c5 implement logic 2025-12-26 18:48:57 +01:00
copilot-swe-agent[bot]
7689da9acd Add future improvements documentation
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-26 13:03:53 +00:00
copilot-swe-agent[bot]
0bf336643d Add implementation summary documentation
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-26 13:01:51 +00:00
copilot-swe-agent[bot]
70dc5d19e7 Fix async handling and improve error messages
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-26 13:00:52 +00:00
copilot-swe-agent[bot]
4da91b0fa3 Fix circular dependency and async issues in RevenueCat service
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-26 12:58:50 +00:00
copilot-swe-agent[bot]
cb219c57c4 Add comprehensive RevenueCat setup and configuration documentation
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-26 12:55:16 +00:00
copilot-swe-agent[bot]
0be5500d78 Add RevenueCat SDK integration with paywall and customer center support
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-26 12:53:51 +00:00
copilot-swe-agent[bot]
94dcccdce3 Initial plan 2025-12-26 12:48:20 +00:00
Jonas Bark
91b6ffdbe2 version++ 2025-12-24 22:38:30 +01:00
Jonas Bark
baa3a73984 Merge branch 'hotfix' 2025-12-24 10:46:53 +01:00
Jonas Bark
dd5c231c47 hopefully fix iap issue on Android 2025-12-24 10:28:58 +01:00
Jonas Bark
3a0d4e1cbc hopefully fix iap issue on Android 2025-12-24 10:08:55 +01:00
Jonas Bark
631f031daa unit test adjustments 2025-12-23 09:10:05 +01:00
Jonas Bark
a487539e6a hotfix 2025-12-22 20:37:44 +01:00
Jonas Bark
ad7454236a hotfix 2025-12-22 20:17:27 +01:00
Jonas Bark
e182fea4d1 hotfix 2025-12-22 20:05:09 +01:00
Jonas Bark
6615061658 hotfix macOS 2025-12-22 20:00:17 +01:00
jonasbark
5c1d423806 Update CHANGELOG.md 2025-12-22 19:34:37 +01:00
Jonas Bark
171f97645f Merge branch 'main' of github.com:jonasbark/swiftcontrol 2025-12-22 19:24:14 +01:00
jonasbark
9511c233a2 Add iPadOS support to connection methods in README
Updated README to include iPadOS in connection methods.
2025-12-22 18:23:47 +01:00
jonasbark
adfc2bd8cf Update Windows Store version to 4.2.2 2025-12-22 15:29:26 +01:00
jonasbark
2adba27dca Fix formatting and clarify trainer app connection 2025-12-22 11:41:41 +01:00
Jonas Bark
b18c85fc8e improve Android notification action handling 2025-12-22 11:13:37 +01:00
Jonas Bark
2e79a43827 axs info 2025-12-22 08:21:02 +01:00
Jonas Bark
0fec34bb56 allow redeeming manually 2025-12-21 22:21:40 +01:00
Jonas Bark
db3e133199 allow redeeming manually 2025-12-21 22:17:47 +01:00
Jonas Bark
971cb91615 allow redeeming manually 2025-12-21 22:16:12 +01:00
Jonas Bark
e5e04f3d59 clarify Android transition 2025-12-21 20:33:51 +01:00
Jonas Bark
fd9f7388e8 check purchases once a day 2025-12-21 16:41:30 +01:00
Jonas Bark
6ae2297246 version++ 2025-12-21 16:00:10 +01:00
Jonas Bark
c6fb2e68b5 win fix 2025-12-21 15:43:44 +01:00
jonas.bark@gmx.de
c84c685a8f attempt to fix remaining trial days calculation 2025-12-21 15:42:17 +01:00
Jonas Bark
102f4a8818 add info for Android users regarding existing purchase 2025-12-21 13:54:08 +01:00
Jonas Bark
661d72fa8c windows adjustments 2025-12-21 10:29:53 +01:00
jonas.bark@gmx.de
38df962e43 windows trial changes 2025-12-21 10:25:52 +01:00
Jonas Bark
e02563733f fix missing entitlements on release builds for macOS 2025-12-20 20:40:53 +01:00
Jonas Bark
c246d2d1fe fix missing entitlements on release builds for macOS 2025-12-20 20:40:12 +01:00
Jonas Bark
8dbed9a8b5 wrong translation 2025-12-20 18:08:13 +01:00
Jonas Bark
6ea4fa82a7 version++ 2025-12-20 11:39:02 +01:00
Jonas Bark
0d78ca6352 version++ 2025-12-20 11:20:39 +01:00
Jonas Bark
b82ad80d1c fix windows build version 2025-12-20 10:56:19 +01:00
Jonas Bark
eece2ce7dc update changelog 2025-12-20 10:30:32 +01:00
jonasbark
3bfd7dd7ab Merge pull request #222 from jonasbark/copilot/implement-in-app-purchase
Implement IAP system with 5-day trial and command limiting
2025-12-20 10:13:33 +01:00
Jonas Bark
b0f3dffc3c screenshots 2025-12-20 10:13:20 +01:00
Jonas Bark
f5234d0c11 update changelog 2025-12-20 10:06:57 +01:00
Jonas Bark
8a12ccb01e cleanup 2025-12-20 10:04:44 +01:00
Jonas Bark
fac2e86240 bugfixes and clarifications 2025-12-20 10:01:37 +01:00
Jonas Bark
39b49bb9de sram fix 2025-12-19 21:06:13 +01:00
Jonas Bark
406ccfa2ce adjust iOS receipt logic 2025-12-19 20:41:45 +01:00
Jonas Bark
16e6b96cc7 SRAM AXS support 2025-12-19 20:41:27 +01:00
Jonas Bark
1e37c8a742 press longer for the simulator, enable long press for devices not supporting long press (e.g. Shimano Di2) 2025-12-19 11:40:07 +01:00
Jonas Bark
5f0389b36f press longer for the simulator, enable long press for devices not supporting long press (e.g. Shimano Di2) 2025-12-19 11:38:30 +01:00
Jonas Bark
8762d85d57 press longer for the simulator, enable long press for devices not supporting long press (e.g. Shimano Di2) 2025-12-19 11:33:13 +01:00
Jonas Bark
018bbd43f1 fix 2025-12-19 10:13:01 +01:00
Jonas Bark
756e3fc556 version++ 2025-12-19 10:09:06 +01:00
Jonas Bark
7ac5f5dbcb fine tune gryoscope logic to react more quickly 2025-12-19 09:29:19 +01:00
Jonas Bark
65c613fd24 fine tune gryoscope logic to react more quickly 2025-12-19 09:29:05 +01:00
Jonas Bark
e0ad9007a4 ui adjustments 2025-12-19 09:21:11 +01:00
Jonas Bark
c3cda5f547 ui adjustments, add polish translations 2025-12-19 08:56:14 +01:00
Jonas Bark
12f379c03d screenshot fix 2025-12-18 15:39:16 +01:00
Jonas Bark
e760c34ede unit test fixes 2025-12-18 15:30:14 +01:00
Jonas Bark
187a15a55d improve trainer controller view 2025-12-18 14:51:49 +01:00
Jonas Bark
3e4751a6b5 refactor sensor logic 2025-12-18 12:24:52 +01:00
Jonas Bark
b05d87196a implement functionality, refactoring 2025-12-18 12:06:34 +01:00
Jonas Bark
b8297848f6 Merge branch 'copilot/add-steering-detection-algorithm' into copilot/implement-in-app-purchase 2025-12-18 11:37:39 +01:00
Jonas Bark
de0f004a48 implement functionality, refactoring 2025-12-18 11:37:21 +01:00
Jonas Bark
0bc9c1d4d2 implement functionality, refactoring 2025-12-18 11:33:14 +01:00
Jonas Bark
3fccb59544 Merge branch 'copilot/implement-in-app-purchase' into copilot/add-steering-detection-algorithm 2025-12-18 09:46:45 +01:00
Jonas Bark
ea76aabf91 update changelog 2025-12-18 09:46:32 +01:00
Jonas Bark
dc1c900bd2 bugfix and animation 2025-12-18 09:26:25 +01:00
Jonas Bark
b1e59d8f2a auto-open key editor on key press 2025-12-18 08:46:31 +01:00
Jonas Bark
006148dbd0 move button simulator page button 2025-12-18 08:33:04 +01:00
Jonas Bark
974ba258f5 teaser new connection methods 2025-12-18 08:11:06 +01:00
copilot-swe-agent[bot]
29d833e9d1 Update README with gyroscope steering device information
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-18 06:55:33 +00:00
copilot-swe-agent[bot]
eea72405bb Fix code review issues in gyroscope steering implementation
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-18 06:54:42 +00:00
copilot-swe-agent[bot]
e500f1ed0b Add unit tests for gyroscope steering algorithm
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-18 06:52:39 +00:00
copilot-swe-agent[bot]
6c3bd2e6a1 Add gyroscope/accelerometer steering support with sensor fusion
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-18 06:51:43 +00:00
copilot-swe-agent[bot]
e54d8968e8 Initial plan 2025-12-18 06:44:46 +00:00
Jonas Bark
9dca2e989a check sandbox on iOS / macOS 2025-12-17 15:57:44 +01:00
Jonas Bark
610c5d6ef5 check sandbox on iOS / macOS 2025-12-17 15:48:30 +01:00
Jonas Bark
7797b34852 improve keymap UI 2025-12-17 14:34:08 +01:00
Jonas Bark
99e9f326f7 fix build 2025-12-17 13:05:05 +01:00
Jonas Bark
0f2d73239b fix build 2025-12-17 12:57:32 +01:00
Jonas Bark
497b489ea9 remove Podfile.loc 2025-12-17 12:40:29 +01:00
Jonas Bark
51581f106a cleanup README.md 2025-12-17 12:17:00 +01:00
Jonas Bark
43e9aa02e0 cleanup README.md 2025-12-17 12:13:23 +01:00
Jonas Bark
089a41cc2b translations and ux changes 2025-12-17 11:39:39 +01:00
Jonas Bark
279ab101cc macOS fix 2025-12-17 11:13:42 +01:00
Jonas Bark
c0f278652e show connection update notifications 2025-12-17 10:54:16 +01:00
Jonas Bark
ac02cc78bc show connection update notifications 2025-12-17 10:34:40 +01:00
Jonas Bark
d42ac3af6b notifications on iOS 2025-12-17 10:20:36 +01:00
Jonas Bark
20cfe76091 limit to 80 on Android during trial period, only count sent out commands 2025-12-17 10:02:32 +01:00
Jonas Bark
b68170b489 fix purchause logic 2025-12-17 09:08:28 +01:00
Jonas Bark
21273fa9ca Merge branch 'main' into copilot/implement-in-app-purchase
# Conflicts:
#	CHANGELOG.md
#	lib/bluetooth/devices/base_device.dart
#	pubspec.yaml
2025-12-17 08:41:47 +01:00
jonasbark
700afb1050 Document local connection method for Rouvy
Added instructions for the local connection method in Rouvy.
2025-12-16 19:56:56 +01:00
Jonas Bark
d943544e56 Merge branch 'main' of github.com:jonasbark/swiftcontrol 2025-12-16 19:53:42 +01:00
Jonas Bark
e994eb01dd less confusing messages 2025-12-16 19:53:25 +01:00
jonasbark
59d953bbc4 Update Windows Store version to 4.1.0 2025-12-16 14:36:30 +01:00
Jonas Bark
12ecbf80e1 version++ 2025-12-16 12:19:03 +01:00
Jonas Bark
a5b76b43bf build fix 2025-12-16 11:25:25 +01:00
Jonas Bark
383055bfe2 flutter version 2025-12-16 10:57:28 +01:00
Jonas Bark
24212e8e4c update changelog 2025-12-16 10:50:36 +01:00
Jonas Bark
1513a53dd4 update MyWhoosh keymap to use A and D keyboard keys for steering 2025-12-16 10:41:10 +01:00
Jonas Bark
fe9dd29964 cleanup, translations 2025-12-16 10:14:48 +01:00
Jonas Bark
eece2bcc0f Merge branch 'main' into copilot/implement-in-app-purchase
# Conflicts:
#	lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart
2025-12-16 09:19:50 +01:00
Jonas Bark
3ca63c0523 permission order 2025-12-16 09:19:06 +01:00
Jonas Bark
b46982918d resolve #224 2025-12-15 20:16:30 +01:00
Jonas Bark
13b075a1f3 only show supported actions 2025-12-15 13:48:18 +01:00
Jonas Bark
f71a417ac5 only show supported actions 2025-12-15 13:47:43 +01:00
Jonas Bark
27065f2906 prefill obp keymap actions 2025-12-15 13:42:54 +01:00
Jonas Bark
b5d938fd47 error reporting when starting connection method 2025-12-15 13:13:57 +01:00
Jonas Bark
46300fc0d4 hide other connection methods in an accordion 2025-12-15 13:03:37 +01:00
Jonas Bark
93882b8b36 prioritize OBP connection methods when available 2025-12-15 12:48:19 +01:00
jonas.bark@gmx.de
f19c6b8dd0 fix windows implementation 2025-12-15 11:12:06 +01:00
Jonas Bark
968e2c5928 fix button mapping for OpenBikeControl, button simulator changes 2025-12-15 09:49:07 +01:00
Jonas Bark
44599b2d33 fix button mapping for OpenBikeControl, button simulator changes 2025-12-15 09:48:36 +01:00
Jonas Bark
613f75fd25 Merge branch 'main' into copilot/implement-in-app-purchase 2025-12-15 09:22:18 +01:00
Jonas Bark
c09ab5482e fix button mapping for OpenBikeControl 2025-12-15 09:13:44 +01:00
Jonas Bark
6f68e6cb62 iap adjustment 2025-12-15 08:37:56 +01:00
Jonas Bark
43ac412efd iap adjustment 2025-12-14 21:35:06 +01:00
Jonas Bark
7149c98564 windows #2 2025-12-14 20:15:33 +01:00
Jonas Bark
0f4e46a758 windows #1 2025-12-14 19:54:41 +01:00
Jonas Bark
23fb927cd6 in app purchase implementation on macOS / iOS 2025-12-14 19:32:23 +01:00
Jonas Bark
d055a260ab fix shadcn design usage 2025-12-14 16:48:04 +01:00
Jonas Bark
d55fa5f7c0 Merge branch 'main' into copilot/implement-in-app-purchase
# Conflicts:
#	lib/bluetooth/devices/base_device.dart
#	lib/pages/configuration.dart
#	lib/utils/settings/settings.dart
2025-12-14 16:42:50 +01:00
Jonas Bark
5cc49bd246 no device information service on Windows 2025-12-14 16:31:14 +01:00
Jonas Bark
c3c49decd1 remove remains of swift_control 2025-12-14 16:22:07 +01:00
Jonas Bark
127c997ea1 less warnings for Click V2 users 2025-12-13 15:17:28 +01:00
Jonas Bark
724d52ba10 add keyboard input to supported devices 2025-12-13 10:22:55 +01:00
Jonas Bark
5cee0fbf55 use latest flutter 2025-12-13 10:11:28 +01:00
Jonas Bark
e44760d0e3 Revert "patch Android only"
This reverts commit 0eba068910.
2025-12-12 10:48:24 +01:00
Jonas Bark
29be3c4411 Merge remote-tracking branch 'origin/main' 2025-12-12 09:08:17 +01:00
Jonas Bark
0eba068910 patch Android only 2025-12-12 09:08:07 +01:00
Jonas Bark
04dee3f14c fix wrong permission for BLE advertising on Android 2025-12-12 09:06:33 +01:00
copilot-swe-agent[bot]
f4fd658c36 Refactor to reduce code duplication and use constants for magic numbers
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-12 07:47:41 +00:00
copilot-swe-agent[bot]
0e80d5612c Fix code review issues: remove unused import and fix negative counter display
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-12 07:45:29 +00:00
copilot-swe-agent[bot]
9302ebc667 Add restore purchases functionality to IAP widget
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-12 07:43:00 +00:00
copilot-swe-agent[bot]
2265866f58 Clarify existing user detection logic with comments
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-12 07:41:11 +00:00
copilot-swe-agent[bot]
8ec6ee5ef0 Improve IAP error handling and add documentation
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-12 07:39:13 +00:00
copilot-swe-agent[bot]
a03d250bdb Add IAP service implementation with trial and command limiting
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-12 07:37:15 +00:00
copilot-swe-agent[bot]
a0ebac41ea Initial plan 2025-12-12 07:29:07 +00:00
jonasbark
b4b3f5db67 Improve Click V2 connection instructions
Updated troubleshooting steps for Click V2 connection reliability.
2025-12-11 23:47:15 +01:00
Jonas Bark
b291f59e10 change icons 2025-12-11 22:55:54 +01:00
Jonas Bark
02de453952 Windows: fix version check URL 2025-12-11 22:53:16 +01:00
Jonas Bark
4c53f6e408 adjust windows logo 2025-12-11 22:27:29 +01:00
Jonas Bark
4f4d67cccc Merge remote-tracking branch 'origin/main' 2025-12-11 20:44:51 +01:00
Jonas Bark
ef056f0503 web log debugging 2025-12-11 20:44:41 +01:00
jonasbark
a6f5755b42 Update MyWhoosh Link instructions for clarity
Emphasized the importance of closing MyWhoosh Link and added clarification about app connectivity issues.
2025-12-11 19:38:02 +01:00
jonasbark
5ce6e37973 Add troubleshooting section for MyWhoosh clicks
Added troubleshooting tip for unrecognized clicks in MyWhoosh.
2025-12-11 18:27:40 +01:00
Jonas Bark
ebebd7ad8b version++ 2025-12-11 10:22:26 +01:00
Jonas Bark
f6c47e3dab fix markdown theme colors 2025-12-11 10:21:28 +01:00
jonasbark
de711e12dc Merge pull request #221 from jonasbark/copilot/configure-hotkeys-for-buttons
Add keyboard hotkey configuration for button simulator
2025-12-11 08:26:35 +00:00
Jonas Bark
b94fed2f21 add wahoo kickr support to readme 2025-12-11 09:26:08 +01:00
Jonas Bark
9316881048 button simulator adjustments 2025-12-11 09:20:02 +01:00
copilot-swe-agent[bot]
c60a990938 Add mounted check in delayed callback and length validation for keys
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-11 07:24:50 +00:00
copilot-swe-agent[bot]
e9aaa96185 Fix remaining code review issues: remove redundant check and await settings save
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-11 07:23:15 +00:00
copilot-swe-agent[bot]
cb497daee4 Address code review feedback: extract constants and fix async handling
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-11 07:21:57 +00:00
copilot-swe-agent[bot]
4881fe4778 Add test for button simulator hotkeys and fix trailing comma
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-11 07:19:28 +00:00
copilot-swe-agent[bot]
5d5d8ffb18 Add keyboard hotkey configuration for button simulator
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-11 07:17:31 +00:00
copilot-swe-agent[bot]
b707812a7e Initial plan 2025-12-11 07:12:08 +00:00
Jonas Bark
9de50dc6fc markdown changes 2025-12-11 08:09:50 +01:00
Jonas Bark
11d308b53b markdown changes 2025-12-11 08:07:12 +01:00
Jonas Bark
0e03ec4a03 clarify mywhoosh link 2025-12-10 21:26:43 +01:00
Jonas Bark
68a04fad96 handling fix 2025-12-10 21:21:23 +01:00
Jonas Bark
ce75fd0f34 add more instructions, clarify mail support 2025-12-10 21:17:49 +01:00
Jonas Bark
d46b71b2d0 md #1 2025-12-10 20:23:41 +01:00
Jonas Bark
6492afc46f MyWhoosh: updated default keymap to use steering instead of navigating 2025-12-10 19:14:13 +01:00
Jonas Bark
c9b068e1b3 control your trainer manually without requiring a controller - just like a Companion app 2025-12-10 18:57:08 +01:00
Jonas Bark
5cdf15a419 UI adjustments 2025-12-10 17:26:00 +01:00
Jonas Bark
24db720927 don't show firmware update warning when we don't have that info, yet 2025-12-10 09:16:57 +01:00
Jonas Bark
94754d3d9b Rouvy doesn't support network controllers, yet 2025-12-10 09:14:07 +01:00
Jonas Bark
bffdae1a9b enable local connection on Windows if the app doesn't support OBP 2025-12-10 09:08:54 +01:00
Jonas Bark
a8b68c2d89 disable MyWhoosh Link connection method when running BikeControl and MyWhoosh on Windows on the same device 2025-12-10 09:03:58 +01:00
Jonas Bark
84f70f13d8 Gamepads: handle analog values correctly on Windows 2025-12-10 08:58:41 +01:00
Jonas Bark
ef1048ec08 adjust Headwind logic according to comment from https://github.com/jonasbark/swiftcontrol/issues/11#issuecomment-3634041684 2025-12-09 21:56:45 +01:00
Jonas Bark
37bc2110f5 update screenshots 2025-12-09 17:59:10 +01:00
Jonas Bark
84fd828d36 work on issue #11 2025-12-09 09:00:01 +01:00
Jonas Bark
a51b4d7958 version++ 2025-12-08 20:15:41 +01:00
Jonas Bark
117467d708 fix issue #215 2025-12-08 19:11:03 +01:00
Jonas Bark
789509f9cf fix build 2025-12-08 18:01:47 +01:00
Jonas Bark
a323dc213d fix build 2025-12-08 18:00:02 +01:00
jonasbark
0ec998a618 Merge pull request #212 from jonasbark/copilot/add-headwind-support
Add KICKR Headwind fan control support
2025-12-08 16:50:23 +00:00
copilot-swe-agent[bot]
0f5e9d59a8 Implement proper Headwind protocol with state tracking and mode switching
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-08 16:48:56 +00:00
copilot-swe-agent[bot]
2280fda916 Use firstOrNull to avoid potential race condition
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-08 16:29:55 +00:00
copilot-swe-agent[bot]
8d4db788a3 Refactor Headwind control logic and remove buttons
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-08 16:27:47 +00:00
Jonas Bark
c2bfc472fe fix patch pipeline 2025-12-08 11:20:31 +01:00
Jonas Bark
09ffd258b7 version++ 2025-12-08 11:09:43 +01:00
Jonas Bark
4ae92ca557 Merge remote-tracking branch 'origin/main' 2025-12-08 11:08:04 +01:00
Jonas Bark
e066054681 fix Di2 buttons not triggering an event 2025-12-08 11:07:55 +01:00
Jonas Bark
a0f4aadd37 fix repeated clicks on analog buttons for gamepads 2025-12-08 10:48:15 +01:00
copilot-swe-agent[bot]
3566dbc37c Address code review feedback: improve type annotations and validation
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-08 08:26:29 +00:00
copilot-swe-agent[bot]
73a23e06ba Fix syntax issues in ButtonEditPage and add missing import
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-08 08:25:09 +00:00
copilot-swe-agent[bot]
a03576d415 Add KICKR Headwind support implementation
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-08 08:23:27 +00:00
copilot-swe-agent[bot]
079db14127 Initial plan 2025-12-08 08:16:38 +00:00
jonasbark
2f4764a01f Update Windows Store version to 4.0.0 2025-12-08 08:57:21 +01:00
Jonas Bark
2671a9807b cleanup 2025-12-07 14:41:06 +01:00
Jonas Bark
da46deb495 fix build 2025-12-07 13:03:54 +01:00
Jonas Bark
0700bd331f fix build 2025-12-07 12:41:14 +01:00
Jonas Bark
14676d9277 Merge branch 'feature/openbikecontrol' 2025-12-07 12:37:05 +01:00
Jonas Bark
3f9c3611ec fix build 2025-12-07 12:36:57 +01:00
jonasbark
26263f4d6b Merge pull request #208 from jonasbark/feature/openbikecontrol
4.0.0
2025-12-07 11:13:09 +00:00
Jonas Bark
105a644599 better web compatibility 2025-12-07 12:10:53 +01:00
Jonas Bark
ba54234734 better web compatibility 2025-12-07 12:05:52 +01:00
Jonas Bark
d39af2c8ff show keys instead of toast 2025-12-07 11:30:06 +01:00
Jonas Bark
eb07b78cce show keys instead of toast 2025-12-07 11:27:14 +01:00
Jonas Bark
f9a13a90a8 fix pairing permission issues 2025-12-07 11:03:21 +01:00
Jonas Bark
6302091c54 improve handling of analog gamepad events 2025-12-07 10:41:21 +01:00
Jonas Bark
1647fe9818 improve handling of analog gamepad events 2025-12-07 10:33:54 +01:00
Jonas Bark
3ece6cb4db cleanup logs, improve handling of analog gamepad events 2025-12-07 10:28:39 +01:00
Jonas Bark
b04732cc24 adjust changelog 2025-12-06 15:43:31 +01:00
Jonas Bark
828819907b refactoring 2025-12-06 15:06:12 +01:00
Jonas Bark
c8c449d2ef screenshot work 2025-12-06 13:42:18 +01:00
Jonas Bark
6b5c202e93 resolve issue #207 2025-12-06 11:56:08 +01:00
Jonas Bark
56c67ae9a5 refactoring 2025-12-06 11:46:18 +01:00
Jonas Bark
94d9467bc3 ui adjustments, fixes 2025-12-06 10:02:56 +01:00
Jonas Bark
fb65616cee create duplicate keymap if needed 2025-12-05 21:35:40 +01:00
Jonas Bark
7e488b3cb1 fix hid device functionality when accessibility service is active 2025-12-05 20:07:48 +01:00
Jonas Bark
9c6084397e fix hid device functionality when accessibility service is active 2025-12-05 20:00:07 +01:00
Jonas Bark
73a0fe6203 fix hid device functionality when accessibility service is active 2025-12-05 19:48:34 +01:00
Jonas Bark
cac1872459 resolve issue #176 2025-12-05 18:08:54 +01:00
Jonas Bark
65f4ca6356 media key detection Windows 2025-12-05 17:57:11 +01:00
Jonas Bark
d771b3da57 cleanup, refactoring 2025-12-05 15:40:04 +01:00
Jonas Bark
d52a062e0c cleanup, refactoring 2025-12-05 13:22:52 +01:00
Jonas Bark
ef350398e1 work on mDNS 2025-12-05 11:14:16 +01:00
Jonas Bark
69fa8834ee work on mDNS 2025-12-05 10:51:40 +01:00
Jonas Bark
ac9bbd3986 work on screenshots 2025-12-04 21:51:16 +00:00
Jonas Bark
6f99f0762a keydown / key up handling for direct connections 2025-12-04 21:17:43 +00:00
Jonas Bark
999fc3faba ui, fixes 2025-12-04 20:59:07 +00:00
Jonas Bark
ebd33666fc ui, fixes 2025-12-04 20:27:53 +00:00
Jonas Bark
8537c5b8c3 ui, fixes 2025-12-04 20:00:01 +00:00
Jonas Bark
3ff59eff6e ui, fixes 2025-12-04 19:42:19 +00:00
Jonas Bark
46752de0e8 ui, fixes 2025-12-04 19:32:02 +00:00
Jonas Bark
27629db924 connection method badges 2025-12-04 14:00:39 +00:00
Jonas Bark
1f00fd9d6c add openbikecontrol as app 2025-12-04 13:27:40 +00:00
Jonas Bark
637bf87dad ui adjustments 2025-12-04 12:58:31 +00:00
Jonas Bark
41415432db ui adjustments 2025-12-01 22:58:29 +00:00
Jonas Bark
745d26dade ui adjustments 2025-12-01 22:01:41 +00:00
Jonas Bark
134de0fcd9 Merge remote-tracking branch 'origin/copilot/ensure-ble-hid-support-windows' into feature/openbikecontrol
# Conflicts:
#	.gitignore
2025-12-01 18:23:14 +00:00
Jonas Bark
ee0c4c083f screenshot adjustments 2025-12-01 18:14:16 +00:00
Jonas Bark
5873ce34e4 translations 2025-12-01 16:58:08 +00:00
Jonas Bark
9904999dd2 translations 2025-12-01 15:46:02 +00:00
Jonas Bark
f5a35ad04b Merge remote-tracking branch 'origin/copilot/extract-translations-to-arb' into feature/openbikecontrol
# Conflicts:
#	lib/pages/trainer.dart
2025-12-01 15:35:54 +00:00
Jonas Bark
7301734b82 zwift keep alive 2025-12-01 15:34:50 +00:00
copilot-swe-agent[bot]
19ada28cf3 Add i18n_extension.dart and fix import/export keys, update imports
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-01 14:48:45 +00:00
copilot-swe-agent[bot]
7655b35b77 Update remaining files to use localized strings
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-01 14:41:28 +00:00
copilot-swe-agent[bot]
0c200eae20 Update widgets and utils to use localized strings
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-01 14:35:11 +00:00
copilot-swe-agent[bot]
18d6c9ec1f Extract translations to intl_en.arb and update pages to use i18n
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-01 14:18:47 +00:00
copilot-swe-agent[bot]
cc16a2c8de Add volume up/down hotkey support for Windows media key detection
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-12-01 14:16:21 +00:00
copilot-swe-agent[bot]
91a6502310 Initial plan 2025-12-01 14:04:35 +00:00
Jonas Bark
bb8720247e add intl 2025-12-01 13:52:20 +00:00
Jonas Bark
b01470339b add intl 2025-12-01 13:50:15 +00:00
Jonas Bark
855fe00346 wording 2025-12-01 13:40:48 +00:00
Jonas Bark
f957258a2c wording 2025-12-01 13:40:00 +00:00
Jonas Bark
945a247274 toast changes 2025-12-01 12:02:41 +00:00
Jonas Bark
59ecfe5186 UI changes 2025-12-01 11:42:54 +00:00
Jonas Bark
dc5e9939c7 UI changes, cleanup 2025-12-01 10:57:23 +00:00
Jonas Bark
79821783e2 auto start connection methods and scanning 2025-12-01 09:30:21 +00:00
jonasbark
531e53eaec Update WINDOWS_STORE_VERSION.txt 2025-11-30 21:08:53 +01:00
Jonas Bark
4f01f23458 Merge branch 'main' into feature/openbikecontrol
# Conflicts:
#	lib/utils/actions/base_actions.dart
2025-11-30 18:46:15 +00:00
Jonas Bark
3760b84fb7 only use direct connection method if they are connected 2025-11-30 18:45:20 +00:00
Jonas Bark
afdb442597 Merge branch 'main' into feature/openbikecontrol
# Conflicts:
#	lib/pages/device.dart
#	lib/widgets/logviewer.dart
2025-11-30 01:09:03 +00:00
Jonas Bark
eadcd17bbb less noise 2025-11-30 01:08:25 +00:00
Jonas Bark
67ca63b047 Merge branch 'feature/kickrbikepro' into feature/openbikecontrol 2025-11-30 01:07:51 +00:00
Jonas Bark
17d3450bd2 fix 2025-11-30 01:07:42 +00:00
Jonas Bark
d7c700a4e5 heureka 2025-11-30 00:44:45 +00:00
Jonas Bark
fd659e40fe heureka 2025-11-29 23:55:43 +00:00
Jonas Bark
bdd7c75ebd attempt to support Wahoo Kickr Bike Pro #195 2025-11-29 21:54:24 +00:00
Jonas Bark
ca5648fec4 attempt to support Wahoo Kickr Bike Pro #195 2025-11-29 19:40:32 +00:00
Jonas Bark
978325ceff attempt to support Wahoo Kickr Bike Pro #195 2025-11-29 19:36:35 +00:00
Jonas Bark
87ad9c630d try kickr 2025-11-29 19:05:38 +00:00
Jonas Bark
6b0ca1b6dd fix 2025-11-29 19:05:22 +00:00
Jonas Bark
3c9a505f4f Merge branch 'main' of github.com:jonasbark/swiftcontrol 2025-11-29 18:42:37 +00:00
Jonas Bark
7bb4ace875 openbikeprotocol Bluetooth emulator 2025-11-29 17:46:12 +00:00
Jonas Bark
499cd86955 openbikeprotocol Bluetooth emulator 2025-11-29 17:10:23 +00:00
Jonas Bark
79bad50ce3 openbikeprotocol emulator 2025-11-29 15:35:09 +00:00
Jonas Bark
2dff9c92fd ftms emulator 2025-11-29 14:45:44 +00:00
Jonas Bark
d05557819e ui adjustments, fixes 2025-11-29 14:37:43 +00:00
Jonas Bark
22a39406ff fix wrong check 2025-11-29 13:51:36 +00:00
Jonas Bark
91d0fd656e consolidate messages 2025-11-29 13:51:05 +00:00
Jonas Bark
4440a04ab8 consolidate messages 2025-11-29 13:46:57 +00:00
Jonas Bark
5bf617d1db move service running message 2025-11-29 13:35:57 +00:00
Jonas Bark
3cf209edd9 less god objects 2025-11-29 13:12:09 +00:00
Jonas Bark
ad95ce23ec add implementation for open bike protocol devices 2025-11-29 12:53:04 +00:00
Jonas Bark
9e29d5dd04 ui adjustments 2025-11-29 10:57:14 +00:00
Jonas Bark
4678ac0255 ui adjustments 2025-11-29 10:54:04 +00:00
Jonas Bark
8660f979b9 ignore device for session fix, logs page 2025-11-29 09:35:38 +00:00
Jonas Bark
c20265ddf8 new ui, BLE fixes 2025-11-28 22:31:18 +00:00
Jonas Bark
2b90606d9c inline permission requests, make them optional unless required 2025-11-28 22:00:48 +00:00
Jonas Bark
c75fd8ab80 Merge remote-tracking branch 'origin/main' into feature/openbikecontrol
# Conflicts:
#	lib/widgets/menu.dart
2025-11-28 20:21:32 +00:00
Jonas Bark
fc13d71960 version++ 2025-11-28 18:50:56 +00:00
Jonas Bark
354179de30 potential fixes for #196 2025-11-28 18:49:55 +00:00
Jonas Bark
e4ea924b1a fix Windows app icon 2025-11-28 17:49:49 +00:00
Jonas Bark
f9b5dda123 new UI 2025-11-28 08:31:34 +00:00
Jonas Bark
4cd38d4502 new UI 2025-11-28 00:26:21 +00:00
Jonas Bark
70c9a5b6a3 new UI 2025-11-27 23:38:00 +00:00
Jonas Bark
4fb46de074 new UI 2025-11-27 23:31:29 +00:00
Jonas Bark
b0487f534c new UI 2025-11-27 22:36:19 +00:00
Jonas Bark
719eb9b50f new UI 2025-11-27 19:59:49 +00:00
Jonas Bark
f3148405d7 Merge branch 'main' into feature/openbikecontrol 2025-11-27 18:10:26 +00:00
Jonas Bark
6da13f18af UI fix 2025-11-27 17:03:14 +00:00
Jonas Bark
b3b6f510d8 work on new ui 2025-11-27 13:22:14 +00:00
Jonas Bark
01400ab955 work on new ui 2025-11-27 12:49:21 +00:00
Jonas Bark
8348848ef8 work on new ui 2025-11-27 09:44:26 +00:00
Jonas Bark
04920e7eee Merge remote-tracking branch 'origin/main' 2025-11-26 22:34:20 +00:00
Jonas Bark
464c5208dc error logging 2025-11-26 22:34:11 +00:00
jonasbark
981254875b Update README.md 2025-11-26 10:32:29 +01:00
Jonas Bark
d941135fff remove media key detection due to Apple restrictions 2025-11-25 19:26:39 +00:00
jonasbark
28663f5cdf Update Windows Store version to 3.6.0 2025-11-24 18:14:41 +01:00
Jonas Bark
bfc12711ad screenshot adjustments 2025-11-23 22:03:21 +00:00
Jonas Bark
076e729e39 screenshot adjustments 2025-11-23 21:56:21 +00:00
Jonas Bark
570f5ca82d missing BikeControl renaming 2025-11-23 21:33:56 +00:00
Jonas Bark
9749a9018d missing BikeControl renaming 2025-11-23 21:26:55 +00:00
Jonas Bark
4724f55e6b some UI adjustments 2025-11-23 21:24:18 +00:00
Jonas Bark
8f68636bfc some UI changes 2025-11-23 21:06:37 +00:00
Jonas Bark
fefcb1db53 status widget for accessibility service 2025-11-23 20:57:52 +00:00
Jonas Bark
98fd5c5d7c status widget 2025-11-23 20:28:28 +00:00
Jonas Bark
e97a76e488 better error handling 2025-11-23 08:56:30 +00:00
Jonas Bark
02f25899e9 show action results in the UI 2025-11-23 08:33:19 +00:00
Jonas Bark
3a0ef5110d more name change work 2025-11-23 08:08:03 +00:00
Jonas Bark
36c5df7d03 Merge remote-tracking branch 'origin/copilot/rename-app-to-bikecontrol' 2025-11-22 18:10:36 +00:00
copilot-swe-agent[bot]
4252ed05ae Complete remaining SwiftControl to BikeControl renames in code
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-21 18:11:41 +00:00
copilot-swe-agent[bot]
2adf3026fd Rename app from SwiftControl to BikeControl and update GitHub repo references
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-21 18:07:48 +00:00
copilot-swe-agent[bot]
2cc705c556 Initial plan 2025-11-21 17:57:39 +00:00
Jonas Bark
faff8ab219 adjust changelog 2025-11-21 07:09:00 +00:00
Jonas Bark
e63e647ebc better formatting 2025-11-20 23:09:56 +00:00
Jonas Bark
e2339321bb Merge branch 'main' of github.com:jonasbark/swiftcontrol 2025-11-20 23:04:57 +00:00
jonasbark
f7c57b1f15 Merge pull request #192 from jonasbark/copilot/add-predefined-actions-keymaps
Add predefined action selector for custom keymaps from selected trainer app
2025-11-20 23:04:28 +00:00
copilot-swe-agent[bot]
a1fad509cf Optimize to avoid redundant settings.getTrainerApp() calls
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-20 23:00:03 +00:00
copilot-swe-agent[bot]
daec33f827 Handle empty actions list and simplify key label logic
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-20 22:58:10 +00:00
copilot-swe-agent[bot]
cf66845a38 Address code review feedback - improve list copying and clarify key formatting
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-20 22:56:27 +00:00
copilot-swe-agent[bot]
7199f5b545 Use current trainer app's keymap instead of showing dialog
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-20 22:54:54 +00:00
copilot-swe-agent[bot]
0490956551 Apply performance optimizations with const widgets
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-20 22:53:18 +00:00
copilot-swe-agent[bot]
8be2108cdc Address code review feedback - improve type checking and readability
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-20 22:52:02 +00:00
copilot-swe-agent[bot]
4595e509c9 Add predefined action selector for custom keymaps
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-20 22:49:49 +00:00
copilot-swe-agent[bot]
17d7953d11 Initial plan 2025-11-20 22:44:31 +00:00
Jonas Bark
4adfe0812d fix compatibility checks on this device on iOS devices 2025-11-20 21:34:03 +00:00
Jonas Bark
7ca9c8752b Merge remote-tracking branch 'origin/main' 2025-11-18 22:45:56 +00:00
Jonas Bark
ab53d23404 add keyboard controls to Rouvys virtual shifting 2025-11-18 22:45:47 +00:00
jonasbark
9894271145 Update Windows Store version to 3.5.0 2025-11-18 23:11:14 +01:00
Jonas Bark
5d9960156c update rouvy keymap to support their latest version 2025-11-18 22:08:16 +00:00
Jonas Bark
aa6782d29b Merge branch 'copilot/add-screenshots-to-release' 2025-11-18 21:54:08 +00:00
Jonas Bark
98d683a6a5 Merge remote-tracking branch 'origin/main' 2025-11-18 21:54:00 +00:00
jonasbark
55a2e4db79 Clarify device troubleshooting headings
Updated headings to include 'Ride' alongside 'Click' for clarity.
2025-11-17 21:54:00 +01:00
Jonas Bark
4db985e2e5 screenshot adjustments 2025-11-17 14:33:23 +01:00
Jonas Bark
bbd95beb36 add bluetooth device detection unit test 2025-11-17 14:18:34 +01:00
Jonas Bark
a9ee0dc9a1 fix unit tests 2025-11-17 14:01:29 +01:00
Jonas Bark
46d3770a28 more work on screenshots 2025-11-17 13:55:27 +01:00
Jonas Bark
99ee63ce1f more work on screenshots 2025-11-17 13:14:07 +01:00
Jonas Bark
cb10ad685e Merge branch 'main' into copilot/add-screenshots-to-release 2025-11-17 12:49:18 +01:00
Jonas Bark
748a21fb54 small refactoring 2025-11-17 12:49:09 +01:00
Jonas Bark
b3ffe867c6 version++ 2025-11-16 21:32:49 +01:00
Jonas Bark
fb1ffec37d version++ 2025-11-16 21:04:28 +01:00
Jonas Bark
9ea4f7157a some possible fixes 2025-11-16 20:53:56 +01:00
Jonas Bark
a9b43bd347 windows build fix 2025-11-16 12:51:32 +01:00
Jonas Bark
b9ac193e77 windows build fix 2025-11-16 12:47:13 +01:00
Jonas Bark
1d4947b3ae windows build fix 2025-11-16 12:46:17 +01:00
Jonas Bark
74e098e9b1 adjust integration tests 2025-11-16 12:42:33 +01:00
Jonas Bark
e5dae225f1 Merge branch 'main' into copilot/add-screenshots-to-release
# Conflicts:
#	lib/bluetooth/connection.dart
#	lib/utils/settings/settings.dart
2025-11-16 12:30:21 +01:00
Jonas Bark
0339089972 version++ 2025-11-16 11:58:05 +01:00
Jonas Bark
1e8bd61264 update changelog 2025-11-16 10:20:47 +01:00
Jonas Bark
79613bc8de resolve issue #179 2025-11-16 10:15:46 +01:00
Jonas Bark
d0ec785e32 remove settings file when corrupted #180 2025-11-16 10:13:37 +01:00
Jonas Bark
020b91fd21 Merge branch 'main' of github.com:jonasbark/swiftcontrol 2025-11-15 12:54:53 +01:00
Jonas Bark
f2406152fd Merge branch 'copilot/update-cycplus-bc2-implementation' 2025-11-15 12:54:45 +01:00
Jonas Bark
ab3ef7be53 resolve #186 2025-11-15 12:54:30 +01:00
jonasbark
bb7484ff2e Merge pull request #185 from jonasbark/copilot/update-cycplus-bc2-implementation
Simplify Cycplus BC2 implementation to match reference state machine
2025-11-15 10:35:28 +01:00
copilot-swe-agent[bot]
80061fd076 Update Cycplus BC2 implementation to match reference
- Only look at bytes at index 6 and 7 (no full frame parsing)
- Implement state machine for pressed/released states
- Track state independently for each index
- Trigger on state transitions (pressed to different pressed)
- Reset state on release (0x00) or after successful trigger

Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-15 09:27:45 +00:00
Jonas Bark
124e005fb1 Merge branch 'main' of github.com:jonasbark/swiftcontrol 2025-11-15 10:27:11 +01:00
Jonas Bark
8e760ef202 more error checking 2025-11-15 10:27:07 +01:00
copilot-swe-agent[bot]
de740f6453 Initial plan 2025-11-15 09:20:32 +00:00
jonasbark
3bde90ae62 Merge pull request #182 from jonasbark/copilot/fix-ble-device-reconnection
Persist ignored BLE devices across app restarts
2025-11-15 09:04:53 +01:00
copilot-swe-agent[bot]
aee8dc2e07 Make getIgnoredDeviceIds and getIgnoredDeviceNames private
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-15 07:57:35 +00:00
jonasbark
b3952542f8 Fix grammar and formatting in README.md 2025-11-14 15:08:05 +01:00
Jonas Bark
910f23a3f6 Merge branch 'copilot/fix-cycplus-bc2-button-logic' 2025-11-14 14:57:47 +01:00
Jonas Bark
5cc9ac85af attempt to handle https://github.com/jonasbark/swiftcontrol/issues/179 2025-11-14 14:57:35 +01:00
copilot-swe-agent[bot]
e10e22d038 Add support for 0xfe button codes in CYCPLUS BC2 device
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-14 13:34:36 +00:00
copilot-swe-agent[bot]
aaeaec36a2 Initial plan 2025-11-14 13:29:59 +00:00
Jonas Bark
c16a593f3c potential fix for https://github.com/jonasbark/swiftcontrol/issues/183 2025-11-14 14:28:47 +01:00
Jonas Bark
50d9f47576 potential fix for https://github.com/jonasbark/swiftcontrol/issues/183 2025-11-14 12:23:30 +01:00
copilot-swe-agent[bot]
a53fb578ef Fix disconnect logic and improve UI flow
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-13 15:25:14 +00:00
copilot-swe-agent[bot]
1f89859a03 Implement persistent ignored devices feature
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-13 15:23:12 +00:00
copilot-swe-agent[bot]
7c1cee6748 Initial plan 2025-11-13 15:17:47 +00:00
Jonas Bark
a4949ad615 error handling 2025-11-12 22:22:44 +01:00
Jonas Bark
a57f4654b0 possible fix for https://github.com/jonasbark/swiftcontrol/issues/180#issuecomment-3523836191 2025-11-12 21:49:01 +01:00
Jonas Bark
8192d3addf show to user when MyWhoosh Link can't be started, cleanup 2025-11-12 09:22:41 +01:00
Jonas Bark
308f461ad4 show to user when MyWhoosh Link can't be started, cleanup 2025-11-12 09:22:19 +01:00
Jonas Bark
513b2ba367 screenshot creation #1 2025-11-11 10:25:56 +01:00
Jonas Bark
69f47fa984 bluetooth naming 2025-11-11 09:06:07 +01:00
copilot-swe-agent[bot]
4daf553514 Add documentation for screenshot generation process
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-11 07:28:00 +00:00
copilot-swe-agent[bot]
aeae148e0b Implement dynamic screenshot generation during build pipeline
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-11 07:26:47 +00:00
copilot-swe-agent[bot]
1a9a265671 Add screenshot packaging and release attachment to build workflow
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-11 07:19:13 +00:00
copilot-swe-agent[bot]
b06e9ad4b3 Initial plan 2025-11-11 07:12:19 +00:00
copilot-swe-agent[bot]
7ecce43a3d Add documentation for Windows global media key detection
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-10 07:53:16 +00:00
copilot-swe-agent[bot]
82cb41c207 Remove CodeQL artifact from repository
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-10 07:52:26 +00:00
copilot-swe-agent[bot]
c356242a8f Improve hotkey registration error handling
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-10 07:52:01 +00:00
copilot-swe-agent[bot]
61ad7c2eef Implement global media key detection for Windows using RegisterHotKey API
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-10 07:49:27 +00:00
copilot-swe-agent[bot]
311104ddf0 Initial plan 2025-11-10 07:44:08 +00:00
Jonas Bark
2b106fd1c9 change mail address 2025-11-09 19:33:32 +01:00
Jonas Bark
1784e008ee a few fixes 2025-11-09 19:17:35 +01:00
Jonas Bark
33ccdbd7af a few fixes 2025-11-09 16:38:13 +01:00
Jonas Bark
d15f1ddc13 Merge branch 'main' of github.com:jonasbark/swiftcontrol 2025-11-09 16:14:34 +01:00
Jonas Bark
e7ea01cd60 Merge branch 'copilot/create-landing-page-for-apps' 2025-11-09 16:14:29 +01:00
Jonas Bark
f7ed426441 cleanup 2025-11-09 16:14:15 +01:00
Jonas Bark
d30485b82e add a clarifying selection to help users choose where SwiftControl should run 2025-11-09 16:13:07 +01:00
Jonas Bark
4e646ab922 add dark mode, logs to the support entry, link to new landing page 2025-11-09 15:57:54 +01:00
jonasbark
4183ede58d Updated .gitignore 2025-11-09 08:54:17 +01:00
copilot-swe-agent[bot]
dd85e99e4b Update landing page per feedback: blue background, black headings, restructured compatibility checker, and instructions section
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-09 07:42:42 +00:00
jonasbark
2334a88452 Merge pull request #174 from jonasbark/copilot/add-changelog-to-releases
Add changelog to GitHub release body
2025-11-09 08:23:40 +01:00
copilot-swe-agent[bot]
ee64b18f75 Refactor: reuse get_latest_changelog.sh output
- Removed duplicate awk logic from generate_release_body.sh
- Now calls get_latest_changelog.sh for changelog content
- Simplified script by removing unused variables
- Adds version header separately for GitHub releases

Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-09 07:21:17 +00:00
copilot-swe-agent[bot]
647dac9e7c Add interactive landing page with compatibility checker
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-09 07:14:46 +00:00
copilot-swe-agent[bot]
df2496eb67 Add changelog to GitHub release body
- Created generate_release_body.sh script to combine changelog with store links
- Updated build.yml workflow to use new release body
- Updated patch.yml workflow to use new release body
- Release body now includes latest changelog entry followed by store download links

Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-09 07:12:43 +00:00
copilot-swe-agent[bot]
859424b895 Initial plan 2025-11-09 07:08:36 +00:00
copilot-swe-agent[bot]
dde3f38bde Initial plan 2025-11-09 07:07:37 +00:00
Jonas Bark
01744c258e attempt to improve UX 2025-11-08 22:45:25 +01:00
Jonas Bark
231aadbc27 detect media key source - don't handle it when coming from phone #110 2025-11-08 22:31:12 +01:00
Jonas Bark
a806a628bd Merge remote-tracking branch 'origin/main' 2025-11-08 20:18:58 +01:00
Jonas Bark
c529fee1fa fix execution on Web 2025-11-08 20:18:42 +01:00
jonasbark
c36a0252e6 Aktualisieren von WINDOWS_STORE_VERSION.txt 2025-11-08 15:58:21 +01:00
Jonas Bark
66486ec38e make Di2 custom keymap requirement clearer #170 2025-11-08 12:55:05 +01:00
Jonas Bark
6f5c6bf1d9 Merge remote-tracking branch 'origin/main' 2025-11-08 09:00:51 +01:00
Jonas Bark
8fc8f2dfda increase version 2025-11-08 09:00:42 +01:00
jonasbark
d36e031e87 Set release date for version 3.4.0
Updated the release date for version 3.4.0 in the changelog.
2025-11-08 08:55:56 +01:00
Jonas Bark
efac0af4b9 update changelog to include Rouvy keymap 2025-11-08 08:54:59 +01:00
Jonas Bark
d7e73524ad Merge branch 'feature/bluetoothmedia' 2025-11-08 08:49:23 +01:00
Jonas Bark
80998c955f media key detection on iOS and macOS 2025-11-08 08:49:06 +01:00
Jonas Bark
d824cb6207 integrate media_key_detector package, add iOS implementation #1 2025-11-07 21:55:07 +01:00
Jonas Bark
ab80d679e1 update Rouvy keymap 2025-11-07 20:53:44 +01:00
Jonas Bark
d4881faab1 code fix, update changelog and readme 2025-11-07 20:49:59 +01:00
Jonas Bark
7c74d61b43 Merge branch 'feature/mediabutton' 2025-11-07 20:45:30 +01:00
Jonas Bark
8ad2906a17 Merge branch 'feature/ble_hid' 2025-11-07 20:37:44 +01:00
Jonas Bark
0f4d19080a prefill mail text when support is used 2025-11-07 20:37:10 +01:00
Jonas Bark
a9a13be6ca fix modifier detection 2025-11-07 20:36:35 +01:00
Jonas Bark
c66badf39e Merge branch 'main' of github.com:jonasbark/swiftcontrol 2025-11-07 19:41:15 +01:00
jonasbark
6c2fc54612 Merge pull request #166 from jonasbark/copilot/add-keyboard-combination-support
Add modifier key support for keyboard mappings
2025-11-07 19:40:45 +01:00
jonasbark
807c0eaa98 Merge pull request #167 from jonasbark/copilot/support-elite-square-control
Fix Elite Square button detection substring mismatch
2025-11-07 19:29:28 +01:00
copilot-swe-agent[bot]
7d7b1e89e9 Final implementation of modifier key support
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-07 18:17:59 +00:00
copilot-swe-agent[bot]
cafb7408d9 Refactor: Consolidate modifier key detection logic
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-07 18:17:07 +00:00
copilot-swe-agent[bot]
723f741bca Improve test code quality and fix edge cases
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-07 18:15:27 +00:00
copilot-swe-agent[bot]
6a3cc0f8be Refactor: Extract helper methods to reduce code duplication
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-07 18:15:07 +00:00
copilot-swe-agent[bot]
66c548fa75 Refactor tests to reduce code duplication
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-07 18:13:21 +00:00
copilot-swe-agent[bot]
0b42f7e9c5 Fix Elite Square button detection logic and add tests
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-07 18:11:18 +00:00
copilot-swe-agent[bot]
35a995eddc Add support for modifier keys in keyboard mapping
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-07 18:10:14 +00:00
copilot-swe-agent[bot]
c3afb23625 Initial plan 2025-11-07 18:05:00 +00:00
copilot-swe-agent[bot]
f15d97585b Initial plan 2025-11-07 18:02:22 +00:00
Jonas Bark
5f03c072ff fix di2 initialization 2025-11-06 18:45:46 +01:00
jonasbark
ce94aea51a Merge pull request #165 from jonasbark/copilot/fix-di-fly-button-triggering
[WIP] Fix Shimano DI2 implementation for DI Fly buttons
2025-11-06 18:44:38 +01:00
copilot-swe-agent[bot]
a27ae070fc Fix DI2 button trigger on startup and add tests
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-06 17:43:29 +00:00
copilot-swe-agent[bot]
7bbdc6a4e2 Initial plan 2025-11-06 17:38:51 +00:00
Jonas Bark
3188002ecb fix a few bugs and use some more clearer texts 2025-11-05 20:11:36 +01:00
Jonas Bark
284d2ca70f resolve yet another Sterzo issue https://github.com/jonasbark/swiftcontrol/issues/111#issuecomment-3487265558 2025-11-04 20:09:44 +01:00
Jonas Bark
57961aec5d bump version 2025-11-04 17:36:01 +01:00
Jonas Bark
1675d7f2d0 bump version 2025-11-04 17:35:32 +01:00
Jonas Bark
baec8d24c3 fix detection of Sterzo devices https://github.com/jonasbark/swiftcontrol/issues/111#issuecomment-3486678629 2025-11-04 17:34:25 +01:00
Jonas Bark
820d0b37db allow to ignore HID device input 2025-11-04 10:05:52 +01:00
Jonas Bark
c18ac16208 support HID key events on Android #110 2025-11-04 09:53:52 +01:00
Jonas Bark
2bbc09bf13 Merge branch 'main' into feature/ble_hid 2025-11-04 08:59:02 +01:00
Jonas Bark
a968723277 update gitignore 2025-11-04 08:58:54 +01:00
Jonas Bark
8668957738 fix name 2025-11-03 20:30:05 +01:00
Jonas Bark
4498729e75 initial support for BLE HID device 2025-11-03 20:26:21 +01:00
Jonas Bark
ac550fad5b do not offer MyWhoosh Link when not compatible 2025-11-03 18:58:41 +01:00
Jonas Bark
c511ac32b6 fix 'Exit' behavior on Android notification tap 2025-11-03 10:02:37 +01:00
Jonas Bark
ee48ce0f4e Merge remote-tracking branch 'origin/main' 2025-11-03 09:30:45 +01:00
Jonas Bark
8a3d64491b version++ 2025-11-03 09:30:38 +01:00
jonasbark
b72cc803f0 Clarify iOS, macOS, and Windows requirements
Updated iOS, macOS, and Windows requirements for Bluetooth buttons.
2025-11-03 09:12:00 +01:00
Jonas Bark
69dd5c85ef detect media keys on macOS / iOS #1 2025-11-03 08:58:16 +01:00
Jonas Bark
ea17b2e142 Merge remote-tracking branch 'origin/main' 2025-11-03 08:45:50 +01:00
Jonas Bark
da62fc4dc6 fix resetting keymap, show all touches by default 2025-11-03 08:45:39 +01:00
jonasbark
239630f681 Fix formatting and grammar issues in README.md
Corrected formatting and grammar in the README file.
2025-11-02 17:54:51 +01:00
Jonas Bark
d95d0cf8cf exit app on Android to apply patch 2025-11-02 17:48:34 +01:00
Jonas Bark
2b25ba942c Merge remote-tracking branch 'origin/main' 2025-11-02 16:22:14 +01:00
Jonas Bark
c65369a746 clarify pairing vs controller vs MyWhoosh Link 2025-11-02 16:22:06 +01:00
Jonas Bark
fa7d5e7853 clarify pairing vs controller vs MyWhoosh Link 2025-11-02 16:20:32 +01:00
Jonas Bark
8ac47cbd4d make Link / emulation UI clearer 2025-11-02 16:02:07 +01:00
Jonas Bark
eb85844503 Merge branch 'main' of github.com:jonasbark/swiftcontrol 2025-11-02 13:56:12 +01:00
Jonas Bark
010d0ed331 UI adjustments 2025-11-02 13:55:56 +01:00
Jonas Bark
1f8f7765a3 fix SwiftControl Web, more generic battery and firmware version reads 2025-11-02 13:24:19 +01:00
Jonas Bark
68f416dda3 fix SwiftControl Web, more generic battery and firmware version reads 2025-11-02 13:10:35 +01:00
Jonas Bark
49e45faec0 fix SwiftControl Web 2025-11-02 10:50:44 +01:00
Jonas Bark
c81516350a initial support for Shimano Di2 D-Fly channel buttons 2025-11-02 10:45:51 +01:00
jonasbark
890f393fd6 Merge pull request #151 from jonasbark/copilot/add-cycplus-bc2-support
Add CYCPLUS BC2 virtual shifter support via Nordic UART Service
2025-11-02 08:26:42 +01:00
copilot-swe-agent[bot]
e46969c5c4 Add CYCPLUS BC2 virtual shifter support
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-02 06:45:59 +00:00
copilot-swe-agent[bot]
1ec9b55645 Initial plan 2025-11-02 06:39:40 +00:00
Jonas Bark
b0caf7c13b UI adjustments 2025-11-01 19:43:30 +01:00
Jonas Bark
302fc15dd7 don't reset after a minute 2025-11-01 19:40:23 +01:00
jonasbark
6a2cf1a1c9 Merge pull request #147 from jonasbark/copilot/fix-miui-service-issue
Add MIUI device detection and battery optimization warning with dismissal
2025-11-01 19:36:16 +01:00
jonasbark
8ea73bc54a Update Windows Store version to 3.3.0 2025-11-01 19:27:07 +01:00
copilot-swe-agent[bot]
7cbab3925f Use AndroidActions type check instead of negated RemoteActions
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-01 10:15:16 +00:00
copilot-swe-agent[bot]
246a1bd2be Add dismiss button to MIUI warning with persistent state
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-11-01 09:54:20 +00:00
copilot-swe-agent[bot]
f7e2a89ed6 Move MIUI warning from requirements to DevicePage widget
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-10-31 18:48:58 +00:00
copilot-swe-agent[bot]
f94252edb9 Address code review feedback - improve comments and efficiency
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-10-31 18:37:58 +00:00
copilot-swe-agent[bot]
b7b6b9803f Add MIUI device detection and warning for accessibility service
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-10-31 18:31:30 +00:00
copilot-swe-agent[bot]
807d868b74 Initial plan 2025-10-31 18:25:43 +00:00
jonasbark
c3e8c4666c Merge pull request #145 from jonasbark/zwift
Zwift Support
2025-10-31 13:16:07 +01:00
Jonas Bark
926651ebb3 zwift emulation rouvy support 2025-10-31 13:15:19 +01:00
Jonas Bark
a7d5624582 update mywhoosh profile 2025-10-31 12:53:04 +01:00
Jonas Bark
03209740ec ux adjustments 2025-10-31 12:18:15 +01:00
jonasbark
af6ae3433e Update lib/bluetooth/devices/zwift/zwift_emulator.dart
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-31 11:28:11 +01:00
Jonas Bark
41f4dd1d57 update changelog 2025-10-31 11:24:08 +01:00
Jonas Bark
d5c1b67675 clarify bluetooth buttons 2025-10-31 11:20:54 +01:00
Jonas Bark
0b18d74ac9 fix already paired gamepad detection 2025-10-31 09:41:34 +01:00
Jonas Bark
fb3fe5f8c0 add rouvy keymap and enable zwift controller emulation 2025-10-31 09:41:19 +01:00
Jonas Bark
796c973fd4 clarify Zwift usage, make controller emulation optional 2025-10-30 09:17:35 +01:00
Jonas Bark
7c6335c4d1 implement remaining Zwift actions 2025-10-29 09:13:17 +01:00
Jonas Bark
af2267c486 allow action unassignment 2025-10-28 18:06:07 +01:00
Jonas Bark
56d9e62610 integration #1 2025-10-28 17:58:44 +01:00
Jonas Bark
7e18a169d4 cleanup 2025-10-28 16:08:59 +01:00
Jonas Bark
74280eda34 zwift click emulation #4 (command works) 2025-10-28 16:05:31 +01:00
Jonas Bark
e1309d4d95 zwift click emulation #3 (connection works) 2025-10-28 14:57:54 +01:00
Jonas Bark
14aa6f7454 zwift click emulation #2 (connection works) 2025-10-28 12:55:39 +01:00
Jonas Bark
1368d7d24e zwift click emulation #1 2025-10-28 12:25:51 +01:00
Jonas Bark
8c09b170c3 some bugfixes, UI adjustments 2025-10-28 09:19:22 +01:00
Jonas Bark
080409b984 add trainer app selection during app start 2025-10-27 21:45:50 +01:00
Jonas Bark
f0ec276547 improve UI for buttons clicked without a keypair 2025-10-27 17:32:08 +01:00
Jonas Bark
23aafcd7bc improve UI for MyWhoosh Link 2025-10-27 17:14:38 +01:00
Jonas Bark
3718a126ac fix keymap explanation not noticing when MyWhoosh Link is connected 2025-10-27 16:48:23 +01:00
Jonas Bark
846dd07bf4 fix UI, fix first button click not handled 2025-10-27 16:44:37 +01:00
Jonas Bark
ba60062a24 Bluetooth HID tests 2025-10-27 16:28:41 +01:00
Jonas Bark
ed4f928fde Click V2 adjustments 2025-10-27 14:40:04 +01:00
Jonas Bark
2a09d550e5 Click V2 adjustments 2025-10-27 14:05:09 +01:00
Jonas Bark
bb1ae4e616 cleanup, fixes 2025-10-27 13:43:18 +01:00
Jonas Bark
828aa70a56 implement MyWhoosh link in the editor 2025-10-27 12:14:41 +01:00
Jonas Bark
4021f3131d refactor connection with remote and controllers 2025-10-27 11:12:23 +01:00
Jonas Bark
80ef81ca64 allow disconnection of bluetooth device 2025-10-27 09:54:01 +01:00
Jonas Bark
fec13d012b show custom keymap hint for gamepads 2025-10-27 09:38:19 +01:00
Jonas Bark
e8ca3fc287 use clipboard again when sharing 2025-10-27 08:27:08 +01:00
Jonas Bark
d5260d801c fix issues in #135 2025-10-26 21:23:57 +01:00
Jonas Bark
916b1ec1fc cleanup 2025-10-26 20:58:52 +01:00
Jonas Bark
7380bb5001 Merge branch 'main' of github.com:jonasbark/swiftcontrol 2025-10-26 20:55:20 +01:00
Jonas Bark
2e95fb556a don't reset in debug mode 2025-10-26 20:54:53 +01:00
jonasbark
90591cbfa2 Merge pull request #137 from michidk/rssi
Displaying the RSSI of connected devices
2025-10-26 20:54:05 +01:00
Michael Lohr
929409db71 implement rssi 2025-10-26 20:32:43 +01:00
Jonas Bark
4263375fb2 fix scanning issue on web https://github.com/jonasbark/swiftcontrol/issues/134#issuecomment-3448689314 2025-10-26 20:28:25 +01:00
jonasbark
bb5d149ba4 Merge pull request #136 from jonasbark/gamepads
Gamepads
2025-10-26 20:17:15 +01:00
Jonas Bark
1a322dc0d3 resolve issue #111 2025-10-26 20:13:54 +01:00
Jonas Bark
d10da94f20 adjust changelog and supported devices 2025-10-26 20:11:17 +01:00
Jonas Bark
7eb28881cb Merge branch 'main' into gamepads 2025-10-26 20:10:34 +01:00
Jonas Bark
823e04d189 resolve issue #133 partially 2025-10-26 19:55:51 +01:00
Jonas Bark
ca5d4aeadb resolve issue #134 2025-10-26 19:53:46 +01:00
Jonas Bark
a4d937c4f3 resolve issue #135 2025-10-26 19:48:17 +01:00
Jonas Bark
fa4add6797 store background image during touch editing, don't show auto rotation warning when not needed 2025-10-26 19:45:11 +01:00
Jonas Bark
ec2ed4e6c5 refactoring #5 2025-10-26 19:27:35 +01:00
Jonas Bark
6bd41d9a54 refactoring #4 2025-10-26 18:53:18 +01:00
Jonas Bark
1ff2a205bc refactoring #3 2025-10-26 17:21:00 +01:00
Jonas Bark
dd73c3249b refactoring #1 2025-10-26 16:26:56 +01:00
Jonas Bark
75eef49317 initial support for gamepads 2025-10-26 10:21:59 +01:00
Jonas Bark
e8858e0c7d fix macOS new version check 2025-10-26 10:06:32 +01:00
Jonas Bark
df9142a6bf update CI 2025-10-25 09:35:26 +02:00
Jonas Bark
36f312403b update changelog 2025-10-25 09:35:06 +02:00
Jonas Bark
d8983889ae fix latest firmware on Click v2 2025-10-25 09:29:35 +02:00
Jonas Bark
bfaf2f2d29 Merge remote-tracking branch 'origin/main' 2025-10-24 18:43:31 +02:00
Jonas Bark
2ba9c284ba scan for all devices, another attempt at #42 2025-10-24 18:43:25 +02:00
jonasbark
ef2b4af28a Update WINDOWS_STORE_VERSION.txt 2025-10-24 12:25:57 +02:00
Jonas Bark
ba042cd07d more work on issue #42 2025-10-24 10:37:28 +02:00
Jonas Bark
f8cb4cff4f update training peaks keymap according to #126 2025-10-24 09:53:55 +02:00
Jonas Bark
92010b787b cleanup 2025-10-24 09:47:37 +02:00
Jonas Bark
e142a8c587 resolve issue #42 2025-10-24 09:47:02 +02:00
Jonas Bark
759dcaa8b8 Merge branch 'fix-38' 2025-10-24 09:44:30 +02:00
Jonas Bark
05939dcf1e implement fix for issue #38 2025-10-24 09:44:06 +02:00
jonasbark
34494819f5 Add instructions for MyWhoosh Link method
Added detailed instructions for using the MyWhoosh Link method, including steps and a video link.
2025-10-23 15:29:11 +02:00
Jonas Bark
a9491b7fa5 Merge branch 'main' into fix-38 2025-10-23 10:49:13 +02:00
Jonas Bark
311a676aea implement fix for issue #38 2025-10-23 10:48:21 +02:00
Jonas Bark
2eab9c581c update readme 2025-10-22 09:43:28 +02:00
Jonas Bark
1284499c25 MyWhoosh Link implementation #2 2025-10-22 09:35:41 +02:00
Jonas Bark
a74471b9f8 MyWhoosh Link implementation #1 2025-10-21 22:43:02 +02:00
Jonas Bark
81f61a5b87 Merge remote-tracking branch 'origin/main' 2025-10-21 10:45:39 +02:00
Jonas Bark
7b2446b6e0 CI cleanup 2025-10-21 10:45:30 +02:00
jonasbark
60898f7536 Update Windows Store version to 3.1.1 2025-10-21 10:25:26 +02:00
Jonas Bark
b2fa7870b6 CI cleanup 2025-10-21 10:21:44 +02:00
Jonas Bark
6ef2ff711a misc fixes 2025-10-21 10:18:12 +02:00
Jonas Bark
9f58dca10e restructure UI to make target selection easier to understand as well as how to get help 2025-10-21 10:10:40 +02:00
Jonas Bark
35e499720b CI patch update 2025-10-20 19:26:22 +02:00
Jonas Bark
7820a80241 Merge remote-tracking branch 'origin/main' 2025-10-20 19:11:08 +02:00
Jonas Bark
ffc6409488 CI patch update 2025-10-20 19:10:57 +02:00
jonasbark
8eaa411a80 Update CHANGELOG for version 3.1.0 enhancements 2025-10-20 19:09:40 +02:00
copilot-swe-agent[bot]
f08714f25a Refine PWM keypress behavior to prevent overlaps
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-10-20 11:47:28 +00:00
copilot-swe-agent[bot]
1f3352ff80 Implement Elite Sterzo Smart improvements for issue #111
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-10-20 11:44:24 +00:00
copilot-swe-agent[bot]
2601844970 Initial plan 2025-10-20 11:37:42 +00:00
Jonas Bark
e4bbb8b279 windows store preparation 2025-10-20 12:19:25 +02:00
Jonas Bark
a13e2aa494 windows store preparation 2025-10-20 11:59:01 +02:00
Jonas Bark
b8383a2280 windows store preparation 2025-10-20 11:36:36 +02:00
Jonas Bark
2cb5ef03ce windows store preparation 2025-10-20 11:35:21 +02:00
Jonas Bark
5203c3a576 windows store preparation 2025-10-20 11:31:11 +02:00
Jonas Bark
36dfb2dc0b windows store preparation 2025-10-20 11:29:18 +02:00
jonasbark
3f6434b5a3 Revise download links and compatibility information
Updated download links for iPhone, macOS, and Windows in the README.
2025-10-20 11:28:15 +02:00
Jonas Bark
d9595a3485 windows store preparation 2025-10-20 11:25:20 +02:00
Jonas Bark
b3352d0c1c restart scanning when bluetooth turned on, cleanup when turned off 2025-10-19 12:55:13 +02:00
Jonas Bark
7e15df1f15 restart scanning when bluetooth turned on, cleanup when turned off
remove Sterzo from Readme until confirmed working
2025-10-19 12:44:44 +02:00
Jonas Bark
b7e086c326 resolve issue #123 2025-10-19 11:15:36 +02:00
Jonas Bark
659e7b0585 resolve #122 2025-10-19 11:09:11 +02:00
Jonas Bark
501ab48da5 Merge branch 'copilot/support-elite-sterzo-smart' 2025-10-19 09:56:50 +02:00
Jonas Bark
3b9ceea64b web CORS proxy workaround for fetching file 2025-10-19 09:56:39 +02:00
Jonas Bark
f3c7bbbcbf Revert "Use file storage instead of SharedPreferences for challenge codes"
This reverts commit a744242c70.
2025-10-19 09:48:51 +02:00
Jonas Bark
9b21a2775e Zwift devices: add firmware update available information 2025-10-19 09:11:51 +02:00
Jonas Bark
b669d4c5ea Android: fix touches for very old Android versions 2025-10-19 08:55:15 +02:00
copilot-swe-agent[bot]
a744242c70 Use file storage instead of SharedPreferences for challenge codes
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-10-19 06:36:11 +00:00
copilot-swe-agent[bot]
7f963f71f8 Load Elite Sterzo challenge codes from HTTP with caching
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-10-19 06:28:13 +00:00
Jonas Bark
9f0ab53e1f add troubleshooting entry for Redmi devices 2025-10-18 12:27:11 +02:00
Jonas Bark
5fc16e9fb7 version++ 2025-10-18 10:06:41 +02:00
Jonas Bark
4329afba1c version++ 2025-10-18 09:58:46 +02:00
Jonas Bark
01f87beef5 resolve issue #116 2025-10-18 09:56:04 +02:00
Jonas Bark
45fecfb4f6 more robust parsing of settings (issue #115) 2025-10-18 09:29:26 +02:00
copilot-swe-agent[bot]
9b020e09ae Fix Elite Sterzo Smart implementation with correct UUIDs and protocol
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-10-17 19:23:58 +00:00
Jonas Bark
3b1c05aba4 version++ 2025-10-17 20:51:17 +02:00
Jonas Bark
90a111944a fix issue #114 by adding missing entitlement 2025-10-17 20:42:26 +02:00
copilot-swe-agent[bot]
ceb029afb0 Add Elite Sterzo Smart support for virtual steering
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
2025-10-17 17:40:12 +00:00
copilot-swe-agent[bot]
dc769ce6a0 Initial plan 2025-10-17 17:33:56 +00:00
Jonas Bark
66b7e74f84 CI change 2025-10-17 13:13:49 +02:00
Jonas Bark
29ef0dfaf4 CI change 2025-10-17 11:21:50 +02:00
Jonas Bark
90144948f4 CI change 2025-10-17 10:35:36 +02:00
Jonas Bark
bda384953e CI change 2025-10-17 10:12:39 +02:00
Jonas Bark
b0fd2a8413 fix logo 2025-10-17 10:10:13 +02:00
Jonas Bark
2403971063 update CI to exclude github build until App Store versions are available - avoid confusion 2025-10-17 10:09:34 +02:00
Jonas Bark
22a0379202 revise restart mechanism, fix Android 'Exit' notification button issue 2025-10-17 09:41:33 +02:00
Jonas Bark
c06a426490 allow macOS and Windows to act as remote 2025-10-17 09:26:31 +02:00
Jonas Bark
908e144e1b macos + ios icon changes 2025-10-17 09:19:21 +02:00
Jonas Bark
0189019e54 Merge branch 'icon_new' 2025-10-17 09:01:48 +02:00
Jonas Bark
5995835d03 more cleanup, refactoring 2025-10-17 08:59:01 +02:00
Jonas Bark
16e637b256 more cleanup, refactoring 2025-10-17 08:52:15 +02:00
Jonas Bark
ac2522e860 remove encryption as it's no longer used, cleanup 2025-10-17 08:15:49 +02:00
Jonas Bark
fdb3ad0efc missing files 2025-10-16 23:56:04 +02:00
Jonas Bark
f7a01f3c32 new icon, cleanup 2025-10-16 23:46:32 +02:00
Jonas Bark
94fd2c7eff Merge remote-tracking branch 'origin/main' 2025-10-16 20:52:46 +02:00
Jonas Bark
f917dfbbb2 elite square: more logging 2025-10-16 20:52:31 +02:00
jonasbark
40bfad6810 Add troubleshooting section for SwiftControl crashes
Added troubleshooting tip for SwiftControl crashes on Windows.
2025-10-16 12:31:09 +02:00
Jonas Bark
fefde66b7b Merge remote-tracking branch 'origin/main' 2025-10-16 12:19:57 +02:00
Jonas Bark
6869adcc09 fix macOS code signing 2025-10-16 12:19:50 +02:00
jonasbark
f5abaec551 Update compatibility matrix in README.md 2025-10-16 12:10:34 +02:00
Jonas Bark
52fbf693b5 fix restart behavior 2025-10-16 11:13:40 +02:00
Jonas Bark
bf3995496e CI 2025-10-15 19:20:51 +02:00
Jonas Bark
f7470a032a CI 2025-10-15 18:56:46 +02:00
Jonas Bark
64c9fe5f03 CI 2025-10-15 18:56:33 +02:00
511 changed files with 28967 additions and 5202 deletions

View File

@@ -6,27 +6,37 @@ on:
build_mac:
description: 'Build for macOS'
required: false
default: 'true'
default: true
type: boolean
build_github:
description: 'Build for GitHub'
required: false
default: true
type: boolean
build_windows:
description: 'Build for Windows'
required: false
default: 'true'
default: true
type: boolean
build_android:
description: 'Build for Android'
required: false
default: 'true'
default: true
type: boolean
build_ios:
description: 'Build for iOS'
required: false
default: 'true'
default: true
type: boolean
build_web:
description: 'Build for Web'
required: false
default: 'true'
default: false
type: boolean
env:
SHOREBIRD_TOKEN: ${{ secrets.SHOREBIRD_TOKEN }}
FLUTTER_VERSION: 3.35.5
FLUTTER_VERSION: 3.38.4
jobs:
build:
@@ -44,7 +54,7 @@ jobs:
uses: actions/checkout@v3
- name: Install certificates
if: github.event.inputs.build_mac == 'true' || github.event.inputs.build_ios == 'true'
if: inputs.build_mac || inputs.build_ios
env:
DEVELOPER_ID_APPLICATION_P12_BASE64_MAC: ${{ secrets.DEVELOPER_ID_APPLICATION_P12_BASE64_MAC }}
DEVELOPER_ID_INSTALLER_P12_BASE64_MAC: ${{ secrets.DEVELOPER_ID_INSTALLER_P12_BASE64_MAC }}
@@ -87,51 +97,57 @@ jobs:
cp $PP_PATH_MACOS ~/Library/MobileDevice/Provisioning\ Profiles
- name: 🐦 Setup Shorebird
if: inputs.build_mac || inputs.build_android || inputs.build_ios || inputs.build_web
uses: shorebirdtech/setup-shorebird@v1
with:
cache: true
- name: 🚀 Shorebird Release macOS
if: github.event.inputs.build_mac == 'true'
uses: shorebirdtech/shorebird-release@v1
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
platform: macos
- name: Decode Keystore
if: github.event.inputs.build_android == 'true'
run: |
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > android/android.keystore;
echo "${{ secrets.KEYSTORE_PROPERTIES }}" > android/keystore.properties;
- name: 🚀 Shorebird Release Android
if: github.event.inputs.build_android == 'true'
uses: shorebirdtech/shorebird-release@v1
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
platform: android
args: "--artifact=apk"
- name: Set Up Flutter
if: github.event.inputs.build_web == 'true'
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: ${{ env.FLUTTER_VERSION }}
- name: Generate translation files
run: |
flutter pub global activate intl_utils;
flutter pub global run intl_utils:generate;
- name: 🚀 Shorebird Release macOS
if: inputs.build_mac
uses: shorebirdtech/shorebird-release@v1
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
platform: macos
args: "-- --dart-define=VERIFYING_SHARED_SECRET=${{ secrets.VERIFYING_SHARED_SECRET }} --dart-define=REVENUECAT_API_KEY_IOS=${{ secrets.REVENUECAT_API_KEY_IOS }}"
- name: Decode Keystore
if: inputs.build_android
run: |
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > android/android.keystore;
echo "${{ secrets.KEYSTORE_PROPERTIES }}" > android/keystore.properties;
- name: 🚀 Shorebird Release Android
if: inputs.build_android
uses: shorebirdtech/shorebird-release@v1
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
platform: android
args: "--artifact=apk -- --dart-define=REVENUECAT_API_KEY_ANDROID=${{ secrets.REVENUECAT_API_KEY_ANDROID }}"
- name: Build Web
if: github.event.inputs.build_web == 'true'
if: inputs.build_web
run: flutter build web --release --base-href "/swiftcontrol/"
- name: Upload static files as artifact
if: github.event.inputs.build_web == 'true'
if: inputs.build_web
id: deployment
uses: actions/upload-pages-artifact@v3
with:
path: build/web
- name: Web Deploy
if: github.event.inputs.build_web == 'true'
if: inputs.build_web
uses: actions/deploy-pages@v4
- name: Extract latest changelog
@@ -141,16 +157,22 @@ jobs:
mkdir -p whatsnew
./scripts/get_latest_changelog.sh | head -c 500 > whatsnew/whatsnew-en-US
- name: Generate release body
if: inputs.build_github
run: |
chmod +x scripts/generate_release_body.sh
./scripts/generate_release_body.sh > /tmp/release_body.md
- name: 🚀 Shorebird Release iOS
if: github.event.inputs.build_ios == 'true'
if: inputs.build_ios
uses: shorebirdtech/shorebird-release@v1
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
platform: ios
args: "--export-options-plist ios/ExportOptions.plist"
args: "--export-options-plist ios/ExportOptions.plist -- --dart-define=VERIFYING_SHARED_SECRET=${{ secrets.VERIFYING_SHARED_SECRET }} --dart-define=REVENUECAT_API_KEY_IOS=${{ secrets.REVENUECAT_API_KEY_IOS }}"
- name: Prepare App Store authentication key
if: github.event.inputs.build_ios == 'true' || github.event.inputs.build_mac == 'true'
if: inputs.build_ios || inputs.build_mac
env:
API_KEY_BASE64: ${{ secrets.APPSTORE_API_KEY_FILE_BASE64 }}
APPSTORE_API_KEY: ${{ secrets.APPSTORE_API_KEY }}
@@ -159,26 +181,26 @@ jobs:
printf %s "$API_KEY_BASE64" | base64 -D > "./private_keys/AuthKey_${APPSTORE_API_KEY}.p8";
- name: Upload to Play Store
if: github.event.inputs.build_android == 'true'
if: inputs.build_android
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{ secrets.SERVICE_ACCOUNT_JSON }}
packageName: de.jonasbark.swiftcontrol
releaseFiles: build/app/outputs/bundle/release/app-release.aab
track: production
track: ${{ github.ref == 'refs/heads/main' && 'production' || 'alpha' }}
whatsNewDirectory: whatsnew
- name: Upload to macOS App Store
if: github.event.inputs.build_mac == 'true'
if: inputs.build_mac
env:
APPSTORE_API_KEY: ${{ secrets.APPSTORE_API_KEY }}
APPSTORE_API_ISSUER_ID: ${{ secrets.APPSTORE_API_ISSUER_ID }}
run: |
productbuild --component "build/macos/Build/Products/Release/SwiftControl.app" /Applications "SwiftControl.pkg" --sign "3rd Party Mac Developer Installer: JONAS TASSILO BARK (UZRHKPVWN9)";
xcrun altool --upload-app -f SwiftControl.pkg -t osx --apiKey "$APPSTORE_API_KEY" --apiIssuer "$APPSTORE_API_ISSUER_ID";
productbuild --component "build/macos/Build/Products/Release/BikeControl.app" /Applications "BikeControl.pkg" --sign "3rd Party Mac Developer Installer: JONAS TASSILO BARK (UZRHKPVWN9)";
xcrun altool --upload-app -f BikeControl.pkg -t osx --apiKey "$APPSTORE_API_KEY" --apiIssuer "$APPSTORE_API_ISSUER_ID";
- name: Upload to iOS App Store
if: github.event.inputs.build_ios == 'true'
if: inputs.build_ios
env:
APPSTORE_API_KEY: ${{ secrets.APPSTORE_API_KEY }}
APPSTORE_API_ISSUER_ID: ${{ secrets.APPSTORE_API_ISSUER_ID }}
@@ -186,98 +208,95 @@ jobs:
xcrun altool --upload-app -f build/ios/ipa/swift_play.ipa -t ios --apiKey "$APPSTORE_API_KEY" --apiIssuer "$APPSTORE_API_ISSUER_ID";
- name: Handle Android archives
if: github.event.inputs.build_android == 'true'
if: inputs.build_android && inputs.build_github && false
run: |
cp build/app/outputs/flutter-apk/app-release.apk build/app/outputs/flutter-apk/SwiftControl.android.apk
cp build/app/outputs/flutter-apk/app-release.apk build/app/outputs/flutter-apk/BikeControl.android.apk
- name: Code Signing of macOS app
if: github.event.inputs.build_mac == 'true'
run: /usr/bin/codesign --deep --force -s "$DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY" --entitlements ../../../../../macos/Runner/Release.entitlements --options runtime SwiftControl.app -v
if: inputs.build_mac && inputs.build_github && false
run: /usr/bin/codesign --deep --force -s "$DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY" --entitlements ../../../../../macos/Runner/Release.entitlements --options runtime BikeControl.app -v
working-directory: build/macos/Build/Products/Release
env:
DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY: ${{ secrets.DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY }}
- name: Handle macOS archives
if: github.event.inputs.build_mac == 'true'
if: inputs.build_mac && inputs.build_github && false
run: |
cd build/macos/Build/Products/Release/
zip -r SwiftControl.macos.zip SwiftControl.app/
zip -r BikeControl.macos.zip BikeControl.app/
- name: Upload Android Artifacts
if: github.event.inputs.build_android == 'true'
if: inputs.build_android && inputs.build_github && false
uses: actions/upload-artifact@v4
with:
overwrite: true
name: Releases
path: |
build/app/outputs/flutter-apk/SwiftControl.android.apk
build/app/outputs/flutter-apk/BikeControl.android.apk
- name: Upload macOS Artifacts
if: github.event.inputs.build_mac == 'true'
if: inputs.build_mac && inputs.build_github && false
uses: actions/upload-artifact@v4
with:
overwrite: true
name: Releases
path: |
build/macos/Build/Products/Release/SwiftControl.macos.zip
build/macos/Build/Products/Release/BikeControl.macos.zip
#10 Extract Version
- name: Extract version from pubspec.yaml
if: inputs.build_github
id: extract_version
run: |
version=$(grep '^version: ' pubspec.yaml | cut -d ' ' -f 2 | tr -d '\r')
echo "VERSION=$version" >> $GITHUB_ENV
#11 Check if Tag Exists
- name: Check if Tag Exists
id: check_tag
run: |
if git rev-parse "v${{ env.VERSION }}" >/dev/null 2>&1; then
echo "TAG_EXISTS=true" >> $GITHUB_ENV
else
echo "TAG_EXISTS=false" >> $GITHUB_ENV
fi
#12 Modify Tag if it Exists
- name: Modify Tag
if: env.TAG_EXISTS == 'true'
id: modify_tag
run: |
new_version="${{ env.VERSION }}-build-${{ github.run_number }}"
echo "VERSION=$new_version" >> $GITHUB_ENV
#13 Create Release
- name: Create Release
if: inputs.build_github
uses: ncipollo/release-action@v1
with:
artifacts: "build/app/outputs/flutter-apk/SwiftControl.android.apk,build/macos/Build/Products/Release/SwiftControl.macos.zip"
artifacts: "build/app/outputs/flutter-apk/BikeControl.android.apk,build/macos/Build/Products/Release/BikeControl.macos.zip"
allowUpdates: true
prerelease: ${{ endsWith(env.VERSION, '1337') }}
bodyFile: scripts/RELEASE_NOTES.md
prerelease: true
bodyFile: /tmp/release_body.md
tag: v${{ env.VERSION }}
token: ${{ secrets.TOKEN }}
windows:
needs: build
if: github.event.inputs.build_windows == 'true'
if: inputs.build_windows
name: Build & Release on Windows
runs-on: windows-latest
runs-on: windows-2025
steps:
#1 Checkout Repository
- name: Checkout Repository
uses: actions/checkout@v3
#2 Setup Java
- name: Set Up Java
uses: actions/setup-java@v3.12.0
with:
distribution: 'oracle'
java-version: '17'
- name: Extract version from pubspec.yaml (Windows)
shell: pwsh
run: |
$version = Select-String '^version: ' pubspec.yaml | ForEach-Object {
($_ -split ' ')[1].Trim()
}
echo "VERSION=$version" >> $env:GITHUB_ENV
- name: 🐦 Setup Shorebird
uses: shorebirdtech/setup-shorebird@v1
with:
cache: true
- name: Set Up Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: ${{ env.FLUTTER_VERSION }}
- name: Generate translation files
run: |
flutter pub global activate intl_utils;
flutter pub global run intl_utils:generate;
- name: 🚀 Shorebird Release Windows
uses: shorebirdtech/shorebird-release@v1
with:
@@ -306,33 +325,36 @@ jobs:
Write-Warning "$dll not found in $source"
}
}
Compress-Archive -Path "build/windows/x64/runner/Release/*" -DestinationPath "build/windows/x64/runner/Release/SwiftControl.windows.zip"
Compress-Archive -Path "build/windows/x64/runner/Release/*" -DestinationPath "build/windows/x64/runner/Release/bike_control.windows.zip"
- uses: microsoft/setup-msstore-cli@v1
if: false
- name: Configure the Microsoft Store CLI
if: false
run: msstore reconfigure --tenantId $ --clientId $ --clientSecret $ --sellerId $
- name: Create MSIX package
run: dart run msix:create
- name: Publish MSIX to the Microsoft Store
if: false
run: msstore publish -v "build/windows/x64/runner/Release/"
#9 Upload Artifacts
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
overwrite: true
name: Releases
path: |
build/windows/x64/runner/Release/SwiftControl.windows.zip
build/windows/x64/runner/Release/bike_control.windows.zip
build/windows/x64/runner/Release/bike_control.msix
#10 Extract Version
- name: Extract version from pubspec.yaml (Windows)
shell: pwsh
run: |
$version = Select-String '^version: ' pubspec.yaml | ForEach-Object {
($_ -split ' ')[1].Trim()
}
echo "VERSION=$version" >> $env:GITHUB_ENV
# add artifact to release
- name: Create Release
- name: Update Release
uses: ncipollo/release-action@v1
with:
allowUpdates: true
artifacts: "build/windows/x64/runner/Release/SwiftControl.windows.zip"
bodyFile: scripts/RELEASE_NOTES.md
artifacts: "build/windows/x64/runner/Release/bike_control.msix"
prerelease: true
tag: v${{ env.VERSION }}
token: ${{ secrets.TOKEN }}

View File

@@ -5,11 +5,12 @@ on:
env:
SHOREBIRD_TOKEN: ${{ secrets.SHOREBIRD_TOKEN }}
FLUTTER_VERSION: 3.35.5
FLUTTER_VERSION: 3.38.5
jobs:
build:
name: Patch iOS, Android & macOS
if: false
runs-on: macos-latest
permissions:
@@ -27,6 +28,17 @@ jobs:
with:
cache: true
- name: Set Up Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: ${{ env.FLUTTER_VERSION }}
- name: Generate translation files
run: |
flutter pub global activate intl_utils;
flutter pub global run intl_utils:generate;
- name: Install certificates
env:
DEVELOPER_ID_APPLICATION_P12_BASE64_MAC: ${{ secrets.DEVELOPER_ID_APPLICATION_P12_BASE64_MAC }}
@@ -75,60 +87,68 @@ jobs:
echo "${{ secrets.KEYSTORE_PROPERTIES }}" > android/keystore.properties;
- name: 🚀 Shorebird Patch macOS
if: false # patch doesn't work: https://github.com/jonasbark/swiftcontrol/issues/143
uses: shorebirdtech/shorebird-patch@v1
with:
platform: macos
release-version: latest
args: '--allow-asset-diffs'
args: '--allow-asset-diffs --allow-native-diffs -- --dart-define=VERIFYING_SHARED_SECRET=${{ secrets.VERIFYING_SHARED_SECRET }} --dart-define=REVENUECAT_API_KEY_IOS=${{ secrets.REVENUECAT_API_KEY_IOS }}'
- name: 🚀 Shorebird Patch Android
uses: shorebirdtech/shorebird-patch@v1
with:
platform: android
release-version: latest
args: '--allow-asset-diffs'
args: '--allow-asset-diffs --allow-native-diffs -- --dart-define=REVENUECAT_API_KEY_ANDROID=${{ secrets.REVENUECAT_API_KEY_ANDROID }}'
- name: 🚀 Shorebird Patch iOS
uses: shorebirdtech/shorebird-patch@v1
with:
platform: ios
release-version: latest
args: '--allow-asset-diffs'
- name: Set Up Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: ${{ env.FLUTTER_VERSION }}
args: '--allow-asset-diffs --allow-native-diffs -- --dart-define=VERIFYING_SHARED_SECRET=${{ secrets.VERIFYING_SHARED_SECRET }} --dart-define=REVENUECAT_API_KEY_IOS=${{ secrets.REVENUECAT_API_KEY_IOS }}'
# shorebird struggles with the app from GitHub
- name: Build macOS
if: false
run: flutter build macos --release;
- name: Sign macOS build
if: false
env:
DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY: ${{ secrets.DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY }}
run: |
flutter build macos --release;
cd build/macos/Build/Products/Release/;
zip -r SwiftControl.macos.zip SwiftControl.app/;
version=$(grep '^version: ' pubspec.yaml | cut -d ' ' -f 2 | tr -d '\r');
echo "VERSION=$version" >> $GITHUB_ENV;
/usr/bin/codesign --deep --force -s "$DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY" --entitlements ../../../../../macos/Runner/Release.entitlements --options runtime SwiftControl.app -v;
cd build/macos/Build/Products/Release/;
/usr/bin/codesign --deep --force -s "$DEVELOPER_ID_APPLICATION_SIGNING_IDENTITY" --entitlements ../../../../../macos/Runner/Release.entitlements --options runtime BikeControl.app -v;
zip -r BikeControl.macos.zip BikeControl.app/;
#9 Upload Artifacts
- name: Upload Artifacts
if: false
uses: actions/upload-artifact@v4
with:
overwrite: true
name: Releases
path: |
build/macos/Build/Products/Release/SwiftControl.macos.zip
build/macos/Build/Products/Release/BikeControl.macos.zip
- name: Generate release body
if: false
run: |
chmod +x scripts/generate_release_body.sh
./scripts/generate_release_body.sh > /tmp/release_body.md
# add artifact to release
- name: Create Release
if: false
uses: ncipollo/release-action@v1
with:
allowUpdates: true
artifacts: "build/macos/Build/Products/Release/SwiftControl.macos.zip"
bodyFile: scripts/RELEASE_NOTES.md
artifacts: "build/macos/Build/Products/Release/BikeControl.macos.zip"
bodyFile: /tmp/release_body.md
prerelease: true
tag: v${{ env.VERSION }}
token: ${{ secrets.TOKEN }}
@@ -141,21 +161,25 @@ jobs:
- name: Checkout Repository
uses: actions/checkout@v3
#2 Setup Java
- name: Set Up Java
uses: actions/setup-java@v3.12.0
with:
distribution: 'oracle'
java-version: '17'
- name: 🐦 Setup Shorebird
uses: shorebirdtech/setup-shorebird@v1
with:
cache: true
- name: Set Up Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: ${{ env.FLUTTER_VERSION }}
- name: Generate translation files
run: |
flutter pub global activate intl_utils;
flutter pub global run intl_utils:generate;
- name: 🚀 Shorebird Patch Windows
uses: shorebirdtech/shorebird-patch@v1
with:
platform: windows
release-version: latest
args: '--allow-asset-diffs'
args: '--allow-asset-diffs --allow-native-diffs'

View File

@@ -1,4 +1,4 @@
name: "Build"
name: "Build Web"
on:
push:
@@ -34,6 +34,12 @@ jobs:
with:
channel: 'stable'
- name: Generate translation files
run: |
flutter pub global activate intl_utils;
flutter pub global run intl_utils:generate;
#4 Install Dependencies
- name: Install Dependencies
run: flutter pub get

6
.gitignore vendored
View File

@@ -10,6 +10,7 @@
.history
.svn/
.swiftpm/
debug/
migrate_working_dir/
android/keystore.properties
@@ -40,10 +41,15 @@ app.*.symbols
# Obfuscation related
app.*.map.json
localazy.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
lib/gen/
service-account.json
.env
lib/generated

3
.vscode/launch.json vendored
View File

@@ -5,7 +5,8 @@
{
"name": "swiftcontrol",
"request": "launch",
"type": "dart"
"type": "dart",
"program": "lib/main.dart"
},
{
"name": "swiftcontrol (profile mode)",

View File

@@ -1,15 +1,130 @@
### 3.0.4 (not released yet)
### 4.4.0 (16-01-2026)
**Features**:
- Support for Thinkrider VS200
**Fixes**:
- Android: Local connection method allows passing keyboard events to the trainer app
- macOS: Compatibility with macOS Tahoe
### 4.3.0 (07-01-2026)
**Features**:
- Onboarding for new users
- support controlling music & volume for Windows, macOS and Android
- App is now available in Italian (thanks to Connect_Thanks2613)
**Fixes**:
- Vibration setting now available for Zwift Ride devices
### 4.2.0 (20-12-2025)
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!
**Features**:
- support for SRAM AXS/eTap
- only single or double click is supported (no individual button mapping possible, yet)
- use your phone/tablet for steering by attaching your device on your handlebar!
- App is now available in Polish (thanks to Wandrocek)
**Fixes**:
- You will now be notified when a connection to your controller is lost
- improved UI of the Keymap customization screen
### 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 the new A+D keys for steering
### 4.0.0 (07-12-2025)
- a brand-new design
- Accessibility Permission is now optional on Android
- Zwift is now fully supported on all operating systems
- you can choose between network based control or bluetooth based control
- MyWhoosh can now also be controlled with BikeControl running on the same iPad / iPhone
- Translations available in German and French
- support for Wahoo KICKR BIKE PRO
- support for the OpenBikeControl protocol for supported Trainer apps
- this enables seamless and official integration, independent of the operating system
- learn more at https://openbikecontrol.org
### 3.6.0 (23-11-2025)
SwiftControl is now called BikeControl!
**Features:**
- show a list of predefined keymaps for the selected trainer app when using a custom keymap
- status icons so it's clear what's missing
**Fixes:**
- Update Rouvy keymap to support virtual shifting in their latest version
### 3.5.0 (16-11-2025)
**New Features:**
- Dark mode support
- Cycplus BC2 support (thanks @schneewoehner)
- Ignored devices now persist across app restarts - remove them from ignored devices via the menu
**Fixes:**
- resolve issues during app start
### 3.4.0 (08-11-2025)
**New Features:**
- Support for Shimano Di2
- Support Keyboard shortcuts with modifier keys (Ctrl, Alt, Shift, ...)
- Support cheap BLE HID remotes
- add Keymap for Rouvy, supporting the new keyboard shortcuts for virtual shifting
**Fixes:**
- fix detection of Elite Square Sterzo devices
- recognize cheap Bluetooth device clicks also when BikeControl is in the background
### 3.3.0 (31-10-2025)
**New Features:**
- Support for Elite Sterzo (thanks @michidk)
- Support for Gamepads
- Support for cheap bluetooth remotes (such as [these](https://www.amazon.com/s?k=bluetooth+remote))
- you can now customize the Keymap right from the Customize section
- show signal strength of connected devices (thanks @michidk)
- Android and Windows only: simulate bluetooth controllers
- enables gamepad and bluetooth remotes support for Zwift, Rouvy and Biketerra
**Fixes:**
- fix firmware version display for Zwift Click V2 devices
- fix touch position on some Android devices
- Wahoo Kickr Bike Shift can now be connected
- update default keymap for TrainingPeaks
### 3.2.0 (2025-10-22)
- a brand-new way of controlling MyWhoosh:
- device pairing no longer required as mouse emulation is no longer needed
- BikeControl can now stay in the background
- more devices can be controlled
- do more, such as define Emotes, Camera angles and steering
### 3.1.0 (2025-10-17)
- new app icon
- adjusted MyWhoosh keyboard navigation mapping (thanks @bin101)
- initial support for Wahook Kickr Bike Shift (thanks @MattW2)
- initial support for Elite Square Smart Frame
- support for Wahook Kickr Bike Shift (thanks @MattW2)
- initial support for Elite Square Smart Frame
- reconnects to your device automatically when connection is lost
- BikeControl now warns you if your device firmware is outdated
- BikeControl is now available in Microsoft Store: https://apps.microsoft.com/detail/9NP42GS03Z26
### 3.0.3 (2025-10-12)
- SwiftControl now supports iOS!
- Note that you can't run SwiftControl and your trainer app on the same iPhone due to iOS limitations but...:
- You can now use SwiftControl as "remote control" for other devices, such as an iPad. Example scenario:
- your phone (Android/iOS) runs SwiftControl and connects to your Click devices
- your iPad or other tablet runs e.g. MyWhoosh (does not need to have SwiftControl installed)
- after pairing SwiftControl to your iPad / tablet via Bluetooth your phone will send the button presses to your iPad / tablet
- BikeControl now supports iOS!
- Note that you can't run BikeControl and your trainer app on the same iPhone due to iOS limitations but...:
- You can now use BikeControl as "remote control" for other devices, such as an iPad. Example scenario:
- your phone (Android/iOS) runs BikeControl and connects to your Click devices
- your iPad or other tablet runs e.g. MyWhoosh (does not need to have BikeControl installed)
- after pairing BikeControl to your iPad / tablet via Bluetooth your phone will send the button presses to your iPad / tablet
- Ride: analog paddles are now supported thanks to contributor @jmoro
- you can now zoom in and out in the Keymap customization screen
@@ -29,8 +144,8 @@
### 2.5.0 (2025-09-25)
- Improve usability
- SwiftControl is now available via the Play Store: https://play.google.com/store/apps/details?id=de.jonasbark.swiftcontrol
- SwiftControl will continue to be available to download for free on GitHub
- BikeControl is now available via the Play Store: https://play.google.com/store/apps/details?id=de.jonasbark.swiftcontrol
- BikeControl will continue to be available to download for free on GitHub
- contact me if you already donated and I'll get a voucher for you :)
### 2.4.0+1 (2025-09-17)

1
INSTRUCTIONS_IOS.md Normal file
View File

@@ -0,0 +1 @@
Moved to [INSTRUCTIONS_MYWHOOSH_LINK.md](INSTRUCTIONS_MYWHOOSH_LINK.md)

17
INSTRUCTIONS_LOCAL.md Normal file
View File

@@ -0,0 +1,17 @@
## What is the Local connection method?
*
The Local connection method works by directly controlling the target trainer app on the same device by simulating user input (taps, keyboard inputs). This method does not require any network connection or additional hardware, making it the simplest and most straightforward way to connect to the trainer app.
There are predefined keymaps (touch positions or keyboard shortcuts) for popular trainer apps, allowing users to easily set up and start using the Local connection method without needing to configure anything manually. You can configure these keymaps in the Configuration tab. Note though that supported keyboard keys depend on the trainer app.
## When to use the Local connection method?
*
The Local connection method is ideal for users who:
- Are running the trainer app on the same device as the controller app (e.g., both apps on a smartphone or tablet).
- Do not want to deal with network configurations or potential connectivity issues.
## Limitations of the Local connection method
*
While the Local connection method is easy to set up and use, it has some limitations:
- It may not work well with trainer apps that have complex user interfaces or require precise timing.
- It is limited to the device on which both the controller and trainer apps are running, meaning it cannot be used for remote control scenarios.

View File

@@ -0,0 +1,38 @@
## Instructions for using the MyWhoosh "Link" connection method
*
1) launch MyWhoosh on the device of your choice
2) make sure the "MyWhoosh Link" app is not active at the same time as BikeControl
3) open BikeControl, follow the on-screen instructions
Here's a video with a few explanations. Note it uses an older version, but the idea is the same.
[![BikeControl Instruction for iOS](https://img.youtube.com/vi/p8sgQhuufeI/0.jpg)](https://www.youtube.com/watch?v=p8sgQhuufeI)
[https://www.youtube.com/watch?v=p8sgQhuufeI](https://www.youtube.com/watch?v=p8sgQhuufeI)
## MyWhoosh "Link" method never connects
*
This is a network/local-discovery problem. BikeControl needs the same kind of local network access as MyWhoosh Link.
Checklist:
- Use the MyWhoosh Link app to confirm if "Link" works in general
- Use MyWhoosh Link app and connect, then close it, then open up BikeControl - this is key for some users
- Both devices are on the **same WiFi SSID**
- Avoid “Guest” networks
- Avoid “extenders/mesh guest mode” and networks with device isolation
- If your router has it, disable:
- “AP isolation / client isolation”
- Try moving both devices to the same band:
- Prefer **2.4 GHz** (often more reliable for local discovery than mixed/steering)
- Temporarily disable:
- VPNs
- iCloud Private Relay (if enabled)
- “Limit IP Address Tracking” (iOS WiFi option)
- iOS WiFi settings for that network:
- Turn off **Private WiFi Address**
- Turn off **Limit IP Address Tracking**
- Mesh networks: may work, but if it doesnt, test with a simple router or phone hotspot.
Official MyWhoosh troubleshooting links:
- https://mywhoosh.com/troubleshoot/
- https://www.facebook.com/groups/mywhoosh/posts/1323791068858873/

View File

@@ -0,0 +1,13 @@
## Remote control is not working - nothing happens
*
- Try to unpair it from your phone / computer Bluetooth settings, then re-pair it.
- Try restarting the pairing process in BikeControl
- try restarting Bluetooth on your phone and on the device you want to control
- If your other device is an iOS device, go to Settings > Accessibility > Touch > AssistiveTouch > Pointer Devices > Devices and pair your device. Make sure AssistiveTouch is enabled.
- it is very important that both devices (e.g. iPhone and iPad) receive the "pairing dialog" after initial connection. If you miss it, unpair and try again. It may take a few seconds for the dialog to appear. Afterwards you may need to click on "Reconnect" in BikeControl / restart BikeControl.
## Remote control only clicks on a single coordinate on my iPad
*
iOS seems to be buggy here - try this in the iOS settings:
AssistiveTouch settings > Pointer Devices > Devices > Connected Devices > iPhone (or BikeControl iOS) > Button 1
switch the setting to None, then back to Single-Tap and it should work again

4
INSTRUCTIONS_ROUVY.md Normal file
View File

@@ -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

0
INSTRUCTIONS_ZWIFT.md Normal file
View File

108
README.md
View File

@@ -1,15 +1,15 @@
# SwiftControl
# BikeControl (formerly SwiftControl)
<img src="logo.jpg" alt="SwiftControl Logo"/>
<img src="logo.png" alt="BikeControl Logo"/>
## Description
With SwiftControl you can **control your favorite trainer app** using your Zwift Click, Zwift Ride or Zwift Play devices. Here's what you can do with it, depending on your configuration:
With BikeControl you can **control your favorite trainer app** using your Zwift Click, Zwift Ride, Zwift Play, Shimano Di2, or other similar devices. Here's what you can do with it, depending on your configuration:
- Virtual Gear shifting
- Steering / turning
- Steering / navigation
- adjust workout intensity
- control music on your device
- more? If you can do it via keyboard, mouse or touch, you can do it with SwiftControl
- more? If you can do it via keyboard, mouse, or touch, you can do it with BikeControl
https://github.com/user-attachments/assets/1f81b674-1628-4763-ad66-5f3ed7a3f159
@@ -17,67 +17,89 @@ https://github.com/user-attachments/assets/1f81b674-1628-4763-ad66-5f3ed7a3f159
## Downloads
Check the compatibility matrix below!
## Download
Best follow our landing page and the "Get Started" button: [bikecontrol.app](https://bikecontrol.app/) to understand on which platform you want to run BikeControl. A testing period is available, allowing you to try out the full functionality of BikeControl:
<a href="https://play.google.com/store/apps/details?id=de.jonasbark.swiftcontrol"><img width="270" height="80" alt="GetItOnGooglePlay_Badge_Web_color_English" src="https://github.com/user-attachments/assets/a059d5a1-2efb-4f65-8117-ef6a99823b21" /></a>
<a href="https://apps.apple.com/us/app/swiftcontrol/id6753721284?platform=iphone"><img width="270" height="80" alt="App Store" src="https://github.com/user-attachments/assets/c23f977a-48f6-4951-811e-ae530dbfa014" /></a>
<a href="https://apps.apple.com/us/app/swiftcontrol/id6753721284?platform=iphone"><img width="270" alt="App Store" src="https://github.com/user-attachments/assets/c23f977a-48f6-4951-811e-ae530dbfa014" /></a>
<a href="https://apps.apple.com/us/app/swiftcontrol/id6753721284?platform=mac"><img width="270" height="80" alt="Mac App Store" src="https://github.com/user-attachments/assets/b3552436-409c-43b0-ba7d-b6a72ae30ff1" /></a>
Get the latest version for Windows here: https://github.com/jonasbark/swiftcontrol/releases
<a href="https://apps.microsoft.com/detail/9NP42GS03Z26"><img width="270" alt="Microsoft Store" src="https://github.com/user-attachments/assets/7a8a3cd6-ec26-4678-a850-732eedd27c48" /></a>
## Supported Apps
- MyWhoosh
- TrainingPeaks Virtual / indieVelo
- Biketerra.com (they do offer native integration already - check it out)
- Rouvy (most Zwift devices are already supported by Rouvy)
- any other! You can add custom mapping and adjust touch points or keyboard shortcuts to your liking
- Zwift
- TrainingPeaks Virtual
- Biketerra.com
- Rouvy
- [OpenBikeControl](https://openbikecontrol.org) compatible apps
- any other!
- You can add custom mapping and adjust touch points or keyboard shortcuts to your liking
## Supported Devices
- Zwift Click
- Zwift Click v2 (mostly, see issue #68)
- Zwift Ride
- Zwift Play
- Shimano Di2
- Configure your levers to use D-Fly channels with Shimano E-Tube app
- SRAM AXS/eTap
- Configure your levers not to do any action in the "SRAM AXS" app
- only single or double click is supported (no individual button mapping possible, yet)
- Wahoo Kickr Bike Shift
- Wahoo Kickr Bike Pro
- CYCPLUS BC2 Virtual Shifter
- Thinkrider VS200 Virtual Shifter (beta)
- Elite Sterzo Smart (for steering support)
- Elite Square Smart Frame (beta)
- Wahoo Kickr Bike Shift (beta)
- Your Phone!
- Mount your phone on the handlebar to detect e.g. steering
- Available on Android and iOS
- Gamepads
- Keyboard input
- like a Companion App
- some trainers do not support keyboard input for all functions - now they do!
- useful when remapping keys from other devices using e.g. AutoHotkey
- Cheap Bluetooth buttons such as [these](https://www.amazon.com/s?k=bluetooth+remote) (beta)
- BLE HID devices and classic Bluetooth HID devices are supported
- works out of the box on Android
- on Windows, iOS and macOS requires BikeControl to act as media player
- We're working on creating an affordable alternative based on an open standard, supported by all major trainer apps
- register your interest [here](https://openbikecontrol.org/#HARDWARE)
Support for other devices can be added; check the issues tab here on GitHub.
## Supported Accessories
- Wahoo KICKR HEADWIND (beta)
- control fan speed using your controller
## Supported Platforms
| Platform you want to run your Trainer app, e.g. MyWhoosh on | Possible | Link | Information |
|-------------------------------------------------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Android | ✅ | <a href="https://play.google.com/store/apps/details?id=de.jonasbark.swiftcontrol"><img width="270" height="80" alt="GetItOnGooglePlay_Badge_Web_color_English" src="https://github.com/user-attachments/assets/a059d5a1-2efb-4f65-8117-ef6a99823b21" /></a> | |
| iPad (and possibly Apple TV) | ✅ | <a href="https://apps.apple.com/us/app/swiftcontrol/id6753721284?platform=iphone"><img width="270" height="80" alt="App Store" src="https://github.com/user-attachments/assets/c23f977a-48f6-4951-811e-ae530dbfa014" /></a> | You will need to use SwiftControl as a "remote" to control the trainer app on your iPad. Typically you would use an iPhone or an Android phone for that. |
| Windows | ✅ | [Get it here](https://github.com/jonasbark/swiftcontrol/releases) | - Windows may flag the app as virus. It likely does so because the app controls the mouse and keyboard.<br>- Bluetooth connection unstable? You may need to use an [external Bluetooth adapter](https://github.com/jonasbark/swiftcontrol/issues/14#issuecomment-3193839509).<br>- Make sure your Zwift device is not paired with Windows Bluetooth settings: [more information](https://github.com/jonasbark/swiftcontrol/issues/70). |
| macOS | ✅ | <a href="https://apps.apple.com/us/app/swiftcontrol/id6753721284?platform=mac"><img width="270" height="80" alt="Mac App Store" src="https://github.com/user-attachments/assets/b3552436-409c-43b0-ba7d-b6a72ae30ff1" /></a> | |
| iPhone | ❌ | | Note that you can't run SwiftControl and your trainer app on the same iPhone due to iOS limitations, but you can use it to remotely control MyWhoosh and similar on e.g. an iPad. |
Follow the "Get Started" button over at [bikecontrol.app](https://bikecontrol.app) to understand on which platform you want to run BikeControl.
You can even try it out in your [Browser](https://jonasbark.github.io/swiftcontrol/), if it supports Bluetooth connections. No controlling possible, though.
For testing purposes you can also run it on [Web](https://jonasbark.github.io/swiftcontrol/) but this is just a tech demo - you won't be able to control other apps.
## Troubleshooting
## Help
Check the troubleshooting guide [here](TROUBLESHOOTING.md).
## How does it work?
The app connects to your Zwift devices automatically. It does not connect to your trainer itself.
- **Android**: SwiftControl uses the AccessibilityService API to simulate touch gestures on specific parts of your screen to trigger actions in training apps. The service monitors which training app window is currently active to ensure gestures are sent to the correct app.
- **iOS**: use SwiftControl as "remote control" for other devices, such as an iPad. Example scenario:
- your phone (Android/iOS) runs SwiftControl and connects to your Zwift devices
- your iPad or other tablet runs e.g. MyWhoosh (does not need to have SwiftControl installed)
- after pairing SwiftControl to your iPad / tablet via Bluetooth your phone will send the button presses to your iPad / tablet
- **macOS** / **Windows** a keyboard or mouse click is used to trigger the action.
- there are predefined Keymaps for MyWhoosh, indieVelo / Training Peaks, and others
- you can also create your own Keymaps for any other app
- you can also use the mouse to click on a certain part of the screen, or use keyboard shortcuts
</details>
## Alternatives
- [qdomyos-zwift](https://www.qzfitness.com/) directly controls the trainer (as opposed to controlling the trainer app). This can be useful if your trainer app does not support virtual shifting.
The app connects to your Controller devices (such as Zwift ones) automatically. BikeControl uses different methods of connecting to the trainer app, depending on the trainer app and operating system:
- Connect to the trainer app on the same device or on another device using Network
- available on Android, iOS, iPadOS, macOS, Windows
- supported by e.g. MyWhoosh, Rouvy and Zwift
- Connect to the trainer app on another device by simulating a Bluetooth device
- available on Android, iOS, iPadOS, macOS, Windows
- supported by e.g. Rouvy and Zwift
- Directly control the trainer app via Accessibility features (simulating touch and keyboard input)
- available on Android, macOS, Windows
- supported by all trainer apps
- Connect to the supported trainer app using the [OpenBikeControl](https://openbikecontrol.org) protocol
- available on Android, iOS, iPadOS, macOS, Windows
## Donate
Please consider donating to support the development of this app :)
- [via PayPal](https://paypal.me/boni)
- [via Credit Card, Google Pay, Apple Pay, etc (USD)](https://donate.stripe.com/8x24gzc5c4ZE3VJdt36J201)
- [via Credit Card, Google Pay, Apple Pay, etc (EUR)](https://donate.stripe.com/9B6aEX0muajY8bZ1Kl6J200)
- [via Credit Card, Google Pay, Apple Pay, etc. (USD)](https://donate.stripe.com/8x24gzc5c4ZE3VJdt36J201)
- [via Credit Card, Google Pay, Apple Pay, etc. (EUR)](https://donate.stripe.com/9B6aEX0muajY8bZ1Kl6J200)

View File

@@ -1,28 +1,38 @@
## Click device cannot be found
## Click / Ride device cannot be found
*
This means BikeControl does NOT see the device via Bluetooth.
- Put the controller into pairing mode (LED should blink)
- Ensure the controller is NOT connected to another app/device (e.g. Zwift)
- Update controller firmware in Zwift Companion, if available
- Reboot Bluetooth / reboot phone/PC
## Click / Ride device does not send any data
*
You may need to update the firmware in Zwift Companion app.
## Click device does not send any data
You may need to update the firmware in Zwift Companion app.
## My Click v2 disconnects after a minute or buttons do not work
*
## My Click v2 disconnects after a minute
Check [this](https://github.com/jonasbark/swiftcontrol/issues/68) discussion.
To make your Click V2 work best you should connect it in the Zwift app once each day.
If you don't do that SwiftControl will need to reconnect every minute.
To make your Click V2 work best you should connect it in the Zwift app once before a workout session.
If you don't do that BikeControl will need to reconnect every minute.
1. Open Zwift app (not the Companion)
2. Log in (subscription not required) and open the device connection screen
3. Connect your Trainer, then connect the Click V2
4. Close the Zwift app again and connect again in SwiftControl
2. Log in (subscription not required) device connection screen
3. Connect trainer, then connect Click v2
4. Keep it connected for ~1030 seconds
5. Close Zwift completely, then connect in BikeControl
## Remote control is not working - nothing happens
- Try to unpair it from your phone / computer Bluetooth settings, then re-pair it.
- Try restarting the pairing process in SwiftControl
- try restarting Bluetooth on your phone and on the device you want to control
- If your other device is an iOS device, go to Settings > Accessibility > Touch > AssistiveTouch > Pointer Devices > Devices and pair your device. Make sure AssistiveTouch is enabled.
- it is very important that both devices (e.g. iPhone and iPad) receive the "pairing dialog" after initial connection. If you miss it, unpair and try again. It may take a few seconds for the dialog to appear. Afterwards you may need to click on "Reconnect" in SwiftControl / restart SwiftControl.
Details/updates: https://github.com/jonasbark/swiftcontrol/issues/68
## Remote control only clicks on a single coordinate on my iPad
iOS seems to be buggy here - try this in the iOS settings:
AssistiveTouch settings > Pointer Devices > Devices > Connected Devices > iPhone (or SwiftControl iOS) > Button 1
switch the setting to None, then back to Single-Tap and it should work again
## Android: Connection works, buttons work but nothing happens in MyWhoosh and similar
*
- especially for Redmi and other chinese Android devices please follow the instructions on [https://dontkillmyapp.com/](https://dontkillmyapp.com/):
- disable battery optimization for BikeControl
- enable auto start of BikeControl
- grant accessibility permission for BikeControl
- see [https://github.com/jonasbark/swiftcontrol/issues/38](https://github.com/OpenBikeControl/bikecontrol/issues/38) for more details
## My Clicks do not get recognized in MyWhoosh, but I am connected / use local control
*
Make sure you've enabled Virtual Shifting in MyWhoosh's settings

View File

@@ -0,0 +1 @@
4.3.0

View File

@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v25.2.0), do not edit directly.
// Autogenerated from Pigeon (v25.5.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -12,25 +12,57 @@ import io.flutter.plugin.common.StandardMethodCodec
import io.flutter.plugin.common.StandardMessageCodec
import java.io.ByteArrayOutputStream
import java.nio.ByteBuffer
private object AccessibilityApiPigeonUtils {
private fun wrapResult(result: Any?): List<Any?> {
return listOf(result)
}
private fun wrapError(exception: Throwable): List<Any?> {
return if (exception is FlutterError) {
listOf(
exception.code,
exception.message,
exception.details
)
} else {
listOf(
exception.javaClass.simpleName,
exception.toString(),
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
)
fun wrapResult(result: Any?): List<Any?> {
return listOf(result)
}
fun wrapError(exception: Throwable): List<Any?> {
return if (exception is FlutterError) {
listOf(
exception.code,
exception.message,
exception.details
)
} else {
listOf(
exception.javaClass.simpleName,
exception.toString(),
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
)
}
}
fun deepEquals(a: Any?, b: Any?): Boolean {
if (a is ByteArray && b is ByteArray) {
return a.contentEquals(b)
}
if (a is IntArray && b is IntArray) {
return a.contentEquals(b)
}
if (a is LongArray && b is LongArray) {
return a.contentEquals(b)
}
if (a is DoubleArray && b is DoubleArray) {
return a.contentEquals(b)
}
if (a is Array<*> && b is Array<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is List<*> && b is List<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is Map<*, *> && b is Map<*, *>) {
return a.size == b.size && a.all {
(b as Map<Any?, Any?>).containsKey(it.key) &&
deepEquals(it.value, b[it.key])
}
}
return a == b
}
}
/**
@@ -93,12 +125,44 @@ data class WindowEvent (
if (this === other) {
return true
}
return packageName == other.packageName
&& top == other.top
&& bottom == other.bottom
&& right == other.right
&& left == other.left
return AccessibilityApiPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int = toList().hashCode()
}
/** Generated class from Pigeon that represents data sent in messages. */
data class AKeyEvent (
val source: String,
val hidKey: String,
val keyDown: Boolean,
val keyUp: Boolean
)
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): AKeyEvent {
val source = pigeonVar_list[0] as String
val hidKey = pigeonVar_list[1] as String
val keyDown = pigeonVar_list[2] as Boolean
val keyUp = pigeonVar_list[3] as Boolean
return AKeyEvent(source, hidKey, keyDown, keyUp)
}
}
fun toList(): List<Any?> {
return listOf(
source,
hidKey,
keyDown,
keyUp,
)
}
override fun equals(other: Any?): Boolean {
if (other !is AKeyEvent) {
return false
}
if (this === other) {
return true
}
return AccessibilityApiPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int = toList().hashCode()
}
@@ -115,6 +179,11 @@ private open class AccessibilityApiPigeonCodec : StandardMessageCodec() {
WindowEvent.fromList(it)
}
}
131.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
AKeyEvent.fromList(it)
}
}
else -> super.readValueOfType(type, buffer)
}
}
@@ -128,6 +197,10 @@ private open class AccessibilityApiPigeonCodec : StandardMessageCodec() {
stream.write(130)
writeValue(stream, value.toList())
}
is AKeyEvent -> {
stream.write(131)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
@@ -141,6 +214,9 @@ interface Accessibility {
fun openPermissions()
fun performTouch(x: Double, y: Double, isKeyDown: Boolean, isKeyUp: Boolean)
fun controlMedia(action: MediaAction)
fun isRunning(): Boolean
fun ignoreHidDevices()
fun setHandledKeys(keys: List<String>)
companion object {
/** The codec used by Accessibility. */
@@ -158,7 +234,7 @@ interface Accessibility {
val wrapped: List<Any?> = try {
listOf(api.hasPermission())
} catch (exception: Throwable) {
wrapError(exception)
AccessibilityApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -174,7 +250,7 @@ interface Accessibility {
api.openPermissions()
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
AccessibilityApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -195,7 +271,7 @@ interface Accessibility {
api.performTouch(xArg, yArg, isKeyDownArg, isKeyUpArg)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
AccessibilityApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -213,7 +289,56 @@ interface Accessibility {
api.controlMedia(actionArg)
listOf(null)
} catch (exception: Throwable) {
wrapError(exception)
AccessibilityApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.accessibility.Accessibility.isRunning$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
listOf(api.isRunning())
} catch (exception: Throwable) {
AccessibilityApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.accessibility.Accessibility.ignoreHidDevices$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
api.ignoreHidDevices()
listOf(null)
} catch (exception: Throwable) {
AccessibilityApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.accessibility.Accessibility.setHandledKeys$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val keysArg = args[0] as List<String>
val wrapped: List<Any?> = try {
api.setHandledKeys(keysArg)
listOf(null)
} catch (exception: Throwable) {
AccessibilityApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -274,3 +399,16 @@ abstract class StreamEventsStreamHandler : AccessibilityApiPigeonEventChannelWra
}
}
abstract class HidKeyPressedStreamHandler : AccessibilityApiPigeonEventChannelWrapper<AKeyEvent> {
companion object {
fun register(messenger: BinaryMessenger, streamHandler: HidKeyPressedStreamHandler, instanceName: String = "") {
var channelName: String = "dev.flutter.pigeon.accessibility.EventChannelMethods.hidKeyPressed"
if (instanceName.isNotEmpty()) {
channelName += ".$instanceName"
}
val internalStreamHandler = AccessibilityApiPigeonStreamHandler<AKeyEvent>(streamHandler)
EventChannel(messenger, channelName, AccessibilityApiPigeonMethodCodec).setStreamHandler(internalStreamHandler)
}
}
}

View File

@@ -1,6 +1,8 @@
package de.jonasbark.accessibility
import AKeyEvent
import Accessibility
import HidKeyPressedStreamHandler
import MediaAction
import PigeonEventSink
import StreamEventsStreamHandler
@@ -10,6 +12,7 @@ import android.content.Intent
import android.graphics.Rect
import android.os.Bundle
import android.provider.Settings
import android.view.KeyEvent
import androidx.core.content.ContextCompat.startActivity
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodChannel
@@ -23,17 +26,21 @@ class AccessibilityPlugin: FlutterPlugin, Accessibility {
/// when the Flutter Engine is detached from the Activity
private lateinit var channel : MethodChannel
private lateinit var context: Context
private lateinit var eventHandler: EventListener
private lateinit var windowEventHandler: WindowEventListener
private lateinit var hidEventHandler: HidEventListener
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "accessibility")
eventHandler = EventListener()
windowEventHandler = WindowEventListener()
hidEventHandler = HidEventListener()
context = flutterPluginBinding.applicationContext
Accessibility.setUp(flutterPluginBinding.binaryMessenger, this)
StreamEventsStreamHandler.register(flutterPluginBinding.binaryMessenger, eventHandler)
Observable.fromService = eventHandler
StreamEventsStreamHandler.register(flutterPluginBinding.binaryMessenger, windowEventHandler)
HidKeyPressedStreamHandler.register(flutterPluginBinding.binaryMessenger, hidEventHandler)
Observable.fromServiceWindow = windowEventHandler
Observable.fromServiceKeys = hidEventHandler
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
@@ -45,6 +52,10 @@ class AccessibilityPlugin: FlutterPlugin, Accessibility {
return enabledServices != null && enabledServices.contains(context.packageName)
}
override fun isRunning(): Boolean {
return Observable.toService != null
}
override fun openPermissions() {
startActivity(context, Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
@@ -59,12 +70,12 @@ class AccessibilityPlugin: FlutterPlugin, Accessibility {
val audioService = context.getSystemService(Context.AUDIO_SERVICE) as android.media.AudioManager
when (action) {
MediaAction.PLAY_PAUSE -> {
audioService.dispatchMediaKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_DOWN, android.view.KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE))
audioService.dispatchMediaKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_UP, android.view.KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE))
audioService.dispatchMediaKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE))
audioService.dispatchMediaKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE))
}
MediaAction.NEXT -> {
audioService.dispatchMediaKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_DOWN, android.view.KeyEvent.KEYCODE_MEDIA_NEXT))
audioService.dispatchMediaKeyEvent(android.view.KeyEvent(android.view.KeyEvent.ACTION_UP, android.view.KeyEvent.KEYCODE_MEDIA_NEXT))
audioService.dispatchMediaKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT))
audioService.dispatchMediaKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT))
}
MediaAction.VOLUME_DOWN -> {
audioService.adjustVolume(android.media.AudioManager.ADJUST_LOWER, android.media.AudioManager.FLAG_SHOW_UI)
@@ -75,16 +86,25 @@ class AccessibilityPlugin: FlutterPlugin, Accessibility {
}
}
override fun ignoreHidDevices() {
Observable.ignoreHidDevices = true
}
override fun setHandledKeys(keys: List<String>) {
// Clear and update the concurrent set
Observable.handledKeys = keys.toSet()
}
}
class EventListener : StreamEventsStreamHandler(), Receiver {
class WindowEventListener : StreamEventsStreamHandler(), Receiver {
private var eventSink: PigeonEventSink<WindowEvent>? = null
override fun onListen(p0: Any?, sink: PigeonEventSink<WindowEvent>) {
eventSink = sink
}
fun onEventsDone() {
override fun onCancel(p0: Any?) {
eventSink?.endOfStream()
eventSink = null
}
@@ -93,4 +113,34 @@ class EventListener : StreamEventsStreamHandler(), Receiver {
eventSink?.success(WindowEvent(packageName = packageName, right = window.right.toLong(), left = window.left.toLong(), bottom = window.bottom.toLong(), top = window.top.toLong()))
}
override fun onKeyEvent(event: KeyEvent) {
}
}
class HidEventListener : HidKeyPressedStreamHandler(), Receiver {
private var keyEventSink: PigeonEventSink<AKeyEvent>? = null
override fun onListen(p0: Any?, sink: PigeonEventSink<AKeyEvent>) {
keyEventSink = sink
}
override fun onChange(packageName: String, window: Rect) {
}
override fun onKeyEvent(event: KeyEvent) {
val keyString = KeyEvent.keyCodeToString(event.keyCode)
keyEventSink?.success(
AKeyEvent(
hidKey = keyString,
source = event.device.name,
keyUp = event.action == KeyEvent.ACTION_UP,
keyDown = event.action == KeyEvent.ACTION_DOWN
)
)
}
}

View File

@@ -3,9 +3,15 @@ package de.jonasbark.accessibility
import android.accessibilityservice.AccessibilityService
import android.accessibilityservice.GestureDescription
import android.accessibilityservice.GestureDescription.StrokeDescription
import android.accessibilityservice.AccessibilityServiceInfo
import android.content.Context
import android.graphics.Path
import android.graphics.Rect
import android.media.AudioManager
import android.os.Build
import android.util.Log
import android.view.InputDevice
import android.view.KeyEvent
import android.view.ViewConfiguration
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
@@ -36,7 +42,7 @@ class AccessibilityService : AccessibilityService(), Listener {
}
val currentPackageName = event.packageName.toString()
val windowSize = getWindowSize()
Observable.fromService?.onChange(packageName = currentPackageName, window = windowSize)
Observable.fromServiceWindow?.onChange(packageName = currentPackageName, window = windowSize)
}
private fun getWindowSize(): Rect {
@@ -50,13 +56,58 @@ class AccessibilityService : AccessibilityService(), Listener {
Log.d("AccessibilityService", "Service Interrupted")
}
override fun onServiceConnected() {
super.onServiceConnected()
// Request key event filtering so we receive onKeyEvent for hardware/HID media keys
try {
val info = serviceInfo ?: AccessibilityServiceInfo()
info.flags = info.flags or AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS
// keep other capabilities as defined in XML
setServiceInfo(info)
} catch (e: Exception) {
Log.w("AccessibilityService", "Failed to set service info for key events: ${e.message}")
}
}
override fun onKeyEvent(event: KeyEvent): Boolean {
val keyString = KeyEvent.keyCodeToString(event.keyCode)
if (!Observable.ignoreHidDevices && isBleRemote(event) && Observable.handledKeys.contains(keyString)) {
// Handle keys that have a keymap defined
Log.d(
"AccessibilityService",
"onKeyEvent: keyCode=${event.keyCode} action=${event.action} scanCode=${event.scanCode} flags=${event.flags}"
)
// Forward key events to the plugin (Flutter) and swallow them so they don't propagate.
Observable.fromServiceKeys?.onKeyEvent(event)
// Return true to indicate we've handled the event and it should be swallowed.
return true
} else {
return false
}
}
private fun isBleRemote(event: KeyEvent): Boolean {
val dev = InputDevice.getDevice(event.deviceId) ?: return false
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
dev.isExternal
} else {
true
}
}
override fun performTouch(x: Double, y: Double, isKeyDown: Boolean, isKeyUp: Boolean) {
val gestureBuilder = GestureDescription.Builder()
val path = Path()
path.moveTo(x.toFloat(), y.toFloat())
path.lineTo(x.toFloat()+1, y.toFloat())
val stroke = StrokeDescription(path, 0, ViewConfiguration.getTapTimeout().toLong(), isKeyDown && !isKeyUp)
val stroke = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
StrokeDescription(path, 0, ViewConfiguration.getTapTimeout().toLong(), isKeyDown && !isKeyUp)
} else {
// API 2425: no “willContinue” support
StrokeDescription(path, 0L, ViewConfiguration.getTapTimeout().toLong())
}
gestureBuilder.addStroke(stroke)
dispatchGesture(gestureBuilder.build(), null, null)

View File

@@ -1,10 +1,16 @@
package de.jonasbark.accessibility
import android.graphics.Rect
import android.view.KeyEvent
import java.util.concurrent.ConcurrentHashMap
object Observable {
var toService: Listener? = null
var fromService: Receiver? = null
var fromServiceWindow: Receiver? = null
var fromServiceKeys: Receiver? = null
var ignoreHidDevices: Boolean = false
// Use concurrent set for thread-safe access from AccessibilityService and plugin
var handledKeys: Set<String> = ConcurrentHashMap.newKeySet()
}
interface Listener {
@@ -13,4 +19,5 @@ interface Listener {
interface Receiver {
fun onChange(packageName: String, window: Rect)
fun onKeyEvent(event: KeyEvent)
}

View File

@@ -9,6 +9,12 @@ abstract class Accessibility {
void performTouch(double x, double y, {bool isKeyDown = true, bool isKeyUp = false});
void controlMedia(MediaAction action);
bool isRunning();
void ignoreHidDevices();
void setHandledKeys(List<String> keys);
}
enum MediaAction { playPause, next, volumeUp, volumeDown }
@@ -29,7 +35,17 @@ class WindowEvent {
});
}
class AKeyEvent {
final String source;
final String hidKey;
final bool keyDown;
final bool keyUp;
AKeyEvent({required this.source, required this.hidKey, required this.keyDown, required this.keyUp});
}
@EventChannelApi()
abstract class EventChannelMethods {
WindowEvent streamEvents();
AKeyEvent hidKeyPressed();
}

View File

@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v25.2.0), do not edit directly.
// Autogenerated from Pigeon (v25.5.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
@@ -14,6 +14,20 @@ PlatformException _createConnectionError(String channelName) {
message: 'Unable to establish connection on channel: "$channelName".',
);
}
bool _deepEquals(Object? a, Object? b) {
if (a is List && b is List) {
return a.length == b.length &&
a.indexed
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
}
if (a is Map && b is Map) {
return a.length == b.length && a.entries.every((MapEntry<Object?, Object?> entry) =>
(b as Map<Object?, Object?>).containsKey(entry.key) &&
_deepEquals(entry.value, b[entry.key]));
}
return a == b;
}
enum MediaAction {
playPause,
@@ -74,12 +88,63 @@ class WindowEvent {
if (identical(this, other)) {
return true;
}
return
packageName == other.packageName
&& top == other.top
&& bottom == other.bottom
&& right == other.right
&& left == other.left;
return _deepEquals(encode(), other.encode());
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => Object.hashAll(_toList())
;
}
class AKeyEvent {
AKeyEvent({
required this.source,
required this.hidKey,
required this.keyDown,
required this.keyUp,
});
String source;
String hidKey;
bool keyDown;
bool keyUp;
List<Object?> _toList() {
return <Object?>[
source,
hidKey,
keyDown,
keyUp,
];
}
Object encode() {
return _toList(); }
static AKeyEvent decode(Object result) {
result as List<Object?>;
return AKeyEvent(
source: result[0]! as String,
hidKey: result[1]! as String,
keyDown: result[2]! as bool,
keyUp: result[3]! as bool,
);
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
bool operator ==(Object other) {
if (other is! AKeyEvent || other.runtimeType != runtimeType) {
return false;
}
if (identical(this, other)) {
return true;
}
return _deepEquals(encode(), other.encode());
}
@override
@@ -102,6 +167,9 @@ class _PigeonCodec extends StandardMessageCodec {
} else if (value is WindowEvent) {
buffer.putUint8(130);
writeValue(buffer, value.encode());
} else if (value is AKeyEvent) {
buffer.putUint8(131);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
@@ -115,6 +183,8 @@ class _PigeonCodec extends StandardMessageCodec {
return value == null ? null : MediaAction.values[value];
case 130:
return WindowEvent.decode(readValue(buffer)!);
case 131:
return AKeyEvent.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
@@ -232,6 +302,80 @@ class Accessibility {
return;
}
}
Future<bool> isRunning() async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.accessibility.Accessibility.isRunning$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final List<Object?>? pigeonVar_replyList =
await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as bool?)!;
}
}
Future<void> ignoreHidDevices() async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.accessibility.Accessibility.ignoreHidDevices$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final List<Object?>? pigeonVar_replyList =
await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
Future<void> setHandledKeys(List<String> keys) async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.accessibility.Accessibility.setHandledKeys$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
binaryMessenger: pigeonVar_binaryMessenger,
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[keys]);
final List<Object?>? pigeonVar_replyList =
await pigeonVar_sendFuture as List<Object?>?;
if (pigeonVar_replyList == null) {
throw _createConnectionError(pigeonVar_channelName);
} else if (pigeonVar_replyList.length > 1) {
throw PlatformException(
code: pigeonVar_replyList[0]! as String,
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else {
return;
}
}
}
Stream<WindowEvent> streamEvents( {String instanceName = ''}) {
@@ -245,3 +389,14 @@ Stream<WindowEvent> streamEvents( {String instanceName = ''}) {
});
}
Stream<AKeyEvent> hidKeyPressed( {String instanceName = ''}) {
if (instanceName.isNotEmpty) {
instanceName = '.$instanceName';
}
final EventChannel hidKeyPressedChannel =
EventChannel('dev.flutter.pigeon.accessibility.EventChannelMethods.hidKeyPressed$instanceName', pigeonMethodCodec);
return hidKeyPressedChannel.receiveBroadcastStream().map((dynamic event) {
return event as AKeyEvent;
});
}

View File

@@ -1,7 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@@ -16,6 +16,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE"/>
<uses-permission android:name="android.permission.BILLING"/>
<!-- legacy for Android 9 or lower -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28" tools:replace="android:maxSdkVersion" />
@@ -25,7 +26,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="SwiftControl"
android:label="BikeControl"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity

View File

@@ -1,5 +1,46 @@
package de.jonasbark.swiftcontrol
import io.flutter.embedding.android.FlutterActivity
import android.hardware.input.InputManager
import android.os.Handler
import android.view.InputDevice
import android.view.KeyEvent
import android.view.MotionEvent
import io.flutter.embedding.android.FlutterFragmentActivity
import org.flame_engine.gamepads_android.GamepadsCompatibleActivity
class MainActivity : FlutterActivity()
class MainActivity: FlutterFragmentActivity(), GamepadsCompatibleActivity {
var keyListener: ((KeyEvent) -> Boolean)? = null
var motionListener: ((MotionEvent) -> Boolean)? = null
override fun isGamepadsInputDevice(device: InputDevice): Boolean {
return device.sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
|| device.sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
// Some bluetooth keyboards are identified as GamePad. Check if it is ALPHABETIC keyboard.
// && device.keyboardType != InputDevice.KEYBOARD_TYPE_ALPHABETIC
}
override fun dispatchGenericMotionEvent(motionEvent: MotionEvent): Boolean {
return motionListener?.invoke(motionEvent) ?: false
}
override fun dispatchKeyEvent(keyEvent: KeyEvent): Boolean {
if (keyListener?.invoke(keyEvent) == true) {
return true
}
return super.dispatchKeyEvent(keyEvent)
}
override fun registerInputDeviceListener(
listener: InputManager.InputDeviceListener, handler: Handler?) {
val inputManager = getSystemService(INPUT_SERVICE) as InputManager
inputManager.registerInputDeviceListener(listener, null)
}
override fun registerKeyEventHandler(handler: (KeyEvent) -> Boolean) {
keyListener = handler
}
override fun registerMotionEventHandler(handler: (MotionEvent) -> Boolean) {
motionListener = handler
}
}

View File

@@ -4,9 +4,9 @@
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
android:src="@mipmap/ic_launcher" />
</item>
</layer-list>

View File

@@ -4,9 +4,9 @@
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
android:src="@mipmap/ic_launcher" />
</item>
</layer-list>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowStateChanged|typeViewClicked"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:accessibilityFlags="flagDefault|flagRequestFilterKeyEvents"
android:canRetrieveWindowContent="true"
android:canRequestFilterKeyEvents="true"
android:canPerformGestures="true"
android:notificationTimeout="100"/>

View File

@@ -1,32 +0,0 @@
# flutter pub run flutter_launcher_icons
flutter_launcher_icons:
image_path: "icon.png"
android: "ic_launcher"
# image_path_android: "assets/icon/icon.png"
min_sdk_android: 24 # android min sdk min:16, default 21
# adaptive_icon_background: "assets/icon/background.png"
# adaptive_icon_foreground: "assets/icon/foreground.png"
# adaptive_icon_monochrome: "assets/icon/monochrome.png"
ios: true
# image_path_ios: "assets/icon/icon.png"
remove_alpha_ios: true
# image_path_ios_dark_transparent: "assets/icon/icon_dark.png"
# image_path_ios_tinted_grayscale: "assets/icon/icon_tinted.png"
# desaturate_tinted_to_grayscale_ios: true
web:
generate: true
image_path: "icon.png"
background_color: "#ffffff"
theme_color: "#ffffff"
windows:
generate: true
image_path: "icon.png"
icon_size: 48 # min:48, max:256, default: 48
macos:
generate: true
image_path: "icon.png"

BIN
icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 555 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,5 +1,6 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '13.0'
platform :ios, '15.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

View File

@@ -7,16 +7,51 @@ PODS:
- Flutter (1.0.0)
- flutter_local_notifications (0.0.1):
- Flutter
- flutter_secure_storage_darwin (10.0.0):
- Flutter
- FlutterMacOS
- gamepads_ios (0.1.1):
- Flutter
- image_picker_ios (0.0.1):
- Flutter
- in_app_purchase_storekit (0.0.1):
- Flutter
- FlutterMacOS
- in_app_review (2.0.0):
- Flutter
- integration_test (0.0.1):
- Flutter
- ios_receipt (0.0.1):
- Flutter
- media_key_detector_ios (0.0.1):
- Flutter
- nsd_ios (0.0.1):
- Flutter
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- permission_handler_apple (9.3.0):
- Flutter
- restart (1.0.0):
- purchases_flutter (9.10.2):
- Flutter
- PurchasesHybridCommon (= 17.25.0)
- purchases_ui_flutter (9.10.2):
- Flutter
- PurchasesHybridCommonUI (= 17.25.0)
- PurchasesHybridCommon (17.25.0):
- RevenueCat (= 5.51.1)
- PurchasesHybridCommonUI (17.25.0):
- PurchasesHybridCommon (= 17.25.0)
- RevenueCatUI (= 5.51.1)
- restart_app (0.0.1):
- Flutter
- RevenueCat (5.51.1)
- RevenueCatUI (5.51.1):
- RevenueCat (= 5.51.1)
- sensors_plus (0.0.1):
- Flutter
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
@@ -33,16 +68,34 @@ DEPENDENCIES:
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- Flutter (from `Flutter`)
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
- gamepads_ios (from `.symlinks/plugins/gamepads_ios/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`)
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
- integration_test (from `.symlinks/plugins/integration_test/ios`)
- ios_receipt (from `.symlinks/plugins/ios_receipt/ios`)
- media_key_detector_ios (from `.symlinks/plugins/media_key_detector_ios/ios`)
- nsd_ios (from `.symlinks/plugins/nsd_ios/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- restart (from `.symlinks/plugins/restart/ios`)
- purchases_flutter (from `.symlinks/plugins/purchases_flutter/ios`)
- purchases_ui_flutter (from `.symlinks/plugins/purchases_ui_flutter/ios`)
- restart_app (from `.symlinks/plugins/restart_app/ios`)
- sensors_plus (from `.symlinks/plugins/sensors_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- universal_ble (from `.symlinks/plugins/universal_ble/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
SPEC REPOS:
trunk:
- PurchasesHybridCommon
- PurchasesHybridCommonUI
- RevenueCat
- RevenueCatUI
EXTERNAL SOURCES:
bluetooth_low_energy_darwin:
:path: ".symlinks/plugins/bluetooth_low_energy_darwin/darwin"
@@ -52,16 +105,38 @@ EXTERNAL SOURCES:
:path: Flutter
flutter_local_notifications:
:path: ".symlinks/plugins/flutter_local_notifications/ios"
flutter_secure_storage_darwin:
:path: ".symlinks/plugins/flutter_secure_storage_darwin/darwin"
gamepads_ios:
:path: ".symlinks/plugins/gamepads_ios/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
in_app_purchase_storekit:
:path: ".symlinks/plugins/in_app_purchase_storekit/darwin"
in_app_review:
:path: ".symlinks/plugins/in_app_review/ios"
integration_test:
:path: ".symlinks/plugins/integration_test/ios"
ios_receipt:
:path: ".symlinks/plugins/ios_receipt/ios"
media_key_detector_ios:
:path: ".symlinks/plugins/media_key_detector_ios/ios"
nsd_ios:
:path: ".symlinks/plugins/nsd_ios/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
restart:
:path: ".symlinks/plugins/restart/ios"
purchases_flutter:
:path: ".symlinks/plugins/purchases_flutter/ios"
purchases_ui_flutter:
:path: ".symlinks/plugins/purchases_ui_flutter/ios"
restart_app:
:path: ".symlinks/plugins/restart_app/ios"
sensors_plus:
:path: ".symlinks/plugins/sensors_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
universal_ble:
@@ -76,16 +151,31 @@ SPEC CHECKSUMS:
device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_local_notifications: ff50f8405aaa0ccdc7dcfb9022ca192e8ad9688f
flutter_secure_storage_darwin: 557817588b80e60213cbecb573c45c76b788018d
gamepads_ios: 1d2930c7a4450a9a1b57444ebf305a6a6cbeea0b
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
in_app_purchase_storekit: 2342c0a5da86593124d08dd13d920f39a52b273a
in_app_review: 436034b18594851a7328d7f1c2ed5ec235b79cfc
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
ios_receipt: c2d5b4c36953c377a024992393976214ce6951e6
media_key_detector_ios: 7ff9aefdfea00bb7b71e184132381b7d0e7e1269
nsd_ios: 8c37babdc6538e3350dbed3a52674d2edde98173
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
restart: b5fe16e6e038f0024b2f3af43768e9d2a1557554
purchases_flutter: 7cbb87481a018c1bb8b4966b7d446a7c19d96d87
purchases_ui_flutter: 1905cebf3f46e03aeefba0f6258000f3cdd32641
PurchasesHybridCommon: 6a79a873ab52f777bfa36e9516f3fcd84d3b3428
PurchasesHybridCommonUI: 3c1f78addfb3f470713548b4eac8c59254d0efe6
restart_app: 806659942bf932f6ce51c5372f91ce5e81c8c14a
RevenueCat: eab035bbab271faccfef5c36eaff2a1ffef14dc0
RevenueCatUI: c6acb3648fa58ccb4f0f178556ed0278b796234f
sensors_plus: 7229095999f30740798f0eeef5cd120357a8f4f2
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
wakelock_plus: 76957ab028e12bfa4e66813c99e46637f367fc7e
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
PODFILE CHECKSUM: 7ebd5c9b932b3af79d5c67e3af873118b74e970f
COCOAPODS: 1.16.2

View File

@@ -65,6 +65,7 @@
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
DFFDC4B9C4D6EF6A3BDE2E73 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
EFDECED99A47773C293F8819 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
F0D040E82EEF2560009B19C0 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -152,6 +153,7 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
F0D040E82EEF2560009B19C0 /* Runner.entitlements */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
@@ -487,12 +489,14 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = UZRHKPVWN9;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -673,12 +677,14 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = UZRHKPVWN9;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -699,12 +705,14 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = UZRHKPVWN9;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.6;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",

View File

@@ -8,6 +8,8 @@ import UIKit
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -1 +1,134 @@
{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}}
{
"images": [
{
"filename": "AppIcon@2x.png",
"idiom": "iphone",
"scale": "2x",
"size": "60x60"
},
{
"filename": "AppIcon@3x.png",
"idiom": "iphone",
"scale": "3x",
"size": "60x60"
},
{
"filename": "AppIcon~ipad.png",
"idiom": "ipad",
"scale": "1x",
"size": "76x76"
},
{
"filename": "AppIcon@2x~ipad.png",
"idiom": "ipad",
"scale": "2x",
"size": "76x76"
},
{
"filename": "AppIcon-83.5@2x~ipad.png",
"idiom": "ipad",
"scale": "2x",
"size": "83.5x83.5"
},
{
"filename": "AppIcon-40@2x.png",
"idiom": "iphone",
"scale": "2x",
"size": "40x40"
},
{
"filename": "AppIcon-40@3x.png",
"idiom": "iphone",
"scale": "3x",
"size": "40x40"
},
{
"filename": "AppIcon-40~ipad.png",
"idiom": "ipad",
"scale": "1x",
"size": "40x40"
},
{
"filename": "AppIcon-40@2x~ipad.png",
"idiom": "ipad",
"scale": "2x",
"size": "40x40"
},
{
"filename": "AppIcon-20@2x.png",
"idiom": "iphone",
"scale": "2x",
"size": "20x20"
},
{
"filename": "AppIcon-20@3x.png",
"idiom": "iphone",
"scale": "3x",
"size": "20x20"
},
{
"filename": "AppIcon-20~ipad.png",
"idiom": "ipad",
"scale": "1x",
"size": "20x20"
},
{
"filename": "AppIcon-20@2x~ipad.png",
"idiom": "ipad",
"scale": "2x",
"size": "20x20"
},
{
"filename": "AppIcon-29.png",
"idiom": "iphone",
"scale": "1x",
"size": "29x29"
},
{
"filename": "AppIcon-29@2x.png",
"idiom": "iphone",
"scale": "2x",
"size": "29x29"
},
{
"filename": "AppIcon-29@3x.png",
"idiom": "iphone",
"scale": "3x",
"size": "29x29"
},
{
"filename": "AppIcon-29~ipad.png",
"idiom": "ipad",
"scale": "1x",
"size": "29x29"
},
{
"filename": "AppIcon-29@2x~ipad.png",
"idiom": "ipad",
"scale": "2x",
"size": "29x29"
},
{
"filename": "AppIcon-60@2x~car.png",
"idiom": "car",
"scale": "2x",
"size": "60x60"
},
{
"filename": "AppIcon-60@3x~car.png",
"idiom": "car",
"scale": "3x",
"size": "60x60"
},
{
"filename": "AppIcon~ios-marketing.png",
"idiom": "ios-marketing",
"scale": "1x",
"size": "1024x1024"
}
],
"info": {
"author": "iconkitchen",
"version": 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 880 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Some files were not shown because too many files have changed in this diff Show More