Files
zapstore/lib/main.dart
T

89 lines
2.6 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:app_links/app_links.dart';
import 'package:flutter/material.dart';
import 'package:flutter_data/flutter_data.dart';
import 'package:flutter_phoenix/flutter_phoenix.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:path_provider/path_provider.dart';
import 'package:zapstore/navigation/router.dart';
import 'package:zapstore/utils/debounce.dart';
import 'package:zapstore/utils/theme.dart';
import 'package:zapstore/widgets/error_container.dart';
const kDbVersion = 1;
final appLinks = AppLinks();
/// Application entry point.
/// - Initializes Riverpod (and Flutter Data local storage)
/// - Handles application errors
/// - Triggers routing
void main() {
runZonedGuarded(() {
runApp(
Phoenix(
child: ProviderScope(
overrides: [
localStorageProvider.overrideWithValue(
LocalStorage(
baseDirFn: () async {
final path = (await getApplicationSupportDirectory()).path;
print('Initializing local storage at $path');
return path;
},
clear: LocalStorageClearStrategy.whenError,
),
)
],
child: const ZapstoreApp(),
),
),
);
}, errorHandler);
FlutterError.onError = (_) => errorHandler(_.exception, _.stack);
}
class ZapstoreApp extends StatelessWidget {
const ZapstoreApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
builder: materialErrorBuilder,
routerConfig: appRouter,
debugShowCheckedModeBanner: false,
theme: theme,
);
}
}
Directory? _dir;
void errorHandler(Object exception, StackTrace? stack) {
debounce((exception: exception, stack: stack), (records) async {
if (records.isEmpty) return;
_dir ??= await getApplicationDocumentsDirectory();
final file = File('${_dir!.path}/errors.json');
final errorMap = await file.exists()
? Map<String, String>.from(jsonDecode(await file.readAsString()))
: <String, String>{};
for (final record in records) {
final full =
'${record.exception}${record.stack?.toString() ?? ''}${DateTime.now()
.toIso8601String()}';
final key = full.split('\n').take(2).join();
// Only keep longest stack of similar errors, prevents duplicates
if (full.length > (errorMap[key]?.length ?? 0)) {
errorMap[key] = full;
}
}
print(errorMap.length);
await file.writeAsString(jsonEncode(errorMap));
});
}