mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-08-17 16:37:31 +02:00
doesnt really work, probably abandon, saving because sunk cost
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import '../dev_config.dart';
|
||||
|
||||
class DeveloperSettingsScreen extends StatefulWidget {
|
||||
const DeveloperSettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
State<DeveloperSettingsScreen> createState() => _DeveloperSettingsScreenState();
|
||||
}
|
||||
|
||||
class _DeveloperSettingsScreenState extends State<DeveloperSettingsScreen> {
|
||||
final Map<String, TextEditingController> _controllers = {};
|
||||
final Map<String, dynamic> _overrides = {};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initializeControllers();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
for (final controller in _controllers.values) {
|
||||
controller.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _initializeControllers() {
|
||||
for (final entry in devConfigForSettings.entries) {
|
||||
if (entry.value is String) {
|
||||
_controllers[entry.key] = TextEditingController(text: entry.value);
|
||||
} else if (entry.value is int) {
|
||||
_controllers[entry.key] = TextEditingController(text: entry.value.toString());
|
||||
} else if (entry.value is double) {
|
||||
_controllers[entry.key] = TextEditingController(text: entry.value.toString());
|
||||
} else if (entry.value is Color) {
|
||||
final color = entry.value as Color;
|
||||
final hex = color.value.toRadixString(16).padLeft(8, '0').toUpperCase();
|
||||
_controllers[entry.key] = TextEditingController(text: hex);
|
||||
} else if (entry.value is Duration) {
|
||||
final duration = entry.value as Duration;
|
||||
_controllers[entry.key] = TextEditingController(text: duration.inMilliseconds.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _saveAndRestart() {
|
||||
// For now, just show a dialog - actual restart would require platform channels
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Restart Required'),
|
||||
content: const Text('Changes saved. Please restart the app to apply new settings.'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSettingWidget(String key, dynamic defaultValue) {
|
||||
if (key == 'kClientName') {
|
||||
// Special read-only case
|
||||
return ListTile(
|
||||
title: Text(key),
|
||||
subtitle: Text(defaultValue.toString()),
|
||||
trailing: const Text('READ ONLY'),
|
||||
);
|
||||
}
|
||||
|
||||
if (defaultValue is bool) {
|
||||
return SwitchListTile(
|
||||
title: Text(key),
|
||||
value: _overrides[key] ?? defaultValue,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_overrides[key] = value;
|
||||
});
|
||||
},
|
||||
);
|
||||
} else if (defaultValue is int || defaultValue is double || defaultValue is String ||
|
||||
defaultValue is Color || defaultValue is Duration) {
|
||||
return ListTile(
|
||||
title: Text(key),
|
||||
subtitle: TextField(
|
||||
controller: _controllers[key],
|
||||
keyboardType: defaultValue is int || defaultValue is double
|
||||
? const TextInputType.numberWithOptions(signed: true, decimal: true)
|
||||
: TextInputType.text,
|
||||
textInputAction: TextInputAction.done,
|
||||
onChanged: (value) {
|
||||
// Store the string value for now - actual parsing would happen on save
|
||||
_overrides[key] = value;
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Developer Settings'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: _saveAndRestart,
|
||||
child: const Text('SAVE', style: TextStyle(color: Colors.white)),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: devConfigForSettings.entries
|
||||
.map((entry) => _buildSettingWidget(entry.key, entry.value))
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -713,7 +713,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
final safeArea = MediaQuery.of(context).padding;
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
bottom: safeArea.bottom + kBottomButtonBarOffset,
|
||||
bottom: safeArea.bottom + dev.kBottomButtonBarOffset,
|
||||
left: leftPositionWithSafeArea(8, safeArea),
|
||||
right: rightPositionWithSafeArea(8, safeArea),
|
||||
),
|
||||
@@ -731,7 +731,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
||||
)
|
||||
],
|
||||
),
|
||||
margin: EdgeInsets.only(bottom: kBottomButtonBarOffset),
|
||||
margin: EdgeInsets.only(bottom: dev.kBottomButtonBarOffset),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
||||
child: Row(
|
||||
children: [
|
||||
|
||||
@@ -117,7 +117,7 @@ class OSMAccountScreen extends StatelessWidget {
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Upload Mode Section (only show in development builds)
|
||||
if (kEnableDevelopmentModes) ...[
|
||||
if (dev.kEnableDevelopmentModes) ...[
|
||||
Card(
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
|
||||
@@ -1,11 +1,41 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../services/localization_service.dart';
|
||||
import '../services/version_service.dart';
|
||||
import '../dev_config.dart';
|
||||
|
||||
class SettingsScreen extends StatelessWidget {
|
||||
class SettingsScreen extends StatefulWidget {
|
||||
const SettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
State<SettingsScreen> createState() => _SettingsScreenState();
|
||||
}
|
||||
|
||||
class _SettingsScreenState extends State<SettingsScreen> {
|
||||
int _versionTapCount = 0;
|
||||
Timer? _tapTimer;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_tapTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onVersionTap() {
|
||||
_tapTimer?.cancel();
|
||||
_versionTapCount++;
|
||||
|
||||
if (_versionTapCount >= 10) {
|
||||
Navigator.pushNamed(context, '/settings/developer');
|
||||
_versionTapCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
_tapTimer = Timer(const Duration(milliseconds: 400), () {
|
||||
_versionTapCount = 0;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final locService = LocalizationService.instance;
|
||||
@@ -100,15 +130,18 @@ class SettingsScreen extends StatelessWidget {
|
||||
),
|
||||
const Divider(),
|
||||
|
||||
// Version display
|
||||
// Version display with secret tap counter
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Text(
|
||||
'Version: ${VersionService().version}',
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Theme.of(context).textTheme.bodySmall?.color?.withOpacity(0.6),
|
||||
child: GestureDetector(
|
||||
onTap: _onVersionTap,
|
||||
child: Text(
|
||||
'Version: ${VersionService().version}',
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Theme.of(context).textTheme.bodySmall?.color?.withOpacity(0.6),
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -345,7 +345,7 @@ class _TileTypeDialogState extends State<_TileTypeDialog> {
|
||||
if (value?.trim().isEmpty == true) return locService.t('tileTypeEditor.maxZoomRequired');
|
||||
final zoom = int.tryParse(value!);
|
||||
if (zoom == null) return locService.t('tileTypeEditor.maxZoomInvalid');
|
||||
if (zoom < 1 || zoom > kAbsoluteMaxZoom) return locService.t('tileTypeEditor.maxZoomRange', params: ['1', kAbsoluteMaxZoom.toString()]);
|
||||
if (zoom < 1 || zoom > dev.kAbsoluteMaxZoom) return locService.t('tileTypeEditor.maxZoomRange', params: ['1', kAbsoluteMaxZoom.toString()]);
|
||||
return null;
|
||||
},
|
||||
),
|
||||
@@ -405,9 +405,9 @@ class _TileTypeDialogState extends State<_TileTypeDialog> {
|
||||
try {
|
||||
// Use a sample tile from configured preview location
|
||||
final url = _urlController.text
|
||||
.replaceAll('{z}', kPreviewTileZoom.toString())
|
||||
.replaceAll('{x}', kPreviewTileX.toString())
|
||||
.replaceAll('{y}', kPreviewTileY.toString());
|
||||
.replaceAll('{z}', dev.kPreviewTileZoom.toString())
|
||||
.replaceAll('{x}', dev.kPreviewTileX.toString())
|
||||
.replaceAll('{y}', dev.kPreviewTileY.toString());
|
||||
|
||||
final response = await http.get(Uri.parse(url));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user