Set account label

This commit is contained in:
Ming Ming 2022-07-10 23:53:24 +08:00
parent b65e8fdb91
commit c4fd0fafdd
6 changed files with 127 additions and 32 deletions

View file

@ -330,6 +330,11 @@
"@settingsAccountPageTitle": { "@settingsAccountPageTitle": {
"description": "Dedicated page for account settings" "description": "Dedicated page for account settings"
}, },
"settingsAccountLabelTitle": "Label",
"@settingsAccountLabelTitle": {
"description": "An account label is used to replace the server URL in the app bar, could be useful for privacy reason"
},
"settingsAccountLabelDescription": "Set a label to be shown in place of the server URL",
"settingsIncludedFoldersTitle": "Included folders", "settingsIncludedFoldersTitle": "Included folders",
"@settingsIncludedFoldersTitle": { "@settingsIncludedFoldersTitle": {
"description": "Change the included folders of an account" "description": "Change the included folders of an account"

View file

@ -6,6 +6,8 @@
"settingsMemoriesSubtitle", "settingsMemoriesSubtitle",
"settingsAccountTitle", "settingsAccountTitle",
"settingsAccountPageTitle", "settingsAccountPageTitle",
"settingsAccountLabelTitle",
"settingsAccountLabelDescription",
"settingsIncludedFoldersTitle", "settingsIncludedFoldersTitle",
"settingsShareFolderTitle", "settingsShareFolderTitle",
"settingsShareFolderDialogTitle", "settingsShareFolderDialogTitle",
@ -118,6 +120,8 @@
"settingsMemoriesSubtitle", "settingsMemoriesSubtitle",
"settingsAccountTitle", "settingsAccountTitle",
"settingsAccountPageTitle", "settingsAccountPageTitle",
"settingsAccountLabelTitle",
"settingsAccountLabelDescription",
"settingsIncludedFoldersTitle", "settingsIncludedFoldersTitle",
"settingsShareFolderTitle", "settingsShareFolderTitle",
"settingsShareFolderDialogTitle", "settingsShareFolderDialogTitle",
@ -240,17 +244,28 @@
"el": [ "el": [
"settingsExifWifiOnlyTitle", "settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle", "settingsExifWifiOnlyFalseSubtitle",
"settingsAccountLabelTitle",
"settingsAccountLabelDescription",
"enhanceStyleTransferStyleDialogTitle" "enhanceStyleTransferStyleDialogTitle"
], ],
"es": [ "es": [
"settingsAccountLabelTitle",
"settingsAccountLabelDescription",
"rootPickerSkipConfirmationDialogContent2" "rootPickerSkipConfirmationDialogContent2"
], ],
"fi": [
"settingsAccountLabelTitle",
"settingsAccountLabelDescription"
],
"fr": [ "fr": [
"collectionsTooltip", "collectionsTooltip",
"settingsExifWifiOnlyTitle", "settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle", "settingsExifWifiOnlyFalseSubtitle",
"settingsAccountLabelTitle",
"settingsAccountLabelDescription",
"settingsPhotoEnhancementTitle", "settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle", "settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle", "settingsEnhanceMaxResolutionTitle",
@ -281,6 +296,8 @@
"pl": [ "pl": [
"settingsExifWifiOnlyTitle", "settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle", "settingsExifWifiOnlyFalseSubtitle",
"settingsAccountLabelTitle",
"settingsAccountLabelDescription",
"settingsPhotoEnhancementTitle", "settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle", "settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle", "settingsEnhanceMaxResolutionTitle",
@ -329,6 +346,8 @@
"pt": [ "pt": [
"settingsExifWifiOnlyTitle", "settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle", "settingsExifWifiOnlyFalseSubtitle",
"settingsAccountLabelTitle",
"settingsAccountLabelDescription",
"settingsPhotoEnhancementTitle", "settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle", "settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle", "settingsEnhanceMaxResolutionTitle",
@ -356,6 +375,8 @@
"ru": [ "ru": [
"settingsExifWifiOnlyTitle", "settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle", "settingsExifWifiOnlyFalseSubtitle",
"settingsAccountLabelTitle",
"settingsAccountLabelDescription",
"settingsPhotoEnhancementTitle", "settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle", "settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle", "settingsEnhanceMaxResolutionTitle",
@ -383,6 +404,8 @@
"zh": [ "zh": [
"settingsExifWifiOnlyTitle", "settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle", "settingsExifWifiOnlyFalseSubtitle",
"settingsAccountLabelTitle",
"settingsAccountLabelDescription",
"settingsPhotoEnhancementTitle", "settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle", "settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle", "settingsEnhanceMaxResolutionTitle",
@ -410,6 +433,8 @@
"zh_Hant": [ "zh_Hant": [
"settingsExifWifiOnlyTitle", "settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle", "settingsExifWifiOnlyFalseSubtitle",
"settingsAccountLabelTitle",
"settingsAccountLabelDescription",
"settingsPhotoEnhancementTitle", "settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle", "settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle", "settingsEnhanceMaxResolutionTitle",

View file

@ -289,6 +289,17 @@ class AccountPref {
(key, value) => provider.setString(key, value)); (key, value) => provider.setString(key, value));
Future<bool> removeTouchRootEtag() => _remove(PrefKey.touchRootEtag); Future<bool> removeTouchRootEtag() => _remove(PrefKey.touchRootEtag);
String? getAccountLabel() => provider.getString(PrefKey.accountLabel);
String getAccountLabelOr([String def = ""]) => getAccountLabel() ?? def;
Future<bool> setAccountLabel(String? value) {
if (value == null) {
return _remove(PrefKey.accountLabel);
} else {
return _set<String>(PrefKey.accountLabel, value,
(key, value) => provider.setString(key, value));
}
}
Future<bool> _set<T>(PrefKey key, T value, Future<bool> _set<T>(PrefKey key, T value,
Future<bool> Function(PrefKey key, T value) setFn) async { Future<bool> Function(PrefKey key, T value) setFn) async {
if (await setFn(key, value)) { if (await setFn(key, value)) {
@ -519,6 +530,7 @@ enum PrefKey {
hasNewSharedAlbum, hasNewSharedAlbum,
isEnableMemoryAlbum, isEnableMemoryAlbum,
touchRootEtag, touchRootEtag,
accountLabel,
} }
extension on PrefKey { extension on PrefKey {
@ -590,6 +602,8 @@ extension on PrefKey {
return "isEnableMemoryAlbum"; return "isEnableMemoryAlbum";
case PrefKey.touchRootEtag: case PrefKey.touchRootEtag:
return "touchRootEtag"; return "touchRootEtag";
case PrefKey.accountLabel:
return "accountLabel";
} }
} }
} }

View file

@ -33,26 +33,27 @@ class _AccountPickerDialogState extends State<AccountPickerDialog> {
@override @override
build(BuildContext context) { build(BuildContext context) {
final otherAccountOptions = _accounts final otherAccountOptions =
.where((a) => a != widget.account) _accounts.where((a) => a != widget.account).map((a) {
.map((a) => SimpleDialogOption( final label = AccountPref.of(a).getAccountLabel();
padding: const EdgeInsets.symmetric(horizontal: 8), return SimpleDialogOption(
onPressed: () => _onItemPressed(a), padding: const EdgeInsets.symmetric(horizontal: 8),
child: ListTile( onPressed: () => _onItemPressed(a),
dense: true, child: ListTile(
title: Text(a.url), dense: true,
subtitle: Text(a.username.toString()), title: Text(label ?? a.url),
trailing: IconButton( subtitle: label == null ? Text(a.username.toString()) : null,
icon: Icon( trailing: IconButton(
Icons.close, icon: Icon(
color: AppTheme.getUnfocusedIconColor(context), Icons.close,
), color: AppTheme.getUnfocusedIconColor(context),
tooltip: L10n.global().deleteTooltip, ),
onPressed: () => _onRemoveItemPressed(a), tooltip: L10n.global().deleteTooltip,
), onPressed: () => _onRemoveItemPressed(a),
), ),
)) ),
.toList(); );
}).toList();
final addAccountOptions = [ final addAccountOptions = [
SimpleDialogOption( SimpleDialogOption(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
@ -72,18 +73,21 @@ class _AccountPickerDialogState extends State<AccountPickerDialog> {
), ),
), ),
]; ];
final accountLabel = AccountPref.of(widget.account).getAccountLabel();
return AppTheme( return AppTheme(
child: SimpleDialog( child: SimpleDialog(
title: ListTile( title: ListTile(
dense: true, dense: true,
title: Text( title: Text(
widget.account.url, accountLabel ?? widget.account.url,
style: const TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(
widget.account.username.toString(),
style: const TextStyle(fontWeight: FontWeight.bold), style: const TextStyle(fontWeight: FontWeight.bold),
), ),
subtitle: accountLabel == null
? Text(
widget.account.username.toString(),
style: const TextStyle(fontWeight: FontWeight.bold),
)
: null,
trailing: IconButton( trailing: IconButton(
icon: Icon( icon: Icon(
Icons.settings_outlined, Icons.settings_outlined,

View file

@ -23,6 +23,7 @@ class HomeSliverAppBar extends StatelessWidget {
@override @override
build(BuildContext context) { build(BuildContext context) {
final accountLabel = AccountPref.of(account).getAccountLabel();
return SliverAppBar( return SliverAppBar(
title: InkWell( title: InkWell(
onTap: () { onTap: () {
@ -57,16 +58,17 @@ class HomeSliverAppBar extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
account.url.substring(account.scheme.length + 3), accountLabel ?? account.address,
style: const TextStyle(fontSize: 16), style: const TextStyle(fontSize: 16),
), ),
Text( if (accountLabel == null)
account.username.toString(), Text(
style: TextStyle( account.username.toString(),
fontSize: 14, style: TextStyle(
color: AppTheme.getSecondaryTextColor(context), fontSize: 14,
color: AppTheme.getSecondaryTextColor(context),
),
), ),
),
], ],
), ),
), ),

View file

@ -26,6 +26,7 @@ import 'package:nc_photos/widget/home.dart';
import 'package:nc_photos/widget/list_tile_center_leading.dart'; import 'package:nc_photos/widget/list_tile_center_leading.dart';
import 'package:nc_photos/widget/root_picker.dart'; import 'package:nc_photos/widget/root_picker.dart';
import 'package:nc_photos/widget/share_folder_picker.dart'; import 'package:nc_photos/widget/share_folder_picker.dart';
import 'package:nc_photos/widget/simple_input_dialog.dart';
import 'package:nc_photos/widget/stateful_slider.dart'; import 'package:nc_photos/widget/stateful_slider.dart';
import 'package:screen_brightness/screen_brightness.dart'; import 'package:screen_brightness/screen_brightness.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
@ -495,6 +496,7 @@ class _AccountSettingsState extends State<AccountSettingsWidget> {
final settings = AccountPref.of(_account); final settings = AccountPref.of(_account);
_isEnableFaceRecognitionApp = settings.isEnableFaceRecognitionAppOr(); _isEnableFaceRecognitionApp = settings.isEnableFaceRecognitionAppOr();
_shareFolder = settings.getShareFolderOr(); _shareFolder = settings.getShareFolderOr();
_label = settings.getAccountLabel();
} }
@override @override
@ -527,6 +529,12 @@ class _AccountSettingsState extends State<AccountSettingsWidget> {
SliverList( SliverList(
delegate: SliverChildListDelegate( delegate: SliverChildListDelegate(
[ [
ListTile(
title: Text(L10n.global().settingsAccountLabelTitle),
subtitle: Text(
_label ?? L10n.global().settingsAccountLabelDescription),
onTap: () => _onLabelPressed(context),
),
ListTile( ListTile(
title: Text(L10n.global().settingsIncludedFoldersTitle), title: Text(L10n.global().settingsIncludedFoldersTitle),
subtitle: Text(_account.roots.map((e) => "/$e").join("; ")), subtitle: Text(_account.roots.map((e) => "/$e").join("; ")),
@ -560,6 +568,24 @@ class _AccountSettingsState extends State<AccountSettingsWidget> {
); );
} }
Future<void> _onLabelPressed(BuildContext context) async {
final result = await showDialog<String>(
context: context,
builder: (context) => SimpleInputDialog(
titleText: L10n.global().settingsAccountLabelTitle,
buttonText: MaterialLocalizations.of(context).okButtonLabel,
initialText: _label ?? "",
));
if (result == null) {
return;
}
if (result.isEmpty) {
_setLabel(null);
} else {
_setLabel(result);
}
}
Future<void> _onIncludedFoldersPressed() async { Future<void> _onIncludedFoldersPressed() async {
try { try {
final result = await Navigator.of(context).pushNamed<Account>( final result = await Navigator.of(context).pushNamed<Account>(
@ -650,6 +676,24 @@ class _AccountSettingsState extends State<AccountSettingsWidget> {
} }
} }
Future<void> _setLabel(String? value) async {
_log.info("[_setLabel] New value: $value");
final oldValue = _label;
setState(() {
_label = value;
});
if (!await AccountPref.of(_account).setAccountLabel(value)) {
_log.severe("[_setLabel] Failed writing pref");
SnackBarManager().showSnackBar(SnackBar(
content: Text(L10n.global().writePreferenceFailureNotification),
duration: k.snackBarDurationNormal,
));
setState(() {
_label = oldValue;
});
}
}
Future<void> _setShareFolder(String value) async { Future<void> _setShareFolder(String value) async {
_log.info("[_setShareFolder] New value: $value"); _log.info("[_setShareFolder] New value: $value");
final oldValue = _shareFolder; final oldValue = _shareFolder;
@ -672,6 +716,7 @@ class _AccountSettingsState extends State<AccountSettingsWidget> {
late Account _account; late Account _account;
late bool _isEnableFaceRecognitionApp; late bool _isEnableFaceRecognitionApp;
late String _shareFolder; late String _shareFolder;
late String? _label;
static final _log = Logger("widget.settings._AccountSettingsState"); static final _log = Logger("widget.settings._AccountSettingsState");
} }