feat: show error message when initialization fails for better debugging

This commit is contained in:
Tien Do Nam
2024-07-29 14:20:04 +02:00
parent af662218f0
commit f66865639f
30 changed files with 111 additions and 41 deletions
+1
View File
@@ -1,6 +1,7 @@
## 1.16.0 (unreleased)
- feat: reduce receive history size to 30 items to increase performance (@Tienisto)
- feat: show error message when initialization fails for better debugging (@Tienisto)
- fix(android): properly close app on back gesture (@Tienisto)
## 1.15.2 (2024-07-25)
@@ -13,6 +13,7 @@ import 'package:dart_mappable/dart_mappable.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_displaymode/flutter_displaymode.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/pages/home_page.dart';
import 'package:localsend_app/pages/home_page_controller.dart';
import 'package:localsend_app/provider/animation_provider.dart';
@@ -21,17 +22,14 @@ import 'package:localsend_app/provider/device_info_provider.dart';
import 'package:localsend_app/provider/network/nearby_devices_provider.dart';
import 'package:localsend_app/provider/network/server/server_provider.dart';
import 'package:localsend_app/provider/persistence_provider.dart';
// [FOSS_REMOVE_START]
import 'package:localsend_app/provider/purchase_provider.dart';
// [FOSS_REMOVE_END]
import 'package:localsend_app/provider/selection/selected_sending_files_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/provider/tv_provider.dart';
import 'package:localsend_app/provider/window_dimensions_provider.dart';
import 'package:localsend_app/refena.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/config/refena.dart';
import 'package:localsend_app/util/i18n.dart';
import 'package:localsend_app/util/native/autostart_helper.dart';
import 'package:localsend_app/util/native/cache_helper.dart';
@@ -59,7 +57,9 @@ Future<RefenaContainer> preInit(List<String> args) async {
final dynamicColors = await getDynamicColors();
final persistenceService = await PersistenceService.initialize(dynamicColors);
final persistenceService = await PersistenceService.initialize(
supportsDynamicColors: dynamicColors != null,
);
if (persistenceService.isFirstAppStart && !persistenceService.isPortableMode()) {
await enableContextMenu();
+55
View File
@@ -0,0 +1,55 @@
import 'package:flutter/material.dart';
import 'package:localsend_app/util/native/platform_check.dart';
import 'package:logging/logging.dart';
import 'package:window_manager/window_manager.dart';
final _logger = Logger('Init');
/// Shows an alternative app if the initialization failed.
void showInitErrorApp({
required Object error,
required StackTrace stackTrace
}) async {
_logger.severe('Error during init', error, stackTrace);
if (checkPlatformIsDesktop()) {
await WindowManager.instance.ensureInitialized();
await WindowManager.instance.show();
}
runApp(_ErrorApp(
error: error,
stackTrace: stackTrace,
));
}
class _ErrorApp extends StatelessWidget {
final Object error;
final StackTrace stackTrace;
const _ErrorApp({
required this.error,
required this.stackTrace,
});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'LocalSend: Error',
debugShowCheckedModeBanner: false,
home: Scaffold(
body: TextFormField(
initialValue: 'Error: $error\n\n$stackTrace',
maxLines: null,
readOnly: true,
decoration: const InputDecoration(
contentPadding: EdgeInsets.all(10),
border: OutlineInputBorder(
borderSide: BorderSide(),
),
),
),
),
);
}
}
+13 -3
View File
@@ -1,13 +1,14 @@
import 'package:common/isolate.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:localsend_app/config/init.dart';
import 'package:localsend_app/config/init_error.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/init.dart';
import 'package:localsend_app/model/persistence/color_mode.dart';
import 'package:localsend_app/pages/home_page.dart';
import 'package:localsend_app/provider/local_ip_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/ui/dynamic_colors.dart';
import 'package:localsend_app/widget/watcher/life_cycle_watcher.dart';
import 'package:localsend_app/widget/watcher/shortcut_watcher.dart';
@@ -17,7 +18,16 @@ import 'package:refena_flutter/refena_flutter.dart';
import 'package:routerino/routerino.dart';
Future<void> main(List<String> args) async {
final container = await preInit(args);
final RefenaContainer container;
try {
container = await preInit(args);
} catch (e, stackTrace) {
showInitErrorApp(
error: e,
stackTrace: stackTrace,
);
return;
}
runApp(RefenaScope.withContainer(
container: container,
+2 -2
View File
@@ -2,14 +2,14 @@ import 'dart:io';
import 'package:desktop_drop/desktop_drop.dart';
import 'package:flutter/material.dart';
import 'package:localsend_app/config/init.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/init.dart';
import 'package:localsend_app/pages/home_page_controller.dart';
import 'package:localsend_app/pages/tabs/receive_tab.dart';
import 'package:localsend_app/pages/tabs/send_tab.dart';
import 'package:localsend_app/pages/tabs/settings_tab.dart';
import 'package:localsend_app/provider/selection/selected_sending_files_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/native/cross_file_converters.dart';
import 'package:localsend_app/widget/responsive_builder.dart';
import 'package:refena_flutter/refena_flutter.dart';
+1 -1
View File
@@ -6,12 +6,12 @@ import 'package:common/model/file_status.dart';
import 'package:common/model/session_status.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/provider/network/send_provider.dart';
import 'package:localsend_app/provider/network/server/server_provider.dart';
import 'package:localsend_app/provider/progress_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/file_size_helper.dart';
import 'package:localsend_app/util/file_speed_helper.dart';
import 'package:localsend_app/util/native/open_file.dart';
+1 -1
View File
@@ -1,13 +1,13 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/model/persistence/receive_history_entry.dart';
import 'package:localsend_app/pages/receive_page.dart';
import 'package:localsend_app/pages/receive_page_controller.dart';
import 'package:localsend_app/provider/receive_history_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/file_size_helper.dart';
import 'package:localsend_app/util/native/directories.dart';
import 'package:localsend_app/util/native/open_file.dart';
+1 -1
View File
@@ -3,6 +3,7 @@ import 'dart:async';
import 'package:common/model/session_status.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/model/persistence/color_mode.dart';
import 'package:localsend_app/pages/receive_options_page.dart';
@@ -10,7 +11,6 @@ import 'package:localsend_app/pages/receive_page_controller.dart';
import 'package:localsend_app/provider/favorites_provider.dart';
import 'package:localsend_app/provider/selection/selected_receiving_files_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/device_type_ext.dart';
import 'package:localsend_app/util/favorites.dart';
import 'package:localsend_app/util/ip_helper.dart';
+1 -1
View File
@@ -3,11 +3,11 @@ import 'dart:async';
import 'package:common/model/device.dart';
import 'package:common/model/session_status.dart';
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/provider/device_info_provider.dart';
import 'package:localsend_app/provider/favorites_provider.dart';
import 'package:localsend_app/provider/network/send_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/favorites.dart';
import 'package:localsend_app/util/native/taskbar_helper.dart';
import 'package:localsend_app/widget/animations/initial_fade_transition.dart';
+1 -1
View File
@@ -2,6 +2,7 @@ import 'package:collection/collection.dart';
import 'package:common/model/device.dart';
import 'package:common/model/session_status.dart';
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/model/send_mode.dart';
import 'package:localsend_app/pages/selected_files_page.dart';
@@ -14,7 +15,6 @@ import 'package:localsend_app/provider/network/send_provider.dart';
import 'package:localsend_app/provider/progress_provider.dart';
import 'package:localsend_app/provider/selection/selected_sending_files_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/favorites.dart';
import 'package:localsend_app/util/file_size_helper.dart';
import 'package:localsend_app/util/native/file_picker.dart';
+1 -1
View File
@@ -4,6 +4,7 @@ import 'package:common/constants.dart';
import 'package:common/model/device.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/model/persistence/color_mode.dart';
import 'package:localsend_app/pages/about/about_page.dart';
@@ -13,7 +14,6 @@ import 'package:localsend_app/pages/language_page.dart';
import 'package:localsend_app/pages/tabs/settings_tab_controller.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/provider/version_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/device_type_ext.dart';
import 'package:localsend_app/util/native/pick_directory_path.dart';
import 'package:localsend_app/util/native/platform_check.dart';
@@ -1,13 +1,13 @@
import 'package:common/model/device_info_result.dart';
import 'package:common/util/sleep.dart';
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/model/persistence/color_mode.dart';
import 'package:localsend_app/pages/language_page.dart';
import 'package:localsend_app/pages/tabs/settings_tab_vm.dart';
import 'package:localsend_app/provider/device_info_provider.dart';
import 'package:localsend_app/provider/network/server/server_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/native/autostart_helper.dart';
import 'package:localsend_app/util/native/context_menu_helper.dart';
import 'package:localsend_app/util/ui/dynamic_colors.dart';
+1 -1
View File
@@ -1,12 +1,12 @@
import 'package:common/util/sleep.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/model/cross_file.dart';
import 'package:localsend_app/provider/local_ip_provider.dart';
import 'package:localsend_app/provider/network/server/server_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/native/platform_check.dart';
import 'package:localsend_app/util/ui/snackbar.dart';
import 'package:localsend_app/widget/dialogs/pin_dialog.dart';
+12 -7
View File
@@ -20,7 +20,6 @@ import 'package:localsend_app/util/native/platform_check.dart';
import 'package:localsend_app/util/security_helper.dart';
import 'package:localsend_app/util/shared_preferences/shared_preferences_file.dart';
import 'package:localsend_app/util/shared_preferences/shared_preferences_portable.dart';
import 'package:localsend_app/util/ui/dynamic_colors.dart';
import 'package:logging/logging.dart';
import 'package:refena_flutter/refena_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
@@ -94,10 +93,13 @@ class PersistenceService {
PersistenceService._(this._prefs, this.isFirstAppStart);
static Future<PersistenceService> initialize(DynamicColors? dynamicColors) async {
static Future<PersistenceService> initialize({
required bool supportsDynamicColors,
}) async {
SharedPreferences prefs;
final portableStore = SharedPreferencesPortable();
bool usingLegacyStore = false;
if (checkPlatform(const [TargetPlatform.windows, TargetPlatform.linux, TargetPlatform.macOS]) && portableStore.exists()) {
_logger.info('Using portable settings.');
SharedPreferencesStorePlatform.instance = portableStore;
@@ -106,6 +108,7 @@ class PersistenceService {
if (legacyStore.exists()) {
_logger.info('Using legacy settings. Will migrate in the next step.');
SharedPreferencesStorePlatform.instance = legacyStore;
usingLegacyStore = true;
} else {
SharedPreferencesStorePlatform.instance = SharedPreferencesFile(filePath: _windowsFile);
}
@@ -114,13 +117,14 @@ class PersistenceService {
final bool isFirstAppStart;
final existingVersion = (await SharedPreferencesStorePlatform.instance.getAll())['flutter.$_version'] as int?;
_logger.info('Existing version: $existingVersion');
if (existingVersion == null) {
if (existingVersion == null && !usingLegacyStore) {
isFirstAppStart = true;
await SharedPreferencesStorePlatform.instance.setValue('Int', 'flutter.$_version', _latestVersion);
} else {
isFirstAppStart = false;
if (existingVersion < _latestVersion) {
await _runMigrations(existingVersion);
final fromVersion = existingVersion ?? 1;
if (fromVersion < _latestVersion) {
await _runMigrations(fromVersion);
}
}
@@ -156,7 +160,6 @@ class PersistenceService {
await prefs.setString(_securityContext, jsonEncode(generateSecurityContext()));
}
final supportsDynamicColors = dynamicColors != null;
if (prefs.getString(_colorKey) == null) {
await _initColorSetting(prefs, supportsDynamicColors);
} else {
@@ -183,7 +186,9 @@ class PersistenceService {
static Future<void> _initColorSetting(SharedPreferences prefs, bool supportsDynamicColors) async {
await prefs.setString(
_colorKey, checkPlatform([TargetPlatform.android]) && supportsDynamicColors ? ColorMode.system.name : ColorMode.localsend.name);
_colorKey,
checkPlatform([TargetPlatform.android]) && supportsDynamicColors ? ColorMode.system.name : ColorMode.localsend.name,
);
}
bool isPortableMode() {
+1 -1
View File
@@ -7,11 +7,11 @@ import 'package:file_selector/file_selector.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/pages/apk_picker_page.dart';
import 'package:localsend_app/provider/device_info_provider.dart';
import 'package:localsend_app/provider/selection/selected_sending_files_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/determine_image_type.dart';
import 'package:localsend_app/util/native/android_saf.dart';
import 'package:localsend_app/util/native/cross_file_converters.dart';
+1 -1
View File
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/widget/responsive_builder.dart';
class BigButton extends StatelessWidget {
+1 -1
View File
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/config/theme.dart';
/// A [DropdownButton] with a custom theme.
/// Currently, there is no easy way to apply color and border radius to all [DropdownButton].
@@ -4,11 +4,11 @@ import 'package:common/model/device.dart';
import 'package:common/util/task_runner.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/provider/last_devices.provider.dart';
import 'package:localsend_app/provider/local_ip_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:refena_flutter/refena_flutter.dart';
import 'package:routerino/routerino.dart';
+1 -1
View File
@@ -1,10 +1,10 @@
import 'package:common/isolate.dart';
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/model/persistence/favorite_device.dart';
import 'package:localsend_app/provider/favorites_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/widget/dialogs/favorite_edit_dialog.dart';
import 'package:refena_flutter/refena_flutter.dart';
import 'package:routerino/routerino.dart';
@@ -1,11 +1,11 @@
import 'package:common/isolate.dart';
import 'package:common/model/device.dart';
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/model/persistence/favorite_device.dart';
import 'package:localsend_app/provider/favorites_provider.dart';
import 'package:localsend_app/provider/settings_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/widget/dialogs/favorite_delete_dialog.dart';
import 'package:refena_flutter/refena_flutter.dart';
import 'package:routerino/routerino.dart';
@@ -2,8 +2,8 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:legalize/legalize.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/util/file_path_helper.dart';
import 'package:routerino/routerino.dart';
+1 -1
View File
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/theme.dart';
import 'package:nanoid2/nanoid2.dart';
import 'package:routerino/routerino.dart';
+1 -1
View File
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/model/state/send/web/web_send_state.dart';
import 'package:localsend_app/provider/network/server/server_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:pretty_qr_code/pretty_qr_code.dart';
import 'package:refena_flutter/refena_flutter.dart';
import 'package:routerino/routerino.dart';
@@ -2,9 +2,9 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:legalize/legalize.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/provider/selection/selected_receiving_files_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/widget/labeled_checkbox.dart';
import 'package:refena_flutter/refena_flutter.dart';
import 'package:routerino/routerino.dart';
+1 -1
View File
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/provider/tv_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:refena_flutter/refena_flutter.dart';
import 'package:routerino/routerino.dart';
+1 -2
View File
@@ -1,9 +1,8 @@
import 'package:flutter/material.dart';
import 'package:localsend_app/config/theme.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/model/state/send/web/web_send_state.dart';
import 'package:localsend_app/provider/network/server/server_provider.dart';
import 'package:localsend_app/theme.dart';
import 'package:refena_flutter/refena_flutter.dart';
import 'package:routerino/routerino.dart';
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:localsend_app/theme.dart';
import 'package:localsend_app/config/theme.dart';
class CustomListTile extends StatelessWidget {
final Widget? icon;
+2 -2
View File
@@ -11,8 +11,8 @@ REGEX_B="s/\/\/ \[FOSS_REMOVE_END\]/\*\//"
sed -i '/# \[FOSS_REMOVE\]/d' pubspec.yaml
# Comment out parts in Dart files
sed -i "$REGEX_A" lib/init.dart
sed -i "$REGEX_B" lib/init.dart
sed -i "$REGEX_A" lib/config/init.dart
sed -i "$REGEX_B" lib/config/init.dart
sed -i "$REGEX_A" lib/pages/donation/donation_page.dart
sed -i "$REGEX_B" lib/pages/donation/donation_page.dart