mirror of
https://github.com/jonasbark/swiftcontrol.git
synced 2026-02-18 00:17:40 +01:00
fix UI
This commit is contained in:
@@ -33,25 +33,26 @@ class DevicePage extends StatefulWidget {
|
||||
class _DevicePageState extends State<DevicePage> with WidgetsBindingObserver {
|
||||
late StreamSubscription<BaseDevice> _connectionStateSubscription;
|
||||
final controller = TextEditingController(text: actionHandler.supportedApp?.name);
|
||||
|
||||
|
||||
List<SupportedApp> _getAllApps() {
|
||||
final baseApps = SupportedApp.supportedApps.where((app) => app is! CustomApp).toList();
|
||||
final customProfiles = settings.getCustomAppProfiles();
|
||||
|
||||
final customApps = customProfiles.map((profile) {
|
||||
final customApp = CustomApp(profileName: profile);
|
||||
final savedKeymap = settings.getCustomAppKeymap(profile);
|
||||
if (savedKeymap != null) {
|
||||
customApp.decodeKeymap(savedKeymap);
|
||||
}
|
||||
return customApp;
|
||||
}).toList();
|
||||
|
||||
|
||||
final customApps =
|
||||
customProfiles.map((profile) {
|
||||
final customApp = CustomApp(profileName: profile);
|
||||
final savedKeymap = settings.getCustomAppKeymap(profile);
|
||||
if (savedKeymap != null) {
|
||||
customApp.decodeKeymap(savedKeymap);
|
||||
}
|
||||
return customApp;
|
||||
}).toList();
|
||||
|
||||
// If no custom profiles exist, add the default "Custom" one
|
||||
if (customApps.isEmpty) {
|
||||
customApps.add(CustomApp());
|
||||
}
|
||||
|
||||
|
||||
return [...baseApps, ...customApps];
|
||||
}
|
||||
|
||||
@@ -182,7 +183,10 @@ ${it.firmwareVersion != null ? ' - Firmware Version: ${it.firmwareVersion}' : ''
|
||||
children: [
|
||||
Flex(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
MediaQuery.sizeOf(context).width > 600
|
||||
? CrossAxisAlignment.center
|
||||
: CrossAxisAlignment.start,
|
||||
direction: MediaQuery.sizeOf(context).width > 600 ? Axis.horizontal : Axis.vertical,
|
||||
spacing: 8,
|
||||
children: [
|
||||
@@ -215,156 +219,151 @@ ${it.firmwareVersion != null ? ' - Firmware Version: ${it.firmwareVersion}' : ''
|
||||
hintText: 'Select your Keymap',
|
||||
),
|
||||
|
||||
if (actionHandler.supportedApp != null)
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (actionHandler.supportedApp! is! CustomApp) {
|
||||
final customApp = CustomApp();
|
||||
Row(
|
||||
children: [
|
||||
if (actionHandler.supportedApp != null)
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
if (actionHandler.supportedApp! is! CustomApp) {
|
||||
final customApp = CustomApp();
|
||||
|
||||
final connectedDevice = connection.devices.firstOrNull;
|
||||
actionHandler.supportedApp!.keymap.keyPairs.forEachIndexed((pair, index) {
|
||||
pair.buttons
|
||||
.filter(
|
||||
(button) => connectedDevice?.availableButtons.contains(button) == true,
|
||||
)
|
||||
.forEachIndexed((button, indexB) {
|
||||
customApp.setKey(
|
||||
button,
|
||||
physicalKey: pair.physicalKey!,
|
||||
logicalKey: pair.logicalKey,
|
||||
isLongPress: pair.isLongPress,
|
||||
touchPosition:
|
||||
pair.touchPosition != Offset.zero
|
||||
? pair.touchPosition
|
||||
: Offset(((indexB + 1)) * 100, 200 + (index * 100)),
|
||||
);
|
||||
});
|
||||
});
|
||||
final connectedDevice = connection.devices.firstOrNull;
|
||||
actionHandler.supportedApp!.keymap.keyPairs.forEachIndexed((pair, index) {
|
||||
pair.buttons
|
||||
.filter(
|
||||
(button) =>
|
||||
connectedDevice?.availableButtons.contains(button) == true,
|
||||
)
|
||||
.forEachIndexed((button, indexB) {
|
||||
customApp.setKey(
|
||||
button,
|
||||
physicalKey: pair.physicalKey!,
|
||||
logicalKey: pair.logicalKey,
|
||||
isLongPress: pair.isLongPress,
|
||||
touchPosition:
|
||||
pair.touchPosition != Offset.zero
|
||||
? pair.touchPosition
|
||||
: Offset(((indexB + 1)) * 100, 200 + (index * 100)),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
actionHandler.supportedApp = customApp;
|
||||
await settings.setApp(customApp);
|
||||
}
|
||||
final result = await Navigator.of(
|
||||
context,
|
||||
).push<bool>(MaterialPageRoute(builder: (_) => TouchAreaSetupPage()));
|
||||
|
||||
if (result == true && actionHandler.supportedApp is CustomApp) {
|
||||
await settings.setApp(actionHandler.supportedApp!);
|
||||
}
|
||||
setState(() {});
|
||||
},
|
||||
child: Text('Customize Keymap'),
|
||||
),
|
||||
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
final profileName = await _showNewProfileDialog();
|
||||
if (profileName != null && profileName.isNotEmpty) {
|
||||
final customApp = CustomApp(profileName: profileName);
|
||||
actionHandler.supportedApp = customApp;
|
||||
await settings.setApp(customApp);
|
||||
controller.text = profileName;
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
child: Text('New Custom Profile'),
|
||||
),
|
||||
|
||||
if (actionHandler.supportedApp is CustomApp)
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
final currentProfile = (actionHandler.supportedApp as CustomApp).profileName;
|
||||
final action = await _showManageProfileDialog(currentProfile);
|
||||
if (action != null) {
|
||||
if (action == 'rename') {
|
||||
final newName = await _showRenameProfileDialog(currentProfile);
|
||||
if (newName != null && newName.isNotEmpty && newName != currentProfile) {
|
||||
await settings.duplicateCustomAppProfile(currentProfile, newName);
|
||||
await settings.deleteCustomAppProfile(currentProfile);
|
||||
final customApp = CustomApp(profileName: newName);
|
||||
final savedKeymap = settings.getCustomAppKeymap(newName);
|
||||
if (savedKeymap != null) {
|
||||
customApp.decodeKeymap(savedKeymap);
|
||||
}
|
||||
actionHandler.supportedApp = customApp;
|
||||
await settings.setApp(customApp);
|
||||
controller.text = newName;
|
||||
setState(() {});
|
||||
}
|
||||
} else if (action == 'duplicate') {
|
||||
final newName = await _showDuplicateProfileDialog(currentProfile);
|
||||
if (newName != null && newName.isNotEmpty) {
|
||||
await settings.duplicateCustomAppProfile(currentProfile, newName);
|
||||
final customApp = CustomApp(profileName: newName);
|
||||
final savedKeymap = settings.getCustomAppKeymap(newName);
|
||||
if (savedKeymap != null) {
|
||||
customApp.decodeKeymap(savedKeymap);
|
||||
}
|
||||
actionHandler.supportedApp = customApp;
|
||||
await settings.setApp(customApp);
|
||||
controller.text = newName;
|
||||
setState(() {});
|
||||
final result = await Navigator.of(
|
||||
context,
|
||||
).push<bool>(MaterialPageRoute(builder: (_) => TouchAreaSetupPage()));
|
||||
|
||||
if (result == true && actionHandler.supportedApp is CustomApp) {
|
||||
await settings.setApp(actionHandler.supportedApp!);
|
||||
}
|
||||
} else if (action == 'delete') {
|
||||
final confirmed = await _showDeleteConfirmDialog(currentProfile);
|
||||
if (confirmed == true) {
|
||||
await settings.deleteCustomAppProfile(currentProfile);
|
||||
controller.text = '';
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
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,
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: Icon(Icons.edit),
|
||||
),
|
||||
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
final profileName = await _showNewProfileDialog();
|
||||
if (profileName != null && profileName.isNotEmpty) {
|
||||
final customApp = CustomApp(profileName: profileName);
|
||||
actionHandler.supportedApp = customApp;
|
||||
await settings.setApp(customApp);
|
||||
controller.text = profileName;
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Text('Import Profile'),
|
||||
},
|
||||
icon: Icon(Icons.add),
|
||||
),
|
||||
|
||||
if (actionHandler.supportedApp is CustomApp)
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
final currentProfile = (actionHandler.supportedApp as CustomApp).profileName;
|
||||
final action = await _showManageProfileDialog(currentProfile);
|
||||
if (action != null) {
|
||||
if (action == 'rename') {
|
||||
final newName = await _showRenameProfileDialog(currentProfile);
|
||||
if (newName != null && newName.isNotEmpty && newName != currentProfile) {
|
||||
await settings.duplicateCustomAppProfile(currentProfile, newName);
|
||||
await settings.deleteCustomAppProfile(currentProfile);
|
||||
final customApp = CustomApp(profileName: newName);
|
||||
final savedKeymap = settings.getCustomAppKeymap(newName);
|
||||
if (savedKeymap != null) {
|
||||
customApp.decodeKeymap(savedKeymap);
|
||||
}
|
||||
actionHandler.supportedApp = customApp;
|
||||
await settings.setApp(customApp);
|
||||
controller.text = newName;
|
||||
setState(() {});
|
||||
}
|
||||
} else if (action == 'duplicate') {
|
||||
final newName = await _showDuplicateProfileDialog(currentProfile);
|
||||
if (newName != null && newName.isNotEmpty) {
|
||||
await settings.duplicateCustomAppProfile(currentProfile, newName);
|
||||
final customApp = CustomApp(profileName: newName);
|
||||
final savedKeymap = settings.getCustomAppKeymap(newName);
|
||||
if (savedKeymap != null) {
|
||||
customApp.decodeKeymap(savedKeymap);
|
||||
}
|
||||
actionHandler.supportedApp = customApp;
|
||||
await settings.setApp(customApp);
|
||||
controller.text = newName;
|
||||
setState(() {});
|
||||
}
|
||||
} else if (action == 'delete') {
|
||||
final confirmed = await _showDeleteConfirmDialog(currentProfile);
|
||||
if (confirmed == true) {
|
||||
await settings.deleteCustomAppProfile(currentProfile);
|
||||
controller.text = '';
|
||||
setState(() {});
|
||||
}
|
||||
} else if (action == 'import') {
|
||||
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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (action == 'export') {
|
||||
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),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
icon: Icon(Icons.more_vert),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -412,148 +411,130 @@ ${it.firmwareVersion != null ? ' - Firmware Version: ${it.firmwareVersion}' : ''
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Future<String?> _showNewProfileDialog() async {
|
||||
final controller = TextEditingController();
|
||||
return showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('New Custom Profile'),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Profile Name',
|
||||
hintText: 'e.g., Workout, Race, Event',
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: Text('New Custom Profile'),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(labelText: 'Profile Name', hintText: 'e.g., Workout, Race, Event'),
|
||||
autofocus: true,
|
||||
),
|
||||
actions: [
|
||||
TextButton(onPressed: () => Navigator.pop(context), child: Text('Cancel')),
|
||||
TextButton(onPressed: () => Navigator.pop(context, controller.text), child: Text('Create')),
|
||||
],
|
||||
),
|
||||
autofocus: true,
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text('Cancel'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, controller.text),
|
||||
child: Text('Create'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Future<String?> _showManageProfileDialog(String currentProfile) async {
|
||||
return showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('Manage Profile: $currentProfile'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
leading: Icon(Icons.edit),
|
||||
title: Text('Rename'),
|
||||
onTap: () => Navigator.pop(context, 'rename'),
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: Text('Manage Profile: $currentProfile'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
leading: Icon(Icons.edit),
|
||||
title: Text('Rename'),
|
||||
onTap: () => Navigator.pop(context, 'rename'),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.copy),
|
||||
title: Text('Duplicate'),
|
||||
onTap: () => Navigator.pop(context, 'duplicate'),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.file_upload),
|
||||
title: Text('Import'),
|
||||
onTap: () => Navigator.pop(context, 'import'),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.share),
|
||||
title: Text('Export'),
|
||||
onTap: () => Navigator.pop(context, 'export'),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.delete, color: Theme.of(context).colorScheme.error),
|
||||
title: Text('Delete', style: TextStyle(color: Theme.of(context).colorScheme.error)),
|
||||
onTap: () => Navigator.pop(context, 'delete'),
|
||||
),
|
||||
],
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.copy),
|
||||
title: Text('Duplicate'),
|
||||
onTap: () => Navigator.pop(context, 'duplicate'),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.delete),
|
||||
title: Text('Delete'),
|
||||
onTap: () => Navigator.pop(context, 'delete'),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text('Cancel'),
|
||||
actions: [TextButton(onPressed: () => Navigator.pop(context), child: Text('Cancel'))],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Future<String?> _showRenameProfileDialog(String currentName) async {
|
||||
final controller = TextEditingController(text: currentName);
|
||||
return showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('Rename Profile'),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Profile Name',
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: Text('Rename Profile'),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(labelText: 'Profile Name'),
|
||||
autofocus: true,
|
||||
),
|
||||
actions: [
|
||||
TextButton(onPressed: () => Navigator.pop(context), child: Text('Cancel')),
|
||||
TextButton(onPressed: () => Navigator.pop(context, controller.text), child: Text('Rename')),
|
||||
],
|
||||
),
|
||||
autofocus: true,
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text('Cancel'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, controller.text),
|
||||
child: Text('Rename'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Future<String?> _showDuplicateProfileDialog(String currentName) async {
|
||||
final controller = TextEditingController(text: '$currentName (Copy)');
|
||||
return showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('Duplicate Profile'),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'New Profile Name',
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: Text('Duplicate Profile'),
|
||||
content: TextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(labelText: 'New Profile Name'),
|
||||
autofocus: true,
|
||||
),
|
||||
actions: [
|
||||
TextButton(onPressed: () => Navigator.pop(context), child: Text('Cancel')),
|
||||
TextButton(onPressed: () => Navigator.pop(context, controller.text), child: Text('Duplicate')),
|
||||
],
|
||||
),
|
||||
autofocus: true,
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text('Cancel'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, controller.text),
|
||||
child: Text('Duplicate'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Future<bool?> _showDeleteConfirmDialog(String profileName) async {
|
||||
return showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('Delete Profile'),
|
||||
content: Text('Are you sure you want to delete "$profileName"? This action cannot be undone.'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
child: Text('Cancel'),
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: Text('Delete Profile'),
|
||||
content: Text('Are you sure you want to delete "$profileName"? This action cannot be undone.'),
|
||||
actions: [
|
||||
TextButton(onPressed: () => Navigator.pop(context, false), child: Text('Cancel')),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
child: Text('Delete'),
|
||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
child: Text('Delete'),
|
||||
style: TextButton.styleFrom(foregroundColor: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Future<String?> _showImportDialog() async {
|
||||
final controller = TextEditingController();
|
||||
|
||||
|
||||
// Try to get data from clipboard
|
||||
try {
|
||||
final clipboardData = await Clipboard.getData('text/plain');
|
||||
@@ -563,38 +544,30 @@ ${it.firmwareVersion != null ? ' - Firmware Version: ${it.firmwareVersion}' : ''
|
||||
} 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,
|
||||
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'),
|
||||
actions: [
|
||||
TextButton(onPressed: () => Navigator.pop(context), child: Text('Cancel')),
|
||||
TextButton(onPressed: () => Navigator.pop(context, controller.text), child: Text('Import')),
|
||||
],
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, controller.text),
|
||||
child: Text('Import'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user