From 755e996ebb2215f799f1b67547a56e0e01fb20d3 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Tue, 2 Nov 2021 18:45:43 +0900 Subject: [PATCH] settings: merged collection quick action editors --- lib/l10n/app_en.arb | 17 +- lib/l10n/app_ko.arb | 7 +- lib/l10n/app_ru.arb | 4 +- .../common/quick_actions/editor_page.dart | 294 ++++++++++-------- .../thumbnails/browsing_actions_editor.dart | 44 --- .../thumbnails/collection_actions_editor.dart | 81 +++++ .../thumbnails/selection_actions_editor.dart | 44 --- .../settings/thumbnails/thumbnails.dart | 6 +- untranslated.json | 11 +- 9 files changed, 267 insertions(+), 241 deletions(-) delete mode 100644 lib/widgets/settings/thumbnails/browsing_actions_editor.dart create mode 100644 lib/widgets/settings/thumbnails/collection_actions_editor.dart delete mode 100644 lib/widgets/settings/thumbnails/selection_actions_editor.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 12c8b9d7c..781f48d72 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -758,17 +758,16 @@ "settingsThumbnailShowVideoDuration": "Show video duration", "@settingsThumbnailShowVideoDuration": {}, - "settingsCollectionBrowsingQuickActionsTile": "Quick actions for item browsing", - "@settingsCollectionBrowsingQuickActionsTile": {}, - "settingsCollectionBrowsingQuickActionEditorTitle": "Quick Actions", - "@settingsCollectionBrowsingQuickActionEditorTitle": {}, + "settingsCollectionQuickActionsTile": "Quick actions", + "@settingsCollectionQuickActionsTile": {}, + "settingsCollectionQuickActionEditorTitle": "Quick Actions", + "@settingsCollectionQuickActionEditorTitle": {}, + "settingsCollectionQuickActionTabBrowsing": "Browsing", + "@settingsCollectionQuickActionTabBrowsing": {}, + "settingsCollectionQuickActionTabSelecting": "Selecting", + "@settingsCollectionQuickActionTabSelecting": {}, "settingsCollectionBrowsingQuickActionEditorBanner": "Touch and hold to move buttons and select which actions are displayed when browsing items.", "@settingsCollectionBrowsingQuickActionEditorBanner": {}, - - "settingsCollectionSelectionQuickActionsTile": "Quick actions for item selection", - "@settingsCollectionSelectionQuickActionsTile": {}, - "settingsCollectionSelectionQuickActionEditorTitle": "Quick Actions", - "@settingsCollectionSelectionQuickActionEditorTitle": {}, "settingsCollectionSelectionQuickActionEditorBanner": "Touch and hold to move buttons and select which actions are displayed when selecting items.", "@settingsCollectionSelectionQuickActionEditorBanner": {}, diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb index 4b3374459..b7fe7475e 100644 --- a/lib/l10n/app_ko.arb +++ b/lib/l10n/app_ko.arb @@ -243,6 +243,7 @@ "collectionActionCopy": "앨범으로 복사", "collectionActionMove": "앨범으로 이동", "collectionActionRescan": "새로 분석", + "collectionActionEdit": "편집", "collectionSortTitle": "정렬", "collectionSortDate": "날짜", @@ -262,9 +263,11 @@ "collectionDeleteFailureFeedback": "{count, plural, other{항목 {count}개를 삭제하지 못했습니다}}", "collectionCopyFailureFeedback": "{count, plural, other{항목 {count}개를 복사하지 못했습니다}}", "collectionMoveFailureFeedback": "{count, plural, other{항목 {count}개를 이동하지 못했습니다}}", + "collectionEditFailureFeedback": "{count, plural, other{항목 {count}개를 편집하지 못했습니다}}", "collectionExportFailureFeedback": "{count, plural, other{항목 {count}개를 내보내지 못했습니다}}", "collectionCopySuccessFeedback": "{count, plural, other{항목 {count}개를 복사했습니다}}", "collectionMoveSuccessFeedback": "{count, plural, other{항목 {count}개를 이동했습니다}}", + "collectionEditSuccessFeedback": "{count, plural, other{항목 {count}개를 편집했습니다}}", "collectionEmptyFavourites": "즐겨찾기가 없습니다", "collectionEmptyVideos": "동영상이 없습니다", @@ -349,8 +352,8 @@ "settingsThumbnailShowRawIcon": "Raw 아이콘 표시", "settingsThumbnailShowVideoDuration": "동영상 길이 표시", - "settingsCollectionSelectionQuickActionsTile": "항목 선택의 빠른 작업", - "settingsCollectionSelectionQuickActionEditorTitle": "빠른 작업", + "settingsCollectionQuickActionsTile": "빠른 작업", + "settingsCollectionQuickActionEditorTitle": "빠른 작업", "settingsCollectionSelectionQuickActionEditorBanner": "버튼을 길게 누른 후 이동하여 항목 선택할 때 표시될 버튼을 선택하세요.", "settingsSectionViewer": "뷰어", diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index d6503be45..d60be8ee2 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -345,8 +345,8 @@ "settingsThumbnailShowRawIcon": "Показать значок RAW-файла", "settingsThumbnailShowVideoDuration": "Показывать продолжительность видео", - "settingsCollectionSelectionQuickActionsTile": "Быстрые действия с объектами", - "settingsCollectionSelectionQuickActionEditorTitle": "Быстрые действия", + "settingsCollectionQuickActionsTile": "Быстрые действия", + "settingsCollectionQuickActionEditorTitle": "Быстрые действия", "settingsCollectionSelectionQuickActionEditorBanner": "Нажмите и удерживайте, чтобы переместить кнопки и выбрать, какие действия будут отображаться при выборе элементов.", "settingsSectionViewer": "Просмотрщик", diff --git a/lib/widgets/settings/common/quick_actions/editor_page.dart b/lib/widgets/settings/common/quick_actions/editor_page.dart index eb3662b3c..6c329871f 100644 --- a/lib/widgets/settings/common/quick_actions/editor_page.dart +++ b/lib/widgets/settings/common/quick_actions/editor_page.dart @@ -15,7 +15,7 @@ import 'package:aves/widgets/viewer/overlay/common.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -class QuickActionEditorPage extends StatefulWidget { +class QuickActionEditorPage extends StatelessWidget { final String title, bannerText; final List allAvailableActions; final Widget? Function(T action) actionIcon; @@ -35,10 +35,50 @@ class QuickActionEditorPage extends StatefulWidget { }) : super(key: key); @override - _QuickActionEditorPageState createState() => _QuickActionEditorPageState(); + Widget build(BuildContext context) { + return MediaQueryDataProvider( + child: Scaffold( + appBar: AppBar( + title: Text(title), + ), + body: SafeArea( + child: QuickActionEditorBody( + bannerText: bannerText, + allAvailableActions: allAvailableActions, + actionIcon: actionIcon, + actionText: actionText, + load: load, + save: save, + ), + ), + ), + ); + } } -class _QuickActionEditorPageState extends State> { +class QuickActionEditorBody extends StatefulWidget { + final String bannerText; + final List allAvailableActions; + final Widget? Function(T action) actionIcon; + final String Function(BuildContext context, T action) actionText; + final List Function() load; + final void Function(List actions) save; + + const QuickActionEditorBody({ + Key? key, + required this.bannerText, + required this.allAvailableActions, + required this.actionIcon, + required this.actionText, + required this.load, + required this.save, + }) : super(key: key); + + @override + _QuickActionEditorBodyState createState() => _QuickActionEditorBodyState(); +} + +class _QuickActionEditorBodyState extends State> with AutomaticKeepAliveClientMixin { final GlobalKey _animatedListKey = GlobalKey(debugLabel: 'quick-actions-animated-list'); Timer? _targetLeavingTimer; late List _quickActions; @@ -77,6 +117,8 @@ class _QuickActionEditorPageState extends State( placement: QuickActionPlacement.header, panelHighlight: _quickActionHighlight, @@ -95,135 +137,126 @@ class _QuickActionEditorPageState extends State( - valueListenable: _quickActionHighlight, - builder: (context, highlight, child) => ActionPanel( - highlight: highlight, - child: child!, - ), - child: SizedBox( - height: OverlayButton.getSize(context) + quickActionVerticalPadding * 2, - child: Stack( - children: [ - Positioned.fill( - child: FractionallySizedBox( - alignment: Alignment.centerLeft, - widthFactor: .5, - child: header, - ), - ), - Positioned.fill( - child: FractionallySizedBox( - alignment: Alignment.centerRight, - widthFactor: .5, - child: footer, - ), - ), - Container( - alignment: Alignment.center, - child: AnimatedList( - key: _animatedListKey, - initialItemCount: _quickActions.length, - scrollDirection: Axis.horizontal, - shrinkWrap: true, - padding: EdgeInsets.zero, - itemBuilder: (context, index, animation) { - if (index >= _quickActions.length) return const SizedBox(); - final action = _quickActions[index]; - return QuickActionButton( - placement: QuickActionPlacement.action, - action: action, - panelHighlight: _quickActionHighlight, - draggedQuickAction: _draggedQuickAction, - draggedAvailableAction: _draggedAvailableAction, - insertAction: _insertQuickAction, - removeAction: _removeQuickAction, - onTargetLeave: _onQuickActionTargetLeave, - draggableFeedbackBuilder: (action) => ActionButton( - text: widget.actionText(context, action), - icon: widget.actionIcon(action), - showCaption: false, - ), - child: _buildQuickActionButton(action, animation), - ); - }, - ), - ), - AnimatedBuilder( - animation: _quickActionsChangeNotifier, - builder: (context, child) => _quickActions.isEmpty - ? Center( - child: Text( - context.l10n.settingsViewerQuickActionEmpty, - style: Theme.of(context).textTheme.caption, - ), - ) - : const SizedBox(), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Text( - context.l10n.settingsViewerQuickActionEditorAvailableButtons, - style: Constants.titleTextStyle, - ), - ), - ValueListenableBuilder( - valueListenable: _availableActionHighlight, - builder: (context, highlight, child) => ActionPanel( - highlight: highlight, - child: child!, - ), - child: AvailableActionPanel( - allActions: widget.allAvailableActions, - quickActions: _quickActions, - quickActionsChangeNotifier: _quickActionsChangeNotifier, - panelHighlight: _availableActionHighlight, - draggedQuickAction: _draggedQuickAction, - draggedAvailableAction: _draggedAvailableAction, - removeQuickAction: _removeQuickAction, - actionIcon: widget.actionIcon, - actionText: widget.actionText, - ), - ), + const Icon(AIcons.info), + const SizedBox(width: 16), + Expanded(child: Text(widget.bannerText)), ], ), ), - ), + const Divider(), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text( + context.l10n.settingsViewerQuickActionEditorDisplayedButtons, + style: Constants.titleTextStyle, + ), + ), + ValueListenableBuilder( + valueListenable: _quickActionHighlight, + builder: (context, highlight, child) => ActionPanel( + highlight: highlight, + child: child!, + ), + child: SizedBox( + height: OverlayButton.getSize(context) + quickActionVerticalPadding * 2, + child: Stack( + children: [ + Positioned.fill( + child: FractionallySizedBox( + alignment: Alignment.centerLeft, + widthFactor: .5, + child: header, + ), + ), + Positioned.fill( + child: FractionallySizedBox( + alignment: Alignment.centerRight, + widthFactor: .5, + child: footer, + ), + ), + Container( + alignment: Alignment.center, + child: AnimatedList( + key: _animatedListKey, + initialItemCount: _quickActions.length, + scrollDirection: Axis.horizontal, + shrinkWrap: true, + padding: EdgeInsets.zero, + itemBuilder: (context, index, animation) { + if (index >= _quickActions.length) return const SizedBox(); + final action = _quickActions[index]; + return QuickActionButton( + placement: QuickActionPlacement.action, + action: action, + panelHighlight: _quickActionHighlight, + draggedQuickAction: _draggedQuickAction, + draggedAvailableAction: _draggedAvailableAction, + insertAction: _insertQuickAction, + removeAction: _removeQuickAction, + onTargetLeave: _onQuickActionTargetLeave, + draggableFeedbackBuilder: (action) => ActionButton( + text: widget.actionText(context, action), + icon: widget.actionIcon(action), + showCaption: false, + ), + child: _buildQuickActionButton(action, animation), + ); + }, + ), + ), + AnimatedBuilder( + animation: _quickActionsChangeNotifier, + builder: (context, child) => _quickActions.isEmpty + ? Center( + child: Text( + context.l10n.settingsViewerQuickActionEmpty, + style: Theme.of(context).textTheme.caption, + ), + ) + : const SizedBox(), + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Text( + context.l10n.settingsViewerQuickActionEditorAvailableButtons, + style: Constants.titleTextStyle, + ), + ), + ValueListenableBuilder( + valueListenable: _availableActionHighlight, + builder: (context, highlight, child) => ActionPanel( + highlight: highlight, + child: child!, + ), + child: AvailableActionPanel( + allActions: widget.allAvailableActions, + quickActions: _quickActions, + quickActionsChangeNotifier: _quickActionsChangeNotifier, + panelHighlight: _availableActionHighlight, + draggedQuickAction: _draggedQuickAction, + draggedAvailableAction: _draggedAvailableAction, + removeQuickAction: _removeQuickAction, + actionIcon: widget.actionIcon, + actionText: widget.actionText, + ), + ), + ], ), ); } @@ -284,7 +317,7 @@ class _QuickActionEditorPageState extends State extends State true; } diff --git a/lib/widgets/settings/thumbnails/browsing_actions_editor.dart b/lib/widgets/settings/thumbnails/browsing_actions_editor.dart deleted file mode 100644 index bc61597ef..000000000 --- a/lib/widgets/settings/thumbnails/browsing_actions_editor.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:aves/model/actions/entry_set_actions.dart'; -import 'package:aves/model/settings/settings.dart'; -import 'package:aves/widgets/common/extensions/build_context.dart'; -import 'package:aves/widgets/settings/common/quick_actions/editor_page.dart'; -import 'package:flutter/material.dart'; - -class BrowsingActionsTile extends StatelessWidget { - const BrowsingActionsTile({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ListTile( - title: Text(context.l10n.settingsCollectionBrowsingQuickActionsTile), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - settings: const RouteSettings(name: BrowsingActionEditorPage.routeName), - builder: (context) => const BrowsingActionEditorPage(), - ), - ); - }, - ); - } -} - -class BrowsingActionEditorPage extends StatelessWidget { - static const routeName = '/settings/collection_browsing_actions'; - - const BrowsingActionEditorPage({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return QuickActionEditorPage( - title: context.l10n.settingsCollectionBrowsingQuickActionEditorTitle, - bannerText: context.l10n.settingsCollectionBrowsingQuickActionEditorBanner, - allAvailableActions: EntrySetActions.browsing, - actionIcon: (action) => action.getIcon(), - actionText: (context, action) => action.getText(context), - load: () => settings.collectionBrowsingQuickActions.toList(), - save: (actions) => settings.collectionBrowsingQuickActions = actions, - ); - } -} diff --git a/lib/widgets/settings/thumbnails/collection_actions_editor.dart b/lib/widgets/settings/thumbnails/collection_actions_editor.dart new file mode 100644 index 000000000..79c4594dc --- /dev/null +++ b/lib/widgets/settings/thumbnails/collection_actions_editor.dart @@ -0,0 +1,81 @@ +import 'package:aves/model/actions/entry_set_actions.dart'; +import 'package:aves/model/settings/settings.dart'; +import 'package:aves/widgets/common/extensions/build_context.dart'; +import 'package:aves/widgets/common/providers/media_query_data_provider.dart'; +import 'package:aves/widgets/settings/common/quick_actions/editor_page.dart'; +import 'package:flutter/material.dart'; +import 'package:tuple/tuple.dart'; + +class CollectionActionsTile extends StatelessWidget { + const CollectionActionsTile({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ListTile( + title: Text(context.l10n.settingsCollectionQuickActionsTile), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + settings: const RouteSettings(name: CollectionActionEditorPage.routeName), + builder: (context) => const CollectionActionEditorPage(), + ), + ); + }, + ); + } +} + +class CollectionActionEditorPage extends StatelessWidget { + static const routeName = '/settings/collection_actions'; + + const CollectionActionEditorPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + final tabs = >[ + Tuple2( + Tab(text: l10n.settingsCollectionQuickActionTabBrowsing), + QuickActionEditorBody( + bannerText: context.l10n.settingsCollectionBrowsingQuickActionEditorBanner, + allAvailableActions: EntrySetActions.browsing, + actionIcon: (action) => action.getIcon(), + actionText: (context, action) => action.getText(context), + load: () => settings.collectionBrowsingQuickActions.toList(), + save: (actions) => settings.collectionBrowsingQuickActions = actions, + ), + ), + Tuple2( + Tab(text: l10n.settingsCollectionQuickActionTabSelecting), + QuickActionEditorBody( + bannerText: context.l10n.settingsCollectionSelectionQuickActionEditorBanner, + allAvailableActions: EntrySetActions.selection, + actionIcon: (action) => action.getIcon(), + actionText: (context, action) => action.getText(context), + load: () => settings.collectionSelectionQuickActions.toList(), + save: (actions) => settings.collectionSelectionQuickActions = actions, + ), + ), + ]; + + return MediaQueryDataProvider( + child: DefaultTabController( + length: tabs.length, + child: Scaffold( + appBar: AppBar( + title: Text(context.l10n.settingsCollectionQuickActionEditorTitle), + bottom: TabBar( + tabs: tabs.map((t) => t.item1).toList(), + ), + ), + body: SafeArea( + child: TabBarView( + children: tabs.map((t) => t.item2).toList(), + ), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/settings/thumbnails/selection_actions_editor.dart b/lib/widgets/settings/thumbnails/selection_actions_editor.dart deleted file mode 100644 index 218736adc..000000000 --- a/lib/widgets/settings/thumbnails/selection_actions_editor.dart +++ /dev/null @@ -1,44 +0,0 @@ -import 'package:aves/model/actions/entry_set_actions.dart'; -import 'package:aves/model/settings/settings.dart'; -import 'package:aves/widgets/common/extensions/build_context.dart'; -import 'package:aves/widgets/settings/common/quick_actions/editor_page.dart'; -import 'package:flutter/material.dart'; - -class SelectionActionsTile extends StatelessWidget { - const SelectionActionsTile({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ListTile( - title: Text(context.l10n.settingsCollectionSelectionQuickActionsTile), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - settings: const RouteSettings(name: SelectionActionEditorPage.routeName), - builder: (context) => const SelectionActionEditorPage(), - ), - ); - }, - ); - } -} - -class SelectionActionEditorPage extends StatelessWidget { - static const routeName = '/settings/collection_selection_actions'; - - const SelectionActionEditorPage({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return QuickActionEditorPage( - title: context.l10n.settingsCollectionSelectionQuickActionEditorTitle, - bannerText: context.l10n.settingsCollectionSelectionQuickActionEditorBanner, - allAvailableActions: EntrySetActions.selection, - actionIcon: (action) => action.getIcon(), - actionText: (context, action) => action.getText(context), - load: () => settings.collectionSelectionQuickActions.toList(), - save: (actions) => settings.collectionSelectionQuickActions = actions, - ); - } -} diff --git a/lib/widgets/settings/thumbnails/thumbnails.dart b/lib/widgets/settings/thumbnails/thumbnails.dart index 3234a42ff..e2e167a76 100644 --- a/lib/widgets/settings/thumbnails/thumbnails.dart +++ b/lib/widgets/settings/thumbnails/thumbnails.dart @@ -6,8 +6,7 @@ import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/aves_expansion_tile.dart'; import 'package:aves/widgets/common/identity/aves_icons.dart'; import 'package:aves/widgets/settings/common/tile_leading.dart'; -import 'package:aves/widgets/settings/thumbnails/browsing_actions_editor.dart'; -import 'package:aves/widgets/settings/thumbnails/selection_actions_editor.dart'; +import 'package:aves/widgets/settings/thumbnails/collection_actions_editor.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -38,8 +37,7 @@ class ThumbnailsSection extends StatelessWidget { expandedNotifier: expandedNotifier, showHighlight: false, children: [ - const BrowsingActionsTile(), - const SelectionActionsTile(), + const CollectionActionsTile(), SwitchListTile( value: currentShowThumbnailLocation, onChanged: (v) => settings.showThumbnailLocation = v, diff --git a/untranslated.json b/untranslated.json index dfaff10b2..2bcf62d1a 100644 --- a/untranslated.json +++ b/untranslated.json @@ -3,11 +3,8 @@ "unsupportedTypeDialogTitle", "unsupportedTypeDialogMessage", "editEntryDateDialogExtractFromTitle", - "collectionActionEdit", - "collectionEditFailureFeedback", - "collectionEditSuccessFeedback", - "settingsCollectionBrowsingQuickActionsTile", - "settingsCollectionBrowsingQuickActionEditorTitle", + "settingsCollectionQuickActionTabBrowsing", + "settingsCollectionQuickActionTabSelecting", "settingsCollectionBrowsingQuickActionEditorBanner", "settingsAllowInstalledAppAccess", "settingsAllowInstalledAppAccessSubtitle" @@ -23,8 +20,8 @@ "collectionActionEdit", "collectionEditFailureFeedback", "collectionEditSuccessFeedback", - "settingsCollectionBrowsingQuickActionsTile", - "settingsCollectionBrowsingQuickActionEditorTitle", + "settingsCollectionQuickActionTabBrowsing", + "settingsCollectionQuickActionTabSelecting", "settingsCollectionBrowsingQuickActionEditorBanner", "settingsAllowInstalledAppAccess", "settingsAllowInstalledAppAccessSubtitle"