fix user bang ui

This commit is contained in:
Fabian Freund
2026-07-10 04:59:48 +02:00
parent 9547169d99
commit 153f07f28e
@@ -22,7 +22,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:nullability/nullability.dart';
import 'package:weblibre/features/bangs/data/models/bang.dart'; import 'package:weblibre/features/bangs/data/models/bang.dart';
import 'package:weblibre/features/bangs/data/models/bang_group.dart'; import 'package:weblibre/features/bangs/data/models/bang_group.dart';
import 'package:weblibre/features/bangs/data/models/bang_key.dart'; import 'package:weblibre/features/bangs/data/models/bang_key.dart';
@@ -56,7 +55,22 @@ class EditBangScreen extends HookConsumerWidget {
final category = useState(initialBang?.category); final category = useState(initialBang?.category);
final subCategory = useState(initialBang?.subCategory); final subCategory = useState(initialBang?.subCategory);
final formatFlags = useState(initialBang?.format); final formatFlags = useState(
initialBang?.format ??
{BangFormat.urlEncodePlaceholder, BangFormat.urlEncodeSpaceToPlus},
);
void updateFormatFlag(BangFormat flag, bool enabled) {
final flags = {...formatFlags.value};
if (enabled) {
flags.add(flag);
} else {
flags.remove(flag);
}
formatFlags.value = flags;
}
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
@@ -65,14 +79,13 @@ class EditBangScreen extends HookConsumerWidget {
IconButton( IconButton(
onPressed: () async { onPressed: () async {
if (formKey.currentState?.validate() ?? false) { if (formKey.currentState?.validate() ?? false) {
final name = nameTextController.text.trim();
final trigger = triggerTextController.text.trim();
final urlTemplate = urlTextController.text.trim();
final existingBang = await ref final existingBang = await ref
.read(bangDataRepositoryProvider.notifier) .read(bangDataRepositoryProvider.notifier)
.getBang( .getBang(BangKey(group: BangGroup.user, trigger: trigger));
BangKey(
group: BangGroup.user,
trigger: triggerTextController.text,
),
);
if ((initialBang == null && existingBang != null) || if ((initialBang == null && existingBang != null) ||
(initialBang != null && (initialBang != null &&
@@ -81,7 +94,7 @@ class EditBangScreen extends HookConsumerWidget {
if (context.mounted) { if (context.mounted) {
ui_helper.showErrorMessage( ui_helper.showErrorMessage(
context, context,
'A Bang with Trigger "${triggerTextController.text}" does already exist', 'A Bang with Trigger "$trigger" does already exist',
); );
} }
@@ -89,7 +102,7 @@ class EditBangScreen extends HookConsumerWidget {
} }
final uri = parseValidatedUrl( final uri = parseValidatedUrl(
urlTextController.text, urlTemplate,
eagerParsing: false, eagerParsing: false,
onlyHttpProtocol: true, onlyHttpProtocol: true,
); );
@@ -99,18 +112,16 @@ class EditBangScreen extends HookConsumerWidget {
final bang = Bang( final bang = Bang(
group: BangGroup.user, group: BangGroup.user,
trigger: triggerTextController.text, trigger: trigger,
websiteName: nameTextController.text, websiteName: name,
domain: uri.host, domain: uri.host,
urlTemplate: urlTextController.text, urlTemplate: urlTemplate,
searxngApi: false, searxngApi: false,
category: category.value, category: category.value,
subCategory: subCategory.value, subCategory: subCategory.value,
additionalTriggers: initialBang?.additionalTriggers, additionalTriggers: initialBang?.additionalTriggers,
snapDomain: initialBang?.snapDomain, snapDomain: initialBang?.snapDomain,
format: formatFlags.value.isNotEmpty format: formatFlags.value,
? formatFlags.value
: null,
); );
if (initialBang != null && if (initialBang != null &&
@@ -155,7 +166,7 @@ class EditBangScreen extends HookConsumerWidget {
), ),
floatingLabelBehavior: FloatingLabelBehavior.always, floatingLabelBehavior: FloatingLabelBehavior.always,
), ),
validator: validateRequired, validator: (value) => validateRequired(value?.trim()),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
TextFormField( TextFormField(
@@ -167,7 +178,7 @@ class EditBangScreen extends HookConsumerWidget {
), ),
floatingLabelBehavior: FloatingLabelBehavior.always, floatingLabelBehavior: FloatingLabelBehavior.always,
), ),
validator: validateRequired, validator: (value) => validateRequired(value?.trim()),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
TextFormField( TextFormField(
@@ -181,12 +192,14 @@ class EditBangScreen extends HookConsumerWidget {
floatingLabelBehavior: FloatingLabelBehavior.always, floatingLabelBehavior: FloatingLabelBehavior.always,
), ),
validator: (value) { validator: (value) {
if (value?.contains('{{{s}}}') != true) { final urlTemplate = value?.trim();
if (urlTemplate?.contains('{{{s}}}') != true) {
return 'Must contain the query placeholder {{{s}}}'; return 'Must contain the query placeholder {{{s}}}';
} }
return validateUrl( return validateUrl(
value, urlTemplate,
eagerParsing: false, eagerParsing: false,
onlyHttpProtocol: true, onlyHttpProtocol: true,
); );
@@ -237,69 +250,45 @@ class EditBangScreen extends HookConsumerWidget {
Text('Flags', style: Theme.of(context).textTheme.labelMedium), Text('Flags', style: Theme.of(context).textTheme.labelMedium),
const SizedBox(height: 4), const SizedBox(height: 4),
CheckboxListTile( CheckboxListTile(
value: contentPadding: EdgeInsets.zero,
formatFlags.value?.contains(BangFormat.openBasePath) ?? value: formatFlags.value.contains(BangFormat.openBasePath),
false,
title: const Text('Open Base Path'), title: const Text('Open Base Path'),
subtitle: const Text( subtitle: const Text(
'When the bang is invoked with no query, opens the base path of the URL (/) instead of any path given in the template (g., /search)', 'When the bang is invoked with no query, opens the base path of the URL (/) instead of any path given in the template (g., /search)',
), ),
onChanged: (value) { onChanged: (value) {
if (value != null) { if (value != null) {
formatFlags.value = updateFormatFlag(BangFormat.openBasePath, value);
value
? {
...?formatFlags.value,
BangFormat.openBasePath,
}
: {...?formatFlags.value}
..remove(BangFormat.openBasePath);
} }
}, },
), ),
CheckboxListTile( CheckboxListTile(
value: contentPadding: EdgeInsets.zero,
formatFlags.value?.contains( value: formatFlags.value.contains(
BangFormat.urlEncodePlaceholder, BangFormat.urlEncodePlaceholder,
) ?? ),
false,
title: const Text('URL Encode Placeholder'), title: const Text('URL Encode Placeholder'),
subtitle: const Text( subtitle: const Text(
'URL encode the search terms. Some sites do not work with this, so it can be disabled by omitting this.', 'URL encode the search terms. Some sites do not work with this, so it can be disabled by omitting this.',
), ),
onChanged: (value) { onChanged: (value) {
if (value != null) { if (value != null) {
formatFlags.value = updateFormatFlag(BangFormat.urlEncodePlaceholder, value);
value
? {
...?formatFlags.value,
BangFormat.urlEncodePlaceholder,
}
: {...?formatFlags.value}
..remove(BangFormat.urlEncodePlaceholder);
} }
}, },
), ),
CheckboxListTile( CheckboxListTile(
value: contentPadding: EdgeInsets.zero,
formatFlags.value?.contains( value: formatFlags.value.contains(
BangFormat.urlEncodeSpaceToPlus, BangFormat.urlEncodeSpaceToPlus,
) ?? ),
false,
title: const Text('URL Encode Space to Plus'), title: const Text('URL Encode Space to Plus'),
subtitle: const Text( subtitle: const Text(
'URL encodes spaces as +, instead of %20. Some sites only work correctly with one or the other.', 'URL encodes spaces as +, instead of %20. Some sites only work correctly with one or the other.',
), ),
onChanged: (value) { onChanged: (value) {
if (value != null) { if (value != null) {
formatFlags.value = updateFormatFlag(BangFormat.urlEncodeSpaceToPlus, value);
value
? {
...?formatFlags.value,
BangFormat.urlEncodeSpaceToPlus,
}
: {...?formatFlags.value}
..remove(BangFormat.urlEncodeSpaceToPlus);
} }
}, },
), ),