better app initialization with bangs
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
import 'package:bang_navigator/features/about/data/repositories/package_info_repository.dart';
|
||||||
|
import 'package:bang_navigator/features/bangs/domain/repositories/sync.dart';
|
||||||
|
import 'package:bang_navigator/features/search_browser/domain/services/session.dart';
|
||||||
|
import 'package:bang_navigator/features/settings/data/repositories/settings_repository.dart';
|
||||||
|
import 'package:exceptions/exceptions.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
|
part 'app_initialization.g.dart';
|
||||||
|
|
||||||
|
@Riverpod(keepAlive: true)
|
||||||
|
class AppInitializationService extends _$AppInitializationService {
|
||||||
|
/// Will de facto restart the app
|
||||||
|
Future<void> reinitialize() async {
|
||||||
|
ref.invalidateSelf();
|
||||||
|
return initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> initialize() async {
|
||||||
|
state = await Result.fromAsync(() async {
|
||||||
|
final errors = <ErrorMessage>[];
|
||||||
|
|
||||||
|
//Ensure Package info is loaded
|
||||||
|
await ref.read(packageInfoProvider.future);
|
||||||
|
|
||||||
|
final syncResults = await ref
|
||||||
|
.read(bangSyncRepositoryProvider.notifier)
|
||||||
|
.syncAllBangGroups(syncInterval: const Duration(days: 7));
|
||||||
|
|
||||||
|
for (final MapEntry(value: result) in syncResults.entries) {
|
||||||
|
result.onFailure(errors.add);
|
||||||
|
}
|
||||||
|
|
||||||
|
final settings = await ref.read(settingsRepositoryProvider.future);
|
||||||
|
if (settings.incognitoMode) {
|
||||||
|
await ref.read(sessionServiceProvider.notifier).clearAllData();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.kagiSession case final String session) {
|
||||||
|
if (session.isNotEmpty) {
|
||||||
|
await ref
|
||||||
|
.read(sessionServiceProvider.notifier)
|
||||||
|
.setKagiSession(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (initialized: true, errors: errors);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Result<({bool initialized, List<ErrorMessage> errors})> build() {
|
||||||
|
return Result.success((initialized: false, errors: List.empty()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'app_initialization.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$appInitializationServiceHash() =>
|
||||||
|
r'7b36828c2368c3b3a97b799dd8192854629c8379';
|
||||||
|
|
||||||
|
/// See also [AppInitializationService].
|
||||||
|
@ProviderFor(AppInitializationService)
|
||||||
|
final appInitializationServiceProvider = NotifierProvider<
|
||||||
|
AppInitializationService,
|
||||||
|
Result<({bool initialized, List<ErrorMessage> errors})>>.internal(
|
||||||
|
AppInitializationService.new,
|
||||||
|
name: r'appInitializationServiceProvider',
|
||||||
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$appInitializationServiceHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef _$AppInitializationService
|
||||||
|
= Notifier<Result<({bool initialized, List<ErrorMessage> errors})>>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
||||||
@@ -44,10 +44,6 @@ class SessionService extends _$SessionService {
|
|||||||
await webViewLoaded.future.whenComplete(() => headlessWebView..dispose());
|
await webViewLoaded.future.whenComplete(() => headlessWebView..dispose());
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializationDone() {
|
|
||||||
state = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool build() => false;
|
void build() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ part of 'session.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$sessionServiceHash() => r'48126bad2cb8d5c38296307bede64bf549365acf';
|
String _$sessionServiceHash() => r'fd2cd03bbf2dd254bb19e541c71a6fb249f5a7bb';
|
||||||
|
|
||||||
/// See also [SessionService].
|
/// See also [SessionService].
|
||||||
@ProviderFor(SessionService)
|
@ProviderFor(SessionService)
|
||||||
final sessionServiceProvider =
|
final sessionServiceProvider =
|
||||||
AutoDisposeNotifierProvider<SessionService, bool>.internal(
|
AutoDisposeNotifierProvider<SessionService, void>.internal(
|
||||||
SessionService.new,
|
SessionService.new,
|
||||||
name: r'sessionServiceProvider',
|
name: r'sessionServiceProvider',
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
@@ -21,6 +21,6 @@ final sessionServiceProvider =
|
|||||||
allTransitiveDependencies: null,
|
allTransitiveDependencies: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef _$SessionService = AutoDisposeNotifier<bool>;
|
typedef _$SessionService = AutoDisposeNotifier<void>;
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member
|
||||||
|
|||||||
+46
-36
@@ -1,11 +1,10 @@
|
|||||||
import 'package:bang_navigator/core/logger.dart';
|
import 'package:bang_navigator/core/logger.dart';
|
||||||
import 'package:bang_navigator/core/providers.dart';
|
import 'package:bang_navigator/core/providers.dart';
|
||||||
import 'package:bang_navigator/features/about/data/repositories/package_info_repository.dart';
|
import 'package:bang_navigator/domain/services/app_initialization.dart';
|
||||||
import 'package:bang_navigator/features/bangs/domain/repositories/sync.dart';
|
|
||||||
import 'package:bang_navigator/features/search_browser/domain/services/session.dart';
|
|
||||||
import 'package:bang_navigator/features/settings/data/repositories/settings_repository.dart';
|
|
||||||
import 'package:bang_navigator/presentation/hooks/on_initialization.dart';
|
import 'package:bang_navigator/presentation/hooks/on_initialization.dart';
|
||||||
|
import 'package:bang_navigator/presentation/widgets/failure_widget.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:home_widget/home_widget.dart';
|
import 'package:home_widget/home_widget.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
|
||||||
@@ -39,28 +38,9 @@ void main() async {
|
|||||||
builder: (context, ref, child) {
|
builder: (context, ref, child) {
|
||||||
useOnInitialization(
|
useOnInitialization(
|
||||||
() async {
|
() async {
|
||||||
await ref.read(packageInfoProvider.future);
|
|
||||||
|
|
||||||
await ref
|
await ref
|
||||||
.read(bangSyncRepositoryProvider.notifier)
|
.read(appInitializationServiceProvider.notifier)
|
||||||
.syncAllBangGroups(syncInterval: const Duration(days: 7));
|
.initialize();
|
||||||
|
|
||||||
final settings =
|
|
||||||
await ref.read(settingsRepositoryProvider.future);
|
|
||||||
|
|
||||||
if (settings.incognitoMode) {
|
|
||||||
await ref.read(sessionServiceProvider.notifier).clearAllData();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.kagiSession case final String session) {
|
|
||||||
if (session.isNotEmpty) {
|
|
||||||
await ref
|
|
||||||
.read(sessionServiceProvider.notifier)
|
|
||||||
.setKagiSession(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ref.read(sessionServiceProvider.notifier).initializationDone();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -76,18 +56,11 @@ class MainApp extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final isInitialized = ref.watch(sessionServiceProvider);
|
final initializationResult = ref.watch(appInitializationServiceProvider);
|
||||||
final router = ref.watch(routerProvider);
|
final router = ref.watch(routerProvider);
|
||||||
|
|
||||||
if (!isInitialized) {
|
final themeData = useMemoized(
|
||||||
return const Center(
|
() => ThemeData(
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return MaterialApp.router(
|
|
||||||
debugShowCheckedModeBanner: false,
|
|
||||||
theme: ThemeData(
|
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
brightness: Brightness.dark,
|
brightness: Brightness.dark,
|
||||||
// colorScheme: ColorScheme.fromSeed(
|
// colorScheme: ColorScheme.fromSeed(
|
||||||
@@ -95,7 +68,44 @@ class MainApp extends HookConsumerWidget {
|
|||||||
// brightness: Brightness.dark,
|
// brightness: Brightness.dark,
|
||||||
// ),
|
// ),
|
||||||
),
|
),
|
||||||
routerConfig: router,
|
);
|
||||||
|
|
||||||
|
return initializationResult.fold(
|
||||||
|
(initializationState) {
|
||||||
|
if (!initializationState.initialized) {
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MaterialApp.router(
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
theme: themeData,
|
||||||
|
routerConfig: router,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onFailure: (errorMessage) {
|
||||||
|
return MaterialApp(
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
theme: themeData,
|
||||||
|
home: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Initiallization Error'),
|
||||||
|
),
|
||||||
|
body: Center(
|
||||||
|
child: FailureWidget(
|
||||||
|
title: 'Could not initialize App',
|
||||||
|
exception: errorMessage.toString(),
|
||||||
|
onRetry: () async {
|
||||||
|
await ref
|
||||||
|
.read(appInitializationServiceProvider.notifier)
|
||||||
|
.reinitialize();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user