lemmur-app-android/lib/pages/settings.dart

299 lines
9.7 KiB
Dart
Raw Normal View History

import 'package:flutter/cupertino.dart';
2021-01-02 16:41:08 +01:00
import 'package:flutter/foundation.dart';
2020-08-31 16:17:39 +02:00
import 'package:flutter/material.dart';
2020-09-08 00:34:09 +02:00
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
2020-08-31 16:17:39 +02:00
2020-09-16 23:22:04 +02:00
import '../hooks/stores.dart';
2021-02-27 17:02:55 +01:00
import '../l10n/l10n.dart';
import '../util/goto.dart';
2020-10-01 17:57:04 +02:00
import '../widgets/about_tile.dart';
2021-02-28 20:01:32 +01:00
import '../widgets/radio_picker.dart';
import 'add_account.dart';
import 'add_instance.dart';
2021-01-06 00:51:19 +01:00
import 'manage_account.dart';
2020-08-31 16:17:39 +02:00
2020-09-30 19:05:00 +02:00
/// Page with a list of different settings sections
2020-09-03 14:33:17 +02:00
class SettingsPage extends StatelessWidget {
2021-01-03 19:43:39 +01:00
const SettingsPage();
2020-08-31 16:17:39 +02:00
@override
2021-02-09 15:12:13 +01:00
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
2021-03-01 14:21:45 +01:00
title: Text(L10n.of(context).settings),
2021-02-09 15:12:13 +01:00
),
body: ListView(
children: [
ListTile(
leading: const Icon(Icons.person),
2021-03-01 14:21:45 +01:00
title: Text(L10n.of(context).accounts),
2021-02-09 15:12:13 +01:00
onTap: () {
goTo(context, (_) => AccountsConfigPage());
},
),
ListTile(
leading: const Icon(Icons.color_lens),
2021-03-01 14:21:45 +01:00
title: Text(L10n.of(context).appearance),
2021-02-09 15:12:13 +01:00
onTap: () {
goTo(context, (_) => const AppearanceConfigPage());
},
),
const AboutTile()
],
),
);
2020-08-31 16:17:39 +02:00
}
2020-09-30 19:05:00 +02:00
/// Settings for theme color, AMOLED switch
2020-09-17 00:24:49 +02:00
class AppearanceConfigPage extends HookWidget {
2021-01-03 19:43:39 +01:00
const AppearanceConfigPage();
2020-08-31 16:17:39 +02:00
@override
Widget build(BuildContext context) {
2020-09-16 23:15:42 +02:00
final configStore = useConfigStore();
2020-08-31 16:17:39 +02:00
return Scaffold(
appBar: AppBar(
2021-03-01 14:21:45 +01:00
title: Text(L10n.of(context).appearance),
2020-08-31 16:17:39 +02:00
),
body: ListView(
children: [
2021-01-03 19:43:39 +01:00
const _SectionHeading('Theme'),
for (final theme in ThemeMode.values)
RadioListTile<ThemeMode>(
value: theme,
2021-01-02 16:41:08 +01:00
title: Text(describeEnum(theme)),
groupValue: configStore.theme,
onChanged: (selected) {
configStore.theme = selected;
},
),
SwitchListTile(
2021-02-27 17:02:55 +01:00
title: const Text('AMOLED dark mode'),
value: configStore.amoledDarkMode,
onChanged: (checked) {
configStore.amoledDarkMode = checked;
},
),
const SizedBox(height: 12),
2021-02-28 20:01:32 +01:00
const _SectionHeading('General'),
ListTile(
2021-03-01 14:21:45 +01:00
title: Text(L10n.of(context).language),
2021-02-28 20:01:32 +01:00
trailing: SizedBox(
width: 120,
child: RadioPicker<Locale>(
title: 'Choose language',
groupValue: configStore.locale,
values: L10n.supportedLocales,
// TODO: add actual language names
onChanged: (selected) {
configStore.locale = selected;
},
),
2021-02-27 17:02:55 +01:00
),
2021-02-28 20:01:32 +01:00
),
],
2020-08-31 16:17:39 +02:00
),
);
}
}
2020-09-30 19:05:00 +02:00
/// Settings for managing accounts
class AccountsConfigPage extends HookWidget {
2020-09-08 00:34:09 +02:00
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();
@override
Widget build(BuildContext context) {
2020-09-16 23:22:04 +02:00
final theme = Theme.of(context);
2020-09-16 23:15:42 +02:00
final accountsStore = useAccountsStore();
removeInstanceDialog(String instanceHost) async {
if (await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
2021-01-03 19:43:39 +01:00
title: const Text('Remove instance?'),
content: Text('Are you sure you want to remove $instanceHost?'),
actions: [
2021-02-09 15:12:13 +01:00
TextButton(
2020-09-23 23:37:26 +02:00
onPressed: () => Navigator.of(context).pop(false),
2021-03-01 14:21:45 +01:00
child: Text(L10n.of(context).no),
2020-09-23 23:37:26 +02:00
),
2021-02-09 15:12:13 +01:00
TextButton(
onPressed: () => Navigator.of(context).pop(true),
2021-03-01 14:21:45 +01:00
child: Text(L10n.of(context).yes),
),
],
),
) ??
false) {
accountsStore.removeInstance(instanceHost);
}
}
Future<void> removeUserDialog(String instanceHost, String username) async {
if (await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
2021-01-03 19:43:39 +01:00
title: const Text('Remove user?'),
content: Text(
'Are you sure you want to remove $username@$instanceHost?'),
actions: [
2021-02-09 15:12:13 +01:00
TextButton(
2020-09-23 23:37:26 +02:00
onPressed: () => Navigator.of(context).pop(false),
2021-03-01 14:21:45 +01:00
child: Text(L10n.of(context).no),
2020-09-23 23:37:26 +02:00
),
2021-02-09 15:12:13 +01:00
TextButton(
onPressed: () => Navigator.of(context).pop(true),
2021-03-01 14:21:45 +01:00
child: Text(L10n.of(context).yes),
),
],
),
) ??
false) {
accountsStore.removeAccount(instanceHost, username);
}
}
return Scaffold(
2020-09-08 00:34:09 +02:00
key: _scaffoldKey,
appBar: AppBar(
2021-03-01 14:21:45 +01:00
title: Text(L10n.of(context).accounts),
),
floatingActionButton: SpeedDial(
animatedIcon: AnimatedIcons.menu_close, // TODO: change to + => x
curve: Curves.bounceIn,
tooltip: 'Add account or instance',
2020-09-24 15:48:05 +02:00
overlayColor: theme.canvasColor,
children: [
SpeedDialChild(
2021-01-03 19:43:39 +01:00
child: const Icon(Icons.person_add),
2021-03-01 14:21:45 +01:00
label: L10n.of(context).add_account,
2020-09-24 15:48:05 +02:00
labelBackgroundColor: theme.canvasColor,
onTap: () => showCupertinoModalPopup(
context: context,
builder: (_) =>
AddAccountPage(instanceHost: accountsStore.instances.last)),
),
SpeedDialChild(
2021-01-03 19:43:39 +01:00
child: const Icon(Icons.dns),
2020-09-24 15:48:05 +02:00
labelBackgroundColor: theme.canvasColor,
2021-03-01 14:21:45 +01:00
label: L10n.of(context).add_instance,
onTap: () => showCupertinoModalPopup(
context: context, builder: (_) => AddInstancePage()),
),
],
2021-01-03 19:43:39 +01:00
child: const Icon(Icons.add),
2020-09-08 00:34:09 +02:00
),
body: ListView(
children: [
2021-01-17 17:35:47 +01:00
if (accountsStore.instances.isEmpty)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(top: 100),
2021-02-09 15:12:13 +01:00
child: TextButton.icon(
onPressed: () => showCupertinoModalPopup(
context: context,
builder: (_) => AddInstancePage(),
),
icon: const Icon(Icons.add),
2021-03-01 14:21:45 +01:00
label: Text(L10n.of(context).add_instance),
2021-02-09 15:12:13 +01:00
),
),
],
),
2021-01-06 00:51:19 +01:00
for (final instance in accountsStore.instances) ...[
2021-01-03 19:43:39 +01:00
const SizedBox(height: 40),
Slidable(
2021-01-03 19:43:39 +01:00
actionPane: const SlidableBehindActionPane(),
secondaryActions: [
IconSlideAction(
2021-01-06 00:51:19 +01:00
onTap: () => removeInstanceDialog(instance),
icon: Icons.delete_sweep,
color: Colors.red,
),
],
2021-01-06 00:51:19 +01:00
key: Key(instance),
// TODO: missing ripple effect
child: Container(
2021-01-06 00:51:19 +01:00
color: theme.scaffoldBackgroundColor,
child: ListTile(
dense: true,
2021-01-03 18:03:59 +01:00
contentPadding: EdgeInsets.zero,
2021-01-06 00:51:19 +01:00
title: _SectionHeading(instance),
),
),
),
2021-01-17 17:35:47 +01:00
for (final username in accountsStore.usernamesFor(instance)) ...[
Slidable(
2021-01-03 19:43:39 +01:00
actionPane: const SlidableBehindActionPane(),
2021-01-06 00:51:19 +01:00
key: Key('$username@$instance'),
secondaryActions: [
IconSlideAction(
2021-01-06 00:51:19 +01:00
onTap: () => removeUserDialog(instance, username),
icon: Icons.delete_sweep,
color: Colors.red,
),
],
2021-01-06 00:51:19 +01:00
// TODO: missing ripple effect
child: Container(
2021-01-06 00:51:19 +01:00
color: theme.scaffoldBackgroundColor,
child: ListTile(
trailing:
2021-01-06 00:51:19 +01:00
username == accountsStore.defaultUsernameFor(instance)
2020-09-03 23:14:26 +02:00
? Icon(
Icons.check_circle_outline,
color: theme.accentColor,
)
: null,
title: Text(username),
onLongPress: () {
2021-01-06 00:51:19 +01:00
accountsStore.setDefaultAccountFor(instance, username);
},
onTap: () {
goTo(
context,
2021-01-06 18:45:56 +01:00
(_) => ManageAccountPage(
2021-01-06 00:51:19 +01:00
instanceHost: instance,
username: username,
));
},
),
),
),
2020-09-08 16:37:58 +02:00
],
2021-01-17 17:35:47 +01:00
if (accountsStore.usernamesFor(instance).isEmpty)
ListTile(
2021-01-03 19:43:39 +01:00
leading: const Icon(Icons.add),
2021-03-01 14:21:45 +01:00
title: Text(L10n.of(context).add_account),
onTap: () {
showCupertinoModalPopup(
context: context,
2021-01-06 00:51:19 +01:00
builder: (_) => AddAccountPage(instanceHost: instance));
},
),
]
],
),
);
}
}
2020-09-03 23:14:26 +02:00
class _SectionHeading extends StatelessWidget {
final String text;
const _SectionHeading(this.text);
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Padding(
2021-01-03 19:43:39 +01:00
padding: const EdgeInsets.only(left: 20),
2020-09-03 23:14:26 +02:00
child: Text(text.toUpperCase(),
style: theme.textTheme.subtitle2.copyWith(color: theme.accentColor)),
);
}
}