#437 tv: toggle button state
This commit is contained in:
parent
1cba919385
commit
da751190c5
47 changed files with 570 additions and 289 deletions
|
@ -114,6 +114,12 @@ class EntryActions {
|
||||||
EntryAction.videoSettings,
|
EntryAction.videoSettings,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
static const videoPlayback = [
|
||||||
|
EntryAction.videoReplay10,
|
||||||
|
EntryAction.videoTogglePlay,
|
||||||
|
EntryAction.videoSkip10,
|
||||||
|
];
|
||||||
|
|
||||||
static const commonMetadataActions = [
|
static const commonMetadataActions = [
|
||||||
EntryAction.editDate,
|
EntryAction.editDate,
|
||||||
EntryAction.editLocation,
|
EntryAction.editLocation,
|
||||||
|
|
|
@ -2,7 +2,10 @@ import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
enum ShareAction { imageOnly, videoOnly, }
|
enum ShareAction {
|
||||||
|
imageOnly,
|
||||||
|
videoOnly,
|
||||||
|
}
|
||||||
|
|
||||||
extension ExtraShareAction on ShareAction {
|
extension ExtraShareAction on ShareAction {
|
||||||
String getText(BuildContext context) {
|
String getText(BuildContext context) {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import 'package:aves/widgets/aves_app.dart';
|
||||||
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons.dart';
|
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
|
@ -5,7 +5,7 @@ import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/widgets/common/basic/link_chip.dart';
|
import 'package:aves/widgets/common/basic/link_chip.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
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_expansion_tile.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons.dart';
|
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
|
@ -21,18 +21,18 @@ import 'package:aves/widgets/collection/collection_page.dart';
|
||||||
import 'package:aves/widgets/collection/entry_set_action_delegate.dart';
|
import 'package:aves/widgets/collection/entry_set_action_delegate.dart';
|
||||||
import 'package:aves/widgets/collection/filter_bar.dart';
|
import 'package:aves/widgets/collection/filter_bar.dart';
|
||||||
import 'package:aves/widgets/collection/query_bar.dart';
|
import 'package:aves/widgets/collection/query_bar.dart';
|
||||||
|
import 'package:aves/widgets/common/action_controls/togglers/favourite.dart';
|
||||||
|
import 'package:aves/widgets/common/action_controls/togglers/title_search.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
|
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
|
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/favourite_toggler.dart';
|
|
||||||
import 'package:aves/widgets/common/app_bar/title_search_toggler.dart';
|
|
||||||
import 'package:aves/widgets/common/basic/menu.dart';
|
import 'package:aves/widgets/common/basic/menu.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_app_bar.dart';
|
import 'package:aves/widgets/common/identity/aves_app_bar.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
||||||
import 'package:aves/widgets/common/search/route.dart';
|
import 'package:aves/widgets/common/search/route.dart';
|
||||||
import 'package:aves/widgets/dialogs/tile_view_dialog.dart';
|
import 'package:aves/widgets/dialogs/tile_view_dialog.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart';
|
import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart';
|
||||||
import 'package:aves/widgets/search/search_delegate.dart';
|
import 'package:aves/widgets/search/search_delegate.dart';
|
||||||
import 'package:aves/widgets/settings/common/quick_actions/action_button.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -176,7 +176,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
children: [
|
children: [
|
||||||
if (isTelevision)
|
if (isTelevision)
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: ActionButton.getTelevisionButtonHeight(context),
|
height: CaptionedButton.getTelevisionButtonHeight(context),
|
||||||
child: ListView(
|
child: ListView(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
|
@ -215,7 +215,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
double get appBarContentHeight {
|
double get appBarContentHeight {
|
||||||
double height = kToolbarHeight;
|
double height = kToolbarHeight;
|
||||||
if (device.isTelevision) {
|
if (device.isTelevision) {
|
||||||
height += ActionButton.getTelevisionButtonHeight(context);
|
height += CaptionedButton.getTelevisionButtonHeight(context);
|
||||||
}
|
}
|
||||||
if (showFilterBar) {
|
if (showFilterBar) {
|
||||||
height += FilterBar.preferredHeight;
|
height += FilterBar.preferredHeight;
|
||||||
|
@ -339,12 +339,10 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
...EntrySetActions.general,
|
...EntrySetActions.general,
|
||||||
...isSelecting ? EntrySetActions.pageSelection : EntrySetActions.pageBrowsing,
|
...isSelecting ? EntrySetActions.pageSelection : EntrySetActions.pageBrowsing,
|
||||||
].where(isVisible).map((action) {
|
].where(isVisible).map((action) {
|
||||||
// TODO TLAD [tv] togglers cf `_toIconActionButton`
|
|
||||||
final enabled = canApply(action);
|
final enabled = canApply(action);
|
||||||
return ActionButton(
|
return CaptionedButton(
|
||||||
text: action.getText(context),
|
iconButton: _buildButtonIcon(context, action, enabled: enabled, selection: selection),
|
||||||
icon: action.getIcon(),
|
captionText: _buildButtonCaption(context, action, enabled: enabled),
|
||||||
enabled: enabled,
|
|
||||||
onPressed: enabled ? () => _onActionSelected(action) : null,
|
onPressed: enabled ? () => _onActionSelected(action) : null,
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
@ -364,7 +362,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
final browsingQuickActions = settings.collectionBrowsingQuickActions;
|
final browsingQuickActions = settings.collectionBrowsingQuickActions;
|
||||||
final selectionQuickActions = isTrash ? [EntrySetAction.delete, EntrySetAction.restore] : settings.collectionSelectionQuickActions;
|
final selectionQuickActions = isTrash ? [EntrySetAction.delete, EntrySetAction.restore] : settings.collectionSelectionQuickActions;
|
||||||
final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
|
final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
|
||||||
(action) => _toIconActionButton(action, enabled: canApply(action), selection: selection),
|
(action) => _buildButtonIcon(context, action, enabled: canApply(action), selection: selection),
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -426,7 +424,12 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
// key is expected by test driver (e.g. 'menu-configureView', 'menu-map')
|
// key is expected by test driver (e.g. 'menu-configureView', 'menu-map')
|
||||||
Key _getActionKey(EntrySetAction action) => Key('menu-${action.name}');
|
Key _getActionKey(EntrySetAction action) => Key('menu-${action.name}');
|
||||||
|
|
||||||
Widget _toIconActionButton(EntrySetAction action, {required bool enabled, required Selection<AvesEntry> selection}) {
|
Widget _buildButtonIcon(
|
||||||
|
BuildContext context,
|
||||||
|
EntrySetAction action, {
|
||||||
|
required bool enabled,
|
||||||
|
required Selection<AvesEntry> selection,
|
||||||
|
}) {
|
||||||
final onPressed = enabled ? () => _onActionSelected(action) : null;
|
final onPressed = enabled ? () => _onActionSelected(action) : null;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case EntrySetAction.toggleTitleSearch:
|
case EntrySetAction.toggleTitleSearch:
|
||||||
|
@ -455,6 +458,24 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildButtonCaption(
|
||||||
|
BuildContext context,
|
||||||
|
EntrySetAction action, {
|
||||||
|
required bool enabled,
|
||||||
|
}) {
|
||||||
|
switch (action) {
|
||||||
|
case EntrySetAction.toggleTitleSearch:
|
||||||
|
return TitleSearchTogglerCaption(
|
||||||
|
enabled: enabled,
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return CaptionedButtonText(
|
||||||
|
text: action.getText(context),
|
||||||
|
enabled: enabled,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PopupMenuItem<EntrySetAction> _toMenuItem(EntrySetAction action, {required bool enabled, required Selection<AvesEntry> selection}) {
|
PopupMenuItem<EntrySetAction> _toMenuItem(EntrySetAction action, {required bool enabled, required Selection<AvesEntry> selection}) {
|
||||||
late Widget child;
|
late Widget child;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ import 'package:aves/widgets/common/grid/sections/section_layout.dart';
|
||||||
import 'package:aves/widgets/common/grid/selector.dart';
|
import 'package:aves/widgets/common/grid/selector.dart';
|
||||||
import 'package:aves/widgets/common/grid/sliver.dart';
|
import 'package:aves/widgets/common/grid/sliver.dart';
|
||||||
import 'package:aves/widgets/common/grid/theme.dart';
|
import 'package:aves/widgets/common/grid/theme.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons.dart';
|
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
|
||||||
import 'package:aves/widgets/common/identity/empty.dart';
|
import 'package:aves/widgets/common/identity/empty.dart';
|
||||||
import 'package:aves/widgets/common/identity/scroll_thumb.dart';
|
import 'package:aves/widgets/common/identity/scroll_thumb.dart';
|
||||||
import 'package:aves/widgets/common/providers/tile_extent_controller_provider.dart';
|
import 'package:aves/widgets/common/providers/tile_extent_controller_provider.dart';
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/model/filters/album.dart';
|
import 'package:aves/model/filters/album.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/menu.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/menu.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/route_layout.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/route_layout.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:async';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/quick_chooser.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/quick_chooser.dart';
|
||||||
import 'package:aves_ui/aves_ui.dart';
|
import 'package:aves_ui/aves_ui.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
|
@ -3,9 +3,9 @@ import 'package:aves/model/filters/album.dart';
|
||||||
import 'package:aves/model/filters/filters.dart';
|
import 'package:aves/model/filters/filters.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/album_chooser.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/album_chooser.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/button.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/button.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/menu.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/menu.dart';
|
||||||
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/filter_nav_page.dart';
|
import 'package:aves/widgets/filter_grids/common/filter_nav_page.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:aves/model/actions/entry_actions.dart';
|
import 'package:aves/model/actions/entry_actions.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/button.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/button.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/rate_chooser.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/rate_chooser.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class RateButton extends ChooserQuickButton<int> {
|
class RateButton extends ChooserQuickButton<int> {
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/quick_chooser.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/quick_chooser.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class RateQuickChooser extends StatefulWidget {
|
class RateQuickChooser extends StatefulWidget {
|
|
@ -1,8 +1,8 @@
|
||||||
import 'package:aves/model/actions/entry_actions.dart';
|
import 'package:aves/model/actions/entry_actions.dart';
|
||||||
import 'package:aves/model/actions/share_actions.dart';
|
import 'package:aves/model/actions/share_actions.dart';
|
||||||
import 'package:aves/model/entry.dart';
|
import 'package:aves/model/entry.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/button.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/button.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/share_chooser.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/share_chooser.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ShareButton extends ChooserQuickButton<ShareAction> {
|
class ShareButton extends ChooserQuickButton<ShareAction> {
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/model/actions/share_actions.dart';
|
import 'package:aves/model/actions/share_actions.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/menu.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/menu.dart';
|
||||||
import 'package:aves/widgets/common/basic/menu.dart';
|
import 'package:aves/widgets/common/basic/menu.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
|
@ -3,9 +3,9 @@ import 'package:aves/model/filters/filters.dart';
|
||||||
import 'package:aves/model/filters/tag.dart';
|
import 'package:aves/model/filters/tag.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/button.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/button.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/menu.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/menu.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/tag_chooser.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/tag_chooser.dart';
|
||||||
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/filter_nav_page.dart';
|
import 'package:aves/widgets/filter_grids/common/filter_nav_page.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/model/filters/filters.dart';
|
import 'package:aves/model/filters/filters.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/common/menu.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/common/menu.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/basic/menu.dart';
|
import 'package:aves/widgets/common/basic/menu.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/fx/sweeper.dart';
|
import 'package:aves/widgets/common/fx/sweeper.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ class _FavouriteTogglerState extends State<FavouriteToggler> {
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
favourites.removeListener(_onChanged);
|
favourites.removeListener(_onChanged);
|
||||||
|
isFavouriteNotifier.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,3 +96,60 @@ class _FavouriteTogglerState extends State<FavouriteToggler> {
|
||||||
isFavouriteNotifier.value = entries.isNotEmpty && entries.every((entry) => entry.isFavourite);
|
isFavouriteNotifier.value = entries.isNotEmpty && entries.every((entry) => entry.isFavourite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FavouriteTogglerCaption extends StatefulWidget {
|
||||||
|
final Set<AvesEntry> entries;
|
||||||
|
final bool enabled;
|
||||||
|
|
||||||
|
const FavouriteTogglerCaption({
|
||||||
|
super.key,
|
||||||
|
required this.entries,
|
||||||
|
required this.enabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<FavouriteTogglerCaption> createState() => _FavouriteTogglerCaptionState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FavouriteTogglerCaptionState extends State<FavouriteTogglerCaption> {
|
||||||
|
final ValueNotifier<bool> isFavouriteNotifier = ValueNotifier(false);
|
||||||
|
|
||||||
|
Set<AvesEntry> get entries => widget.entries;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
favourites.addListener(_onChanged);
|
||||||
|
_onChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant FavouriteTogglerCaption oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
_onChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
favourites.removeListener(_onChanged);
|
||||||
|
isFavouriteNotifier.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ValueListenableBuilder<bool>(
|
||||||
|
valueListenable: isFavouriteNotifier,
|
||||||
|
builder: (context, isFavourite, child) {
|
||||||
|
return CaptionedButtonText(
|
||||||
|
text: isFavourite ? context.l10n.entryActionRemoveFavourite : context.l10n.entryActionAddFavourite,
|
||||||
|
enabled: widget.enabled,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onChanged() {
|
||||||
|
isFavouriteNotifier.value = entries.isNotEmpty && entries.every((entry) => entry.isFavourite);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ import 'dart:async';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/basic/menu.dart';
|
import 'package:aves/widgets/common/basic/menu.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
||||||
import 'package:aves/widgets/viewer/video/controller.dart';
|
import 'package:aves/widgets/viewer/video/controller.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -47,3 +48,34 @@ class MuteToggler extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MuteTogglerCaption extends StatelessWidget {
|
||||||
|
final AvesVideoController? controller;
|
||||||
|
final bool enabled;
|
||||||
|
|
||||||
|
const MuteTogglerCaption({
|
||||||
|
super.key,
|
||||||
|
required this.controller,
|
||||||
|
required this.enabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
bool get isMuted => controller?.isMuted ?? false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ValueListenableBuilder<bool>(
|
||||||
|
valueListenable: controller?.canMuteNotifier ?? ValueNotifier(false),
|
||||||
|
builder: (context, canDo, child) {
|
||||||
|
return StreamBuilder<double>(
|
||||||
|
stream: controller?.volumeStream ?? Stream.value(1.0),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return CaptionedButtonText(
|
||||||
|
text: isMuted ? context.l10n.videoActionUnmute : context.l10n.videoActionMute,
|
||||||
|
enabled: canDo && enabled,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/basic/menu.dart';
|
import 'package:aves/widgets/common/basic/menu.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
||||||
import 'package:aves/widgets/viewer/video/controller.dart';
|
import 'package:aves/widgets/viewer/video/controller.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -98,3 +99,29 @@ class _PlayTogglerState extends State<PlayToggler> with SingleTickerProviderStat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PlayTogglerCaption extends StatelessWidget {
|
||||||
|
final AvesVideoController? controller;
|
||||||
|
final bool enabled;
|
||||||
|
|
||||||
|
const PlayTogglerCaption({
|
||||||
|
super.key,
|
||||||
|
required this.controller,
|
||||||
|
required this.enabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
bool get isPlaying => controller?.isPlaying ?? false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return StreamBuilder<VideoStatus>(
|
||||||
|
stream: controller?.statusStream ?? Stream.value(VideoStatus.idle),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return CaptionedButtonText(
|
||||||
|
text: isPlaying ? context.l10n.videoActionPause : context.l10n.videoActionPlay,
|
||||||
|
enabled: enabled,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
|
import 'package:aves/model/query.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/basic/menu.dart';
|
import 'package:aves/widgets/common/basic/menu.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class TitleSearchToggler extends StatelessWidget {
|
class TitleSearchToggler extends StatelessWidget {
|
||||||
final bool queryEnabled, isMenuItem;
|
final bool queryEnabled, isMenuItem;
|
||||||
|
@ -30,3 +33,26 @@ class TitleSearchToggler extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TitleSearchTogglerCaption extends StatelessWidget {
|
||||||
|
final bool enabled;
|
||||||
|
|
||||||
|
const TitleSearchTogglerCaption({
|
||||||
|
super.key,
|
||||||
|
required this.enabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// `Query` may not be available during hero
|
||||||
|
return Selector<Query?, bool>(
|
||||||
|
selector: (context, query) => query?.enabled ?? false,
|
||||||
|
builder: (context, queryEnabled, child) {
|
||||||
|
return CaptionedButtonText(
|
||||||
|
text: queryEnabled ? context.l10n.collectionActionHideTitleSearch : context.l10n.collectionActionShowTitleSearch,
|
||||||
|
enabled: enabled,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
105
lib/widgets/common/identity/buttons/captioned_button.dart
Normal file
105
lib/widgets/common/identity/buttons/captioned_button.dart
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/rendering.dart';
|
||||||
|
|
||||||
|
class CaptionedButton extends StatelessWidget {
|
||||||
|
final Animation<double> scale;
|
||||||
|
final Widget captionText;
|
||||||
|
final Widget iconButton;
|
||||||
|
final bool showCaption;
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
|
||||||
|
CaptionedButton({
|
||||||
|
super.key,
|
||||||
|
this.scale = kAlwaysCompleteAnimation,
|
||||||
|
Widget? icon,
|
||||||
|
Widget? iconButton,
|
||||||
|
String? caption,
|
||||||
|
Widget? captionText,
|
||||||
|
this.showCaption = true,
|
||||||
|
required this.onPressed,
|
||||||
|
}) : assert(icon != null || iconButton != null),
|
||||||
|
assert(caption != null || captionText != null),
|
||||||
|
iconButton = iconButton ?? IconButton(icon: icon!, onPressed: onPressed),
|
||||||
|
captionText = captionText ?? CaptionedButtonText(text: caption!, enabled: onPressed != null);
|
||||||
|
|
||||||
|
static const double padding = 8;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
width: _width(context),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: padding),
|
||||||
|
OverlayButton(
|
||||||
|
scale: scale,
|
||||||
|
child: iconButton,
|
||||||
|
),
|
||||||
|
if (showCaption) ...[
|
||||||
|
const SizedBox(height: padding),
|
||||||
|
ScaleTransition(
|
||||||
|
scale: scale,
|
||||||
|
child: captionText,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
const SizedBox(height: padding),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double _width(BuildContext context) => OverlayButton.getSize(context) + padding * 2;
|
||||||
|
|
||||||
|
static Size getSize(BuildContext context, String text, {required bool showCaption}) {
|
||||||
|
final width = _width(context);
|
||||||
|
var height = width;
|
||||||
|
if (showCaption) {
|
||||||
|
final para = RenderParagraph(
|
||||||
|
TextSpan(text: text, style: CaptionedButtonText.textStyle(context)),
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
textScaleFactor: MediaQuery.textScaleFactorOf(context),
|
||||||
|
maxLines: CaptionedButtonText.maxLines,
|
||||||
|
)..layout(const BoxConstraints(), parentUsesSize: true);
|
||||||
|
height += para.getMaxIntrinsicHeight(width) + padding;
|
||||||
|
}
|
||||||
|
return Size(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double getTelevisionButtonHeight(BuildContext context) {
|
||||||
|
final text = 'whatever' * 42;
|
||||||
|
return CaptionedButton.getSize(context, text, showCaption: true).height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CaptionedButtonText extends StatelessWidget {
|
||||||
|
final String text;
|
||||||
|
final bool enabled;
|
||||||
|
|
||||||
|
static const int maxLines = 2;
|
||||||
|
|
||||||
|
const CaptionedButtonText({
|
||||||
|
super.key,
|
||||||
|
required this.text,
|
||||||
|
required this.enabled,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var style = textStyle(context);
|
||||||
|
if (!enabled) {
|
||||||
|
style = style.copyWith(color: style.color!.withOpacity(.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Text(
|
||||||
|
text,
|
||||||
|
style: style,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: maxLines,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TextStyle textStyle(BuildContext context) => Theme.of(context).textTheme.bodySmall!;
|
||||||
|
}
|
|
@ -13,13 +13,13 @@ import 'package:aves/utils/change_notifier.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/utils/math_utils.dart';
|
import 'package:aves/utils/math_utils.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
import 'package:aves/widgets/common/map/attribution.dart';
|
import 'package:aves/widgets/common/map/attribution.dart';
|
||||||
import 'package:aves/widgets/common/map/buttons/panel.dart';
|
import 'package:aves/widgets/common/map/buttons/panel.dart';
|
||||||
import 'package:aves/widgets/common/map/decorator.dart';
|
import 'package:aves/widgets/common/map/decorator.dart';
|
||||||
import 'package:aves/widgets/common/map/leaflet/map.dart';
|
import 'package:aves/widgets/common/map/leaflet/map.dart';
|
||||||
import 'package:aves/widgets/common/thumbnail/image.dart';
|
import 'package:aves/widgets/common/thumbnail/image.dart';
|
||||||
import 'package:aves/widgets/dialogs/aves_selection_dialog.dart';
|
import 'package:aves/widgets/dialogs/aves_selection_dialog.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
|
||||||
import 'package:aves_map/aves_map.dart';
|
import 'package:aves_map/aves_map.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:fluster/fluster.dart';
|
import 'package:fluster/fluster.dart';
|
||||||
|
|
|
@ -10,7 +10,7 @@ import 'package:aves/widgets/collection/collection_grid.dart';
|
||||||
import 'package:aves/widgets/common/basic/menu.dart';
|
import 'package:aves/widgets/common/basic/menu.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/grid/theme.dart';
|
import 'package:aves/widgets/common/grid/theme.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons.dart';
|
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
|
||||||
import 'package:aves/widgets/common/thumbnail/decorated.dart';
|
import 'package:aves/widgets/common/thumbnail/decorated.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
|
@ -11,7 +11,7 @@ import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/utils/debouncer.dart';
|
import 'package:aves/utils/debouncer.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons.dart';
|
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
|
||||||
import 'package:aves/widgets/common/map/geo_map.dart';
|
import 'package:aves/widgets/common/map/geo_map.dart';
|
||||||
import 'package:aves/widgets/common/providers/map_theme_provider.dart';
|
import 'package:aves/widgets/common/providers/map_theme_provider.dart';
|
||||||
import 'package:aves_map/aves_map.dart';
|
import 'package:aves_map/aves_map.dart';
|
||||||
|
|
|
@ -8,17 +8,17 @@ import 'package:aves/model/query.dart';
|
||||||
import 'package:aves/model/selection.dart';
|
import 'package:aves/model/selection.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
|
import 'package:aves/widgets/common/action_controls/togglers/title_search.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
|
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
|
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/title_search_toggler.dart';
|
|
||||||
import 'package:aves/widgets/common/basic/menu.dart';
|
import 'package:aves/widgets/common/basic/menu.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_app_bar.dart';
|
import 'package:aves/widgets/common/identity/aves_app_bar.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
||||||
import 'package:aves/widgets/common/search/route.dart';
|
import 'package:aves/widgets/common/search/route.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/action_delegates/chip_set.dart';
|
import 'package:aves/widgets/filter_grids/common/action_delegates/chip_set.dart';
|
||||||
import 'package:aves/widgets/filter_grids/common/query_bar.dart';
|
import 'package:aves/widgets/filter_grids/common/query_bar.dart';
|
||||||
import 'package:aves/widgets/search/search_delegate.dart';
|
import 'package:aves/widgets/search/search_delegate.dart';
|
||||||
import 'package:aves/widgets/settings/common/quick_actions/action_button.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -143,7 +143,7 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
children: [
|
children: [
|
||||||
if (isTelevision)
|
if (isTelevision)
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: ActionButton.getTelevisionButtonHeight(context),
|
height: CaptionedButton.getTelevisionButtonHeight(context),
|
||||||
child: ListView(
|
child: ListView(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
|
@ -166,7 +166,7 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
double get appBarContentHeight {
|
double get appBarContentHeight {
|
||||||
double height = kToolbarHeight;
|
double height = kToolbarHeight;
|
||||||
if (device.isTelevision) {
|
if (device.isTelevision) {
|
||||||
height += ActionButton.getTelevisionButtonHeight(context);
|
height += CaptionedButton.getTelevisionButtonHeight(context);
|
||||||
}
|
}
|
||||||
if (context.read<Query>().enabled) {
|
if (context.read<Query>().enabled) {
|
||||||
height += FilterQueryBar.preferredHeight;
|
height += FilterQueryBar.preferredHeight;
|
||||||
|
@ -281,12 +281,10 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
...ChipSetActions.general,
|
...ChipSetActions.general,
|
||||||
...isSelecting ? ChipSetActions.selection : ChipSetActions.browsing,
|
...isSelecting ? ChipSetActions.selection : ChipSetActions.browsing,
|
||||||
].where(isVisible).map((action) {
|
].where(isVisible).map((action) {
|
||||||
// TODO TLAD [tv] togglers cf `FilterGridAppBar.toMenuItem`
|
|
||||||
final enabled = canApply(action);
|
final enabled = canApply(action);
|
||||||
return ActionButton(
|
return CaptionedButton(
|
||||||
text: action.getText(context),
|
iconButton: _buildButtonIcon(context, actionDelegate, action, enabled: enabled),
|
||||||
icon: action.getIcon(),
|
captionText: _buildButtonCaption(context, action, enabled: enabled),
|
||||||
enabled: enabled,
|
|
||||||
onPressed: enabled ? () => _onActionSelected(context, action, actionDelegate) : null,
|
onPressed: enabled ? () => _onActionSelected(context, action, actionDelegate) : null,
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
@ -302,7 +300,7 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
final isSelecting = selection.isSelecting;
|
final isSelecting = selection.isSelecting;
|
||||||
|
|
||||||
final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
|
final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
|
||||||
(action) => _toActionButton(context, actionDelegate, action, enabled: canApply(action)),
|
(action) => _buildButtonIcon(context, actionDelegate, action, enabled: canApply(action)),
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -342,7 +340,7 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _toActionButton(
|
Widget _buildButtonIcon(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
CSAD actionDelegate,
|
CSAD actionDelegate,
|
||||||
ChipSetAction action, {
|
ChipSetAction action, {
|
||||||
|
@ -370,6 +368,24 @@ class _FilterGridAppBarState<T extends CollectionFilter, CSAD extends ChipSetAct
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildButtonCaption(
|
||||||
|
BuildContext context,
|
||||||
|
ChipSetAction action, {
|
||||||
|
required bool enabled,
|
||||||
|
}) {
|
||||||
|
switch (action) {
|
||||||
|
case ChipSetAction.toggleTitleSearch:
|
||||||
|
return TitleSearchTogglerCaption(
|
||||||
|
enabled: enabled,
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return CaptionedButtonText(
|
||||||
|
text: action.getText(context),
|
||||||
|
enabled: enabled,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _onActivityChanged() {
|
void _onActivityChanged() {
|
||||||
if (context.read<Selection<FilterGridItem<T>>>().isSelecting) {
|
if (context.read<Selection<FilterGridItem<T>>>().isSelecting) {
|
||||||
_browseToSelectAnimation.forward();
|
_browseToSelectAnimation.forward();
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/rendering.dart';
|
|
||||||
|
|
||||||
class ActionButton extends StatelessWidget {
|
|
||||||
final String text;
|
|
||||||
final Widget? icon;
|
|
||||||
final bool enabled, showCaption;
|
|
||||||
final VoidCallback? onPressed;
|
|
||||||
|
|
||||||
const ActionButton({
|
|
||||||
super.key,
|
|
||||||
required this.text,
|
|
||||||
required this.icon,
|
|
||||||
this.enabled = true,
|
|
||||||
this.showCaption = true,
|
|
||||||
this.onPressed,
|
|
||||||
}) : assert(onPressed == null || enabled);
|
|
||||||
|
|
||||||
static const int maxLines = 2;
|
|
||||||
static const double padding = 8;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final textStyle = _textStyle(context);
|
|
||||||
final _enabled = onPressed != null || enabled;
|
|
||||||
return SizedBox(
|
|
||||||
width: _width(context),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const SizedBox(height: padding),
|
|
||||||
OverlayButton(
|
|
||||||
child: IconButton(
|
|
||||||
icon: icon ?? const SizedBox(),
|
|
||||||
onPressed: onPressed ?? (_enabled ? () {} : null),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (showCaption) ...[
|
|
||||||
const SizedBox(height: padding),
|
|
||||||
Text(
|
|
||||||
text,
|
|
||||||
style: _enabled ? textStyle : textStyle.copyWith(color: textStyle.color!.withOpacity(.2)),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: maxLines,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
const SizedBox(height: padding),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static TextStyle _textStyle(BuildContext context) => Theme.of(context).textTheme.bodySmall!;
|
|
||||||
|
|
||||||
static double _width(BuildContext context) => OverlayButton.getSize(context) + padding * 2;
|
|
||||||
|
|
||||||
static Size getSize(BuildContext context, String text, {required bool showCaption}) {
|
|
||||||
final width = _width(context);
|
|
||||||
var height = width;
|
|
||||||
if (showCaption) {
|
|
||||||
final para = RenderParagraph(
|
|
||||||
TextSpan(text: text, style: _textStyle(context)),
|
|
||||||
textDirection: TextDirection.ltr,
|
|
||||||
textScaleFactor: MediaQuery.textScaleFactorOf(context),
|
|
||||||
maxLines: maxLines,
|
|
||||||
)..layout(const BoxConstraints(), parentUsesSize: true);
|
|
||||||
height += para.getMaxIntrinsicHeight(width) + padding;
|
|
||||||
}
|
|
||||||
return Size(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static double getTelevisionButtonHeight(BuildContext context) {
|
|
||||||
final text = 'whatever' * 42;
|
|
||||||
return ActionButton.getSize(context, text, showCaption: true).height;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||||
import 'package:aves/widgets/settings/common/quick_actions/action_button.dart';
|
|
||||||
import 'package:aves/widgets/settings/common/quick_actions/placeholder.dart';
|
import 'package:aves/widgets/settings/common/quick_actions/placeholder.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
@ -13,7 +13,7 @@ class AvailableActionPanel<T extends Object> extends StatelessWidget {
|
||||||
final ValueNotifier<T?> draggedQuickAction;
|
final ValueNotifier<T?> draggedQuickAction;
|
||||||
final ValueNotifier<T?> draggedAvailableAction;
|
final ValueNotifier<T?> draggedAvailableAction;
|
||||||
final bool Function(T? action) removeQuickAction;
|
final bool Function(T? action) removeQuickAction;
|
||||||
final Widget? Function(T action) actionIcon;
|
final Widget Function(T action) actionIcon;
|
||||||
final String Function(BuildContext context, T action) actionText;
|
final String Function(BuildContext context, T action) actionText;
|
||||||
|
|
||||||
static const double spacing = 8;
|
static const double spacing = 8;
|
||||||
|
@ -107,11 +107,11 @@ class AvailableActionPanel<T extends Object> extends StatelessWidget {
|
||||||
bool enabled = true,
|
bool enabled = true,
|
||||||
bool showCaption = true,
|
bool showCaption = true,
|
||||||
}) =>
|
}) =>
|
||||||
ActionButton(
|
CaptionedButton(
|
||||||
text: actionText(context, action),
|
|
||||||
icon: actionIcon(action),
|
icon: actionIcon(action),
|
||||||
enabled: enabled,
|
caption: actionText(context, action),
|
||||||
showCaption: showCaption,
|
showCaption: showCaption,
|
||||||
|
onPressed: enabled ? () {} : null,
|
||||||
);
|
);
|
||||||
|
|
||||||
void _setDraggedQuickAction(T? action) => draggedQuickAction.value = action;
|
void _setDraggedQuickAction(T? action) => draggedQuickAction.value = action;
|
||||||
|
@ -121,7 +121,7 @@ class AvailableActionPanel<T extends Object> extends StatelessWidget {
|
||||||
void _setPanelHighlight(bool flag) => panelHighlight.value = flag;
|
void _setPanelHighlight(bool flag) => panelHighlight.value = flag;
|
||||||
|
|
||||||
static double heightFor(BuildContext context, List<String> captions, double width) {
|
static double heightFor(BuildContext context, List<String> captions, double width) {
|
||||||
final buttonSizes = captions.map((v) => ActionButton.getSize(context, v, showCaption: true));
|
final buttonSizes = captions.map((v) => CaptionedButton.getSize(context, v, showCaption: true));
|
||||||
final actionsPerRun = (width - padding.horizontal + spacing) ~/ (buttonSizes.first.width + spacing);
|
final actionsPerRun = (width - padding.horizontal + spacing) ~/ (buttonSizes.first.width + spacing);
|
||||||
final runCount = (captions.length / actionsPerRun).ceil();
|
final runCount = (captions.length / actionsPerRun).ceil();
|
||||||
var height = .0;
|
var height = .0;
|
||||||
|
|
|
@ -5,12 +5,12 @@ import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/utils/change_notifier.dart';
|
import 'package:aves/utils/change_notifier.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/settings/common/quick_actions/action_button.dart';
|
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
import 'package:aves/widgets/settings/common/quick_actions/action_panel.dart';
|
import 'package:aves/widgets/settings/common/quick_actions/action_panel.dart';
|
||||||
import 'package:aves/widgets/settings/common/quick_actions/available_actions.dart';
|
import 'package:aves/widgets/settings/common/quick_actions/available_actions.dart';
|
||||||
import 'package:aves/widgets/settings/common/quick_actions/placeholder.dart';
|
import 'package:aves/widgets/settings/common/quick_actions/placeholder.dart';
|
||||||
import 'package:aves/widgets/settings/common/quick_actions/quick_actions.dart';
|
import 'package:aves/widgets/settings/common/quick_actions/quick_actions.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -19,7 +19,7 @@ import 'package:smooth_page_indicator/smooth_page_indicator.dart';
|
||||||
class QuickActionEditorPage<T extends Object> extends StatelessWidget {
|
class QuickActionEditorPage<T extends Object> extends StatelessWidget {
|
||||||
final String title, bannerText;
|
final String title, bannerText;
|
||||||
final List<List<T>> allAvailableActions;
|
final List<List<T>> allAvailableActions;
|
||||||
final Widget? Function(T action) actionIcon;
|
final Widget Function(T action) actionIcon;
|
||||||
final String Function(BuildContext context, T action) actionText;
|
final String Function(BuildContext context, T action) actionText;
|
||||||
final List<T> Function() load;
|
final List<T> Function() load;
|
||||||
final void Function(List<T> actions) save;
|
final void Function(List<T> actions) save;
|
||||||
|
@ -58,7 +58,7 @@ class QuickActionEditorPage<T extends Object> extends StatelessWidget {
|
||||||
class QuickActionEditorBody<T extends Object> extends StatefulWidget {
|
class QuickActionEditorBody<T extends Object> extends StatefulWidget {
|
||||||
final String bannerText;
|
final String bannerText;
|
||||||
final List<List<T>> allAvailableActions;
|
final List<List<T>> allAvailableActions;
|
||||||
final Widget? Function(T action) actionIcon;
|
final Widget Function(T action) actionIcon;
|
||||||
final String Function(BuildContext context, T action) actionText;
|
final String Function(BuildContext context, T action) actionText;
|
||||||
final List<T> Function() load;
|
final List<T> Function() load;
|
||||||
final void Function(List<T> actions) save;
|
final void Function(List<T> actions) save;
|
||||||
|
@ -208,10 +208,11 @@ class _QuickActionEditorBodyState<T extends Object> extends State<QuickActionEdi
|
||||||
insertAction: _insertQuickAction,
|
insertAction: _insertQuickAction,
|
||||||
removeAction: _removeQuickAction,
|
removeAction: _removeQuickAction,
|
||||||
onTargetLeave: _onQuickActionTargetLeave,
|
onTargetLeave: _onQuickActionTargetLeave,
|
||||||
draggableFeedbackBuilder: (action) => ActionButton(
|
draggableFeedbackBuilder: (action) => CaptionedButton(
|
||||||
text: widget.actionText(context, action),
|
|
||||||
icon: widget.actionIcon(action),
|
icon: widget.actionIcon(action),
|
||||||
|
caption: widget.actionText(context, action),
|
||||||
showCaption: false,
|
showCaption: false,
|
||||||
|
onPressed: () {},
|
||||||
),
|
),
|
||||||
child: _buildQuickActionButton(action, animation),
|
child: _buildQuickActionButton(action, animation),
|
||||||
);
|
);
|
||||||
|
@ -361,7 +362,7 @@ class _QuickActionEditorBodyState<T extends Object> extends State<QuickActionEdi
|
||||||
padding: const EdgeInsets.symmetric(vertical: _QuickActionEditorBodyState.quickActionVerticalPadding, horizontal: 4),
|
padding: const EdgeInsets.symmetric(vertical: _QuickActionEditorBodyState.quickActionVerticalPadding, horizontal: 4),
|
||||||
child: OverlayButton(
|
child: OverlayButton(
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: widget.actionIcon(action) ?? const SizedBox(),
|
icon: widget.actionIcon(action),
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
enum QuickActionPlacement { header, action, footer }
|
enum QuickActionPlacement { header, action, footer }
|
||||||
|
|
|
@ -10,7 +10,7 @@ import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/fx/borders.dart';
|
import 'package:aves/widgets/common/fx/borders.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons.dart';
|
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
|
||||||
import 'package:aves/widgets/home_widget.dart';
|
import 'package:aves/widgets/home_widget.dart';
|
||||||
import 'package:aves/widgets/settings/common/collection_tile.dart';
|
import 'package:aves/widgets/settings/common/collection_tile.dart';
|
||||||
import 'package:aves/widgets/settings/common/tiles.dart';
|
import 'package:aves/widgets/settings/common/tiles.dart';
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'package:aves/model/filters/album.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons.dart';
|
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
|
||||||
import 'package:aves/widgets/filter_grids/album_pick.dart';
|
import 'package:aves/widgets/filter_grids/album_pick.dart';
|
||||||
import 'package:aves/widgets/navigation/drawer/tile.dart';
|
import 'package:aves/widgets/navigation/drawer/tile.dart';
|
||||||
import 'package:aves/widgets/settings/navigation/drawer_editor_banner.dart';
|
import 'package:aves/widgets/settings/navigation/drawer_editor_banner.dart';
|
||||||
|
|
|
@ -8,7 +8,7 @@ import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/widgets/common/basic/menu.dart';
|
import 'package:aves/widgets/common/basic/menu.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons.dart';
|
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
|
||||||
import 'package:aves/widgets/common/identity/empty.dart';
|
import 'package:aves/widgets/common/identity/empty.dart';
|
||||||
import 'package:aves/widgets/settings/privacy/file_picker/crumb_line.dart';
|
import 'package:aves/widgets/settings/privacy/file_picker/crumb_line.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
|
|
@ -5,7 +5,7 @@ import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons.dart';
|
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
|
||||||
import 'package:aves/widgets/common/identity/empty.dart';
|
import 'package:aves/widgets/common/identity/empty.dart';
|
||||||
import 'package:aves/widgets/settings/privacy/file_picker/file_picker_page.dart';
|
import 'package:aves/widgets/settings/privacy/file_picker/file_picker_page.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
|
@ -16,8 +16,8 @@ import 'package:aves/theme/colors.dart';
|
||||||
import 'package:aves/theme/format.dart';
|
import 'package:aves/theme/format.dart';
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/utils/file_utils.dart';
|
import 'package:aves/utils/file_utils.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/rate_button.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/rate_button.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/tag_button.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/tag_button.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||||
import 'package:aves/widgets/viewer/action/entry_info_action_delegate.dart';
|
import 'package:aves/widgets/viewer/action/entry_info_action_delegate.dart';
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:async';
|
||||||
import 'package:aves/model/entry.dart';
|
import 'package:aves/model/entry.dart';
|
||||||
import 'package:aves/services/common/services.dart';
|
import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
import 'package:aves/widgets/viewer/panorama_page.dart';
|
import 'package:aves/widgets/viewer/panorama_page.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:aves/model/actions/slideshow_actions.dart';
|
import 'package:aves/model/actions/slideshow_actions.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/viewer_buttons.dart';
|
import 'package:aves/widgets/viewer/overlay/viewer_buttons.dart';
|
||||||
import 'package:aves/widgets/viewer/slideshow_page.dart';
|
import 'package:aves/widgets/viewer/slideshow_page.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -14,7 +14,7 @@ class SlideshowButtons extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// TODO TLAD [tv] action buttons
|
// TODO TLAD [tv] captioned buttons
|
||||||
const padding = ViewerButtonRowContent.padding;
|
const padding = ViewerButtonRowContent.padding;
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import 'package:aves/model/actions/entry_actions.dart';
|
import 'package:aves/model/actions/entry_actions.dart';
|
||||||
import 'package:aves/model/settings/enums/enums.dart';
|
import 'package:aves/model/settings/enums/enums.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/video/play_toggler.dart';
|
import 'package:aves/widgets/common/action_controls/togglers/play.dart';
|
||||||
import 'package:aves/widgets/viewer/video/controller.dart';
|
import 'package:aves/widgets/viewer/video/controller.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/model/actions/entry_actions.dart';
|
import 'package:aves/model/actions/entry_actions.dart';
|
||||||
import 'package:aves/model/entry.dart';
|
import 'package:aves/model/entry.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/video/controls.dart';
|
import 'package:aves/widgets/viewer/overlay/video/controls.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/video/progress_bar.dart';
|
import 'package:aves/widgets/viewer/overlay/video/progress_bar.dart';
|
||||||
import 'package:aves/widgets/viewer/video/controller.dart';
|
import 'package:aves/widgets/viewer/video/controller.dart';
|
||||||
|
|
|
@ -5,20 +5,20 @@ import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/theme/icons.dart';
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/favourite_toggler.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/move_button.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/move_button.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/rate_button.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/rate_button.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/share_button.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/share_button.dart';
|
import 'package:aves/widgets/common/action_controls/quick_choosers/tag_button.dart';
|
||||||
import 'package:aves/widgets/common/app_bar/quick_choosers/tag_button.dart';
|
import 'package:aves/widgets/common/action_controls/togglers/favourite.dart';
|
||||||
|
import 'package:aves/widgets/common/action_controls/togglers/mute.dart';
|
||||||
|
import 'package:aves/widgets/common/action_controls/togglers/play.dart';
|
||||||
import 'package:aves/widgets/common/basic/menu.dart';
|
import 'package:aves/widgets/common/basic/menu.dart';
|
||||||
import 'package:aves/widgets/common/basic/popup_menu_button.dart';
|
import 'package:aves/widgets/common/basic/popup_menu_button.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/settings/common/quick_actions/action_button.dart';
|
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
import 'package:aves/widgets/viewer/action/entry_action_delegate.dart';
|
import 'package:aves/widgets/viewer/action/entry_action_delegate.dart';
|
||||||
import 'package:aves/widgets/viewer/notifications.dart';
|
import 'package:aves/widgets/viewer/notifications.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
|
||||||
import 'package:aves/widgets/viewer/overlay/video/mute_toggler.dart';
|
|
||||||
import 'package:aves/widgets/viewer/overlay/video/play_toggler.dart';
|
|
||||||
import 'package:aves/widgets/viewer/video/conductor.dart';
|
import 'package:aves/widgets/viewer/video/conductor.dart';
|
||||||
import 'package:aves/widgets/viewer/video/controller.dart';
|
import 'package:aves/widgets/viewer/video/controller.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
@ -49,16 +49,17 @@ class ViewerButtons extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final actionDelegate = EntryActionDelegate(mainEntry, pageEntry, collection);
|
||||||
|
|
||||||
if (device.isTelevision) {
|
if (device.isTelevision) {
|
||||||
return _TvButtonRowContent(
|
return _TvButtonRowContent(
|
||||||
|
actionDelegate: actionDelegate,
|
||||||
scale: scale,
|
scale: scale,
|
||||||
mainEntry: mainEntry,
|
mainEntry: mainEntry,
|
||||||
pageEntry: pageEntry,
|
pageEntry: pageEntry,
|
||||||
collection: collection,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final actionDelegate = EntryActionDelegate(mainEntry, pageEntry, collection);
|
|
||||||
final trashed = mainEntry.trashed;
|
final trashed = mainEntry.trashed;
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
top: false,
|
top: false,
|
||||||
|
@ -75,6 +76,7 @@ class ViewerButtons extends StatelessWidget {
|
||||||
final exportActions = EntryActions.export.where((action) => !quickActions.contains(action)).where(actionDelegate.isVisible).toList();
|
final exportActions = EntryActions.export.where((action) => !quickActions.contains(action)).where(actionDelegate.isVisible).toList();
|
||||||
final videoActions = EntryActions.video.where((action) => !quickActions.contains(action)).where(actionDelegate.isVisible).toList();
|
final videoActions = EntryActions.video.where((action) => !quickActions.contains(action)).where(actionDelegate.isVisible).toList();
|
||||||
return ViewerButtonRowContent(
|
return ViewerButtonRowContent(
|
||||||
|
actionDelegate: EntryActionDelegate(mainEntry, pageEntry, collection),
|
||||||
quickActions: quickActions,
|
quickActions: quickActions,
|
||||||
topLevelActions: topLevelActions,
|
topLevelActions: topLevelActions,
|
||||||
exportActions: exportActions,
|
exportActions: exportActions,
|
||||||
|
@ -82,7 +84,6 @@ class ViewerButtons extends StatelessWidget {
|
||||||
scale: scale,
|
scale: scale,
|
||||||
mainEntry: mainEntry,
|
mainEntry: mainEntry,
|
||||||
pageEntry: pageEntry,
|
pageEntry: pageEntry,
|
||||||
collection: collection,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -93,48 +94,64 @@ class ViewerButtons extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TvButtonRowContent extends StatelessWidget {
|
class _TvButtonRowContent extends StatelessWidget {
|
||||||
|
final EntryActionDelegate actionDelegate;
|
||||||
final Animation<double> scale;
|
final Animation<double> scale;
|
||||||
final AvesEntry mainEntry, pageEntry;
|
final AvesEntry mainEntry, pageEntry;
|
||||||
final CollectionLens? collection;
|
|
||||||
|
|
||||||
const _TvButtonRowContent({
|
const _TvButtonRowContent({
|
||||||
|
required this.actionDelegate,
|
||||||
required this.scale,
|
required this.scale,
|
||||||
required this.mainEntry,
|
required this.mainEntry,
|
||||||
required this.pageEntry,
|
required this.pageEntry,
|
||||||
required this.collection,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final actionDelegate = EntryActionDelegate(mainEntry, pageEntry, collection);
|
return Selector<VideoConductor, AvesVideoController?>(
|
||||||
|
selector: (context, vc) => vc.getController(pageEntry),
|
||||||
|
builder: (context, videoController, child) {
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
...EntryActions.topLevel,
|
...EntryActions.topLevel,
|
||||||
...EntryActions.export,
|
...EntryActions.export,
|
||||||
|
...EntryActions.videoPlayback,
|
||||||
...EntryActions.video,
|
...EntryActions.video,
|
||||||
].where(actionDelegate.isVisible).map((action) {
|
].where(actionDelegate.isVisible).map((action) {
|
||||||
// TODO TLAD [tv] togglers cf `_buildOverlayButton`
|
|
||||||
// TODO TLAD [tv] use `scale`
|
|
||||||
final enabled = actionDelegate.canApply(action);
|
final enabled = actionDelegate.canApply(action);
|
||||||
return ActionButton(
|
return CaptionedButton(
|
||||||
text: action.getText(context),
|
scale: scale,
|
||||||
icon: action.getIcon(),
|
iconButton: _buildButtonIcon(
|
||||||
|
context: context,
|
||||||
|
action: action,
|
||||||
|
mainEntry: mainEntry,
|
||||||
|
pageEntry: pageEntry,
|
||||||
|
videoController: videoController,
|
||||||
|
actionDelegate: actionDelegate,
|
||||||
|
),
|
||||||
|
captionText: _buildButtonCaption(
|
||||||
|
context: context,
|
||||||
|
action: action,
|
||||||
|
mainEntry: mainEntry,
|
||||||
|
pageEntry: pageEntry,
|
||||||
|
videoController: videoController,
|
||||||
enabled: enabled,
|
enabled: enabled,
|
||||||
|
),
|
||||||
onPressed: enabled ? () => actionDelegate.onActionSelected(context, action) : null,
|
onPressed: enabled ? () => actionDelegate.onActionSelected(context, action) : null,
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewerButtonRowContent extends StatelessWidget {
|
class ViewerButtonRowContent extends StatelessWidget {
|
||||||
|
final EntryActionDelegate actionDelegate;
|
||||||
final List<EntryAction> quickActions, topLevelActions, exportActions, videoActions;
|
final List<EntryAction> quickActions, topLevelActions, exportActions, videoActions;
|
||||||
final Animation<double> scale;
|
final Animation<double> scale;
|
||||||
final AvesEntry mainEntry, pageEntry;
|
final AvesEntry mainEntry, pageEntry;
|
||||||
final CollectionLens? collection;
|
|
||||||
final ValueNotifier<String?> _popupExpandedNotifier = ValueNotifier(null);
|
final ValueNotifier<String?> _popupExpandedNotifier = ValueNotifier(null);
|
||||||
|
|
||||||
AvesEntry get favouriteTargetEntry => mainEntry.isBurst ? pageEntry : mainEntry;
|
AvesEntry get favouriteTargetEntry => mainEntry.isBurst ? pageEntry : mainEntry;
|
||||||
|
@ -143,6 +160,7 @@ class ViewerButtonRowContent extends StatelessWidget {
|
||||||
|
|
||||||
ViewerButtonRowContent({
|
ViewerButtonRowContent({
|
||||||
super.key,
|
super.key,
|
||||||
|
required this.actionDelegate,
|
||||||
required this.quickActions,
|
required this.quickActions,
|
||||||
required this.topLevelActions,
|
required this.topLevelActions,
|
||||||
required this.exportActions,
|
required this.exportActions,
|
||||||
|
@ -150,7 +168,6 @@ class ViewerButtonRowContent extends StatelessWidget {
|
||||||
required this.scale,
|
required this.scale,
|
||||||
required this.mainEntry,
|
required this.mainEntry,
|
||||||
required this.pageEntry,
|
required this.pageEntry,
|
||||||
required this.collection,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -216,7 +233,7 @@ class ViewerButtonRowContent extends StatelessWidget {
|
||||||
onSelected: (action) {
|
onSelected: (action) {
|
||||||
_popupExpandedNotifier.value = null;
|
_popupExpandedNotifier.value = null;
|
||||||
// wait for the popup menu to hide before proceeding with the action
|
// wait for the popup menu to hide before proceeding with the action
|
||||||
Future.delayed(Durations.popupMenuAnimation * timeDilation, () => _onActionSelected(context, action));
|
Future.delayed(Durations.popupMenuAnimation * timeDilation, () => actionDelegate.onActionSelected(context, action));
|
||||||
},
|
},
|
||||||
onCanceled: () {
|
onCanceled: () {
|
||||||
_popupExpandedNotifier.value = null;
|
_popupExpandedNotifier.value = null;
|
||||||
|
@ -239,101 +256,18 @@ class ViewerButtonRowContent extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildOverlayButton(BuildContext context, EntryAction action, AvesVideoController? videoController) {
|
Widget _buildOverlayButton(BuildContext context, EntryAction action, AvesVideoController? videoController) {
|
||||||
Widget? child;
|
|
||||||
void onPressed() => _onActionSelected(context, action);
|
|
||||||
|
|
||||||
ValueListenableBuilder<bool> _buildFromListenable(ValueListenable<bool>? enabledNotifier) {
|
|
||||||
return ValueListenableBuilder<bool>(
|
|
||||||
valueListenable: enabledNotifier ?? ValueNotifier(false),
|
|
||||||
builder: (context, canDo, child) => IconButton(
|
|
||||||
icon: child!,
|
|
||||||
onPressed: canDo ? onPressed : null,
|
|
||||||
tooltip: action.getText(context),
|
|
||||||
),
|
|
||||||
child: action.getIcon(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final blurred = settings.enableBlurEffect;
|
|
||||||
switch (action) {
|
|
||||||
case EntryAction.copy:
|
|
||||||
child = MoveButton(
|
|
||||||
copy: true,
|
|
||||||
blurred: blurred,
|
|
||||||
onChooserValue: (album) => _entryActionDelegate.quickMove(context, album, copy: true),
|
|
||||||
onPressed: onPressed,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case EntryAction.move:
|
|
||||||
child = MoveButton(
|
|
||||||
copy: false,
|
|
||||||
blurred: blurred,
|
|
||||||
onChooserValue: (album) => _entryActionDelegate.quickMove(context, album, copy: false),
|
|
||||||
onPressed: onPressed,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case EntryAction.share:
|
|
||||||
child = ShareButton(
|
|
||||||
blurred: blurred,
|
|
||||||
entries: {mainEntry},
|
|
||||||
onChooserValue: (action) => _entryActionDelegate.quickShare(context, action),
|
|
||||||
onPressed: onPressed,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case EntryAction.toggleFavourite:
|
|
||||||
child = FavouriteToggler(
|
|
||||||
entries: {favouriteTargetEntry},
|
|
||||||
onPressed: onPressed,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case EntryAction.videoToggleMute:
|
|
||||||
child = MuteToggler(
|
|
||||||
controller: videoController,
|
|
||||||
onPressed: onPressed,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case EntryAction.videoTogglePlay:
|
|
||||||
child = PlayToggler(
|
|
||||||
controller: videoController,
|
|
||||||
onPressed: onPressed,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case EntryAction.videoCaptureFrame:
|
|
||||||
child = _buildFromListenable(videoController?.canCaptureFrameNotifier);
|
|
||||||
break;
|
|
||||||
case EntryAction.videoSelectStreams:
|
|
||||||
child = _buildFromListenable(videoController?.canSelectStreamNotifier);
|
|
||||||
break;
|
|
||||||
case EntryAction.videoSetSpeed:
|
|
||||||
child = _buildFromListenable(videoController?.canSetSpeedNotifier);
|
|
||||||
break;
|
|
||||||
case EntryAction.editRating:
|
|
||||||
child = RateButton(
|
|
||||||
blurred: blurred,
|
|
||||||
onChooserValue: (rating) => _entryActionDelegate.quickRate(context, rating),
|
|
||||||
onPressed: onPressed,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case EntryAction.editTags:
|
|
||||||
child = TagButton(
|
|
||||||
blurred: blurred,
|
|
||||||
onChooserValue: (filter) => _entryActionDelegate.quickTag(context, filter),
|
|
||||||
onPressed: onPressed,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
child = IconButton(
|
|
||||||
icon: action.getIcon(),
|
|
||||||
onPressed: onPressed,
|
|
||||||
tooltip: action.getText(context),
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: padding / 2),
|
padding: const EdgeInsets.symmetric(horizontal: padding / 2),
|
||||||
child: OverlayButton(
|
child: OverlayButton(
|
||||||
scale: scale,
|
scale: scale,
|
||||||
child: child,
|
child: _buildButtonIcon(
|
||||||
|
context: context,
|
||||||
|
action: action,
|
||||||
|
mainEntry: mainEntry,
|
||||||
|
pageEntry: pageEntry,
|
||||||
|
videoController: videoController,
|
||||||
|
actionDelegate: actionDelegate,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -390,8 +324,6 @@ class ViewerButtonRowContent extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupMenuItem<EntryAction> _buildRotateAndFlipMenuItems(BuildContext context) {
|
PopupMenuItem<EntryAction> _buildRotateAndFlipMenuItems(BuildContext context) {
|
||||||
final actionDelegate = _entryActionDelegate;
|
|
||||||
|
|
||||||
Widget buildDivider() => const SizedBox(
|
Widget buildDivider() => const SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
child: VerticalDivider(
|
child: VerticalDivider(
|
||||||
|
@ -443,8 +375,139 @@ class ViewerButtonRowContent extends StatelessWidget {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
EntryActionDelegate get _entryActionDelegate => EntryActionDelegate(mainEntry, pageEntry, collection);
|
|
||||||
|
Widget _buildButtonIcon({
|
||||||
void _onActionSelected(BuildContext context, EntryAction action) => _entryActionDelegate.onActionSelected(context, action);
|
required BuildContext context,
|
||||||
|
required EntryAction action,
|
||||||
|
required AvesEntry mainEntry,
|
||||||
|
required AvesEntry pageEntry,
|
||||||
|
required AvesVideoController? videoController,
|
||||||
|
required EntryActionDelegate actionDelegate,
|
||||||
|
}) {
|
||||||
|
Widget? child;
|
||||||
|
void onPressed() => actionDelegate.onActionSelected(context, action);
|
||||||
|
|
||||||
|
ValueListenableBuilder<bool> _buildFromListenable(ValueListenable<bool>? enabledNotifier) {
|
||||||
|
return ValueListenableBuilder<bool>(
|
||||||
|
valueListenable: enabledNotifier ?? ValueNotifier(false),
|
||||||
|
builder: (context, canDo, child) => IconButton(
|
||||||
|
icon: child!,
|
||||||
|
onPressed: canDo ? onPressed : null,
|
||||||
|
tooltip: action.getText(context),
|
||||||
|
),
|
||||||
|
child: action.getIcon(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final blurred = settings.enableBlurEffect;
|
||||||
|
switch (action) {
|
||||||
|
case EntryAction.copy:
|
||||||
|
child = MoveButton(
|
||||||
|
copy: true,
|
||||||
|
blurred: blurred,
|
||||||
|
onChooserValue: (album) => actionDelegate.quickMove(context, album, copy: true),
|
||||||
|
onPressed: onPressed,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case EntryAction.move:
|
||||||
|
child = MoveButton(
|
||||||
|
copy: false,
|
||||||
|
blurred: blurred,
|
||||||
|
onChooserValue: (album) => actionDelegate.quickMove(context, album, copy: false),
|
||||||
|
onPressed: onPressed,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case EntryAction.share:
|
||||||
|
child = ShareButton(
|
||||||
|
blurred: blurred,
|
||||||
|
entries: {mainEntry},
|
||||||
|
onChooserValue: (action) => actionDelegate.quickShare(context, action),
|
||||||
|
onPressed: onPressed,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case EntryAction.toggleFavourite:
|
||||||
|
final favouriteTargetEntry = mainEntry.isBurst ? pageEntry : mainEntry;
|
||||||
|
child = FavouriteToggler(
|
||||||
|
entries: {favouriteTargetEntry},
|
||||||
|
onPressed: onPressed,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case EntryAction.videoToggleMute:
|
||||||
|
child = MuteToggler(
|
||||||
|
controller: videoController,
|
||||||
|
onPressed: onPressed,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case EntryAction.videoTogglePlay:
|
||||||
|
child = PlayToggler(
|
||||||
|
controller: videoController,
|
||||||
|
onPressed: onPressed,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case EntryAction.videoCaptureFrame:
|
||||||
|
child = _buildFromListenable(videoController?.canCaptureFrameNotifier);
|
||||||
|
break;
|
||||||
|
case EntryAction.videoSelectStreams:
|
||||||
|
child = _buildFromListenable(videoController?.canSelectStreamNotifier);
|
||||||
|
break;
|
||||||
|
case EntryAction.videoSetSpeed:
|
||||||
|
child = _buildFromListenable(videoController?.canSetSpeedNotifier);
|
||||||
|
break;
|
||||||
|
case EntryAction.editRating:
|
||||||
|
child = RateButton(
|
||||||
|
blurred: blurred,
|
||||||
|
onChooserValue: (rating) => actionDelegate.quickRate(context, rating),
|
||||||
|
onPressed: onPressed,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case EntryAction.editTags:
|
||||||
|
child = TagButton(
|
||||||
|
blurred: blurred,
|
||||||
|
onChooserValue: (filter) => actionDelegate.quickTag(context, filter),
|
||||||
|
onPressed: onPressed,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
child = IconButton(
|
||||||
|
icon: action.getIcon(),
|
||||||
|
onPressed: onPressed,
|
||||||
|
tooltip: action.getText(context),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildButtonCaption({
|
||||||
|
required BuildContext context,
|
||||||
|
required EntryAction action,
|
||||||
|
required AvesEntry mainEntry,
|
||||||
|
required AvesEntry pageEntry,
|
||||||
|
required AvesVideoController? videoController,
|
||||||
|
required bool enabled,
|
||||||
|
}) {
|
||||||
|
switch (action) {
|
||||||
|
case EntryAction.toggleFavourite:
|
||||||
|
final favouriteTargetEntry = mainEntry.isBurst ? pageEntry : mainEntry;
|
||||||
|
return FavouriteTogglerCaption(
|
||||||
|
entries: {favouriteTargetEntry},
|
||||||
|
enabled: enabled,
|
||||||
|
);
|
||||||
|
case EntryAction.videoToggleMute:
|
||||||
|
return MuteTogglerCaption(
|
||||||
|
controller: videoController,
|
||||||
|
enabled: enabled,
|
||||||
|
);
|
||||||
|
case EntryAction.videoTogglePlay:
|
||||||
|
return PlayTogglerCaption(
|
||||||
|
controller: videoController,
|
||||||
|
enabled: enabled,
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return CaptionedButtonText(
|
||||||
|
text: action.getText(context),
|
||||||
|
enabled: enabled,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ import 'package:aves/model/wallpaper_target.dart';
|
||||||
import 'package:aves/services/wallpaper_service.dart';
|
import 'package:aves/services/wallpaper_service.dart';
|
||||||
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
import 'package:aves/widgets/dialogs/wallpaper_settings_dialog.dart';
|
import 'package:aves/widgets/dialogs/wallpaper_settings_dialog.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
|
||||||
import 'package:aves/widgets/viewer/overlay/viewer_buttons.dart';
|
import 'package:aves/widgets/viewer/overlay/viewer_buttons.dart';
|
||||||
import 'package:aves/widgets/viewer/video/conductor.dart';
|
import 'package:aves/widgets/viewer/video/conductor.dart';
|
||||||
import 'package:aves/widgets/viewer/visual/conductor.dart';
|
import 'package:aves/widgets/viewer/visual/conductor.dart';
|
||||||
|
|
|
@ -9,7 +9,7 @@ import 'package:aves/widgets/aves_app.dart';
|
||||||
import 'package:aves/widgets/common/basic/insets.dart';
|
import 'package:aves/widgets/common/basic/insets.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/extensions/media_query.dart';
|
import 'package:aves/widgets/common/extensions/media_query.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/common.dart';
|
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
|
@ -10,7 +10,7 @@ import 'package:aves/widgets/common/basic/link_chip.dart';
|
||||||
import 'package:aves/widgets/common/basic/markdown_container.dart';
|
import 'package:aves/widgets/common/basic/markdown_container.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_logo.dart';
|
import 'package:aves/widgets/common/identity/aves_logo.dart';
|
||||||
import 'package:aves/widgets/common/identity/buttons.dart';
|
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
|
||||||
import 'package:aves/widgets/home_page.dart';
|
import 'package:aves/widgets/home_page.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
Loading…
Reference in a new issue