diff --git a/apps/weblibre/lib/features/geckoview/features/search/domain/providers/engine_suggestions.dart b/apps/weblibre/lib/features/geckoview/features/search/domain/providers/engine_suggestions.dart index 40894a0a..55726839 100644 --- a/apps/weblibre/lib/features/geckoview/features/search/domain/providers/engine_suggestions.dart +++ b/apps/weblibre/lib/features/geckoview/features/search/domain/providers/engine_suggestions.dart @@ -34,7 +34,8 @@ class EngineSuggestions extends _$EngineSuggestions { /// autocomplete (history/top-domains); when that yields nothing, falls back /// to a popular-domain prefix match from the bundled Tranco-derived /// `sites.db` so typing "git" still completes to "github.com" without any - /// local history. + /// local history. The fallback can be turned off via the + /// `popularSitesAutocompleteEnabled` setting. Future getAutocompleteSuggestion(String query) async { final engineResult = await ref .read(engineSuggestionsServiceProvider) @@ -47,6 +48,16 @@ class EngineSuggestions extends _$EngineSuggestions { if (!ref.mounted) return null; + final popularSitesEnabled = ref.read( + generalSettingsWithDefaultsProvider.select( + (s) => s.popularSitesAutocompleteEnabled, + ), + ); + + if (!popularSitesEnabled) { + return null; + } + final popularSites = await ref .read(popularSitesRepositoryProvider.notifier) .searchByPrefix(query, limit: 1); diff --git a/apps/weblibre/lib/features/geckoview/features/search/domain/providers/engine_suggestions.g.dart b/apps/weblibre/lib/features/geckoview/features/search/domain/providers/engine_suggestions.g.dart index 3da37f6f..2b7d1498 100644 --- a/apps/weblibre/lib/features/geckoview/features/search/domain/providers/engine_suggestions.g.dart +++ b/apps/weblibre/lib/features/geckoview/features/search/domain/providers/engine_suggestions.g.dart @@ -33,7 +33,7 @@ final class EngineSuggestionsProvider EngineSuggestions create() => EngineSuggestions(); } -String _$engineSuggestionsHash() => r'4918e80a1e7dfb59fe67d0895e62a39f2704851f'; +String _$engineSuggestionsHash() => r'b2bc587d8df12b5614e2c00494a0d666e2c30746'; abstract class _$EngineSuggestions extends $StreamNotifier> { diff --git a/apps/weblibre/lib/features/settings/presentation/screens/search_settings.dart b/apps/weblibre/lib/features/settings/presentation/screens/search_settings.dart index 97e256bb..7fd284d8 100644 --- a/apps/weblibre/lib/features/settings/presentation/screens/search_settings.dart +++ b/apps/weblibre/lib/features/settings/presentation/screens/search_settings.dart @@ -90,6 +90,12 @@ const List searchSettingsSections = [ keywords: ['submit', 'keyboard', 'suggestions'], child: _AcceptSuggestionOnSubmitTile(), ), + SettingsEntryDefinition( + title: 'Popular site suggestions', + subtitle: 'Complete typed text with well-known domains', + keywords: ['popular sites', 'domains', 'ghost text', 'autocomplete'], + child: _PopularSitesAutocompleteTile(), + ), ], ), SettingsSectionDefinition( @@ -387,6 +393,36 @@ class _AcceptSuggestionOnSubmitTile extends HookConsumerWidget { } } +class _PopularSitesAutocompleteTile extends HookConsumerWidget { + const _PopularSitesAutocompleteTile(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final popularSitesAutocompleteEnabled = ref.watch( + generalSettingsWithDefaultsProvider.select( + (s) => s.popularSitesAutocompleteEnabled, + ), + ); + + return SwitchListTile.adaptive( + title: const Text('Popular site suggestions'), + subtitle: const Text( + 'Complete typed text with well-known domains when your history has no match', + ), + secondary: const Icon(MdiIcons.web), + value: popularSitesAutocompleteEnabled, + onChanged: (value) async { + await ref + .read(saveGeneralSettingsControllerProvider.notifier) + .save( + (currentSettings) => currentSettings.copyWith + .popularSitesAutocompleteEnabled(value), + ); + }, + ); + } +} + class _LocalIndexEnabledTile extends HookConsumerWidget { const _LocalIndexEnabledTile(); diff --git a/apps/weblibre/lib/features/user/data/models/general_settings.dart b/apps/weblibre/lib/features/user/data/models/general_settings.dart index 675830d4..2e55dd43 100644 --- a/apps/weblibre/lib/features/user/data/models/general_settings.dart +++ b/apps/weblibre/lib/features/user/data/models/general_settings.dart @@ -264,6 +264,11 @@ class GeneralSettings with FastEquatable { /// accept and complete an inline search suggestion. Defaults to false. final bool acceptSuggestionOnSubmit; + /// Whether the bundled Tranco-derived popular-domain list may supply the + /// omnibar's inline ghost-text completion when the engine's own autocomplete + /// (history/top domains) has no match. Defaults to true. + final bool popularSitesAutocompleteEnabled; + /// Whether dark mode should use pure-black ("OLED"/high-contrast) surfaces. /// Only takes effect when the effective brightness is dark. Defaults to false. final bool pureBlack; @@ -357,6 +362,7 @@ class GeneralSettings with FastEquatable { required this.enableLocalSearchIndex, required this.indexPrivateTabs, required this.acceptSuggestionOnSubmit, + required this.popularSitesAutocompleteEnabled, required this.pureBlack, required this.globalDesktopMode, required this.desktopModeSites, @@ -433,6 +439,7 @@ class GeneralSettings with FastEquatable { bool? enableLocalSearchIndex, bool? indexPrivateTabs, bool? acceptSuggestionOnSubmit, + bool? popularSitesAutocompleteEnabled, bool? pureBlack, bool? globalDesktopMode, List? desktopModeSites, @@ -520,6 +527,8 @@ class GeneralSettings with FastEquatable { enableLocalSearchIndex = enableLocalSearchIndex ?? true, indexPrivateTabs = indexPrivateTabs ?? false, acceptSuggestionOnSubmit = acceptSuggestionOnSubmit ?? true, + popularSitesAutocompleteEnabled = + popularSitesAutocompleteEnabled ?? true, pureBlack = pureBlack ?? false, globalDesktopMode = globalDesktopMode ?? false, desktopModeSites = desktopModeSites ?? const [], @@ -687,6 +696,7 @@ class GeneralSettings with FastEquatable { enableLocalSearchIndex, indexPrivateTabs, acceptSuggestionOnSubmit, + popularSitesAutocompleteEnabled, pureBlack, globalDesktopMode, desktopModeSites, diff --git a/apps/weblibre/lib/features/user/data/models/general_settings.g.dart b/apps/weblibre/lib/features/user/data/models/general_settings.g.dart index 47dea43c..b3dc1ea9 100644 --- a/apps/weblibre/lib/features/user/data/models/general_settings.g.dart +++ b/apps/weblibre/lib/features/user/data/models/general_settings.g.dart @@ -167,6 +167,10 @@ abstract class _$GeneralSettingsCWProxy { GeneralSettings acceptSuggestionOnSubmit(bool acceptSuggestionOnSubmit); + GeneralSettings popularSitesAutocompleteEnabled( + bool popularSitesAutocompleteEnabled, + ); + GeneralSettings pureBlack(bool pureBlack); GeneralSettings globalDesktopMode(bool globalDesktopMode); @@ -252,6 +256,7 @@ abstract class _$GeneralSettingsCWProxy { bool enableLocalSearchIndex, bool indexPrivateTabs, bool acceptSuggestionOnSubmit, + bool popularSitesAutocompleteEnabled, bool pureBlack, bool globalDesktopMode, List desktopModeSites, @@ -563,6 +568,11 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy { GeneralSettings acceptSuggestionOnSubmit(bool acceptSuggestionOnSubmit) => call(acceptSuggestionOnSubmit: acceptSuggestionOnSubmit); + @override + GeneralSettings popularSitesAutocompleteEnabled( + bool popularSitesAutocompleteEnabled, + ) => call(popularSitesAutocompleteEnabled: popularSitesAutocompleteEnabled); + @override GeneralSettings pureBlack(bool pureBlack) => call(pureBlack: pureBlack); @@ -658,6 +668,7 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy { Object? enableLocalSearchIndex = const $CopyWithPlaceholder(), Object? indexPrivateTabs = const $CopyWithPlaceholder(), Object? acceptSuggestionOnSubmit = const $CopyWithPlaceholder(), + Object? popularSitesAutocompleteEnabled = const $CopyWithPlaceholder(), Object? pureBlack = const $CopyWithPlaceholder(), Object? globalDesktopMode = const $CopyWithPlaceholder(), Object? desktopModeSites = const $CopyWithPlaceholder(), @@ -1068,6 +1079,12 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy { ? _value.acceptSuggestionOnSubmit // ignore: cast_nullable_to_non_nullable : acceptSuggestionOnSubmit as bool, + popularSitesAutocompleteEnabled: + popularSitesAutocompleteEnabled == const $CopyWithPlaceholder() || + popularSitesAutocompleteEnabled == null + ? _value.popularSitesAutocompleteEnabled + // ignore: cast_nullable_to_non_nullable + : popularSitesAutocompleteEnabled as bool, pureBlack: pureBlack == const $CopyWithPlaceholder() || pureBlack == null ? _value.pureBlack // ignore: cast_nullable_to_non_nullable @@ -1243,6 +1260,8 @@ GeneralSettings _$GeneralSettingsFromJson( enableLocalSearchIndex: json['enableLocalSearchIndex'] as bool?, indexPrivateTabs: json['indexPrivateTabs'] as bool?, acceptSuggestionOnSubmit: json['acceptSuggestionOnSubmit'] as bool?, + popularSitesAutocompleteEnabled: + json['popularSitesAutocompleteEnabled'] as bool?, pureBlack: json['pureBlack'] as bool?, globalDesktopMode: json['globalDesktopMode'] as bool?, desktopModeSites: (json['desktopModeSites'] as List?) @@ -1340,6 +1359,7 @@ Map _$GeneralSettingsToJson( 'enableLocalSearchIndex': instance.enableLocalSearchIndex, 'indexPrivateTabs': instance.indexPrivateTabs, 'acceptSuggestionOnSubmit': instance.acceptSuggestionOnSubmit, + 'popularSitesAutocompleteEnabled': instance.popularSitesAutocompleteEnabled, 'pureBlack': instance.pureBlack, 'globalDesktopMode': instance.globalDesktopMode, 'desktopModeSites': instance.desktopModeSites, diff --git a/apps/weblibre/lib/features/user/domain/repositories/general_settings.dart b/apps/weblibre/lib/features/user/domain/repositories/general_settings.dart index 6240b57f..85d10d13 100644 --- a/apps/weblibre/lib/features/user/domain/repositories/general_settings.dart +++ b/apps/weblibre/lib/features/user/domain/repositories/general_settings.dart @@ -112,6 +112,7 @@ const generalSettingColumnTypes = { 'enableLocalSearchIndex': DriftSqlType.bool, 'indexPrivateTabs': DriftSqlType.bool, 'acceptSuggestionOnSubmit': DriftSqlType.bool, + 'popularSitesAutocompleteEnabled': DriftSqlType.bool, 'pureBlack': DriftSqlType.bool, 'showSearchCloseButton': DriftSqlType.bool, 'homeTarget': DriftSqlType.string,