mirror of
https://github.com/jonasbark/swiftcontrol.git
synced 2026-02-18 00:17:40 +01:00
Add import/export functionality for keymap profiles
Co-authored-by: jonasbark <1151304+jonasbark@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import 'dart:io';
|
||||
import 'package:dartx/dartx.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:swift_control/bluetooth/devices/zwift_clickv2.dart';
|
||||
import 'package:swift_control/main.dart';
|
||||
import 'package:swift_control/pages/touch_area.dart';
|
||||
@@ -284,6 +285,55 @@ ${it.firmwareVersion != null ? ' - Firmware Version: ${it.firmwareVersion}' : ''
|
||||
},
|
||||
child: Text('Manage Profile'),
|
||||
),
|
||||
|
||||
if (actionHandler.supportedApp is CustomApp)
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
final currentProfile = (actionHandler.supportedApp as CustomApp).profileName;
|
||||
final jsonData = settings.exportCustomAppProfile(currentProfile);
|
||||
if (jsonData != null) {
|
||||
await Clipboard.setData(ClipboardData(text: jsonData));
|
||||
if (mounted) {
|
||||
_snackBarMessengerKey.currentState!.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Profile "$currentProfile" exported to clipboard'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Text('Export Profile'),
|
||||
),
|
||||
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
final jsonData = await _showImportDialog();
|
||||
if (jsonData != null && jsonData.isNotEmpty) {
|
||||
final success = await settings.importCustomAppProfile(jsonData);
|
||||
if (mounted) {
|
||||
if (success) {
|
||||
_snackBarMessengerKey.currentState!.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Profile imported successfully'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
setState(() {});
|
||||
} else {
|
||||
_snackBarMessengerKey.currentState!.showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Failed to import profile. Invalid format.'),
|
||||
duration: Duration(seconds: 2),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Text('Import Profile'),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (actionHandler.supportedApp != null)
|
||||
@@ -468,4 +518,51 @@ ${it.firmwareVersion != null ? ' - Firmware Version: ${it.firmwareVersion}' : ''
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<String?> _showImportDialog() async {
|
||||
final controller = TextEditingController();
|
||||
|
||||
// Try to get data from clipboard
|
||||
try {
|
||||
final clipboardData = await Clipboard.getData('text/plain');
|
||||
if (clipboardData?.text != null) {
|
||||
controller.text = clipboardData!.text!;
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore clipboard errors
|
||||
}
|
||||
|
||||
return showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('Import Profile'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text('Paste the exported JSON data below:'),
|
||||
SizedBox(height: 16),
|
||||
TextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'JSON Data',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
maxLines: 5,
|
||||
autofocus: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text('Cancel'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, controller.text),
|
||||
child: Text('Import'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dartx/dartx.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
@@ -100,6 +102,37 @@ class Settings {
|
||||
await _prefs.setStringList('customapp_$newProfileName', sourceData);
|
||||
}
|
||||
}
|
||||
|
||||
String? exportCustomAppProfile(String profileName) {
|
||||
final data = _prefs.getStringList('customapp_$profileName');
|
||||
if (data == null) return null;
|
||||
|
||||
// Export as JSON with metadata
|
||||
return jsonEncode({
|
||||
'version': 1,
|
||||
'profileName': profileName,
|
||||
'keymap': data,
|
||||
});
|
||||
}
|
||||
|
||||
Future<bool> importCustomAppProfile(String jsonData, {String? newProfileName}) async {
|
||||
try {
|
||||
final decoded = jsonDecode(jsonData);
|
||||
|
||||
// Validate the structure
|
||||
if (decoded['version'] == null || decoded['keymap'] == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final profileName = newProfileName ?? decoded['profileName'] ?? 'Imported';
|
||||
final keymap = List<String>.from(decoded['keymap']);
|
||||
|
||||
await _prefs.setStringList('customapp_$profileName', keymap);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String? getLastSeenVersion() {
|
||||
return _prefs.getString('last_seen_version');
|
||||
|
||||
Reference in New Issue
Block a user