|
|
|
@ -27,11 +27,25 @@ import 'package:neon/src/widgets/exception.dart';
|
|
|
|
|
import 'package:package_info_plus/package_info_plus.dart'; |
|
|
|
|
import 'package:provider/provider.dart'; |
|
|
|
|
|
|
|
|
|
enum SettingsCageories { |
|
|
|
|
apps, |
|
|
|
|
theme, |
|
|
|
|
navigation, |
|
|
|
|
pushNotifications, |
|
|
|
|
startup, |
|
|
|
|
systemTray, |
|
|
|
|
accounts, |
|
|
|
|
other, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class SettingsPage extends StatefulWidget { |
|
|
|
|
const SettingsPage({ |
|
|
|
|
this.initialCategory, |
|
|
|
|
super.key, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
final SettingsCageories? initialCategory; |
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
State<SettingsPage> createState() => _SettingsPageState(); |
|
|
|
|
} |
|
|
|
@ -42,6 +56,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
final globalOptions = Provider.of<GlobalOptions>(context); |
|
|
|
|
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false); |
|
|
|
|
final appImplementations = Provider.of<Iterable<AppImplementation>>(context); |
|
|
|
|
|
|
|
|
|
return Scaffold( |
|
|
|
|
resizeToAvoidBottomInset: false, |
|
|
|
|
appBar: AppBar( |
|
|
|
@ -68,38 +83,25 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
), |
|
|
|
|
body: StreamBuilder<List<Account>>( |
|
|
|
|
stream: accountsBloc.accounts, |
|
|
|
|
initialData: accountsBloc.accounts.valueOrNull, |
|
|
|
|
builder: ( |
|
|
|
|
final context, |
|
|
|
|
final accountsSnapshot, |
|
|
|
|
) { |
|
|
|
|
final settingsExportHelper = SettingsExportHelper( |
|
|
|
|
globalOptions: globalOptions, |
|
|
|
|
appImplementations: appImplementations, |
|
|
|
|
accountSpecificOptions: { |
|
|
|
|
if (accountsSnapshot.hasData) ...{ |
|
|
|
|
for (final account in accountsSnapshot.requireData) ...{ |
|
|
|
|
account: accountsBloc.getOptionsFor(account).options, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
); |
|
|
|
|
final platform = Provider.of<NeonPlatform>(context, listen: false); |
|
|
|
|
return StreamBuilder<Account?>( |
|
|
|
|
stream: accountsBloc.activeAccount, |
|
|
|
|
builder: ( |
|
|
|
|
final context, |
|
|
|
|
final activeAccountSnapshot, |
|
|
|
|
) => |
|
|
|
|
StreamBuilder<bool>( |
|
|
|
|
return StreamBuilder<bool>( |
|
|
|
|
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: <SettingsTile>[ |
|
|
|
|
for (final appImplementation in appImplementations) ...[ |
|
|
|
|
if (appImplementation.options.options.isNotEmpty) ...[ |
|
|
|
@ -116,6 +118,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
), |
|
|
|
|
SettingsCategory( |
|
|
|
|
title: Text(AppLocalizations.of(context).optionsCategoryTheme), |
|
|
|
|
key: ValueKey(SettingsCageories.theme.name), |
|
|
|
|
tiles: [ |
|
|
|
|
DropdownButtonSettingsTile( |
|
|
|
|
option: globalOptions.themeMode, |
|
|
|
@ -130,6 +133,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
), |
|
|
|
|
SettingsCategory( |
|
|
|
|
title: Text(AppLocalizations.of(context).optionsCategoryNavigation), |
|
|
|
|
key: ValueKey(SettingsCageories.navigation.name), |
|
|
|
|
tiles: [ |
|
|
|
|
DropdownButtonSettingsTile( |
|
|
|
|
option: globalOptions.navigationMode, |
|
|
|
@ -139,6 +143,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
if (platform.canUsePushNotifications) ...[ |
|
|
|
|
SettingsCategory( |
|
|
|
|
title: Text(AppLocalizations.of(context).optionsCategoryPushNotifications), |
|
|
|
|
key: ValueKey(SettingsCageories.pushNotifications.name), |
|
|
|
|
tiles: [ |
|
|
|
|
if (pushNotificationsEnabledEnabledSnapshot.hasData && |
|
|
|
|
!pushNotificationsEnabledEnabledSnapshot.requireData) ...[ |
|
|
|
@ -163,6 +168,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
if (platform.canUseWindowManager) ...[ |
|
|
|
|
SettingsCategory( |
|
|
|
|
title: Text(AppLocalizations.of(context).optionsCategoryStartup), |
|
|
|
|
key: ValueKey(SettingsCageories.startup.name), |
|
|
|
|
tiles: [ |
|
|
|
|
CheckBoxSettingsTile( |
|
|
|
|
option: globalOptions.startupMinimized, |
|
|
|
@ -176,6 +182,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
if (platform.canUseWindowManager && platform.canUseSystemTray) ...[ |
|
|
|
|
SettingsCategory( |
|
|
|
|
title: Text(AppLocalizations.of(context).optionsCategorySystemTray), |
|
|
|
|
key: ValueKey(SettingsCageories.systemTray.name), |
|
|
|
|
tiles: [ |
|
|
|
|
CheckBoxSettingsTile( |
|
|
|
|
option: globalOptions.systemTrayEnabled, |
|
|
|
@ -186,9 +193,9 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
], |
|
|
|
|
), |
|
|
|
|
], |
|
|
|
|
if (accountsSnapshot.hasData) ...[ |
|
|
|
|
SettingsCategory( |
|
|
|
|
title: Text(AppLocalizations.of(context).optionsCategoryAccounts), |
|
|
|
|
key: ValueKey(SettingsCageories.accounts.name), |
|
|
|
|
tiles: [ |
|
|
|
|
if (accountsSnapshot.requireData.length > 1) ...[ |
|
|
|
|
CheckBoxSettingsTile( |
|
|
|
@ -215,9 +222,9 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
) |
|
|
|
|
], |
|
|
|
|
), |
|
|
|
|
], |
|
|
|
|
SettingsCategory( |
|
|
|
|
title: Text(AppLocalizations.of(context).optionsCategoryOther), |
|
|
|
|
key: ValueKey(SettingsCageories.other.name), |
|
|
|
|
tiles: <SettingsTile>[ |
|
|
|
|
CustomSettingsTile( |
|
|
|
|
leading: Icon( |
|
|
|
@ -243,6 +250,8 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
), |
|
|
|
|
title: Text(AppLocalizations.of(context).settingsExport), |
|
|
|
|
onTap: () async { |
|
|
|
|
final settingsExportHelper = _buildSettingsExportHelper(context); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
final fileName = |
|
|
|
|
'nextcloud-neon-settings-${DateTime.now().millisecondsSinceEpoch ~/ 1000}.json.base64'; |
|
|
|
@ -268,6 +277,8 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
), |
|
|
|
|
title: Text(AppLocalizations.of(context).settingsImport), |
|
|
|
|
onTap: () async { |
|
|
|
|
final settingsExportHelper = _buildSettingsExportHelper(context); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
final result = await FilePicker.platform.pickFiles( |
|
|
|
|
withData: true, |
|
|
|
@ -287,8 +298,8 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
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<String, dynamic>); |
|
|
|
|
} catch (e, s) { |
|
|
|
|
debugPrint(e.toString()); |
|
|
|
@ -301,12 +312,25 @@ class _SettingsPageState extends State<SettingsPage> {
|
|
|
|
|
), |
|
|
|
|
], |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
); |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SettingsExportHelper _buildSettingsExportHelper(final BuildContext context) { |
|
|
|
|
final globalOptions = Provider.of<GlobalOptions>(context); |
|
|
|
|
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false); |
|
|
|
|
final appImplementations = Provider.of<Iterable<AppImplementation>>(context); |
|
|
|
|
|
|
|
|
|
return SettingsExportHelper( |
|
|
|
|
globalOptions: globalOptions, |
|
|
|
|
appImplementations: appImplementations, |
|
|
|
|
accountSpecificOptions: accountsBloc.accounts.value.asMap().map( |
|
|
|
|
(final _, final account) => MapEntry(account, accountsBloc.getOptionsFor(account).options), |
|
|
|
|
), |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
enum SettingsAccountAction { |
|
|
|
|