apply content blocking
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
import 'package:bang_navigator/features/content_block/domain/repositories/host.dart';
|
||||||
|
import 'package:bang_navigator/features/settings/data/repositories/settings_repository.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
part 'providers.g.dart';
|
||||||
|
|
||||||
|
@Riverpod(keepAlive: true)
|
||||||
|
Stream<Set<String>?> blockContentHosts(BlockContentHostsRef ref) {
|
||||||
|
final hostRepository = ref.watch(hostRepositoryProvider.notifier);
|
||||||
|
final enableContentBlocking = ref.watch(
|
||||||
|
settingsRepositoryProvider
|
||||||
|
.select((value) => value.valueOrNull?.enableContentBlocking ?? false),
|
||||||
|
);
|
||||||
|
final enableHostList = ref.watch(
|
||||||
|
settingsRepositoryProvider
|
||||||
|
.select((value) => value.valueOrNull?.enableHostList ?? {}),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!enableContentBlocking || enableHostList.isEmpty) {
|
||||||
|
return Stream.value(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hostRepository
|
||||||
|
.watchHosts(sources: enableHostList)
|
||||||
|
.map((hosts) => hosts.toSet());
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'providers.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$blockContentHostsHash() => r'27e7902adda8d8d3b6d29fdc43c5d7ad5c3a8e9a';
|
||||||
|
|
||||||
|
/// See also [blockContentHosts].
|
||||||
|
@ProviderFor(blockContentHosts)
|
||||||
|
final blockContentHostsProvider = StreamProvider<Set<String>?>.internal(
|
||||||
|
blockContentHosts,
|
||||||
|
name: r'blockContentHostsProvider',
|
||||||
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$blockContentHostsHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef BlockContentHostsRef = StreamProviderRef<Set<String>?>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:bang_navigator/core/logger.dart';
|
import 'package:bang_navigator/core/logger.dart';
|
||||||
import 'package:bang_navigator/features/bangs/domain/providers.dart';
|
import 'package:bang_navigator/features/bangs/domain/providers.dart';
|
||||||
@@ -9,6 +10,7 @@ import 'package:bang_navigator/features/search_browser/domain/entities/sheet.dar
|
|||||||
import 'package:bang_navigator/features/search_browser/domain/providers.dart';
|
import 'package:bang_navigator/features/search_browser/domain/providers.dart';
|
||||||
import 'package:bang_navigator/features/settings/data/repositories/settings_repository.dart';
|
import 'package:bang_navigator/features/settings/data/repositories/settings_repository.dart';
|
||||||
import 'package:bang_navigator/features/web_view/domain/entities/web_view_page.dart';
|
import 'package:bang_navigator/features/web_view/domain/entities/web_view_page.dart';
|
||||||
|
import 'package:bang_navigator/features/web_view/domain/providers.dart';
|
||||||
import 'package:bang_navigator/features/web_view/presentation/controllers/switch_new_tab.dart';
|
import 'package:bang_navigator/features/web_view/presentation/controllers/switch_new_tab.dart';
|
||||||
import 'package:bang_navigator/features/web_view/presentation/widgets/web_page_dialog.dart';
|
import 'package:bang_navigator/features/web_view/presentation/widgets/web_page_dialog.dart';
|
||||||
import 'package:bang_navigator/features/web_view/utils/download_helper.dart';
|
import 'package:bang_navigator/features/web_view/utils/download_helper.dart';
|
||||||
@@ -86,12 +88,6 @@ class _WebViewState extends ConsumerState<WebView> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final showEarlyAccessFeatures = ref.watch(
|
|
||||||
settingsRepositoryProvider.select(
|
|
||||||
(value) => value.valueOrNull?.showEarlyAccessFeatures ?? true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
final initialSettings = useMemoized(
|
final initialSettings = useMemoized(
|
||||||
() => InAppWebViewSettings(
|
() => InAppWebViewSettings(
|
||||||
// isInspectable: kDebugMode,
|
// isInspectable: kDebugMode,
|
||||||
@@ -109,6 +105,36 @@ class _WebViewState extends ConsumerState<WebView> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final showEarlyAccessFeatures = ref.watch(
|
||||||
|
settingsRepositoryProvider.select(
|
||||||
|
(value) => value.valueOrNull?.showEarlyAccessFeatures ?? true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// We keep listening to changes and cache them in this ref.
|
||||||
|
// This is important, since our WebView will not have the main scope anymore
|
||||||
|
// to react to updates from ref.watch
|
||||||
|
//
|
||||||
|
// With this solution we dont need to read on every interception request
|
||||||
|
// and can just obtain the value from here
|
||||||
|
final blockContentHosts = useRef<Set<String>?>(null);
|
||||||
|
ref.listen(
|
||||||
|
blockContentHostsProvider,
|
||||||
|
(previous, next) {
|
||||||
|
blockContentHosts.value = next.valueOrNull;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ref.listen(
|
||||||
|
settingsRepositoryProvider
|
||||||
|
.select((value) => value.valueOrNull?.enableJavascript),
|
||||||
|
(previous, next) async {
|
||||||
|
await widget.page.value.controller?.setSettings(
|
||||||
|
settings: initialSettings.copy()..javaScriptEnabled = next,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
final webViewProgress = useValueNotifier(100);
|
final webViewProgress = useValueNotifier(100);
|
||||||
|
|
||||||
useOnAppLifecycleStateChange((previous, current) async {
|
useOnAppLifecycleStateChange((previous, current) async {
|
||||||
@@ -131,16 +157,6 @@ class _WebViewState extends ConsumerState<WebView> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ref.listen(
|
|
||||||
settingsRepositoryProvider
|
|
||||||
.select((value) => value.valueOrNull?.enableJavascript),
|
|
||||||
(previous, next) async {
|
|
||||||
await widget.page.value.controller?.setSettings(
|
|
||||||
settings: initialSettings.copy()..javaScriptEnabled = next,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
InAppWebView(
|
InAppWebView(
|
||||||
@@ -218,6 +234,17 @@ class _WebViewState extends ConsumerState<WebView> {
|
|||||||
action: ServerTrustAuthResponseAction.PROCEED,
|
action: ServerTrustAuthResponseAction.PROCEED,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
shouldInterceptRequest: (controller, request) async {
|
||||||
|
if (blockContentHosts.value?.contains(request.url.host) == true) {
|
||||||
|
return WebResourceResponse(
|
||||||
|
contentType: "text/plain",
|
||||||
|
data: utf8.encode("Blocked"),
|
||||||
|
statusCode: 403,
|
||||||
|
reasonPhrase: "Forbidden",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
onProgressChanged: (controller, progress) {
|
onProgressChanged: (controller, progress) {
|
||||||
webViewProgress.value = progress;
|
webViewProgress.value = progress;
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user