mirror of
https://github.com/rzuasti/oott.git
synced 2026-07-08 19:21:54 +02:00
Catch uncaught async errors and surface response-shape failures
Wrap main in runZonedGuarded and install FlutterError.onError / PlatformDispatcher.onError so background async failures get logged instead of dying silently. Guard PrefUtil.init so a SharedPreferences platform error no longer aborts startup. Recognize TypeError and FormatException in dioErrorToUserMessage to give a clearer message when the backend returns an unexpected JSON shape or bad timestamp. Wrap Settings._save in try/catch so prefs write failures show a snackbar instead of leaving the Save button silently dead. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
e70676a193
commit
140ebab035
+29
-4
@@ -1,3 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:frontend/theme/catppuccin_mocha_theme.dart';
|
||||
import 'package:frontend/utils/pref_utils.dart';
|
||||
@@ -5,10 +8,32 @@ import 'package:provider/provider.dart';
|
||||
import 'navigation.dart';
|
||||
import 'theme/gruvbox_theme.dart';
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await PrefUtil.init();
|
||||
runApp(const MainApp());
|
||||
void main() {
|
||||
runZonedGuarded(
|
||||
() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
FlutterError.onError = (details) {
|
||||
FlutterError.presentError(details);
|
||||
debugPrint('FlutterError: ${details.exceptionAsString()}');
|
||||
};
|
||||
PlatformDispatcher.instance.onError = (error, stack) {
|
||||
debugPrint('Uncaught platform error: $error\n$stack');
|
||||
return true;
|
||||
};
|
||||
|
||||
try {
|
||||
await PrefUtil.init();
|
||||
} catch (e, stack) {
|
||||
debugPrint('PrefUtil.init failed, continuing with defaults: $e\n$stack');
|
||||
}
|
||||
|
||||
runApp(const MainApp());
|
||||
},
|
||||
(error, stack) {
|
||||
debugPrint('Uncaught zone error: $error\n$stack');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
final class MainApp extends StatelessWidget {
|
||||
|
||||
@@ -69,20 +69,28 @@ class _SettingsState extends State<Settings> {
|
||||
|
||||
Future<void> _save() async {
|
||||
if (!_formKey.currentState!.validate()) return;
|
||||
final urlOk = await PrefUtil.setValue('base_url', _baseUrlController.text);
|
||||
if (!mounted) return;
|
||||
final keyOk = await PrefUtil.setValue(
|
||||
'api_key',
|
||||
XOR().xorEncode(_apiKeyController.text),
|
||||
);
|
||||
if (!mounted) return;
|
||||
final themeOk = await context.read<AppState>().setTheme(_selectedTheme);
|
||||
if (!mounted) return;
|
||||
if (urlOk && keyOk && themeOk) {
|
||||
BackendAPI.instance.reconfigureFromPrefs();
|
||||
UISnackbars.showSuccess(context, 'Settings saved successfully');
|
||||
} else {
|
||||
UISnackbars.showError(context, 'Failed to save settings');
|
||||
try {
|
||||
final urlOk = await PrefUtil.setValue(
|
||||
'base_url',
|
||||
_baseUrlController.text,
|
||||
);
|
||||
if (!mounted) return;
|
||||
final keyOk = await PrefUtil.setValue(
|
||||
'api_key',
|
||||
XOR().xorEncode(_apiKeyController.text),
|
||||
);
|
||||
if (!mounted) return;
|
||||
final themeOk = await context.read<AppState>().setTheme(_selectedTheme);
|
||||
if (!mounted) return;
|
||||
if (urlOk && keyOk && themeOk) {
|
||||
BackendAPI.instance.reconfigureFromPrefs();
|
||||
UISnackbars.showSuccess(context, 'Settings saved successfully');
|
||||
} else {
|
||||
UISnackbars.showError(context, 'Failed to save settings');
|
||||
}
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
UISnackbars.showError(context, 'Failed to save settings: $e');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,10 @@ LogInterceptor _buildLogInterceptor() => LogInterceptor(
|
||||
);
|
||||
|
||||
String dioErrorToUserMessage(Object error) {
|
||||
if (error is TypeError || error is FormatException) {
|
||||
debugPrint('Backend response shape error: $error');
|
||||
return 'Unexpected response shape from backend.';
|
||||
}
|
||||
if (error is! DioException) {
|
||||
debugPrint('Non-Dio error from backend call: $error');
|
||||
return 'Unexpected error.';
|
||||
|
||||
Reference in New Issue
Block a user