thumb zoom prep
This commit is contained in:
parent
655d251890
commit
09cf4fef3e
20 changed files with 271 additions and 219 deletions
|
@ -125,6 +125,7 @@ class AIcons {
|
||||||
static const IconData setCover = MdiIcons.imageEditOutline;
|
static const IconData setCover = MdiIcons.imageEditOutline;
|
||||||
static const IconData share = Icons.share_outlined;
|
static const IconData share = Icons.share_outlined;
|
||||||
static const IconData show = Icons.visibility_outlined;
|
static const IconData show = Icons.visibility_outlined;
|
||||||
|
static const IconData showFullscreen = MdiIcons.arrowExpand;
|
||||||
static const IconData slideshow = Icons.slideshow_outlined;
|
static const IconData slideshow = Icons.slideshow_outlined;
|
||||||
static const IconData speed = Icons.speed_outlined;
|
static const IconData speed = Icons.speed_outlined;
|
||||||
static const IconData stats = Icons.donut_small_outlined;
|
static const IconData stats = Icons.donut_small_outlined;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:aves/model/entry.dart';
|
||||||
import 'package:aves/model/favourites.dart';
|
import 'package:aves/model/favourites.dart';
|
||||||
import 'package:aves/model/filters/favourite.dart';
|
import 'package:aves/model/filters/favourite.dart';
|
||||||
import 'package:aves/model/filters/mime.dart';
|
import 'package:aves/model/filters/mime.dart';
|
||||||
|
import 'package:aves/model/selection.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
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/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
|
@ -21,6 +22,7 @@ import 'package:aves/widgets/collection/grid/section_layout.dart';
|
||||||
import 'package:aves/widgets/collection/grid/tile.dart';
|
import 'package:aves/widgets/collection/grid/tile.dart';
|
||||||
import 'package:aves/widgets/common/basic/draggable_scrollbar/scrollbar.dart';
|
import 'package:aves/widgets/common/basic/draggable_scrollbar/scrollbar.dart';
|
||||||
import 'package:aves/widgets/common/basic/insets.dart';
|
import 'package:aves/widgets/common/basic/insets.dart';
|
||||||
|
import 'package:aves/widgets/common/behaviour/routes.dart';
|
||||||
import 'package:aves/widgets/common/behaviour/sloppy_scroll_physics.dart';
|
import 'package:aves/widgets/common/behaviour/sloppy_scroll_physics.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';
|
||||||
|
@ -39,8 +41,10 @@ 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';
|
||||||
import 'package:aves/widgets/common/thumbnail/decorated.dart';
|
import 'package:aves/widgets/common/thumbnail/decorated.dart';
|
||||||
import 'package:aves/widgets/common/thumbnail/image.dart';
|
import 'package:aves/widgets/common/thumbnail/image.dart';
|
||||||
|
import 'package:aves/widgets/common/thumbnail/notifications.dart';
|
||||||
import 'package:aves/widgets/common/tile_extent_controller.dart';
|
import 'package:aves/widgets/common/tile_extent_controller.dart';
|
||||||
import 'package:aves/widgets/navigation/nav_bar/nav_bar.dart';
|
import 'package:aves/widgets/navigation/nav_bar/nav_bar.dart';
|
||||||
|
import 'package:aves/widgets/viewer/entry_viewer_page.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
|
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
|
||||||
|
@ -152,7 +156,12 @@ class _CollectionGridContentState extends State<_CollectionGridContent> {
|
||||||
tileAnimationDelay = Duration.zero;
|
tileAnimationDelay = Duration.zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
return StreamBuilder(
|
return NotificationListener<OpenViewerNotification>(
|
||||||
|
onNotification: (notification) {
|
||||||
|
_goToViewer(collection, notification.entry);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
child: StreamBuilder(
|
||||||
stream: source.eventBus.on<AspectRatioChangedEvent>(),
|
stream: source.eventBus.on<AspectRatioChangedEvent>(),
|
||||||
builder: (context, snapshot) => SectionedEntryListLayoutProvider(
|
builder: (context, snapshot) => SectionedEntryListLayoutProvider(
|
||||||
collection: collection,
|
collection: collection,
|
||||||
|
@ -205,6 +214,7 @@ class _CollectionGridContentState extends State<_CollectionGridContent> {
|
||||||
tileAnimationDelay: tileAnimationDelay,
|
tileAnimationDelay: tileAnimationDelay,
|
||||||
child: child!,
|
child: child!,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: child,
|
child: child,
|
||||||
|
@ -227,6 +237,34 @@ class _CollectionGridContentState extends State<_CollectionGridContent> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _goToViewer(CollectionLens collection, AvesEntry entry) {
|
||||||
|
final selection = context.read<Selection<AvesEntry>>();
|
||||||
|
Navigator.maybeOf(context)?.push(
|
||||||
|
TransparentMaterialPageRoute(
|
||||||
|
settings: const RouteSettings(name: EntryViewerPage.routeName),
|
||||||
|
pageBuilder: (context, a, sa) {
|
||||||
|
final viewerCollection = collection.copyWith(
|
||||||
|
listenToSource: false,
|
||||||
|
);
|
||||||
|
assert(viewerCollection.sortedEntries.map((entry) => entry.id).contains(entry.id));
|
||||||
|
Widget child = EntryViewerPage(
|
||||||
|
collection: viewerCollection,
|
||||||
|
initialEntry: entry,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (selection.isSelecting) {
|
||||||
|
child = ChangeNotifierProvider<Selection<AvesEntry>>.value(
|
||||||
|
value: selection,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return child;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CollectionSectionedContent extends StatefulWidget {
|
class _CollectionSectionedContent extends StatefulWidget {
|
||||||
|
|
|
@ -6,10 +6,9 @@ import 'package:aves/model/source/enums/enums.dart';
|
||||||
import 'package:aves/services/intent_service.dart';
|
import 'package:aves/services/intent_service.dart';
|
||||||
import 'package:aves/widgets/collection/grid/list_details.dart';
|
import 'package:aves/widgets/collection/grid/list_details.dart';
|
||||||
import 'package:aves/widgets/collection/grid/list_details_theme.dart';
|
import 'package:aves/widgets/collection/grid/list_details_theme.dart';
|
||||||
import 'package:aves/widgets/common/behaviour/routes.dart';
|
|
||||||
import 'package:aves/widgets/common/grid/scaling.dart';
|
import 'package:aves/widgets/common/grid/scaling.dart';
|
||||||
import 'package:aves/widgets/common/thumbnail/decorated.dart';
|
import 'package:aves/widgets/common/thumbnail/decorated.dart';
|
||||||
import 'package:aves/widgets/viewer/entry_viewer_page.dart';
|
import 'package:aves/widgets/common/thumbnail/notifications.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
@ -40,7 +39,7 @@ class InteractiveTile extends StatelessWidget {
|
||||||
if (selection.isSelecting) {
|
if (selection.isSelecting) {
|
||||||
selection.toggleSelection(entry);
|
selection.toggleSelection(entry);
|
||||||
} else {
|
} else {
|
||||||
_goToViewer(context);
|
OpenViewerNotification(entry).dispatch(context);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AppMode.pickSingleMediaExternal:
|
case AppMode.pickSingleMediaExternal:
|
||||||
|
@ -79,24 +78,6 @@ class InteractiveTile extends StatelessWidget {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _goToViewer(BuildContext context) {
|
|
||||||
Navigator.maybeOf(context)?.push(
|
|
||||||
TransparentMaterialPageRoute(
|
|
||||||
settings: const RouteSettings(name: EntryViewerPage.routeName),
|
|
||||||
pageBuilder: (context, a, sa) {
|
|
||||||
final viewerCollection = collection.copyWith(
|
|
||||||
listenToSource: false,
|
|
||||||
);
|
|
||||||
assert(viewerCollection.sortedEntries.map((entry) => entry.id).contains(entry.id));
|
|
||||||
return EntryViewerPage(
|
|
||||||
collection: viewerCollection,
|
|
||||||
initialEntry: entry,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Tile extends StatelessWidget {
|
class Tile extends StatelessWidget {
|
||||||
|
|
|
@ -22,28 +22,13 @@ class GridItemSelectionOverlay<T> extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final isSelecting = context.select<Selection<T>, bool>((selection) => selection.isSelecting);
|
final isSelecting = context.select<Selection<T>, bool>((selection) => selection.isSelecting);
|
||||||
final child = isSelecting
|
return AnimatedSwitcher(
|
||||||
|
duration: duration,
|
||||||
|
child: isSelecting
|
||||||
? Selector<Selection<T>, bool>(
|
? Selector<Selection<T>, bool>(
|
||||||
selector: (context, selection) => selection.isSelected([item]),
|
selector: (context, selection) => selection.isSelected([item]),
|
||||||
builder: (context, isSelected, child) {
|
builder: (context, isSelected, child) {
|
||||||
var child = isSelecting
|
return AnimatedContainer(
|
||||||
? OverlayIcon(
|
|
||||||
key: ValueKey(isSelected),
|
|
||||||
icon: isSelected ? AIcons.selected : AIcons.unselected,
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
)
|
|
||||||
: const SizedBox();
|
|
||||||
child = AnimatedSwitcher(
|
|
||||||
duration: duration,
|
|
||||||
switchInCurve: Curves.easeOutBack,
|
|
||||||
switchOutCurve: Curves.easeOutBack,
|
|
||||||
transitionBuilder: (child, animation) => ScaleTransition(
|
|
||||||
scale: animation,
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
child = AnimatedContainer(
|
|
||||||
alignment: AlignmentDirectional.topEnd,
|
alignment: AlignmentDirectional.topEnd,
|
||||||
padding: padding,
|
padding: padding,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
@ -51,15 +36,24 @@ class GridItemSelectionOverlay<T> extends StatelessWidget {
|
||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
),
|
),
|
||||||
duration: duration,
|
duration: duration,
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
duration: duration,
|
||||||
|
switchInCurve: Curves.easeOutBack,
|
||||||
|
switchOutCurve: Curves.easeOutBack,
|
||||||
|
transitionBuilder: (child, animation) => ScaleTransition(
|
||||||
|
scale: animation,
|
||||||
child: child,
|
child: child,
|
||||||
|
),
|
||||||
|
child: OverlayIcon(
|
||||||
|
key: ValueKey(isSelected),
|
||||||
|
icon: isSelected ? AIcons.selected : AIcons.unselected,
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return child;
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: const SizedBox();
|
: const SizedBox(),
|
||||||
return AnimatedSwitcher(
|
|
||||||
duration: duration,
|
|
||||||
child: child,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,12 @@ class GridTheme extends StatelessWidget {
|
||||||
final fontSize = (iconSize * .7).floorToDouble();
|
final fontSize = (iconSize * .7).floorToDouble();
|
||||||
iconSize *= mq.textScaleFactor;
|
iconSize *= mq.textScaleFactor;
|
||||||
final highlightBorderWidth = extent * .1;
|
final highlightBorderWidth = extent * .1;
|
||||||
|
final interactiveDimension = min(iconSize * 2, kMinInteractiveDimension);
|
||||||
return GridThemeData(
|
return GridThemeData(
|
||||||
iconSize: iconSize,
|
iconSize: iconSize,
|
||||||
fontSize: fontSize,
|
fontSize: fontSize,
|
||||||
highlightBorderWidth: highlightBorderWidth,
|
highlightBorderWidth: highlightBorderWidth,
|
||||||
|
interactiveDimension: interactiveDimension,
|
||||||
showFavourite: settings.showThumbnailFavourite,
|
showFavourite: settings.showThumbnailFavourite,
|
||||||
locationIcon: showLocation ? settings.thumbnailLocationIcon : ThumbnailOverlayLocationIcon.none,
|
locationIcon: showLocation ? settings.thumbnailLocationIcon : ThumbnailOverlayLocationIcon.none,
|
||||||
tagIcon: settings.thumbnailTagIcon,
|
tagIcon: settings.thumbnailTagIcon,
|
||||||
|
@ -52,7 +54,7 @@ class GridTheme extends StatelessWidget {
|
||||||
typedef GridThemeIconBuilder = List<Widget> Function(BuildContext context, AvesEntry entry);
|
typedef GridThemeIconBuilder = List<Widget> Function(BuildContext context, AvesEntry entry);
|
||||||
|
|
||||||
class GridThemeData {
|
class GridThemeData {
|
||||||
final double iconSize, fontSize, highlightBorderWidth;
|
final double iconSize, fontSize, highlightBorderWidth, interactiveDimension;
|
||||||
final bool showFavourite, showMotionPhoto, showRating, showRaw, showTrash, showVideoDuration;
|
final bool showFavourite, showMotionPhoto, showRating, showRaw, showTrash, showVideoDuration;
|
||||||
final bool showLocated, showUnlocated, showTagged, showUntagged;
|
final bool showLocated, showUnlocated, showTagged, showUntagged;
|
||||||
late final GridThemeIconBuilder iconBuilder;
|
late final GridThemeIconBuilder iconBuilder;
|
||||||
|
@ -61,6 +63,7 @@ class GridThemeData {
|
||||||
required this.iconSize,
|
required this.iconSize,
|
||||||
required this.fontSize,
|
required this.fontSize,
|
||||||
required this.highlightBorderWidth,
|
required this.highlightBorderWidth,
|
||||||
|
required this.interactiveDimension,
|
||||||
required this.showFavourite,
|
required this.showFavourite,
|
||||||
required ThumbnailOverlayLocationIcon locationIcon,
|
required ThumbnailOverlayLocationIcon locationIcon,
|
||||||
required ThumbnailOverlayTagIcon tagIcon,
|
required ThumbnailOverlayTagIcon tagIcon,
|
||||||
|
|
9
lib/widgets/common/thumbnail/notifications.dart
Normal file
9
lib/widgets/common/thumbnail/notifications.dart
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import 'package:aves/model/entry.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class OpenViewerNotification extends Notification {
|
||||||
|
final AvesEntry entry;
|
||||||
|
|
||||||
|
const OpenViewerNotification(this.entry);
|
||||||
|
}
|
|
@ -2,6 +2,9 @@ import 'dart:math';
|
||||||
|
|
||||||
import 'package:aves/model/entry.dart';
|
import 'package:aves/model/entry.dart';
|
||||||
import 'package:aves/model/highlight.dart';
|
import 'package:aves/model/highlight.dart';
|
||||||
|
import 'package:aves/model/selection.dart';
|
||||||
|
import 'package:aves/theme/durations.dart';
|
||||||
|
import 'package:aves/theme/icons.dart';
|
||||||
import 'package:aves/widgets/common/fx/sweeper.dart';
|
import 'package:aves/widgets/common/fx/sweeper.dart';
|
||||||
import 'package:aves/widgets/common/grid/theme.dart';
|
import 'package:aves/widgets/common/grid/theme.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -70,3 +73,43 @@ class _ThumbnailHighlightOverlayState extends State<ThumbnailHighlightOverlay> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ThumbnailZoomOverlay extends StatelessWidget {
|
||||||
|
final VoidCallback? onZoom;
|
||||||
|
|
||||||
|
const ThumbnailZoomOverlay({
|
||||||
|
super.key,
|
||||||
|
this.onZoom,
|
||||||
|
});
|
||||||
|
|
||||||
|
static const alignment = AlignmentDirectional.bottomEnd;
|
||||||
|
static const duration = Durations.thumbnailOverlayAnimation;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final isSelecting = context.select<Selection<AvesEntry>, bool>((selection) => selection.isSelecting);
|
||||||
|
final interactiveDimension = context.select<GridThemeData, double>((t) => t.interactiveDimension);
|
||||||
|
return AnimatedSwitcher(
|
||||||
|
duration: duration,
|
||||||
|
child: isSelecting
|
||||||
|
? Align(
|
||||||
|
alignment: alignment,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: onZoom,
|
||||||
|
child: Container(
|
||||||
|
alignment: alignment,
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 2),
|
||||||
|
width: interactiveDimension,
|
||||||
|
height: interactiveDimension,
|
||||||
|
child: Icon(
|
||||||
|
AIcons.showFullscreen,
|
||||||
|
size: context.select<GridThemeData, double>((t) => t.iconSize),
|
||||||
|
color: Colors.white70,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
import 'package:aves/widgets/common/basic/reselectable_radio_list_tile.dart';
|
import 'package:aves/widgets/common/basic/list_tiles/reselectable_radio.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/model/source/collection_lens.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/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/widgets/common/basic/color_list_tile.dart';
|
import 'package:aves/widgets/common/basic/list_tiles/color.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/dialogs/aves_dialog.dart';
|
import 'package:aves/widgets/dialogs/aves_dialog.dart';
|
||||||
|
|
|
@ -2,8 +2,8 @@ import 'package:aves/image_providers/app_icon_image_provider.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/services/common/services.dart';
|
import 'package:aves/services/common/services.dart';
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/list_tiles/reselectable_radio.dart';
|
||||||
import 'package:aves/widgets/common/basic/query_bar.dart';
|
import 'package:aves/widgets/common/basic/query_bar.dart';
|
||||||
import 'package:aves/widgets/common/basic/reselectable_radio_list_tile.dart';
|
|
||||||
import 'package:aves/widgets/common/basic/scaffold.dart';
|
import 'package:aves/widgets/common/basic/scaffold.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
|
|
@ -2,8 +2,8 @@ import 'dart:collection';
|
||||||
|
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/widgets/aves_app.dart';
|
import 'package:aves/widgets/aves_app.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/list_tiles/reselectable_radio.dart';
|
||||||
import 'package:aves/widgets/common/basic/query_bar.dart';
|
import 'package:aves/widgets/common/basic/query_bar.dart';
|
||||||
import 'package:aves/widgets/common/basic/reselectable_radio_list_tile.dart';
|
|
||||||
import 'package:aves/widgets/common/basic/scaffold.dart';
|
import 'package:aves/widgets/common/basic/scaffold.dart';
|
||||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/settings/language/locale_tile.dart';
|
import 'package:aves/widgets/settings/language/locale_tile.dart';
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import 'package:aves/model/settings/enums/enums.dart';
|
import 'package:aves/model/settings/enums/enums.dart';
|
||||||
import 'package:aves/model/settings/enums/subtitle_position.dart';
|
import 'package:aves/model/settings/enums/subtitle_position.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/widgets/common/basic/color_list_tile.dart';
|
import 'package:aves/widgets/common/basic/list_tiles/color.dart';
|
||||||
|
import 'package:aves/widgets/common/basic/list_tiles/slider.dart';
|
||||||
import 'package:aves/widgets/common/basic/scaffold.dart';
|
import 'package:aves/widgets/common/basic/scaffold.dart';
|
||||||
import 'package:aves/widgets/common/basic/slider_list_tile.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/tiles.dart';
|
import 'package:aves/widgets/settings/common/tiles.dart';
|
||||||
import 'package:aves/widgets/settings/video/subtitle_sample.dart';
|
import 'package:aves/widgets/settings/video/subtitle_sample.dart';
|
||||||
|
|
|
@ -3,10 +3,8 @@ import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/widgets/common/basic/scaffold.dart';
|
import 'package:aves/widgets/common/basic/scaffold.dart';
|
||||||
import 'package:aves/widgets/viewer/controller.dart';
|
import 'package:aves/widgets/viewer/controller.dart';
|
||||||
import 'package:aves/widgets/viewer/entry_viewer_stack.dart';
|
import 'package:aves/widgets/viewer/entry_viewer_stack.dart';
|
||||||
import 'package:aves/widgets/viewer/multipage/conductor.dart';
|
|
||||||
import 'package:aves/widgets/viewer/overlay/bottom.dart';
|
import 'package:aves/widgets/viewer/overlay/bottom.dart';
|
||||||
import 'package:aves/widgets/viewer/video/conductor.dart';
|
import 'package:aves/widgets/viewer/providers.dart';
|
||||||
import 'package:aves/widgets/viewer/visual/conductor.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
@ -43,18 +41,18 @@ class _EntryViewerPageState extends State<EntryViewerPage> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final collection = widget.collection;
|
final collection = widget.collection;
|
||||||
return AvesScaffold(
|
return AvesScaffold(
|
||||||
body: ViewStateConductorProvider(
|
body: MultiProvider(
|
||||||
child: VideoConductorProvider(
|
providers: [
|
||||||
collection: collection,
|
ViewStateConductorProvider(),
|
||||||
child: MultiPageConductorProvider(
|
VideoConductorProvider(collection: collection),
|
||||||
|
MultiPageConductorProvider(),
|
||||||
|
],
|
||||||
child: EntryViewerStack(
|
child: EntryViewerStack(
|
||||||
collection: collection,
|
collection: collection,
|
||||||
initialEntry: widget.initialEntry,
|
initialEntry: widget.initialEntry,
|
||||||
viewerController: _viewerController,
|
viewerController: _viewerController,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
backgroundColor: Navigator.canPop(context)
|
backgroundColor: Navigator.canPop(context)
|
||||||
? Colors.transparent
|
? Colors.transparent
|
||||||
: Theme.of(context).brightness == Brightness.dark
|
: Theme.of(context).brightness == Brightness.dark
|
||||||
|
@ -64,63 +62,3 @@ class _EntryViewerPageState extends State<EntryViewerPage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewStateConductorProvider extends StatelessWidget {
|
|
||||||
final Widget? child;
|
|
||||||
|
|
||||||
const ViewStateConductorProvider({
|
|
||||||
super.key,
|
|
||||||
this.child,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ProxyProvider<MediaQueryData, ViewStateConductor>(
|
|
||||||
create: (context) => ViewStateConductor(),
|
|
||||||
update: (context, mq, value) {
|
|
||||||
value!.viewportSize = mq.size;
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
dispose: (context, value) => value.dispose(),
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VideoConductorProvider extends StatelessWidget {
|
|
||||||
final CollectionLens? collection;
|
|
||||||
final Widget? child;
|
|
||||||
|
|
||||||
const VideoConductorProvider({
|
|
||||||
super.key,
|
|
||||||
this.collection,
|
|
||||||
required this.child,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Provider<VideoConductor>(
|
|
||||||
create: (context) => VideoConductor(collection: collection),
|
|
||||||
dispose: (context, value) => value.dispose(),
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MultiPageConductorProvider extends StatelessWidget {
|
|
||||||
final Widget? child;
|
|
||||||
|
|
||||||
const MultiPageConductorProvider({
|
|
||||||
super.key,
|
|
||||||
required this.child,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Provider<MultiPageConductor>(
|
|
||||||
create: (context) => MultiPageConductor(),
|
|
||||||
dispose: (context, value) => value.dispose(),
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
41
lib/widgets/viewer/providers.dart
Normal file
41
lib/widgets/viewer/providers.dart
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
|
import 'package:aves/widgets/viewer/multipage/conductor.dart';
|
||||||
|
import 'package:aves/widgets/viewer/video/conductor.dart';
|
||||||
|
import 'package:aves/widgets/viewer/visual/conductor.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class ViewStateConductorProvider extends ProxyProvider<MediaQueryData, ViewStateConductor> {
|
||||||
|
ViewStateConductorProvider({
|
||||||
|
super.key,
|
||||||
|
super.child,
|
||||||
|
}) : super(
|
||||||
|
create: (context) => ViewStateConductor(),
|
||||||
|
update: (context, mq, value) {
|
||||||
|
value!.viewportSize = mq.size;
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
dispose: (context, value) => value.dispose(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class VideoConductorProvider extends Provider<VideoConductor> {
|
||||||
|
VideoConductorProvider({
|
||||||
|
super.key,
|
||||||
|
CollectionLens? collection,
|
||||||
|
super.child,
|
||||||
|
}) : super(
|
||||||
|
create: (context) => VideoConductor(collection: collection),
|
||||||
|
dispose: (context, value) => value.dispose(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiPageConductorProvider extends Provider<MultiPageConductor> {
|
||||||
|
MultiPageConductorProvider({
|
||||||
|
super.key,
|
||||||
|
super.child,
|
||||||
|
}) : super(
|
||||||
|
create: (context) => MultiPageConductor(),
|
||||||
|
dispose: (context, value) => value.dispose(),
|
||||||
|
);
|
||||||
|
}
|
|
@ -8,10 +8,11 @@ import 'package:aves/widgets/common/basic/scaffold.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/empty.dart';
|
import 'package:aves/widgets/common/identity/empty.dart';
|
||||||
import 'package:aves/widgets/viewer/controller.dart';
|
import 'package:aves/widgets/viewer/controller.dart';
|
||||||
import 'package:aves/widgets/viewer/entry_viewer_page.dart';
|
|
||||||
import 'package:aves/widgets/viewer/entry_viewer_stack.dart';
|
import 'package:aves/widgets/viewer/entry_viewer_stack.dart';
|
||||||
|
import 'package:aves/widgets/viewer/providers.dart';
|
||||||
import 'package:aves_magnifier/aves_magnifier.dart';
|
import 'package:aves_magnifier/aves_magnifier.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class ScreenSaverPage extends StatefulWidget {
|
class ScreenSaverPage extends StatefulWidget {
|
||||||
static const routeName = '/screen_saver';
|
static const routeName = '/screen_saver';
|
||||||
|
@ -80,16 +81,17 @@ class _ScreenSaverPageState extends State<ScreenSaverPage> with WidgetsBindingOb
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
child = ViewStateConductorProvider(
|
child = MultiProvider(
|
||||||
child: VideoConductorProvider(
|
providers: [
|
||||||
child: MultiPageConductorProvider(
|
ViewStateConductorProvider(),
|
||||||
|
VideoConductorProvider(),
|
||||||
|
MultiPageConductorProvider(),
|
||||||
|
],
|
||||||
child: EntryViewerStack(
|
child: EntryViewerStack(
|
||||||
collection: collection,
|
collection: collection,
|
||||||
initialEntry: entries.first,
|
initialEntry: entries.first,
|
||||||
viewerController: _viewerController,
|
viewerController: _viewerController,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||||
import 'package:aves/widgets/common/identity/empty.dart';
|
import 'package:aves/widgets/common/identity/empty.dart';
|
||||||
import 'package:aves/widgets/settings/viewer/slideshow.dart';
|
import 'package:aves/widgets/settings/viewer/slideshow.dart';
|
||||||
import 'package:aves/widgets/viewer/controller.dart';
|
import 'package:aves/widgets/viewer/controller.dart';
|
||||||
import 'package:aves/widgets/viewer/entry_viewer_page.dart';
|
|
||||||
import 'package:aves/widgets/viewer/entry_viewer_stack.dart';
|
import 'package:aves/widgets/viewer/entry_viewer_stack.dart';
|
||||||
|
import 'package:aves/widgets/viewer/providers.dart';
|
||||||
import 'package:aves_magnifier/aves_magnifier.dart';
|
import 'package:aves_magnifier/aves_magnifier.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -69,9 +69,12 @@ class _SlideshowPageState extends State<SlideshowPage> {
|
||||||
text: context.l10n.collectionEmptyImages,
|
text: context.l10n.collectionEmptyImages,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
)
|
)
|
||||||
: ViewStateConductorProvider(
|
: MultiProvider(
|
||||||
child: VideoConductorProvider(
|
providers: [
|
||||||
child: MultiPageConductorProvider(
|
ViewStateConductorProvider(),
|
||||||
|
VideoConductorProvider(),
|
||||||
|
MultiPageConductorProvider(),
|
||||||
|
],
|
||||||
child: NotificationListener<SlideshowActionNotification>(
|
child: NotificationListener<SlideshowActionNotification>(
|
||||||
onNotification: (notification) {
|
onNotification: (notification) {
|
||||||
_onActionSelected(notification.action);
|
_onActionSelected(notification.action);
|
||||||
|
@ -86,8 +89,6 @@ class _SlideshowPageState extends State<SlideshowPage> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,12 @@ import 'package:aves/widgets/common/basic/insets.dart';
|
||||||
import 'package:aves/widgets/common/basic/scaffold.dart';
|
import 'package:aves/widgets/common/basic/scaffold.dart';
|
||||||
import 'package:aves/widgets/viewer/controller.dart';
|
import 'package:aves/widgets/viewer/controller.dart';
|
||||||
import 'package:aves/widgets/viewer/entry_horizontal_pager.dart';
|
import 'package:aves/widgets/viewer/entry_horizontal_pager.dart';
|
||||||
import 'package:aves/widgets/viewer/entry_viewer_page.dart';
|
|
||||||
import 'package:aves/widgets/viewer/multipage/conductor.dart';
|
import 'package:aves/widgets/viewer/multipage/conductor.dart';
|
||||||
import 'package:aves/widgets/viewer/notifications.dart';
|
import 'package:aves/widgets/viewer/notifications.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/bottom.dart';
|
import 'package:aves/widgets/viewer/overlay/bottom.dart';
|
||||||
import 'package:aves/widgets/viewer/overlay/video/video.dart';
|
import 'package:aves/widgets/viewer/overlay/video/video.dart';
|
||||||
import 'package:aves/widgets/viewer/page_entry_builder.dart';
|
import 'package:aves/widgets/viewer/page_entry_builder.dart';
|
||||||
|
import 'package:aves/widgets/viewer/providers.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:aves/widgets/viewer/video_action_delegate.dart';
|
import 'package:aves/widgets/viewer/video_action_delegate.dart';
|
||||||
|
@ -37,14 +37,15 @@ class WallpaperPage extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AvesScaffold(
|
return AvesScaffold(
|
||||||
body: entry != null
|
body: entry != null
|
||||||
? ViewStateConductorProvider(
|
? MultiProvider(
|
||||||
child: VideoConductorProvider(
|
providers: [
|
||||||
child: MultiPageConductorProvider(
|
ViewStateConductorProvider(),
|
||||||
|
VideoConductorProvider(),
|
||||||
|
MultiPageConductorProvider(),
|
||||||
|
],
|
||||||
child: EntryEditor(
|
child: EntryEditor(
|
||||||
entry: entry!,
|
entry: entry!,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
: const SizedBox(),
|
: const SizedBox(),
|
||||||
backgroundColor: Theme.of(context).brightness == Brightness.dark ? Colors.black : Colors.white,
|
backgroundColor: Theme.of(context).brightness == Brightness.dark ? Colors.black : Colors.white,
|
||||||
|
|
Loading…
Reference in a new issue