actions-test/lib/screens/settings/main.dart
Jakob Meier 1af8d6f068
Migrated from localstore to shared preferences
(only for user, server and theme)

This was done, because localstore is somewhat inconsistent
in terms of events on different platforms.
Also storing user, server and theme using shared-preferences
should fit into flutters ecosystem a little better
2023-03-29 18:27:05 +02:00

266 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/backend/themes.dart';
import 'package:outbag_app/backend/user.dart';
import 'package:outbag_app/screens/settings/dialogs/password.dart';
import 'package:outbag_app/tools/fetch_wrapper.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class SettingsPage extends StatefulWidget {
Function refreshTheme;
SettingsPage({super.key, required this.refreshTheme});
@override
State<StatefulWidget> createState() => _SettingsPageState();
}
class _SettingsPageState extends State<SettingsPage> {
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context)
.textTheme
.apply(displayColor: Theme.of(context).colorScheme.onSurface);
final user = context.watch<User>();
final meta = context.watch<AccountMeta?>();
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context)!.settings),
),
body: SingleChildScrollView(
child: Center(
child: Column(children: [
// uswer information widget
Padding(
padding: const EdgeInsets.all(14),
child: Card(
child: Padding(
padding: const EdgeInsets.all(8),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8),
child: Text(user.humanReadable,
style: textTheme.titleLarge)),
ListTile(
title: Text(
AppLocalizations.of(context)!.limitRoomCount),
subtitle: Text(AppLocalizations.of(context)!
.limitRoomCountSubtitle),
trailing: Text('${meta?.maxRoomCount ?? ""}'),
),
ListTile(
title: Text(
AppLocalizations.of(context)!.limitRoomSize),
subtitle: Text(AppLocalizations.of(context)!
.limitRoomSizeSubtitle),
trailing: Text('${meta?.maxRoomSize ?? ""}'),
),
ListTile(
title: Text(AppLocalizations.of(context)!
.limitRoomMemberCount),
subtitle: Text(AppLocalizations.of(context)!
.limitRoomMemberCountSubtitle),
trailing:
Text('${meta?.maxRoomMemberCount ?? ""}')),
ListTile(
title: Text(AppLocalizations.of(context)!
.userDiscoverable),
subtitle: Text(AppLocalizations.of(context)!
.userDiscoverableSubtitle),
trailing: Checkbox(
tristate: true,
value: meta?.discoverable,
onChanged: (_) {
// TODO: implement changeVisibility
},
))
],
)))),
// change theme button
ListTile(
title: Text(AppLocalizations.of(context)!.changeThemeTitle),
subtitle: Text(AppLocalizations.of(context)!.changeThemeSubtitle),
trailing: const Icon(Icons.chevron_right),
onTap: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
AppLocalizations.of(context)!.changeThemeTitle),
content: SingleChildScrollView(
child: Column(children: [
Padding(
padding: const EdgeInsets.all(8),
child: Text(AppLocalizations.of(context)!
.changeThemeSubtitle),
),
SegmentedButton<AppTheme>(
selected: {context.watch<AppTheme>()},
selectedIcon: Icon(context.watch<AppTheme>().icon),
showSelectedIcon: true,
multiSelectionEnabled: false,
emptySelectionAllowed: false,
segments: AppTheme.list().map((item) {
return ButtonSegment<AppTheme>(
value: item,
icon: Icon(item.icon),
label: Text(item.name(context)));
}).toList(),
onSelectionChanged: (item) async {
try {
await item.first.toDisk();
widget.refreshTheme();
} catch (_) {}
},
),
])),
actions: [
FilledButton(
child: Text(AppLocalizations.of(context)!.close),
onPressed: () {
context.pop();
},
)
],
));
},
),
// change password button
ListTile(
title: Text(AppLocalizations.of(context)!.changePasswordTitle),
subtitle:
Text(AppLocalizations.of(context)!.changePasswordSubtitle),
onTap: () {
showDialog(
context: context,
builder: (context) => const ChangePasswordDialog());
},
trailing: const Icon(Icons.chevron_right),
),
// export account to json
ListTile(
title: Text(AppLocalizations.of(context)!.exportAccountTitle),
subtitle: Text(AppLocalizations.of(context)!.exportAccountSubtitle),
onTap: () {
// TODO: show confirm dialog
// NOTE: json dump the localstore
// including users and rooms
// NOTE: feature not confirmed
},
trailing: const Icon(Icons.chevron_right),
),
// delete account button
ListTile(
title: Text(AppLocalizations.of(context)!.deleteAccountTitle),
subtitle: Text(AppLocalizations.of(context)!.deleteAccountSubtitle),
onTap: () {
// show confirm dialog
// NOTE: same as logout
// and performs a network request
// but deletes account beforehand
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text(
AppLocalizations.of(context)!.deleteAccountTitle),
content: Text(
AppLocalizations.of(context)!.deleteAccountConfirm),
actions: [
TextButton(
onPressed: () {
// close popup
Navigator.of(ctx).pop();
},
child: Text(AppLocalizations.of(context)!.cancel),
),
FilledButton(
onPressed: () async {
// send request
final scaffMgr = ScaffoldMessenger.of(ctx);
final nav = Navigator.of(ctx);
final router = GoRouter.of(ctx);
doNetworkRequest(scaffMgr,
req: () => postWithCreadentials(
path: 'deleteAccount',
target: user.server,
body: {},
credentials: user),
onOK: (_) async {
// delete everything
// delete user data (meta)
try {
await User.removeDisk();
} catch (_) {}
// TODO: delete all rooms
// go back home
router.pushReplacementNamed('home');
},
after: () {
// close popup
nav.pop();
});
},
child: Text(AppLocalizations.of(context)!.yes),
)
],
));
},
trailing: const Icon(Icons.chevron_right),
),
// logout button
Padding(
padding: const EdgeInsets.all(8),
child: FilledButton.tonal(
child: Text(AppLocalizations.of(context)!.logOut),
onPressed: () {
// show confirm dialog
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text(AppLocalizations.of(context)!.logOut),
content: Text(
AppLocalizations.of(context)!.logOutConfirm),
actions: [
TextButton(
onPressed: () {
// close popup
Navigator.of(ctx).pop();
},
child:
Text(AppLocalizations.of(context)!.cancel),
),
FilledButton(
onPressed: () async {
// send request
final router = GoRouter.of(ctx);
// delete everything
// delete user data (meta)
try {
await User.removeDisk();
} catch (_) {}
// TODO: delete all rooms
// go back home
router.pushReplacementNamed('home');
},
child: Text(AppLocalizations.of(context)!.yes),
)
],
));
},
))
]))));
}
}