Compare commits
1 Commits
v0.8.92-pr
...
v0.8.92-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79ce7cadf6 |
@@ -19,10 +19,10 @@ class Migration {
|
||||
required Future<Config> Function(MigrationData data) sync,
|
||||
}) async {
|
||||
_oldVersion = await preferences.getVersion();
|
||||
MigrationData data = MigrationData(configMap: configMap);
|
||||
if (_oldVersion == currentVersion) {
|
||||
return Config.realFromJson(configMap);
|
||||
}
|
||||
MigrationData data = MigrationData(configMap: configMap);
|
||||
if (_oldVersion == 0 && configMap != null) {
|
||||
final clashConfigMap = await preferences.getClashConfigMap();
|
||||
if (clashConfigMap != null) {
|
||||
|
||||
@@ -41,26 +41,28 @@ class AppController {
|
||||
|
||||
extension InitControllerExt on AppController {
|
||||
Future<void> _init() async {
|
||||
try {
|
||||
updateTray();
|
||||
autoUpdateProfiles();
|
||||
autoCheckUpdate();
|
||||
autoLaunch?.updateStatus(_ref.read(appSettingProvider).autoLaunch);
|
||||
if (!_ref.read(appSettingProvider).silentLaunch) {
|
||||
window?.show();
|
||||
} else {
|
||||
window?.hide();
|
||||
}
|
||||
await _handleFailedPreference();
|
||||
await _handlerDisclaimer();
|
||||
await _showCrashlyticsTip();
|
||||
await _connectCore();
|
||||
await _initCore();
|
||||
await _initStatus();
|
||||
_ref.read(initProvider.notifier).value = true;
|
||||
} catch (e) {
|
||||
commonPrint.log('init error: $e');
|
||||
FlutterError.onError = (details) {
|
||||
commonPrint.log(
|
||||
'exception: ${details.exception} stack: ${details.stack}',
|
||||
logLevel: LogLevel.warning,
|
||||
);
|
||||
};
|
||||
updateTray();
|
||||
autoUpdateProfiles();
|
||||
autoCheckUpdate();
|
||||
autoLaunch?.updateStatus(_ref.read(appSettingProvider).autoLaunch);
|
||||
if (!_ref.read(appSettingProvider).silentLaunch) {
|
||||
window?.show();
|
||||
} else {
|
||||
window?.hide();
|
||||
}
|
||||
await _handleFailedPreference();
|
||||
await _handlerDisclaimer();
|
||||
await _showCrashlyticsTip();
|
||||
await _connectCore();
|
||||
await _initCore();
|
||||
await _initStatus();
|
||||
_ref.read(initProvider.notifier).value = true;
|
||||
}
|
||||
|
||||
Future<void> _handleFailedPreference() async {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:fl_clash/pages/error.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
@@ -9,11 +10,22 @@ import 'application.dart';
|
||||
import 'common/common.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
final version = await system.version;
|
||||
final container = await globalState.init(version);
|
||||
HttpOverrides.global = FlClashHttpOverrides();
|
||||
runApp(
|
||||
UncontrolledProviderScope(container: container, child: const Application()),
|
||||
);
|
||||
try {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
final version = await system.version;
|
||||
final container = await globalState.init(version);
|
||||
HttpOverrides.global = FlClashHttpOverrides();
|
||||
runApp(
|
||||
UncontrolledProviderScope(
|
||||
container: container,
|
||||
child: const Application(),
|
||||
),
|
||||
);
|
||||
} catch (e, s) {
|
||||
return runApp(
|
||||
MaterialApp(
|
||||
home: InitErrorScreen(error: e, stack: s),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
121
lib/pages/error.dart
Normal file
121
lib/pages/error.dart
Normal file
@@ -0,0 +1,121 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class InitErrorScreen extends StatelessWidget {
|
||||
final Object error;
|
||||
final StackTrace stack;
|
||||
|
||||
const InitErrorScreen({super.key, required this.error, required this.stack});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('System Init Failed'),
|
||||
backgroundColor: colorScheme.error,
|
||||
foregroundColor: colorScheme.onError,
|
||||
elevation: 0,
|
||||
),
|
||||
body: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 1. Header Section
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.report_problem,
|
||||
color: colorScheme.error,
|
||||
size: 32,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const Expanded(
|
||||
child: Text(
|
||||
'The application encountered a critical error during startup and cannot continue.',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
_buildSectionLabel('Error Details:'),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.errorContainer.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: colorScheme.error.withOpacity(0.5)),
|
||||
),
|
||||
child: SelectableText(
|
||||
error.toString(),
|
||||
style: TextStyle(
|
||||
color: colorScheme.onErrorContainer,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
_buildSectionLabel('Stack Trace:'),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).brightness == Brightness.dark
|
||||
? Colors.grey[900]
|
||||
: Colors.grey[200],
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: Colors.grey.withOpacity(0.5)),
|
||||
),
|
||||
child: SelectableText(
|
||||
stack.toString(),
|
||||
style: const TextStyle(
|
||||
fontFamily: 'monospace', // Makes code easier to read
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 80),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () => _copyToClipboard(context),
|
||||
label: const Text('Copy Details'),
|
||||
icon: const Icon(Icons.copy),
|
||||
backgroundColor: colorScheme.error,
|
||||
foregroundColor: colorScheme.onError,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSectionLabel(String text) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Text(
|
||||
text,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _copyToClipboard(BuildContext context) {
|
||||
final text = '=== ERROR ===\n$error\n\n=== STACK TRACE ===\n$stack';
|
||||
Clipboard.setData(ClipboardData(text: text));
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Error details copied to clipboard'),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export 'editor.dart';
|
||||
export 'error.dart';
|
||||
export 'home.dart';
|
||||
export 'scan.dart';
|
||||
export 'editor.dart';
|
||||
@@ -22,7 +22,6 @@ import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import 'common/common.dart';
|
||||
import 'database/database.dart';
|
||||
import 'enum/enum.dart';
|
||||
import 'l10n/l10n.dart';
|
||||
import 'models/models.dart';
|
||||
|
||||
@@ -56,12 +55,6 @@ class GlobalState {
|
||||
}
|
||||
|
||||
Future<ProviderContainer> init(int version) async {
|
||||
FlutterError.onError = (details) {
|
||||
commonPrint.log(
|
||||
'exception: ${details.exception} stack: ${details.stack}',
|
||||
logLevel: LogLevel.warning,
|
||||
);
|
||||
};
|
||||
coreSHA256 = const String.fromEnvironment('CORE_SHA256');
|
||||
isPre = const String.fromEnvironment('APP_ENV') != 'stable';
|
||||
await _initDynamicColor();
|
||||
|
||||
Reference in New Issue
Block a user