diff --git a/lib/labs/coma_divider.dart b/lib/labs/coma_divider.dart deleted file mode 100644 index 7af9b3bbf..000000000 --- a/lib/labs/coma_divider.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; - -class ComaDivider extends StatelessWidget { - final Color color; - final Alignment alignment; - - const ComaDivider({ - this.color = Colors.white70, - this.alignment = Alignment.center, - }); - - double get peakStop => (alignment.x + 1 / 2).clamp(.02, .98); - - @override - Widget build(BuildContext context) { - return Container( - height: 1, - decoration: BoxDecoration( - gradient: LinearGradient( - stops: [ - 0, - peakStop, - 1, - ], - colors: [ - Colors.transparent, - color, - Colors.transparent, - ], - ), - ), - ); - } -} diff --git a/lib/labs/sliver_transition_grid_delegate.dart b/lib/labs/sliver_transition_grid_delegate.dart deleted file mode 100644 index b8e2fa411..000000000 --- a/lib/labs/sliver_transition_grid_delegate.dart +++ /dev/null @@ -1,176 +0,0 @@ -import 'dart:math' as math; -import 'dart:ui' show lerpDouble; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/rendering.dart'; - -class SliverTransitionGridDelegateWithCrossAxisCount extends SliverGridDelegate { - const SliverTransitionGridDelegateWithCrossAxisCount({ - @required this.crossAxisCount, - this.mainAxisSpacing = 0.0, - this.crossAxisSpacing = 0.0, - this.childAspectRatio = 1.0, - }) : assert(crossAxisCount != null && crossAxisCount > 0), - assert(mainAxisSpacing != null && mainAxisSpacing >= 0), - assert(crossAxisSpacing != null && crossAxisSpacing >= 0), - assert(childAspectRatio != null && childAspectRatio > 0); - - /// The number of children in the cross axis. - final double crossAxisCount; - - /// The number of logical pixels between each child along the main axis. - final double mainAxisSpacing; - - /// The number of logical pixels between each child along the cross axis. - final double crossAxisSpacing; - - /// The ratio of the cross-axis to the main-axis extent of each child. - final double childAspectRatio; - - @override - SliverGridLayout getLayout(SliverConstraints constraints) { - final t = crossAxisCount - crossAxisCount.truncateToDouble(); - return SliverTransitionGridTileLayout( - current: _buildSettings(constraints, crossAxisCount), - floor: t != 0 ? _buildSettings(constraints, crossAxisCount.floorToDouble()) : null, - ceil: t != 0 ? _buildSettings(constraints, crossAxisCount.ceilToDouble()) : null, - t: t, - reverseCrossAxis: axisDirectionIsReversed(constraints.crossAxisDirection), - ); - } - - SliverTransitionGridTileLayoutSettings _buildSettings(SliverConstraints constraints, double crossAxisCount) { - final usableCrossAxisExtent = constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1); - final childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount; - final childMainAxisExtent = childCrossAxisExtent / childAspectRatio; - final current = SliverTransitionGridTileLayoutSettings( - crossAxisCount: crossAxisCount, - mainAxisStride: childMainAxisExtent + mainAxisSpacing, - crossAxisStride: childCrossAxisExtent + crossAxisSpacing, - childMainAxisExtent: childMainAxisExtent, - childCrossAxisExtent: childCrossAxisExtent, - ); - return current; - } - - @override - bool shouldRelayout(SliverTransitionGridDelegateWithCrossAxisCount oldDelegate) { - return oldDelegate.crossAxisCount != crossAxisCount || oldDelegate.mainAxisSpacing != mainAxisSpacing || oldDelegate.crossAxisSpacing != crossAxisSpacing || oldDelegate.childAspectRatio != childAspectRatio; - } -} - -class SliverTransitionGridTileLayoutSettings { - final double crossAxisCount; - - /// The number of pixels from the leading edge of one tile to the leading edge - /// of the next tile in the main axis. - final double mainAxisStride; - - /// The number of pixels from the leading edge of one tile to the leading edge - /// of the next tile in the cross axis. - final double crossAxisStride; - - /// The number of pixels from the leading edge of one tile to the trailing - /// edge of the same tile in the main axis. - final double childMainAxisExtent; - - /// The number of pixels from the leading edge of one tile to the trailing - /// edge of the same tile in the cross axis. - final double childCrossAxisExtent; - - const SliverTransitionGridTileLayoutSettings({ - @required this.crossAxisCount, - @required this.mainAxisStride, - @required this.crossAxisStride, - @required this.childMainAxisExtent, - @required this.childCrossAxisExtent, - }) : assert(crossAxisCount != null && crossAxisCount > 0), - assert(mainAxisStride != null && mainAxisStride >= 0), - assert(crossAxisStride != null && crossAxisStride >= 0), - assert(childMainAxisExtent != null && childMainAxisExtent >= 0), - assert(childCrossAxisExtent != null && childCrossAxisExtent >= 0); -} - -class SliverTransitionGridTileLayout extends SliverGridLayout { - /// Creates a layout that uses equally sized and spaced tiles. - /// - /// All of the arguments must not be null and must not be negative. The - /// `crossAxisCount` argument must be greater than zero. - const SliverTransitionGridTileLayout({ - @required this.current, - this.floor, - this.ceil, - this.t = 0, - @required this.reverseCrossAxis, - }) : assert(reverseCrossAxis != null); - - final SliverTransitionGridTileLayoutSettings current, floor, ceil; - final double t; - - /// Whether the children should be placed in the opposite order of increasing - /// coordinates in the cross axis. - /// - /// For example, if the cross axis is horizontal, the children are placed from - /// left to right when [reverseCrossAxis] is false and from right to left when - /// [reverseCrossAxis] is true. - /// - /// Typically set to the return value of [axisDirectionIsReversed] applied to - /// the [SliverConstraints.crossAxisDirection]. - final bool reverseCrossAxis; - - @override - int getMinChildIndexForScrollOffset(double scrollOffset) { - final settings = t == 0 ? current : floor; - final index = settings.mainAxisStride > 0.0 ? (settings.crossAxisCount * (scrollOffset ~/ settings.mainAxisStride)).floor() : 0; - return index; - } - - @override - int getMaxChildIndexForScrollOffset(double scrollOffset) { - final settings = t == 0 ? current : floor; - if (settings.mainAxisStride > 0.0) { - final mainAxisCount = (scrollOffset / settings.mainAxisStride).ceil(); - final index = math.max(0, settings.crossAxisCount * mainAxisCount - 1).ceil(); - return index; - } - return 0; - } - - double _getScrollOffset(int index, SliverTransitionGridTileLayoutSettings settings) { - return (index ~/ settings.crossAxisCount) * settings.mainAxisStride; - } - - double _getCrossAxisOffset(int index, SliverTransitionGridTileLayoutSettings settings) { - final crossAxisStart = (index % settings.crossAxisCount) * settings.crossAxisStride; - if (reverseCrossAxis) { - return settings.crossAxisCount * settings.crossAxisStride - crossAxisStart - settings.childCrossAxisExtent - (settings.crossAxisStride - settings.childCrossAxisExtent); - } - return crossAxisStart; - } - - @override - SliverGridGeometry getGeometryForChildIndex(int index) { - return SliverGridGeometry( - scrollOffset: t == 0 ? _getScrollOffset(index, current) : lerpDouble(_getScrollOffset(index, floor), _getScrollOffset(index, ceil), t), - crossAxisOffset: t == 0 ? _getCrossAxisOffset(index, current) : lerpDouble(_getCrossAxisOffset(index, floor), _getCrossAxisOffset(index, ceil), t), - mainAxisExtent: current.childMainAxisExtent, - crossAxisExtent: current.childCrossAxisExtent, - ); - } - - @override - double computeMaxScrollOffset(int childCount) { - assert(childCount != null); - - if (t != 0) { - final index = childCount - 1; - final maxScrollOffset = lerpDouble(_getScrollOffset(index, floor), _getScrollOffset(index, ceil), t) + current.mainAxisStride; - return maxScrollOffset; - } - - final mainAxisCount = ((childCount - 1) ~/ current.crossAxisCount) + 1; - final mainAxisSpacing = current.mainAxisStride - current.childMainAxisExtent; - final maxScrollOffset = current.mainAxisStride * mainAxisCount - mainAxisSpacing; - return maxScrollOffset; - } -} diff --git a/lib/utils/durations.dart b/lib/utils/durations.dart index b8ba3b72d..9270148e3 100644 --- a/lib/utils/durations.dart +++ b/lib/utils/durations.dart @@ -28,6 +28,9 @@ class Durations { static const fullscreenPageAnimation = Duration(milliseconds: 300); static const fullscreenOverlayAnimation = Duration(milliseconds: 200); + // info + static const mapStyleSwitchAnimation = Duration(milliseconds: 300); + // delays & refresh intervals static const opToastDisplay = Duration(seconds: 2); static const collectionScrollMonitoringTimerDelay = Duration(milliseconds: 100); diff --git a/lib/labs/outlined_text.dart b/lib/widgets/common/fx/outlined_text.dart similarity index 100% rename from lib/labs/outlined_text.dart rename to lib/widgets/common/fx/outlined_text.dart diff --git a/lib/widgets/fullscreen/info/location_section.dart b/lib/widgets/fullscreen/info/location_section.dart index 6413da77d..732e63759 100644 --- a/lib/widgets/fullscreen/info/location_section.dart +++ b/lib/widgets/fullscreen/info/location_section.dart @@ -3,6 +3,7 @@ import 'package:aves/model/image_entry.dart'; import 'package:aves/model/settings/coordinate_format.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; +import 'package:aves/utils/durations.dart'; import 'package:aves/widgets/common/aves_filter_chip.dart'; import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/fullscreen/info/common.dart'; @@ -32,7 +33,7 @@ class LocationSection extends StatefulWidget { _LocationSectionState createState() => _LocationSectionState(); } -class _LocationSectionState extends State { +class _LocationSectionState extends State with SingleTickerProviderStateMixin { String _loadedUri; static const extent = 48.0; @@ -106,22 +107,28 @@ class _LocationSectionState extends State { if (notification is MapStyleChangedNotification) setState(() {}); return false; }, - child: settings.infoMapStyle.isGoogleMaps - ? EntryGoogleMap( - latLng: entry.latLng, - geoUri: entry.geoUri, - initialZoom: settings.infoMapZoom, - markerId: entry.uri ?? entry.path, - markerBuilder: buildMarker, - ) - : EntryLeafletMap( - latLng: entry.latLng, - geoUri: entry.geoUri, - initialZoom: settings.infoMapZoom, - style: settings.infoMapStyle, - markerSize: Size(extent, extent + pointerSize.height), - markerBuilder: buildMarker, - ), + child: AnimatedSize( + alignment: Alignment.topCenter, + curve: Curves.easeInOutCubic, + duration: Durations.mapStyleSwitchAnimation, + vsync: this, + child: settings.infoMapStyle.isGoogleMaps + ? EntryGoogleMap( + latLng: entry.latLng, + geoUri: entry.geoUri, + initialZoom: settings.infoMapZoom, + markerId: entry.uri ?? entry.path, + markerBuilder: buildMarker, + ) + : EntryLeafletMap( + latLng: entry.latLng, + geoUri: entry.geoUri, + initialZoom: settings.infoMapZoom, + style: settings.infoMapStyle, + markerSize: Size(extent, extent + pointerSize.height), + markerBuilder: buildMarker, + ), + ), ), if (entry.hasGps) InfoRowGroup(Map.fromEntries([ diff --git a/lib/widgets/fullscreen/info/maps/scale_layer.dart b/lib/widgets/fullscreen/info/maps/scale_layer.dart index ac92d838d..7d821ee83 100644 --- a/lib/widgets/fullscreen/info/maps/scale_layer.dart +++ b/lib/widgets/fullscreen/info/maps/scale_layer.dart @@ -1,6 +1,6 @@ import 'dart:math'; -import 'package:aves/labs/outlined_text.dart'; +import 'package:aves/widgets/common/fx/outlined_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/plugin_api.dart';