mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-03-13 18:58:53 +01:00
Change root dirs of the current account
This commit is contained in:
parent
ea5706161d
commit
c2b06cfeb6
4 changed files with 137 additions and 3 deletions
|
@ -525,6 +525,15 @@
|
|||
"description": "Edit the opened album"
|
||||
},
|
||||
"doneButtonTooltip": "Done",
|
||||
"editTooltip": "Edit",
|
||||
"editAccountConflictFailureNotification": "An account already exists with the same settings",
|
||||
"@editAccountConflictFailureNotification": {
|
||||
"description": "Error when user modified an account such that it's identical to another one"
|
||||
},
|
||||
"genericProcessingDialogContent": "Please wait",
|
||||
"@genericProcessingDialogContent": {
|
||||
"description": "Generic dialog shown when the app is temporarily blocking user input to work on something"
|
||||
},
|
||||
|
||||
"changelogTitle": "Changelog",
|
||||
"@changelogTitle": {
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/pref.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/widget/home.dart';
|
||||
import 'package:nc_photos/widget/root_picker.dart';
|
||||
import 'package:nc_photos/widget/sign_in.dart';
|
||||
|
||||
/// A dialog that allows the user to switch between accounts
|
||||
class AccountPickerDialog extends StatefulWidget {
|
||||
AccountPickerDialog({
|
||||
Key key,
|
||||
|
@ -76,6 +80,14 @@ class _AccountPickerDialogState extends State<AccountPickerDialog> {
|
|||
widget.account.username,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
trailing: IconButton(
|
||||
icon: Icon(
|
||||
Icons.edit,
|
||||
color: AppTheme.getSecondaryTextColor(context),
|
||||
),
|
||||
tooltip: AppLocalizations.of(context).editTooltip,
|
||||
onPressed: () => _onEditPressed(),
|
||||
),
|
||||
),
|
||||
children: otherAccountOptions + addAccountOptions,
|
||||
);
|
||||
|
@ -99,6 +111,46 @@ class _AccountPickerDialogState extends State<AccountPickerDialog> {
|
|||
));
|
||||
}
|
||||
|
||||
void _onEditPressed() async {
|
||||
try {
|
||||
final result = await Navigator.of(context).pushNamed(RootPicker.routeName,
|
||||
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;
|
||||
}
|
||||
final accounts = Pref.inst().getAccounts([]);
|
||||
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(
|
||||
content: Text(AppLocalizations.of(context)
|
||||
.editAccountConflictFailureNotification),
|
||||
duration: k.snackBarDurationNormal,
|
||||
));
|
||||
return;
|
||||
}
|
||||
accounts[Pref.inst().getCurrentAccountIndex()] = result;
|
||||
Pref.inst()..setAccounts(accounts);
|
||||
Navigator.pushNamedAndRemoveUntil(
|
||||
context, Home.routeName, (route) => false,
|
||||
arguments: HomeArguments(result));
|
||||
}
|
||||
} catch (e, stacktrace) {
|
||||
_log.shout("[_onEditPressed] Exception", e, stacktrace);
|
||||
SnackBarManager().showSnackBar(SnackBar(
|
||||
content: Text(exception_util.toUserString(e, context)),
|
||||
duration: k.snackBarDurationNormal,
|
||||
));
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
|
||||
void _removeAccount(Account account) {
|
||||
final currentAccounts = Pref.inst().getAccounts([]);
|
||||
final currentAccount =
|
||||
|
@ -115,4 +167,7 @@ class _AccountPickerDialogState extends State<AccountPickerDialog> {
|
|||
}
|
||||
|
||||
List<Account> _accounts;
|
||||
|
||||
static final _log =
|
||||
Logger("widget.account_picker_dialog._AccountPickerDialogState");
|
||||
}
|
||||
|
|
|
@ -47,6 +47,11 @@ mixin DirPickerMixin<T extends StatefulWidget> on State<T> {
|
|||
@protected
|
||||
bool canPickDir(File file) => true;
|
||||
|
||||
@protected
|
||||
void pickAll(List<File> dirs) {
|
||||
_picks.addAll(dirs);
|
||||
}
|
||||
|
||||
void _initBloc() {
|
||||
_log.info("[_initBloc] Initialize bloc");
|
||||
_bloc = LsDirBloc();
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/api/api_util.dart' as api_util;
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file/data_source.dart';
|
||||
import 'package:nc_photos/exception_util.dart' as exception_util;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/use_case/ls_single_file.dart';
|
||||
import 'package:nc_photos/widget/dir_picker_mixin.dart';
|
||||
import 'package:nc_photos/widget/processing_dialog.dart';
|
||||
|
||||
class RootPickerArguments {
|
||||
RootPickerArguments(this.account);
|
||||
|
@ -38,6 +44,38 @@ class RootPicker extends StatefulWidget {
|
|||
|
||||
class _RootPickerState extends State<RootPicker>
|
||||
with DirPickerMixin<RootPicker> {
|
||||
@override
|
||||
initState() {
|
||||
super.initState();
|
||||
_initAccount();
|
||||
}
|
||||
|
||||
void _initAccount() async {
|
||||
try {
|
||||
final fileSrc = FileWebdavDataSource();
|
||||
final files = <File>[];
|
||||
for (final r in widget.account.roots) {
|
||||
if (r.isNotEmpty) {
|
||||
_isIniting = true;
|
||||
_ensureInitDialog();
|
||||
files.add(await LsSingleFile(fileSrc).call(widget.account,
|
||||
"${api_util.getWebdavRootUrlRelative(widget.account)}/$r"));
|
||||
}
|
||||
}
|
||||
setState(() {
|
||||
_isIniting = false;
|
||||
pickAll(files);
|
||||
});
|
||||
} catch (e) {
|
||||
SnackBarManager().showSnackBar(SnackBar(
|
||||
content: Text(exception_util.toUserString(e, context)),
|
||||
duration: k.snackBarDurationNormal,
|
||||
));
|
||||
} finally {
|
||||
_dismissInitDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
build(BuildContext context) {
|
||||
return AppTheme(
|
||||
|
@ -77,7 +115,10 @@ class _RootPickerState extends State<RootPicker>
|
|||
),
|
||||
),
|
||||
Expanded(
|
||||
child: buildDirPicker(context),
|
||||
child: IgnorePointer(
|
||||
ignoring: _isIniting,
|
||||
child: buildDirPicker(context),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
|
@ -126,8 +167,7 @@ class _RootPickerState extends State<RootPicker>
|
|||
],
|
||||
)).then((value) {
|
||||
if (value == true) {
|
||||
// default is to include all files, so we just return the same account
|
||||
Navigator.of(context).pop(widget.account);
|
||||
Navigator.of(context).pop(widget.account.copyWith(roots: [""]));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -147,5 +187,30 @@ class _RootPickerState extends State<RootPicker>
|
|||
Navigator.of(context).pop(newAccount);
|
||||
}
|
||||
|
||||
void _ensureInitDialog() {
|
||||
if (_isInitDialogShown) {
|
||||
return;
|
||||
}
|
||||
_isInitDialogShown = true;
|
||||
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||
showDialog(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (context) => ProcessingDialog(
|
||||
text: AppLocalizations.of(context).genericProcessingDialogContent),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void _dismissInitDialog() {
|
||||
if (!_isInitDialogShown) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
bool _isIniting = false;
|
||||
bool _isInitDialogShown = false;
|
||||
|
||||
static final _log = Logger("widget.root_picker._RootPickerState");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue