actions-test/lib/screens/settings/main.dart
Jakob Meier ecccec7950
Fixed bug where homescreen would load twice
Moved AccountMeta provider into <User> context
and migrated to using a FutureProvider to perform the network request

NOTE: Bug was caused by AccountMeta? being loaded late,
causing the root provider to be reloaded.
2023-03-29 18:27:05 +02:00

270 lines
12 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;
Function refreshUser;
SettingsPage(
{super.key, required this.refreshTheme, required this.refreshUser});
@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');
widget.refreshUser();
},
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');
widget.refreshUser();
},
child: Text(AppLocalizations.of(context)!.yes),
)
],
));
},
))
]))));
}
}