2021-04-10 06:28:12 +02:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter/widgets.dart';
|
2021-07-03 11:11:04 +02:00
|
|
|
import 'package:logging/logging.dart';
|
2021-04-10 06:28:12 +02:00
|
|
|
import 'package:nc_photos/account.dart';
|
2021-07-25 07:00:38 +02:00
|
|
|
import 'package:nc_photos/app_localizations.dart';
|
2021-07-03 11:11:04 +02:00
|
|
|
import 'package:nc_photos/exception_util.dart' as exception_util;
|
2021-04-10 06:28:12 +02:00
|
|
|
import 'package:nc_photos/k.dart' as k;
|
|
|
|
import 'package:nc_photos/pref.dart';
|
|
|
|
import 'package:nc_photos/snack_bar_manager.dart';
|
2021-04-17 10:59:16 +02:00
|
|
|
import 'package:nc_photos/theme.dart';
|
2021-04-10 06:28:12 +02:00
|
|
|
import 'package:nc_photos/widget/home.dart';
|
2021-07-03 11:11:04 +02:00
|
|
|
import 'package:nc_photos/widget/root_picker.dart';
|
2021-04-10 06:28:12 +02:00
|
|
|
import 'package:nc_photos/widget/sign_in.dart';
|
|
|
|
|
2021-07-03 11:11:04 +02:00
|
|
|
/// A dialog that allows the user to switch between accounts
|
2021-04-10 06:28:12 +02:00
|
|
|
class AccountPickerDialog extends StatefulWidget {
|
2021-09-15 08:58:06 +02:00
|
|
|
const AccountPickerDialog({
|
2021-07-23 22:05:57 +02:00
|
|
|
Key? key,
|
|
|
|
required this.account,
|
2021-04-10 06:28:12 +02:00
|
|
|
}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
createState() => _AccountPickerDialogState();
|
|
|
|
|
|
|
|
final Account account;
|
|
|
|
}
|
|
|
|
|
|
|
|
class _AccountPickerDialogState extends State<AccountPickerDialog> {
|
|
|
|
@override
|
|
|
|
initState() {
|
|
|
|
super.initState();
|
2021-07-23 22:05:57 +02:00
|
|
|
_accounts = Pref.inst().getAccountsOr([]);
|
2021-04-10 06:28:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
build(BuildContext context) {
|
|
|
|
final otherAccountOptions = _accounts
|
|
|
|
.where((a) => a != widget.account)
|
|
|
|
.map((a) => SimpleDialogOption(
|
2021-07-05 07:24:09 +02:00
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
2021-04-10 06:28:12 +02:00
|
|
|
onPressed: () => _onItemPressed(a),
|
|
|
|
child: ListTile(
|
2021-07-05 07:24:09 +02:00
|
|
|
dense: true,
|
2021-04-10 06:28:12 +02:00
|
|
|
title: Text(a.url),
|
|
|
|
subtitle: Text(a.username),
|
|
|
|
trailing: IconButton(
|
2021-07-02 21:47:01 +02:00
|
|
|
icon: Icon(
|
|
|
|
Icons.close,
|
|
|
|
color: AppTheme.getSecondaryTextColor(context),
|
|
|
|
),
|
2021-08-29 13:51:43 +02:00
|
|
|
tooltip: L10n.global().deleteTooltip,
|
2021-07-02 21:47:01 +02:00
|
|
|
onPressed: () => _onRemoveItemPressed(a),
|
|
|
|
),
|
2021-04-10 06:28:12 +02:00
|
|
|
),
|
|
|
|
))
|
|
|
|
.toList();
|
|
|
|
final addAccountOptions = [
|
|
|
|
SimpleDialogOption(
|
2021-07-05 07:24:09 +02:00
|
|
|
padding: const EdgeInsets.all(8),
|
2021-04-10 06:28:12 +02:00
|
|
|
onPressed: () {
|
|
|
|
Navigator.of(context)
|
|
|
|
..pop()
|
|
|
|
..pushNamed(SignIn.routeName);
|
|
|
|
},
|
|
|
|
child: Tooltip(
|
2021-08-29 13:51:43 +02:00
|
|
|
message: L10n.global().addServerTooltip,
|
2021-04-17 10:59:16 +02:00
|
|
|
child: Center(
|
|
|
|
child: Icon(
|
|
|
|
Icons.add,
|
|
|
|
color: AppTheme.getSecondaryTextColor(context),
|
|
|
|
),
|
2021-04-10 06:28:12 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
];
|
2021-08-30 12:14:16 +02:00
|
|
|
return AppTheme(
|
|
|
|
child: SimpleDialog(
|
|
|
|
title: ListTile(
|
|
|
|
dense: true,
|
|
|
|
title: Text(
|
|
|
|
widget.account.url,
|
|
|
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
|
|
|
),
|
|
|
|
subtitle: Text(
|
|
|
|
widget.account.username,
|
|
|
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
|
|
|
),
|
|
|
|
trailing: IconButton(
|
|
|
|
icon: Icon(
|
|
|
|
Icons.edit,
|
|
|
|
color: AppTheme.getSecondaryTextColor(context),
|
|
|
|
),
|
|
|
|
tooltip: L10n.global().editTooltip,
|
|
|
|
onPressed: () => _onEditPressed(),
|
2021-07-03 11:11:04 +02:00
|
|
|
),
|
|
|
|
),
|
2021-08-30 12:14:16 +02:00
|
|
|
titlePadding: const EdgeInsetsDirectional.fromSTEB(8, 16, 8, 0),
|
|
|
|
contentPadding: const EdgeInsetsDirectional.fromSTEB(0, 12, 0, 8),
|
|
|
|
children: otherAccountOptions + addAccountOptions,
|
2021-04-10 06:28:12 +02:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
void _onItemPressed(Account account) {
|
|
|
|
Pref.inst().setCurrentAccountIndex(_accounts.indexOf(account));
|
|
|
|
Navigator.of(context).pushNamedAndRemoveUntil(Home.routeName, (_) => false,
|
|
|
|
arguments: HomeArguments(account));
|
|
|
|
}
|
|
|
|
|
|
|
|
void _onRemoveItemPressed(Account account) {
|
2021-07-23 22:05:57 +02:00
|
|
|
try {
|
|
|
|
_removeAccount(account);
|
|
|
|
setState(() {
|
|
|
|
_accounts = Pref.inst().getAccounts()!;
|
|
|
|
});
|
|
|
|
SnackBarManager().showSnackBar(SnackBar(
|
2021-07-25 07:00:38 +02:00
|
|
|
content:
|
2021-08-29 13:51:43 +02:00
|
|
|
Text(L10n.global().removeServerSuccessNotification(account.url)),
|
2021-07-23 22:05:57 +02:00
|
|
|
duration: k.snackBarDurationNormal,
|
|
|
|
));
|
|
|
|
} catch (e) {
|
|
|
|
SnackBarManager().showSnackBar(SnackBar(
|
2021-08-29 13:51:43 +02:00
|
|
|
content: Text(exception_util.toUserString(e)),
|
2021-07-23 22:05:57 +02:00
|
|
|
duration: k.snackBarDurationNormal,
|
|
|
|
));
|
|
|
|
}
|
2021-04-10 06:28:12 +02:00
|
|
|
}
|
|
|
|
|
2021-07-03 11:11:04 +02:00
|
|
|
void _onEditPressed() async {
|
|
|
|
try {
|
2021-07-23 22:05:57 +02:00
|
|
|
final result = await Navigator.of(context).pushNamed<Account>(
|
|
|
|
RootPicker.routeName,
|
2021-07-03 11:11:04 +02:00
|
|
|
arguments: RootPickerArguments(widget.account));
|
|
|
|
if (result != null) {
|
|
|
|
// we've got a good account
|
|
|
|
if (result == widget.account) {
|
|
|
|
// no changes, do nothing
|
|
|
|
_log.fine("[_onEditPressed] No changes");
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
return;
|
|
|
|
}
|
2021-07-23 22:05:57 +02:00
|
|
|
final accounts = Pref.inst().getAccounts()!;
|
2021-07-03 11:11:04 +02:00
|
|
|
if (accounts.contains(result)) {
|
|
|
|
// conflict with another account. This normally won't happen because
|
|
|
|
// the app passwords are unique to each entry, but just in case
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
SnackBarManager().showSnackBar(SnackBar(
|
2021-08-30 12:14:16 +02:00
|
|
|
content: Text(L10n.global().editAccountConflictFailureNotification),
|
2021-07-03 11:11:04 +02:00
|
|
|
duration: k.snackBarDurationNormal,
|
|
|
|
));
|
|
|
|
return;
|
|
|
|
}
|
2021-07-23 22:05:57 +02:00
|
|
|
accounts[Pref.inst().getCurrentAccountIndex()!] = result;
|
2021-09-15 08:58:06 +02:00
|
|
|
Pref.inst().setAccounts(accounts);
|
2021-07-03 11:11:04 +02:00
|
|
|
Navigator.pushNamedAndRemoveUntil(
|
|
|
|
context, Home.routeName, (route) => false,
|
|
|
|
arguments: HomeArguments(result));
|
|
|
|
}
|
|
|
|
} catch (e, stacktrace) {
|
|
|
|
_log.shout("[_onEditPressed] Exception", e, stacktrace);
|
|
|
|
SnackBarManager().showSnackBar(SnackBar(
|
2021-08-29 13:51:43 +02:00
|
|
|
content: Text(exception_util.toUserString(e)),
|
2021-07-03 11:11:04 +02:00
|
|
|
duration: k.snackBarDurationNormal,
|
|
|
|
));
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-10 06:28:12 +02:00
|
|
|
void _removeAccount(Account account) {
|
2021-07-23 22:05:57 +02:00
|
|
|
final currentAccounts = Pref.inst().getAccounts()!;
|
2021-04-10 06:28:12 +02:00
|
|
|
final currentAccount =
|
2021-07-23 22:05:57 +02:00
|
|
|
currentAccounts[Pref.inst().getCurrentAccountIndex()!];
|
2021-04-10 06:28:12 +02:00
|
|
|
final newAccounts =
|
|
|
|
currentAccounts.where((element) => element != account).toList();
|
|
|
|
final newAccountIndex = newAccounts.indexOf(currentAccount);
|
|
|
|
if (newAccountIndex == -1) {
|
|
|
|
throw StateError("Active account not found in resulting account list");
|
|
|
|
}
|
|
|
|
Pref.inst()
|
|
|
|
..setAccounts(newAccounts)
|
|
|
|
..setCurrentAccountIndex(newAccountIndex);
|
|
|
|
}
|
|
|
|
|
2021-07-23 22:05:57 +02:00
|
|
|
late List<Account> _accounts;
|
2021-07-03 11:11:04 +02:00
|
|
|
|
|
|
|
static final _log =
|
|
|
|
Logger("widget.account_picker_dialog._AccountPickerDialogState");
|
2021-04-10 06:28:12 +02:00
|
|
|
}
|