From 18f062a614e2dec7f380939e7eb2c9e3f1209c9c Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Tue, 11 Jul 2023 18:39:39 +0200 Subject: [PATCH] neon: constrain settings pages --- .../neon/lib/src/pages/account_settings.dart | 190 ++++---- .../lib/src/pages/nextcloud_app_settings.dart | 98 ++-- .../neon/neon/lib/src/pages/settings.dart | 457 +++++++++--------- 3 files changed, 388 insertions(+), 357 deletions(-) diff --git a/packages/neon/neon/lib/src/pages/account_settings.dart b/packages/neon/neon/lib/src/pages/account_settings.dart index daebb0fc..f99d90b8 100644 --- a/packages/neon/neon/lib/src/pages/account_settings.dart +++ b/packages/neon/neon/lib/src/pages/account_settings.dart @@ -10,13 +10,14 @@ import 'package:neon/src/settings/widgets/custom_settings_tile.dart'; import 'package:neon/src/settings/widgets/dropdown_button_settings_tile.dart'; import 'package:neon/src/settings/widgets/settings_category.dart'; import 'package:neon/src/settings/widgets/settings_list.dart'; +import 'package:neon/src/theme/dialog.dart'; import 'package:neon/src/utils/confirmation_dialog.dart'; import 'package:neon/src/widgets/exception.dart'; import 'package:neon/src/widgets/linear_progress_indicator.dart'; import 'package:nextcloud/nextcloud.dart'; class AccountSettingsPage extends StatelessWidget { - AccountSettingsPage({ + const AccountSettingsPage({ required this.bloc, required this.account, super.key, @@ -25,104 +26,115 @@ class AccountSettingsPage extends StatelessWidget { final AccountsBloc bloc; final Account account; - late final _options = bloc.getOptionsFor(account); - late final _userDetailsBloc = bloc.getUserDetailsBlocFor(account); - late final _name = account.client.humanReadableID; - @override - Widget build(final BuildContext context) => Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - title: Text(_name), - actions: [ - IconButton( - onPressed: () async { - if (await showConfirmationDialog( - context, - AppLocalizations.of(context).accountOptionsRemoveConfirm(account.client.humanReadableID), - )) { - final isActive = bloc.activeAccount.value == account; + Widget build(final BuildContext context) { + final options = bloc.getOptionsFor(account); + final userDetailsBloc = bloc.getUserDetailsBlocFor(account); + final name = account.client.humanReadableID; + + final appBar = AppBar( + title: Text(name), + actions: [ + IconButton( + onPressed: () async { + if (await showConfirmationDialog( + context, + AppLocalizations.of(context).accountOptionsRemoveConfirm(account.client.humanReadableID), + )) { + final isActive = bloc.activeAccount.value == account; - bloc.removeAccount(account); + bloc.removeAccount(account); - // ignore: use_build_context_synchronously - if (!context.mounted) { - return; - } + // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } - if (isActive) { - const HomeRoute().go(context); - } else { - Navigator.of(context).pop(); - } - } - }, - tooltip: AppLocalizations.of(context).accountOptionsRemove, - icon: Icon(MdiIcons.delete), - ), - IconButton( - onPressed: () async { - if (await showConfirmationDialog( - context, - AppLocalizations.of(context).settingsResetForConfirmation(_name), - )) { - await _options.reset(); - } - }, - tooltip: AppLocalizations.of(context).settingsResetFor(_name), - icon: Icon(MdiIcons.cogRefresh), - ), - ], + if (isActive) { + const HomeRoute().go(context); + } else { + Navigator.of(context).pop(); + } + } + }, + tooltip: AppLocalizations.of(context).accountOptionsRemove, + icon: Icon(MdiIcons.delete), ), - body: ResultBuilder.behaviorSubject( - stream: _userDetailsBloc.userDetails, - builder: (final context, final userDetails) => SettingsList( - categories: [ - SettingsCategory( - title: Text(AppLocalizations.of(context).accountOptionsCategoryStorageInfo), - tiles: [ - CustomSettingsTile( - title: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (userDetails.hasData) ...[ - LinearProgressIndicator( - value: userDetails.requireData.quota.relative / 100, - backgroundColor: Theme.of(context).colorScheme.primary.withOpacity(0.3), - ), - const SizedBox( - height: 10, - ), - Text( - AppLocalizations.of(context).accountOptionsQuotaUsedOf( - filesize(userDetails.requireData.quota.used, 1), - filesize(userDetails.requireData.quota.total, 1), - userDetails.requireData.quota.relative.toString(), - ), - ), - ], - NeonException( - userDetails.error, - onRetry: _userDetailsBloc.refresh, - ), - NeonLinearProgressIndicator( - visible: userDetails.isLoading, + IconButton( + onPressed: () async { + if (await showConfirmationDialog( + context, + AppLocalizations.of(context).settingsResetForConfirmation(name), + )) { + await options.reset(); + } + }, + tooltip: AppLocalizations.of(context).settingsResetFor(name), + icon: Icon(MdiIcons.cogRefresh), + ), + ], + ); + + final body = ResultBuilder.behaviorSubject( + stream: userDetailsBloc.userDetails, + builder: (final context, final userDetails) => SettingsList( + categories: [ + SettingsCategory( + title: Text(AppLocalizations.of(context).accountOptionsCategoryStorageInfo), + tiles: [ + CustomSettingsTile( + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (userDetails.hasData) ...[ + LinearProgressIndicator( + value: userDetails.requireData.quota.relative / 100, + backgroundColor: Theme.of(context).colorScheme.primary.withOpacity(0.3), + ), + const SizedBox( + height: 10, + ), + Text( + AppLocalizations.of(context).accountOptionsQuotaUsedOf( + filesize(userDetails.requireData.quota.used, 1), + filesize(userDetails.requireData.quota.total, 1), + userDetails.requireData.quota.relative.toString(), ), - ], + ), + ], + NeonException( + userDetails.error, + onRetry: userDetailsBloc.refresh, ), - ), - ], + NeonLinearProgressIndicator( + visible: userDetails.isLoading, + ), + ], + ), ), - SettingsCategory( - title: Text(AppLocalizations.of(context).optionsCategoryGeneral), - tiles: [ - DropdownButtonSettingsTile( - option: _options.initialApp, - ), - ], + ], + ), + SettingsCategory( + title: Text(AppLocalizations.of(context).optionsCategoryGeneral), + tiles: [ + DropdownButtonSettingsTile( + option: options.initialApp, ), ], ), + ], + ), + ); + + return Scaffold( + resizeToAvoidBottomInset: false, + appBar: appBar, + body: Center( + child: ConstrainedBox( + constraints: NeonDialogTheme.of(context).constraints, + child: body, ), - ); + ), + ); + } } diff --git a/packages/neon/neon/lib/src/pages/nextcloud_app_settings.dart b/packages/neon/neon/lib/src/pages/nextcloud_app_settings.dart index bea73d1b..6d236458 100644 --- a/packages/neon/neon/lib/src/pages/nextcloud_app_settings.dart +++ b/packages/neon/neon/lib/src/pages/nextcloud_app_settings.dart @@ -8,6 +8,7 @@ import 'package:neon/src/settings/widgets/checkbox_settings_tile.dart'; import 'package:neon/src/settings/widgets/dropdown_button_settings_tile.dart'; import 'package:neon/src/settings/widgets/settings_category.dart'; import 'package:neon/src/settings/widgets/settings_list.dart'; +import 'package:neon/src/theme/dialog.dart'; import 'package:neon/src/utils/confirmation_dialog.dart'; class NextcloudAppSettingsPage extends StatelessWidget { @@ -19,53 +20,62 @@ class NextcloudAppSettingsPage extends StatelessWidget { final AppImplementation appImplementation; @override - Widget build(final BuildContext context) => Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - title: Text(appImplementation.name(context)), - actions: [ - IconButton( - onPressed: () async { - if (await showConfirmationDialog( - context, - AppLocalizations.of(context).settingsResetForConfirmation(appImplementation.name(context)), - )) { - await appImplementation.options.reset(); - } - }, - tooltip: AppLocalizations.of(context).settingsResetFor(appImplementation.name(context)), - icon: Icon(MdiIcons.cogRefresh), - ), - ], + Widget build(final BuildContext context) { + final appBar = AppBar( + title: Text(appImplementation.name(context)), + actions: [ + IconButton( + onPressed: () async { + if (await showConfirmationDialog( + context, + AppLocalizations.of(context).settingsResetForConfirmation(appImplementation.name(context)), + )) { + await appImplementation.options.reset(); + } + }, + tooltip: AppLocalizations.of(context).settingsResetFor(appImplementation.name(context)), + icon: Icon(MdiIcons.cogRefresh), ), - body: SettingsList( - categories: [ - for (final category in [...appImplementation.options.categories, null]) ...[ - if (appImplementation.options.options - .where((final option) => option.category == category) - .isNotEmpty) ...[ - SettingsCategory( - title: Text( - category != null ? category.name(context) : AppLocalizations.of(context).optionsCategoryOther, - ), - tiles: [ - for (final option - in appImplementation.options.options.where((final option) => option.category == category)) ...[ - if (option is ToggleOption) ...[ - CheckBoxSettingsTile( - option: option, - ), - ] else if (option is SelectOption) ...[ - DropdownButtonSettingsTile( - option: option, - ), - ], - ], + ], + ); + + final body = SettingsList( + categories: [ + for (final category in [...appImplementation.options.categories, null]) ...[ + if (appImplementation.options.options.where((final option) => option.category == category).isNotEmpty) ...[ + SettingsCategory( + title: Text( + category != null ? category.name(context) : AppLocalizations.of(context).optionsCategoryOther, + ), + tiles: [ + for (final option + in appImplementation.options.options.where((final option) => option.category == category)) ...[ + if (option is ToggleOption) ...[ + CheckBoxSettingsTile( + option: option, + ), + ] else if (option is SelectOption) ...[ + DropdownButtonSettingsTile( + option: option, + ), ], - ), + ], ], - ], + ), ], + ], + ], + ); + + return Scaffold( + resizeToAvoidBottomInset: false, + appBar: appBar, + body: Center( + child: ConstrainedBox( + constraints: NeonDialogTheme.of(context).constraints, + child: body, ), - ); + ), + ); + } } diff --git a/packages/neon/neon/lib/src/pages/settings.dart b/packages/neon/neon/lib/src/pages/settings.dart index 06134363..61d4930e 100644 --- a/packages/neon/neon/lib/src/pages/settings.dart +++ b/packages/neon/neon/lib/src/pages/settings.dart @@ -19,6 +19,7 @@ import 'package:neon/src/settings/widgets/settings_list.dart'; import 'package:neon/src/settings/widgets/settings_tile.dart'; import 'package:neon/src/settings/widgets/text_settings_tile.dart'; import 'package:neon/src/theme/branding.dart'; +import 'package:neon/src/theme/dialog.dart'; import 'package:neon/src/utils/confirmation_dialog.dart'; import 'package:neon/src/utils/global_options.dart'; import 'package:neon/src/utils/save_file.dart'; @@ -57,263 +58,271 @@ class _SettingsPageState extends State { final accountsBloc = Provider.of(context, listen: false); final appImplementations = Provider.of>(context); - return Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - title: Text(AppLocalizations.of(context).settings), - actions: [ - IconButton( - onPressed: () async { - if (await showConfirmationDialog(context, AppLocalizations.of(context).settingsResetAllConfirmation)) { - await globalOptions.reset(); + final appBar = AppBar( + title: Text(AppLocalizations.of(context).settings), + actions: [ + IconButton( + onPressed: () async { + if (await showConfirmationDialog(context, AppLocalizations.of(context).settingsResetAllConfirmation)) { + await globalOptions.reset(); - for (final appImplementation in appImplementations) { - await appImplementation.options.reset(); - } + for (final appImplementation in appImplementations) { + await appImplementation.options.reset(); + } - for (final account in accountsBloc.accounts.value) { - await accountsBloc.getOptionsFor(account).reset(); - } + for (final account in accountsBloc.accounts.value) { + await accountsBloc.getOptionsFor(account).reset(); } - }, - tooltip: AppLocalizations.of(context).settingsResetAll, - icon: Icon(MdiIcons.cogRefresh), - ), - ], - ), - body: StreamBuilder>( - stream: accountsBloc.accounts, - initialData: accountsBloc.accounts.valueOrNull, - builder: ( - final context, - final accountsSnapshot, - ) { - final platform = Provider.of(context, listen: false); - return StreamBuilder( - stream: globalOptions.pushNotificationsEnabled.enabled, - initialData: globalOptions.pushNotificationsEnabled.enabled.valueOrNull, - builder: ( - final context, - final pushNotificationsEnabledEnabledSnapshot, - ) => - SettingsList( - initialCategory: widget.initialCategory?.name, - categories: [ + } + }, + tooltip: AppLocalizations.of(context).settingsResetAll, + icon: Icon(MdiIcons.cogRefresh), + ), + ], + ); + final body = StreamBuilder>( + stream: accountsBloc.accounts, + initialData: accountsBloc.accounts.valueOrNull, + builder: ( + final context, + final accountsSnapshot, + ) { + final platform = Provider.of(context, listen: false); + return StreamBuilder( + stream: globalOptions.pushNotificationsEnabled.enabled, + initialData: globalOptions.pushNotificationsEnabled.enabled.valueOrNull, + builder: ( + final context, + final pushNotificationsEnabledEnabledSnapshot, + ) => + SettingsList( + initialCategory: widget.initialCategory?.name, + categories: [ + SettingsCategory( + title: Text(AppLocalizations.of(context).settingsApps), + key: ValueKey(SettingsCageories.apps.name), + tiles: [ + for (final appImplementation in appImplementations) ...[ + if (appImplementation.options.options.isNotEmpty) ...[ + CustomSettingsTile( + leading: appImplementation.buildIcon(), + title: Text(appImplementation.name(context)), + onTap: () { + NextcloudAppSettingsRoute(appid: appImplementation.id).go(context); + }, + ), + ], + ], + ], + ), + SettingsCategory( + title: Text(AppLocalizations.of(context).optionsCategoryTheme), + key: ValueKey(SettingsCageories.theme.name), + tiles: [ + DropdownButtonSettingsTile( + option: globalOptions.themeMode, + ), + CheckBoxSettingsTile( + option: globalOptions.themeOLEDAsDark, + ), + CheckBoxSettingsTile( + option: globalOptions.themeKeepOriginalAccentColor, + ), + ], + ), + SettingsCategory( + title: Text(AppLocalizations.of(context).optionsCategoryNavigation), + key: ValueKey(SettingsCageories.navigation.name), + tiles: [ + DropdownButtonSettingsTile( + option: globalOptions.navigationMode, + ), + ], + ), + if (platform.canUsePushNotifications) ...[ SettingsCategory( - title: Text(AppLocalizations.of(context).settingsApps), - key: ValueKey(SettingsCageories.apps.name), - tiles: [ - for (final appImplementation in appImplementations) ...[ - if (appImplementation.options.options.isNotEmpty) ...[ - CustomSettingsTile( - leading: appImplementation.buildIcon(), - title: Text(appImplementation.name(context)), - onTap: () { - NextcloudAppSettingsRoute(appid: appImplementation.id).go(context); - }, + title: Text(AppLocalizations.of(context).optionsCategoryPushNotifications), + key: ValueKey(SettingsCageories.pushNotifications.name), + tiles: [ + if (pushNotificationsEnabledEnabledSnapshot.hasData && + !pushNotificationsEnabledEnabledSnapshot.requireData) ...[ + TextSettingsTile( + text: AppLocalizations.of(context).globalOptionsPushNotificationsEnabledDisabledNotice, + style: TextStyle( + fontWeight: FontWeight.w600, + fontStyle: FontStyle.italic, + color: Theme.of(context).colorScheme.error, ), - ], + ), ], + CheckBoxSettingsTile( + option: globalOptions.pushNotificationsEnabled, + ), + DropdownButtonSettingsTile( + option: globalOptions.pushNotificationsDistributor, + ), ], ), + ], + if (platform.canUseWindowManager) ...[ SettingsCategory( - title: Text(AppLocalizations.of(context).optionsCategoryTheme), - key: ValueKey(SettingsCageories.theme.name), + title: Text(AppLocalizations.of(context).optionsCategoryStartup), + key: ValueKey(SettingsCageories.startup.name), tiles: [ - DropdownButtonSettingsTile( - option: globalOptions.themeMode, - ), CheckBoxSettingsTile( - option: globalOptions.themeOLEDAsDark, + option: globalOptions.startupMinimized, ), CheckBoxSettingsTile( - option: globalOptions.themeKeepOriginalAccentColor, + option: globalOptions.startupMinimizeInsteadOfExit, ), ], ), + ], + if (platform.canUseWindowManager && platform.canUseSystemTray) ...[ SettingsCategory( - title: Text(AppLocalizations.of(context).optionsCategoryNavigation), - key: ValueKey(SettingsCageories.navigation.name), + title: Text(AppLocalizations.of(context).optionsCategorySystemTray), + key: ValueKey(SettingsCageories.systemTray.name), tiles: [ - DropdownButtonSettingsTile( - option: globalOptions.navigationMode, + CheckBoxSettingsTile( + option: globalOptions.systemTrayEnabled, + ), + CheckBoxSettingsTile( + option: globalOptions.systemTrayHideToTrayWhenMinimized, ), ], ), - if (platform.canUsePushNotifications) ...[ - SettingsCategory( - title: Text(AppLocalizations.of(context).optionsCategoryPushNotifications), - key: ValueKey(SettingsCageories.pushNotifications.name), - tiles: [ - if (pushNotificationsEnabledEnabledSnapshot.hasData && - !pushNotificationsEnabledEnabledSnapshot.requireData) ...[ - TextSettingsTile( - text: AppLocalizations.of(context).globalOptionsPushNotificationsEnabledDisabledNotice, - style: TextStyle( - fontWeight: FontWeight.w600, - fontStyle: FontStyle.italic, - color: Theme.of(context).colorScheme.error, - ), - ), - ], - CheckBoxSettingsTile( - option: globalOptions.pushNotificationsEnabled, - ), - DropdownButtonSettingsTile( - option: globalOptions.pushNotificationsDistributor, - ), - ], - ), - ], - if (platform.canUseWindowManager) ...[ - SettingsCategory( - title: Text(AppLocalizations.of(context).optionsCategoryStartup), - key: ValueKey(SettingsCageories.startup.name), - tiles: [ - CheckBoxSettingsTile( - option: globalOptions.startupMinimized, - ), - CheckBoxSettingsTile( - option: globalOptions.startupMinimizeInsteadOfExit, - ), - ], - ), - ], - if (platform.canUseWindowManager && platform.canUseSystemTray) ...[ - SettingsCategory( - title: Text(AppLocalizations.of(context).optionsCategorySystemTray), - key: ValueKey(SettingsCageories.systemTray.name), - tiles: [ - CheckBoxSettingsTile( - option: globalOptions.systemTrayEnabled, - ), - CheckBoxSettingsTile( - option: globalOptions.systemTrayHideToTrayWhenMinimized, - ), - ], - ), - ], - SettingsCategory( - title: Text(AppLocalizations.of(context).optionsCategoryAccounts), - key: ValueKey(SettingsCageories.accounts.name), - tiles: [ - if (accountsSnapshot.requireData.length > 1) ...[ - CheckBoxSettingsTile( - option: globalOptions.rememberLastUsedAccount, - ), - DropdownButtonSettingsTile( - option: globalOptions.initialAccount, - ), - ], - for (final account in accountsSnapshot.requireData) ...[ - AccountSettingsTile( - account: account, - onTap: () { - AccountSettingsRoute(accountid: account.id).go(context); - }, - ), - ], - CustomSettingsTile( - title: ElevatedButton.icon( - onPressed: () async => const LoginRoute().push(context), - icon: Icon(MdiIcons.accountPlus), - label: Text(AppLocalizations.of(context).globalOptionsAccountsAdd), - ), - ) + ], + SettingsCategory( + title: Text(AppLocalizations.of(context).optionsCategoryAccounts), + key: ValueKey(SettingsCageories.accounts.name), + tiles: [ + if (accountsSnapshot.requireData.length > 1) ...[ + CheckBoxSettingsTile( + option: globalOptions.rememberLastUsedAccount, + ), + DropdownButtonSettingsTile( + option: globalOptions.initialAccount, + ), ], - ), - SettingsCategory( - title: Text(AppLocalizations.of(context).optionsCategoryOther), - key: ValueKey(SettingsCageories.other.name), - tiles: [ - CustomSettingsTile( - leading: Icon( - MdiIcons.scriptText, - color: Theme.of(context).colorScheme.primary, - ), - title: Text(AppLocalizations.of(context).licenses), - onTap: () async { - final branding = Branding.of(context); - showLicensePage( - context: context, - applicationName: branding.name, - applicationIcon: branding.logo, - applicationLegalese: branding.legalese, - applicationVersion: Provider.of(context, listen: false).version, - ); + for (final account in accountsSnapshot.requireData) ...[ + AccountSettingsTile( + account: account, + onTap: () { + AccountSettingsRoute(accountid: account.id).go(context); }, ), - CustomSettingsTile( - leading: Icon( - MdiIcons.export, - color: Theme.of(context).colorScheme.primary, - ), - title: Text(AppLocalizations.of(context).settingsExport), - onTap: () async { - final settingsExportHelper = _buildSettingsExportHelper(context); + ], + CustomSettingsTile( + title: ElevatedButton.icon( + onPressed: () async => const LoginRoute().push(context), + icon: Icon(MdiIcons.accountPlus), + label: Text(AppLocalizations.of(context).globalOptionsAccountsAdd), + ), + ) + ], + ), + SettingsCategory( + title: Text(AppLocalizations.of(context).optionsCategoryOther), + key: ValueKey(SettingsCageories.other.name), + tiles: [ + CustomSettingsTile( + leading: Icon( + MdiIcons.scriptText, + color: Theme.of(context).colorScheme.primary, + ), + title: Text(AppLocalizations.of(context).licenses), + onTap: () async { + final branding = Branding.of(context); + showLicensePage( + context: context, + applicationName: branding.name, + applicationIcon: branding.logo, + applicationLegalese: branding.legalese, + applicationVersion: Provider.of(context, listen: false).version, + ); + }, + ), + CustomSettingsTile( + leading: Icon( + MdiIcons.export, + color: Theme.of(context).colorScheme.primary, + ), + title: Text(AppLocalizations.of(context).settingsExport), + onTap: () async { + final settingsExportHelper = _buildSettingsExportHelper(context); - try { - final fileName = - 'nextcloud-neon-settings-${DateTime.now().millisecondsSinceEpoch ~/ 1000}.json.base64'; - final data = base64.encode( - utf8.encode( - json.encode( - settingsExportHelper.toJsonExport(), - ), + try { + final fileName = + 'nextcloud-neon-settings-${DateTime.now().millisecondsSinceEpoch ~/ 1000}.json.base64'; + final data = base64.encode( + utf8.encode( + json.encode( + settingsExportHelper.toJsonExport(), ), - ); - await saveFileWithPickDialog(fileName, Uint8List.fromList(utf8.encode(data))); - } catch (e, s) { - debugPrint(e.toString()); - debugPrint(s.toString()); - NeonException.showSnackbar(context, e); - } - }, + ), + ); + await saveFileWithPickDialog(fileName, Uint8List.fromList(utf8.encode(data))); + } catch (e, s) { + debugPrint(e.toString()); + debugPrint(s.toString()); + NeonException.showSnackbar(context, e); + } + }, + ), + CustomSettingsTile( + leading: Icon( + MdiIcons.import, + color: Theme.of(context).colorScheme.primary, ), - CustomSettingsTile( - leading: Icon( - MdiIcons.import, - color: Theme.of(context).colorScheme.primary, - ), - title: Text(AppLocalizations.of(context).settingsImport), - onTap: () async { - final settingsExportHelper = _buildSettingsExportHelper(context); + title: Text(AppLocalizations.of(context).settingsImport), + onTap: () async { + final settingsExportHelper = _buildSettingsExportHelper(context); - try { - final result = await FilePicker.platform.pickFiles( - withData: true, - ); + try { + final result = await FilePicker.platform.pickFiles( + withData: true, + ); - if (result == null) { - return; - } + if (result == null) { + return; + } - if (!result.files.single.path!.endsWith('.json.base64')) { - if (mounted) { - NeonException.showSnackbar( - context, - AppLocalizations.of(context).settingsImportWrongFileExtension, - ); - } - return; + if (!result.files.single.path!.endsWith('.json.base64')) { + if (mounted) { + NeonException.showSnackbar( + context, + AppLocalizations.of(context).settingsImportWrongFileExtension, + ); } + return; + } - final data = json.decode(utf8.decode(base64.decode(utf8.decode(result.files.single.bytes!)))); + final data = json.decode(utf8.decode(base64.decode(utf8.decode(result.files.single.bytes!)))); - await settingsExportHelper.applyFromJson(data as Map); - } catch (e, s) { - debugPrint(e.toString()); - debugPrint(s.toString()); - NeonException.showSnackbar(context, e); - } - }, - ), - ], - ), - ], - ), - ); - }, + await settingsExportHelper.applyFromJson(data as Map); + } catch (e, s) { + debugPrint(e.toString()); + debugPrint(s.toString()); + NeonException.showSnackbar(context, e); + } + }, + ), + ], + ), + ], + ), + ); + }, + ); + + return Scaffold( + resizeToAvoidBottomInset: false, + appBar: appBar, + body: Center( + child: ConstrainedBox( + constraints: NeonDialogTheme.of(context).constraints, + child: body, + ), ), ); }