mirror of
https://github.com/jonasbark/swiftcontrol.git
synced 2026-02-18 00:17:40 +01:00
Implement percentage-based keymap storage for better device compatibility
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
This commit is contained in:
@@ -31,11 +31,21 @@ class _DevicePageState extends State<DevicePage> {
|
||||
List<SupportedApp> _getAllApps() {
|
||||
final baseApps = SupportedApp.supportedApps.where((app) => app is! CustomApp).toList();
|
||||
final customProfiles = settings.getCustomAppProfiles();
|
||||
|
||||
// Get screen size for percentage-based decoding
|
||||
Size? screenSize;
|
||||
try {
|
||||
final view = WidgetsBinding.instance.platformDispatcher.views.first;
|
||||
screenSize = view.physicalSize / view.devicePixelRatio;
|
||||
} catch (e) {
|
||||
screenSize = MediaQuery.maybeOf(context)?.size;
|
||||
}
|
||||
|
||||
final customApps = customProfiles.map((profile) {
|
||||
final customApp = CustomApp(profileName: profile);
|
||||
final savedKeymap = settings.getCustomAppKeymap(profile);
|
||||
if (savedKeymap != null) {
|
||||
customApp.decodeKeymap(savedKeymap);
|
||||
customApp.decodeKeymap(savedKeymap, screenSize: screenSize);
|
||||
}
|
||||
return customApp;
|
||||
}).toList();
|
||||
@@ -227,7 +237,14 @@ ${it.firmwareVersion != null ? ' - Firmware Version: ${it.firmwareVersion}' : ''
|
||||
final customApp = CustomApp(profileName: newName);
|
||||
final savedKeymap = settings.getCustomAppKeymap(newName);
|
||||
if (savedKeymap != null) {
|
||||
customApp.decodeKeymap(savedKeymap);
|
||||
Size? screenSize;
|
||||
try {
|
||||
final view = WidgetsBinding.instance.platformDispatcher.views.first;
|
||||
screenSize = view.physicalSize / view.devicePixelRatio;
|
||||
} catch (e) {
|
||||
screenSize = MediaQuery.maybeOf(context)?.size;
|
||||
}
|
||||
customApp.decodeKeymap(savedKeymap, screenSize: screenSize);
|
||||
}
|
||||
actionHandler.supportedApp = customApp;
|
||||
await settings.setApp(customApp);
|
||||
@@ -241,7 +258,14 @@ ${it.firmwareVersion != null ? ' - Firmware Version: ${it.firmwareVersion}' : ''
|
||||
final customApp = CustomApp(profileName: newName);
|
||||
final savedKeymap = settings.getCustomAppKeymap(newName);
|
||||
if (savedKeymap != null) {
|
||||
customApp.decodeKeymap(savedKeymap);
|
||||
Size? screenSize;
|
||||
try {
|
||||
final view = WidgetsBinding.instance.platformDispatcher.views.first;
|
||||
screenSize = view.physicalSize / view.devicePixelRatio;
|
||||
} catch (e) {
|
||||
screenSize = MediaQuery.maybeOf(context)?.size;
|
||||
}
|
||||
customApp.decodeKeymap(savedKeymap, screenSize: screenSize);
|
||||
}
|
||||
actionHandler.supportedApp = customApp;
|
||||
await settings.setApp(customApp);
|
||||
|
||||
@@ -22,19 +22,19 @@ class CustomApp extends SupportedApp {
|
||||
return keyPair.touchPosition;
|
||||
}
|
||||
|
||||
List<String> encodeKeymap() {
|
||||
List<String> encodeKeymap({Size? screenSize}) {
|
||||
// encode to save in preferences
|
||||
return keymap.keyPairs.map((e) => e.encode()).toList();
|
||||
return keymap.keyPairs.map((e) => e.encode(screenSize: screenSize)).toList();
|
||||
}
|
||||
|
||||
void decodeKeymap(List<String> data) {
|
||||
void decodeKeymap(List<String> data, {Size? screenSize}) {
|
||||
// decode from preferences
|
||||
|
||||
if (data.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final keyPairs = data.map((e) => KeyPair.decode(e)).whereNotNull().toList();
|
||||
final keyPairs = data.map((e) => KeyPair.decode(e, screenSize: screenSize)).whereNotNull().toList();
|
||||
if (keyPairs.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -73,23 +73,52 @@ class KeyPair {
|
||||
};
|
||||
}
|
||||
|
||||
String encode() {
|
||||
String encode({Size? screenSize}) {
|
||||
// encode to save in preferences
|
||||
// If screenSize is provided, store as percentages for better compatibility across devices
|
||||
final touchPosData = screenSize != null && touchPosition != Offset.zero
|
||||
? {
|
||||
'x_percent': touchPosition.dx / screenSize.width,
|
||||
'y_percent': touchPosition.dy / screenSize.height,
|
||||
}
|
||||
: {'x': touchPosition.dx, 'y': touchPosition.dy};
|
||||
|
||||
return jsonEncode({
|
||||
'actions': buttons.map((e) => e.name).toList(),
|
||||
'logicalKey': logicalKey?.keyId.toString() ?? '0',
|
||||
'physicalKey': physicalKey?.usbHidUsage.toString() ?? '0',
|
||||
'touchPosition': {'x': touchPosition.dx, 'y': touchPosition.dy},
|
||||
'touchPosition': touchPosData,
|
||||
'isLongPress': isLongPress,
|
||||
});
|
||||
}
|
||||
|
||||
static KeyPair? decode(String data) {
|
||||
static KeyPair? decode(String data, {Size? screenSize}) {
|
||||
// decode from preferences
|
||||
final decoded = jsonDecode(data);
|
||||
if (decoded['actions'] == null || decoded['logicalKey'] == null || decoded['physicalKey'] == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Support both percentage-based (new) and pixel-based (old) formats
|
||||
final touchPosData = decoded['touchPosition'];
|
||||
final Offset touchPosition;
|
||||
|
||||
if (touchPosData.containsKey('x_percent') && touchPosData.containsKey('y_percent')) {
|
||||
// New percentage-based format
|
||||
if (screenSize != null) {
|
||||
touchPosition = Offset(
|
||||
touchPosData['x_percent'] * screenSize.width,
|
||||
touchPosData['y_percent'] * screenSize.height,
|
||||
);
|
||||
} else {
|
||||
// Fallback if no screen size provided
|
||||
touchPosition = Offset.zero;
|
||||
}
|
||||
} else {
|
||||
// Old pixel-based format
|
||||
touchPosition = Offset(touchPosData['x'], touchPosData['y']);
|
||||
}
|
||||
|
||||
return KeyPair(
|
||||
buttons:
|
||||
decoded['actions']
|
||||
@@ -98,7 +127,7 @@ class KeyPair {
|
||||
logicalKey: int.parse(decoded['logicalKey']) != 0 ? LogicalKeyboardKey(int.parse(decoded['logicalKey'])) : null,
|
||||
physicalKey:
|
||||
int.parse(decoded['physicalKey']) != 0 ? PhysicalKeyboardKey(int.parse(decoded['physicalKey'])) : null,
|
||||
touchPosition: Offset(decoded['touchPosition']['x'], decoded['touchPosition']['y']),
|
||||
touchPosition: touchPosition,
|
||||
isLongPress: decoded['isLongPress'] ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:dartx/dartx.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:swift_control/utils/keymap/apps/supported_app.dart';
|
||||
|
||||
@@ -31,7 +32,15 @@ class Settings {
|
||||
final customApp = CustomApp(profileName: appName);
|
||||
final appSetting = _prefs.getStringList('customapp_$appName');
|
||||
if (appSetting != null) {
|
||||
customApp.decodeKeymap(appSetting);
|
||||
// Get screen size for percentage-based decoding
|
||||
Size? screenSize;
|
||||
try {
|
||||
final view = WidgetsBinding.instance.platformDispatcher.views.first;
|
||||
screenSize = view.physicalSize / view.devicePixelRatio;
|
||||
} catch (e) {
|
||||
screenSize = null;
|
||||
}
|
||||
customApp.decodeKeymap(appSetting, screenSize: screenSize);
|
||||
}
|
||||
actionHandler.init(customApp);
|
||||
} else {
|
||||
@@ -52,7 +61,16 @@ class Settings {
|
||||
|
||||
Future<void> setApp(SupportedApp app) async {
|
||||
if (app is CustomApp) {
|
||||
await _prefs.setStringList('customapp_${app.profileName}', app.encodeKeymap());
|
||||
// Get screen size for percentage-based encoding
|
||||
Size? screenSize;
|
||||
try {
|
||||
final view = WidgetsBinding.instance.platformDispatcher.views.first;
|
||||
screenSize = view.physicalSize / view.devicePixelRatio;
|
||||
} catch (e) {
|
||||
// Fallback if screen size is not available
|
||||
screenSize = null;
|
||||
}
|
||||
await _prefs.setStringList('customapp_${app.profileName}', app.encodeKeymap(screenSize: screenSize));
|
||||
}
|
||||
await _prefs.setString('app', app.name);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user