aves_mio1/lib/widgets/dialogs/map/style_editor_dialog.dart
FabioMich66 19a982ede6
Some checks are pending
Quality check / Flutter analysis (push) Waiting to run
Quality check / CodeQL analysis (java-kotlin) (push) Waiting to run
first commit
2026-03-05 15:51:30 +01:00

146 lines
4.6 KiB
Dart

import 'package:aves/model/settings/settings.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/dialogs/aves_dialog.dart';
import 'package:aves_map/aves_map.dart';
import 'package:flutter/material.dart';
class MapStyleEditorDialog extends StatefulWidget {
static const routeName = '/dialog/map_style_editor';
final EntryMapStyle? initialValue;
const MapStyleEditorDialog({
super.key,
this.initialValue,
});
@override
State<MapStyleEditorDialog> createState() => _MapStyleEditorDialogState();
}
class _MapStyleEditorDialogState extends State<MapStyleEditorDialog> {
late final Set<EntryMapStyle> _otherCustomStyles;
final TextEditingController _nameController = TextEditingController();
final TextEditingController _urlController = TextEditingController();
final TextEditingController _subdomainsController = TextEditingController();
final TextEditingController _userAgentController = TextEditingController();
final ValueNotifier<bool> _isValidNotifier = ValueNotifier(false);
@override
void initState() {
super.initState();
final initialValue = widget.initialValue;
_otherCustomStyles = settings.customMapStyles.where((v) => v != initialValue).toSet();
_nameController.text = initialValue?.name ?? '';
_urlController.text = initialValue?.url ?? '';
_subdomainsController.text = initialValue?.subdomains.join(',') ?? '';
_userAgentController.text = initialValue?.userAgent ?? '';
_validate();
}
@override
void dispose() {
_nameController.dispose();
_urlController.dispose();
_subdomainsController.dispose();
_userAgentController.dispose();
_isValidNotifier.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final l10n = context.l10n;
return AvesDialog(
scrollableContent: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: TextField(
controller: _nameController,
decoration: InputDecoration(
labelText: l10n.mapStyleEditorDialogName,
),
autofocus: true,
onChanged: (_) => _validate(),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: TextField(
controller: _urlController,
decoration: InputDecoration(
labelText: l10n.mapStyleEditorDialogUrl,
),
keyboardType: TextInputType.url,
onChanged: (_) => _validate(),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: TextField(
controller: _subdomainsController,
decoration: InputDecoration(
labelText: l10n.mapStyleEditorDialogSubdomains,
),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: TextField(
controller: _userAgentController,
decoration: InputDecoration(
labelText: l10n.mapStyleEditorDialogUserAgent,
),
),
),
],
actions: [
const CancelButton(),
ValueListenableBuilder<bool>(
valueListenable: _isValidNotifier,
builder: (context, isValid, child) {
return TextButton(
onPressed: isValid ? () => _submit(context) : null,
child: Text(widget.initialValue != null ? l10n.applyButtonLabel : l10n.createButtonLabel),
);
},
),
],
);
}
EntryMapStyle _buildStyle() {
final name = _nameController.text.trim();
final url = _urlController.text.trim();
final subdomains = _subdomainsController.text.split(',').map((v) => v.trim()).toList();
final userAgent = _userAgentController.text.trim();
return EntryMapStyle(
key: 'custom_$name',
name: name,
url: url,
subdomains: subdomains,
userAgent: userAgent.isNotEmpty ? userAgent : null,
);
}
Future<void> _validate() async {
final style = _buildStyle();
final name = style.name ?? '';
final url = style.url ?? '';
if (name.isEmpty || url.isEmpty) {
_isValidNotifier.value = false;
return;
}
final key = style.key;
final duplicate = _otherCustomStyles.any((v) => v.key == key || v.url == url);
_isValidNotifier.value = !duplicate;
}
void _submit(BuildContext context) {
if (_isValidNotifier.value) {
Navigator.maybeOf(context)?.pop<EntryMapStyle>(_buildStyle());
}
}
}