From 4b23ae3dba6c4232bcbabf4f751c0bef29bd6488 Mon Sep 17 00:00:00 2001 From: Fabian Freund Date: Mon, 22 Jul 2024 09:02:50 +0200 Subject: [PATCH] add setting for readability --- .../presentation/screens/browser.dart | 10 +++++- .../settings/data/models/settings.dart | 7 ++++- .../settings/data/models/settings.g.dart | 13 ++++++++ .../repositories/settings_repository.dart | 12 ++++++- .../repositories/settings_repository.g.dart | 2 +- .../presentation/screens/settings.dart | 13 ++++++++ .../services/readerability_script.dart | 31 +++++++++++++------ .../services/readerability_script.g.dart | 2 +- 8 files changed, 76 insertions(+), 14 deletions(-) diff --git a/app/lib/features/search_browser/presentation/screens/browser.dart b/app/lib/features/search_browser/presentation/screens/browser.dart index db381935..2d559717 100644 --- a/app/lib/features/search_browser/presentation/screens/browser.dart +++ b/app/lib/features/search_browser/presentation/screens/browser.dart @@ -191,6 +191,13 @@ class KagiScreen extends HookConsumerWidget { readerabilityControllerProvider(controller), ); + final enableReadability = ref.watch( + settingsRepositoryProvider.select( + (value) => (value.valueOrNull ?? Settings.withDefaults()) + .enableReadability, + ), + ); + final isReaderable = useValueListenable( activeWebView.isReaderable, ); @@ -213,7 +220,8 @@ class KagiScreen extends HookConsumerWidget { ); return Visibility( - visible: isReaderable == true || readerableApplied, + visible: enableReadability && + (isReaderable == true || readerableApplied), child: InkWell( onTap: readerabilityState.isLoading ? null diff --git a/app/lib/features/settings/data/models/settings.dart b/app/lib/features/settings/data/models/settings.dart index cc626380..926d39a0 100644 --- a/app/lib/features/settings/data/models/settings.dart +++ b/app/lib/features/settings/data/models/settings.dart @@ -19,6 +19,7 @@ class Settings with FastEquatable { final ThemeMode themeMode; final KagiTool? quickAction; final bool quickActionVoiceInput; + final bool enableReadability; Settings({ required this.kagiSession, @@ -32,6 +33,7 @@ class Settings with FastEquatable { required this.themeMode, required this.quickAction, required this.quickActionVoiceInput, + required this.enableReadability, }); Settings.withDefaults({ @@ -46,6 +48,7 @@ class Settings with FastEquatable { ThemeMode? themeMode, this.quickAction, bool? quickActionVoiceInput, + bool? enableReadability, }) : showEarlyAccessFeatures = showEarlyAccessFeatures ?? true, incognitoMode = incognitoMode ?? true, enableJavascript = enableJavascript ?? true, @@ -54,7 +57,8 @@ class Settings with FastEquatable { blockHttpProtocol = blockHttpProtocol ?? false, enableHostList = enableHostList ?? {HostSource.stevenBlackUnified}, themeMode = themeMode ?? ThemeMode.dark, - quickActionVoiceInput = quickActionVoiceInput ?? false; + quickActionVoiceInput = quickActionVoiceInput ?? false, + enableReadability = enableReadability ?? true; @override bool get cacheHash => true; @@ -72,5 +76,6 @@ class Settings with FastEquatable { themeMode, quickAction, quickActionVoiceInput, + enableReadability, ]; } diff --git a/app/lib/features/settings/data/models/settings.g.dart b/app/lib/features/settings/data/models/settings.g.dart index 156bfcf8..d42c970b 100644 --- a/app/lib/features/settings/data/models/settings.g.dart +++ b/app/lib/features/settings/data/models/settings.g.dart @@ -29,6 +29,8 @@ abstract class _$SettingsCWProxy { Settings quickActionVoiceInput(bool quickActionVoiceInput); + Settings enableReadability(bool enableReadability); + /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Settings(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. /// /// Usage @@ -47,6 +49,7 @@ abstract class _$SettingsCWProxy { ThemeMode? themeMode, KagiTool? quickAction, bool? quickActionVoiceInput, + bool? enableReadability, }); } @@ -97,6 +100,10 @@ class _$SettingsCWProxyImpl implements _$SettingsCWProxy { Settings quickActionVoiceInput(bool quickActionVoiceInput) => this(quickActionVoiceInput: quickActionVoiceInput); + @override + Settings enableReadability(bool enableReadability) => + this(enableReadability: enableReadability); + @override /// This function **does support** nullification of nullable fields. All `null` values passed to `non-nullable` fields will be ignored. You can also use `Settings(...).copyWith.fieldName(...)` to override fields one at a time with nullification support. @@ -117,6 +124,7 @@ class _$SettingsCWProxyImpl implements _$SettingsCWProxy { Object? themeMode = const $CopyWithPlaceholder(), Object? quickAction = const $CopyWithPlaceholder(), Object? quickActionVoiceInput = const $CopyWithPlaceholder(), + Object? enableReadability = const $CopyWithPlaceholder(), }) { return Settings( kagiSession: kagiSession == const $CopyWithPlaceholder() @@ -174,6 +182,11 @@ class _$SettingsCWProxyImpl implements _$SettingsCWProxy { ? _value.quickActionVoiceInput // ignore: cast_nullable_to_non_nullable : quickActionVoiceInput as bool, + enableReadability: enableReadability == const $CopyWithPlaceholder() || + enableReadability == null + ? _value.enableReadability + // ignore: cast_nullable_to_non_nullable + : enableReadability as bool, ); } } diff --git a/app/lib/features/settings/data/repositories/settings_repository.dart b/app/lib/features/settings/data/repositories/settings_repository.dart index 916cecb4..ee5eb132 100644 --- a/app/lib/features/settings/data/repositories/settings_repository.dart +++ b/app/lib/features/settings/data/repositories/settings_repository.dart @@ -20,7 +20,8 @@ enum _StorageKeys { enableHostList('enable_host_lists'), themeMode('theme_mode'), quickAction('enable_quick_action'), - quickActionVoiceInput('enable_quick_action_voice_input'); + quickActionVoiceInput('enable_quick_action_voice_input'), + enableReadability('enable_readability'); final String key; @@ -132,6 +133,13 @@ class SettingsRepository extends _$SettingsRepository { ); } + if (newSettings.enableReadability != oldSettings.enableReadability) { + await sharedPreferences.setBool( + _StorageKeys.enableReadability.key, + newSettings.enableReadability, + ); + } + ref.invalidateSelf(); } } @@ -162,6 +170,8 @@ class SettingsRepository extends _$SettingsRepository { parseKagiTool(sharedPreferences.getInt(_StorageKeys.quickAction.key)), quickActionVoiceInput: sharedPreferences.getBool(_StorageKeys.quickActionVoiceInput.key), + enableReadability: + sharedPreferences.getBool(_StorageKeys.enableReadability.key), ); } } diff --git a/app/lib/features/settings/data/repositories/settings_repository.g.dart b/app/lib/features/settings/data/repositories/settings_repository.g.dart index 38fbe235..1a88eb75 100644 --- a/app/lib/features/settings/data/repositories/settings_repository.g.dart +++ b/app/lib/features/settings/data/repositories/settings_repository.g.dart @@ -7,7 +7,7 @@ part of 'settings_repository.dart'; // ************************************************************************** String _$settingsRepositoryHash() => - r'34d3c771d6ebb17cb9aa41211e035b4d1cbf2183'; + r'f7c42efda64f0fb647e5daf0a92c2d118596cc52'; /// See also [SettingsRepository]. @ProviderFor(SettingsRepository) diff --git a/app/lib/features/settings/presentation/screens/settings.dart b/app/lib/features/settings/presentation/screens/settings.dart index acdf79bc..fa16627f 100644 --- a/app/lib/features/settings/presentation/screens/settings.dart +++ b/app/lib/features/settings/presentation/screens/settings.dart @@ -241,6 +241,19 @@ class SettingsScreen extends HookConsumerWidget { ); }, ), + SwitchListTile.adaptive( + title: const Text('Enable Reader Mode'), + subtitle: const Text( + 'Optional browser app bar tool that extracts and simplifies web pages for improved readability by removing ads, sidebars, and other non-essential elements.', + ), + value: settings.enableReadability, + onChanged: (value) async { + await ref.read(saveSettingsControllerProvider.notifier).save( + (currentSettings) => + currentSettings.copyWith.enableReadability(value), + ); + }, + ), const SizedBox( height: 16, ), diff --git a/app/lib/features/web_view/presentation/services/readerability_script.dart b/app/lib/features/web_view/presentation/services/readerability_script.dart index 0695dd2c..1e5c037a 100644 --- a/app/lib/features/web_view/presentation/services/readerability_script.dart +++ b/app/lib/features/web_view/presentation/services/readerability_script.dart @@ -1,3 +1,5 @@ +import 'package:bang_navigator/features/settings/data/models/settings.dart'; +import 'package:bang_navigator/features/settings/data/repositories/settings_repository.dart'; import 'package:bang_navigator/features/web_view/domain/providers.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; @@ -7,10 +9,17 @@ part 'readerability_script.g.dart'; @Riverpod() class ReaderabilityScriptService extends _$ReaderabilityScriptService { late Future _readerabilityScript; + late bool _enableReadability; @override Future build(InAppWebViewController? controller) async { _readerabilityScript = ref.watch(readerabilityScriptProvider.future); + _enableReadability = ref.watch( + settingsRepositoryProvider.select( + (value) => + (value.valueOrNull ?? Settings.withDefaults()).enableReadability, + ), + ); } Future _injectScript() async { @@ -20,7 +29,7 @@ class ReaderabilityScriptService extends _$ReaderabilityScriptService { } } - Future ensureScriptInjected() async { + Future _ensureScriptInjected() async { if (controller != null) { final injected = await controller!.evaluateJavascript( source: @@ -34,22 +43,26 @@ class ReaderabilityScriptService extends _$ReaderabilityScriptService { } Future isReaderable() async { - await ensureScriptInjected(); + if (_enableReadability) { + await _ensureScriptInjected(); - if (controller != null) { - return await controller!.evaluateJavascript( - source: 'isReaderable();', - ) as bool; + if (controller != null) { + return await controller!.evaluateJavascript( + source: 'isReaderable();', + ) as bool; + } } return false; } Future applyReaderable() async { - await ensureScriptInjected(); + if (_enableReadability) { + await _ensureScriptInjected(); - if (controller != null) { - await controller!.evaluateJavascript(source: 'applyReaderable();'); + if (controller != null) { + await controller!.evaluateJavascript(source: 'applyReaderable();'); + } } } } diff --git a/app/lib/features/web_view/presentation/services/readerability_script.g.dart b/app/lib/features/web_view/presentation/services/readerability_script.g.dart index 6a7ca54b..cb6a94ea 100644 --- a/app/lib/features/web_view/presentation/services/readerability_script.g.dart +++ b/app/lib/features/web_view/presentation/services/readerability_script.g.dart @@ -7,7 +7,7 @@ part of 'readerability_script.dart'; // ************************************************************************** String _$readerabilityScriptServiceHash() => - r'780980e6771d8d860e261fb4bc41236a60e0aaab'; + r'7a4fe65f683c31545b2f2bcb3ea199619be4bf4b'; /// Copied from Dart SDK class _SystemHash {