diff --git a/app/assets/images/ublock.svg b/app/assets/images/ublock.svg
new file mode 100644
index 00000000..ea2ffd3c
--- /dev/null
+++ b/app/assets/images/ublock.svg
@@ -0,0 +1,44 @@
+
+
diff --git a/app/lib/core/providers/router.dart b/app/lib/core/providers/router.dart
index 921f87e2..963ac6da 100644
--- a/app/lib/core/providers/router.dart
+++ b/app/lib/core/providers/router.dart
@@ -2,10 +2,34 @@ import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:weblibre/core/routing/routes.dart';
+import 'package:weblibre/features/user/domain/repositories/onboarding.dart';
part 'router.g.dart';
@Riverpod(keepAlive: true)
-GoRouter router(Ref ref) {
- return GoRouter(debugLogDiagnostics: true, routes: $appRoutes);
+Future router(Ref ref) async {
+ String? initialLocation;
+
+ final onboardingMandatory = await ref
+ .read(onboardingRepositoryProvider.notifier)
+ .isOutdated();
+
+ if (onboardingMandatory) {
+ final current = await ref
+ .read(onboardingRepositoryProvider.notifier)
+ .getCurrentRevision();
+
+ final route = OnboardingRoute(
+ currentRevision: current ?? -1,
+ targetRevision: OnboardingRepository.targetRevision,
+ );
+
+ initialLocation = route.location;
+ }
+
+ return GoRouter(
+ debugLogDiagnostics: true,
+ routes: $appRoutes,
+ initialLocation: initialLocation,
+ );
}
diff --git a/app/lib/core/providers/router.g.dart b/app/lib/core/providers/router.g.dart
index c098746c..fdd8fdc9 100644
--- a/app/lib/core/providers/router.g.dart
+++ b/app/lib/core/providers/router.g.dart
@@ -6,11 +6,11 @@ part of 'router.dart';
// RiverpodGenerator
// **************************************************************************
-String _$routerHash() => r'25fc899b87c080600f6e1d87d510db333378bdfd';
+String _$routerHash() => r'ce7cc5b5f236781a06867a852a08ed03d3582022';
/// See also [router].
@ProviderFor(router)
-final routerProvider = Provider.internal(
+final routerProvider = FutureProvider.internal(
router,
name: r'routerProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
@@ -22,6 +22,6 @@ final routerProvider = Provider.internal(
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
-typedef RouterRef = ProviderRef;
+typedef RouterRef = FutureProviderRef;
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
diff --git a/app/lib/core/routing/routes.dart b/app/lib/core/routing/routes.dart
index 90b12a45..5d93de80 100644
--- a/app/lib/core/routing/routes.dart
+++ b/app/lib/core/routing/routes.dart
@@ -16,6 +16,7 @@ import 'package:weblibre/features/geckoview/features/search/presentation/screens
import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart';
import 'package:weblibre/features/geckoview/features/tabs/presentation/screens/container_edit.dart';
import 'package:weblibre/features/geckoview/features/tabs/presentation/screens/container_list.dart';
+import 'package:weblibre/features/onboarding/presentation/onboarding.dart';
import 'package:weblibre/features/settings/presentation/screens/bang_settings.dart';
import 'package:weblibre/features/settings/presentation/screens/general_settings.dart';
import 'package:weblibre/features/settings/presentation/screens/settings.dart';
@@ -43,3 +44,25 @@ class AboutRoute extends GoRouteData with _$AboutRoute {
return DialogPage(builder: (_) => const AboutDialogScreen());
}
}
+
+@TypedGoRoute(
+ name: 'OnboardingRoute',
+ path: '/onboarding/:currentRevision/:targetRevision',
+)
+class OnboardingRoute extends GoRouteData with _$OnboardingRoute {
+ final int currentRevision;
+ final int targetRevision;
+
+ const OnboardingRoute({
+ required this.currentRevision,
+ required this.targetRevision,
+ });
+
+ @override
+ Widget build(BuildContext context, GoRouterState state) {
+ return OnboardingScreen(
+ currentRevision: currentRevision,
+ targetRevision: targetRevision,
+ );
+ }
+}
diff --git a/app/lib/core/routing/routes.g.dart b/app/lib/core/routing/routes.g.dart
index 8e195e8c..e2889eb8 100644
--- a/app/lib/core/routing/routes.g.dart
+++ b/app/lib/core/routing/routes.g.dart
@@ -8,6 +8,7 @@ part of 'routes.dart';
List get $appRoutes => [
$aboutRoute,
+ $onboardingRoute,
$settingsRoute,
$browserRoute,
$bangCategoriesRoute,
@@ -41,6 +42,40 @@ mixin _$AboutRoute on GoRouteData {
void replace(BuildContext context) => context.replace(location);
}
+RouteBase get $onboardingRoute => GoRouteData.$route(
+ path: '/onboarding/:currentRevision/:targetRevision',
+ name: 'OnboardingRoute',
+
+ factory: _$OnboardingRoute._fromState,
+);
+
+mixin _$OnboardingRoute on GoRouteData {
+ static OnboardingRoute _fromState(GoRouterState state) => OnboardingRoute(
+ currentRevision: int.parse(state.pathParameters['currentRevision']!)!,
+ targetRevision: int.parse(state.pathParameters['targetRevision']!)!,
+ );
+
+ OnboardingRoute get _self => this as OnboardingRoute;
+
+ @override
+ String get location => GoRouteData.$location(
+ '/onboarding/${Uri.encodeComponent(_self.currentRevision.toString())}/${Uri.encodeComponent(_self.targetRevision.toString())}',
+ );
+
+ @override
+ void go(BuildContext context) => context.go(location);
+
+ @override
+ Future push(BuildContext context) => context.push(location);
+
+ @override
+ void pushReplacement(BuildContext context) =>
+ context.pushReplacement(location);
+
+ @override
+ void replace(BuildContext context) => context.replace(location);
+}
+
RouteBase get $settingsRoute => GoRouteData.$route(
path: '/settings',
name: 'SettingsRoute',
diff --git a/app/lib/features/bangs/data/database/daos/bang.dart b/app/lib/features/bangs/data/database/daos/bang.dart
index ae90ffa1..f4a5927c 100644
--- a/app/lib/features/bangs/data/database/daos/bang.dart
+++ b/app/lib/features/bangs/data/database/daos/bang.dart
@@ -34,6 +34,7 @@ class BangDao extends DatabaseAccessor with _$BangDaoMixin {
}
Selectable getBangDataList({
+ Iterable? triggers,
Iterable? groups,
String? domain,
String? category,
@@ -41,6 +42,9 @@ class BangDao extends DatabaseAccessor with _$BangDaoMixin {
bool? orderMostFrequentFirst,
}) {
final selectable = select(db.bangDataView);
+ if (triggers != null) {
+ selectable.where((t) => t.trigger.isIn(triggers));
+ }
if (groups != null) {
selectable.where((t) => t.group.isInValues(groups));
}
diff --git a/app/lib/features/bangs/domain/providers/bangs.dart b/app/lib/features/bangs/domain/providers/bangs.dart
index 3766db31..5d410f94 100644
--- a/app/lib/features/bangs/domain/providers/bangs.dart
+++ b/app/lib/features/bangs/domain/providers/bangs.dart
@@ -30,6 +30,7 @@ Stream