durations cleanup

This commit is contained in:
Thibault Deckers 2020-06-11 11:34:09 +09:00
parent ac1dc99cba
commit 3fe1d955d6
21 changed files with 99 additions and 57 deletions

View file

@ -15,4 +15,3 @@ __We collect anonymous data to improve the app.__ We use Google Firebase for Ana
## Links ## Links
[Sources](https://github.com/deckerst/aves) [Sources](https://github.com/deckerst/aves)
'''; ''';

View file

@ -19,9 +19,6 @@ class Constants {
], ],
); );
// ref _PopupMenuRoute._kMenuDuration
static const popupMenuTransitionDuration = Duration(milliseconds: 300);
static const svgBackground = Colors.white; static const svgBackground = Colors.white;
static const svgColorFilter = ColorFilter.mode(svgBackground, BlendMode.dstOver); static const svgColorFilter = ColorFilter.mode(svgBackground, BlendMode.dstOver);

35
lib/utils/durations.dart Normal file
View file

@ -0,0 +1,35 @@
import 'package:flutter/scheduler.dart';
class Durations {
// common animations
static const iconAnimation = Duration(milliseconds: 300);
static const opToastAnimation = Duration(milliseconds: 600);
static const sweeperOpacityAnimation = Duration(milliseconds: 150);
static const sweepingAnimation = Duration(milliseconds: 650);
static const popupMenuAnimation = Duration(milliseconds: 300); // ref _PopupMenuRoute._kMenuDuration
static const staggeredAnimation = Duration(milliseconds: 375);
// collection animations
static const appBarTitleAnimation = Duration(milliseconds: 300);
static const filterBarRemovalAnimation = Duration(milliseconds: 200);
static const collectionOpOverlayAnimation = Duration(milliseconds: 300);
static const collectionScalingBackgroundAnimation = Duration(milliseconds: 200);
static const sectionHeaderAnimation = Duration(milliseconds: 200);
static const thumbnailTransition = Duration(milliseconds: 200);
static const thumbnailOverlayAnimation = Duration(milliseconds: 200);
// search animations
static const filterRowExpandAnimation = Duration(milliseconds: 300);
// fullscreen animations
static const fullscreenPageAnimation = Duration(milliseconds: 300);
static const fullscreenOverlayAnimation = Duration(milliseconds: 200);
// delays & refresh intervals
static const opToastDisplay = Duration(seconds: 2);
static const collectionScrollMonitoringTimerDelay = Duration(milliseconds: 100);
static const collectionScalingCompleteNotificationDelay = Duration(milliseconds: 300);
static const appBarProgressTimerInterval = Duration(seconds: 1);
static const videoProgressTimerInterval = Duration(milliseconds: 300);
static var staggeredAnimationDelay = Durations.staggeredAnimation ~/ 6 * timeDilation;
}

View file

@ -1,4 +1,5 @@
import 'package:aves/utils/constants.dart'; import 'package:aves/utils/constants.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/common/icons.dart';
import 'package:aves/widgets/common/menu_row.dart'; import 'package:aves/widgets/common/menu_row.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
@ -48,7 +49,8 @@ class _LicensesState extends State<Licenses> {
final child = LicenseRow(_packages[index]); final child = LicenseRow(_packages[index]);
return AnimationConfiguration.staggeredList( return AnimationConfiguration.staggeredList(
position: index, position: index,
duration: const Duration(milliseconds: 375), duration: Durations.staggeredAnimation,
delay: Durations.staggeredAnimationDelay,
child: SlideAnimation( child: SlideAnimation(
verticalOffset: 50.0, verticalOffset: 50.0,
child: FadeInAnimation( child: FadeInAnimation(

View file

@ -5,7 +5,7 @@ import 'package:aves/model/collection_lens.dart';
import 'package:aves/model/collection_source.dart'; import 'package:aves/model/collection_source.dart';
import 'package:aves/model/image_entry.dart'; import 'package:aves/model/image_entry.dart';
import 'package:aves/model/settings.dart'; import 'package:aves/model/settings.dart';
import 'package:aves/utils/constants.dart'; import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/album/filter_bar.dart'; import 'package:aves/widgets/album/filter_bar.dart';
import 'package:aves/widgets/album/search/search_delegate.dart'; import 'package:aves/widgets/album/search/search_delegate.dart';
import 'package:aves/widgets/common/action_delegates/selection_action_delegate.dart'; import 'package:aves/widgets/common/action_delegates/selection_action_delegate.dart';
@ -49,7 +49,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
collection: collection, collection: collection,
); );
_browseToSelectAnimation = AnimationController( _browseToSelectAnimation = AnimationController(
duration: const Duration(milliseconds: 300), duration: Durations.iconAnimation,
vsync: this, vsync: this,
); );
_registerWidget(widget); _registerWidget(widget);
@ -142,7 +142,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
valueListenable: collection.source.stateNotifier, valueListenable: collection.source.stateNotifier,
builder: (context, sourceState, child) { builder: (context, sourceState, child) {
return AnimatedSwitcher( return AnimatedSwitcher(
duration: Duration(milliseconds: (300 * timeDilation).toInt()), duration: Durations.appBarTitleAnimation,
transitionBuilder: (child, animation) => FadeTransition( transitionBuilder: (child, animation) => FadeTransition(
opacity: animation, opacity: animation,
child: SizeTransition( child: SizeTransition(
@ -297,7 +297,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
void _onCollectionActionSelected(CollectionAction action) async { void _onCollectionActionSelected(CollectionAction action) async {
// wait for the popup menu to hide before proceeding with the action // wait for the popup menu to hide before proceeding with the action
await Future.delayed(Constants.popupMenuTransitionDuration); await Future.delayed(Durations.popupMenuAnimation * timeDilation);
switch (action) { switch (action) {
case CollectionAction.copy: case CollectionAction.copy:
case CollectionAction.move: case CollectionAction.move:
@ -384,7 +384,7 @@ class _SourceStateSubtitleState extends State<SourceStateSubtitle> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_progressTimer = Timer.periodic(const Duration(milliseconds: 1000), (timer) => setState(() {})); _progressTimer = Timer.periodic(Durations.appBarProgressTimerInterval, (_) => setState(() {}));
} }
@override @override

View file

@ -1,4 +1,5 @@
import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/filters.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/common/aves_filter_chip.dart'; import 'package:aves/widgets/common/aves_filter_chip.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -56,7 +57,7 @@ class _FilterBarState extends State<FilterBar> {
), ),
) )
: (context, animation) => _buildChip(filter), : (context, animation) => _buildChip(filter),
duration: animate ? const Duration(milliseconds: 200) : Duration.zero, duration: animate ? Durations.filterBarRemovalAnimation : Duration.zero,
); );
}); });
added.forEach((filter) { added.forEach((filter) {

View file

@ -4,12 +4,12 @@ import 'package:aves/model/collection_lens.dart';
import 'package:aves/model/collection_source.dart'; import 'package:aves/model/collection_source.dart';
import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/utils/constants.dart'; import 'package:aves/utils/constants.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/album/grid/header_album.dart'; import 'package:aves/widgets/album/grid/header_album.dart';
import 'package:aves/widgets/album/grid/header_date.dart'; import 'package:aves/widgets/album/grid/header_date.dart';
import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/common/icons.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class SectionHeader extends StatelessWidget { class SectionHeader extends StatelessWidget {
@ -190,11 +190,11 @@ class SectionSelectableLeading extends StatelessWidget {
final sectionEntries = collection.sections[sectionKey]; final sectionEntries = collection.sections[sectionKey];
final selected = collection.isSelected(sectionEntries); final selected = collection.isSelected(sectionEntries);
final child = TooltipTheme( final child = TooltipTheme(
key: ValueKey(selected),
data: TooltipTheme.of(context).copyWith( data: TooltipTheme.of(context).copyWith(
preferBelow: false, preferBelow: false,
), ),
child: IconButton( child: IconButton(
key: ValueKey(selected),
iconSize: 26, iconSize: 26,
padding: const EdgeInsets.only(top: 1), padding: const EdgeInsets.only(top: 1),
alignment: Alignment.topLeft, alignment: Alignment.topLeft,
@ -214,7 +214,7 @@ class SectionSelectableLeading extends StatelessWidget {
), ),
); );
return AnimatedSwitcher( return AnimatedSwitcher(
duration: Duration(milliseconds: (200 * timeDilation).toInt()), duration: Durations.sectionHeaderAnimation,
switchInCurve: Curves.easeOutBack, switchInCurve: Curves.easeOutBack,
switchOutCurve: Curves.easeOutBack, switchOutCurve: Curves.easeOutBack,
transitionBuilder: (child, animation) => ScaleTransition( transitionBuilder: (child, animation) => ScaleTransition(
@ -227,7 +227,7 @@ class SectionSelectableLeading extends StatelessWidget {
) )
: browsingBuilder?.call(context) ?? const SizedBox(height: leadingDimension); : browsingBuilder?.call(context) ?? const SizedBox(height: leadingDimension);
return AnimatedSwitcher( return AnimatedSwitcher(
duration: Duration(milliseconds: (200 * timeDilation).toInt()), duration: Durations.sectionHeaderAnimation,
switchInCurve: Curves.easeInOut, switchInCurve: Curves.easeInOut,
switchOutCurve: Curves.easeInOut, switchOutCurve: Curves.easeInOut,
transitionBuilder: (child, animation) { transitionBuilder: (child, animation) {

View file

@ -2,6 +2,7 @@ import 'dart:math';
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:aves/model/image_entry.dart'; import 'package:aves/model/image_entry.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/album/grid/list_section_layout.dart'; import 'package:aves/widgets/album/grid/list_section_layout.dart';
import 'package:aves/widgets/album/grid/list_sliver.dart'; import 'package:aves/widgets/album/grid/list_sliver.dart';
import 'package:aves/widgets/album/grid/tile_extent_manager.dart'; import 'package:aves/widgets/album/grid/tile_extent_manager.dart';
@ -118,7 +119,7 @@ class _GridScaleGestureDetectorState extends State<GridScaleGestureDetector> {
_scrollToEntry(entry); _scrollToEntry(entry);
// warning: posting `onScaled` in the next frame with `addPostFrameCallback` // warning: posting `onScaled` in the next frame with `addPostFrameCallback`
// would trigger only when the scrollable offset actually changes // would trigger only when the scrollable offset actually changes
Future.delayed(const Duration(milliseconds: 300)).then((_) => widget.onScaled?.call(entry)); Future.delayed(Durations.collectionScalingCompleteNotificationDelay).then((_) => widget.onScaled?.call(entry));
_applyingScale = false; _applyingScale = false;
}); });
} }
@ -200,7 +201,7 @@ class _ScaleOverlayState extends State<ScaleOverlay> {
], ],
), ),
), ),
duration: const Duration(milliseconds: 200), duration: Durations.collectionScalingBackgroundAnimation,
child: ValueListenableBuilder<double>( child: ValueListenableBuilder<double>(
valueListenable: widget.scaledExtentNotifier, valueListenable: widget.scaledExtentNotifier,
builder: (context, extent, child) { builder: (context, extent, child) {

View file

@ -1,5 +1,6 @@
import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/filters.dart';
import 'package:aves/utils/constants.dart'; import 'package:aves/utils/constants.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/common/aves_filter_chip.dart'; import 'package:aves/widgets/common/aves_filter_chip.dart';
import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/common/icons.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -95,7 +96,7 @@ class ExpandableFilterRow extends StatelessWidget {
children: [ children: [
titleRow, titleRow,
AnimatedSwitcher( AnimatedSwitcher(
duration: const Duration(milliseconds: 300), duration: Durations.filterRowExpandAnimation,
child: filterChips, child: filterChips,
layoutBuilder: (currentChild, previousChildren) => Stack( layoutBuilder: (currentChild, previousChildren) => Stack(
children: [ children: [

View file

@ -2,10 +2,10 @@ import 'dart:math';
import 'package:aves/model/collection_lens.dart'; import 'package:aves/model/collection_lens.dart';
import 'package:aves/model/image_entry.dart'; import 'package:aves/model/image_entry.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/common/fx/sweeper.dart'; import 'package:aves/widgets/common/fx/sweeper.dart';
import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/common/icons.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class ThumbnailEntryOverlay extends StatelessWidget { class ThumbnailEntryOverlay extends StatelessWidget {
@ -57,7 +57,7 @@ class ThumbnailSelectionOverlay extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final duration = Duration(milliseconds: (200 * timeDilation).toInt()); final duration = Durations.thumbnailOverlayAnimation;
final fontSize = min(14.0, (extent / 8)).roundToDouble(); final fontSize = min(14.0, (extent / 8)).roundToDouble();
final iconSize = fontSize * 2; final iconSize = fontSize * 2;
final collection = Provider.of<CollectionLens>(context); final collection = Provider.of<CollectionLens>(context);

View file

@ -1,6 +1,7 @@
import 'dart:math'; import 'dart:math';
import 'package:aves/model/image_entry.dart'; import 'package:aves/model/image_entry.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/common/image_providers/thumbnail_provider.dart'; import 'package:aves/widgets/common/image_providers/thumbnail_provider.dart';
import 'package:aves/widgets/common/image_providers/uri_image_provider.dart'; import 'package:aves/widgets/common/image_providers/uri_image_provider.dart';
import 'package:aves/widgets/common/transition_image.dart'; import 'package:aves/widgets/common/transition_image.dart';
@ -93,7 +94,7 @@ class _ThumbnailRasterImageState extends State<ThumbnailRasterImage> {
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) { frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
if (wasSynchronouslyLoaded) return child; if (wasSynchronouslyLoaded) return child;
return AnimatedSwitcher( return AnimatedSwitcher(
duration: const Duration(milliseconds: 200), duration: Durations.thumbnailTransition,
transitionBuilder: (child, animation) { transitionBuilder: (child, animation) {
var shouldFade = true; var shouldFade = true;
if (child is Image && child.image == _fastThumbnailProvider) { if (child is Image && child.image == _fastThumbnailProvider) {

View file

@ -4,6 +4,7 @@ import 'package:aves/model/collection_lens.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/mime_types.dart'; import 'package:aves/model/mime_types.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/album/app_bar.dart'; import 'package:aves/widgets/album/app_bar.dart';
import 'package:aves/widgets/album/empty.dart'; import 'package:aves/widgets/album/empty.dart';
import 'package:aves/widgets/album/grid/list_section_layout.dart'; import 'package:aves/widgets/album/grid/list_section_layout.dart';
@ -220,7 +221,7 @@ class _CollectionScrollViewState extends State<CollectionScrollView> {
void _onScrollChange() { void _onScrollChange() {
widget.isScrollingNotifier.value = true; widget.isScrollingNotifier.value = true;
_stopScrollMonitoringTimer(); _stopScrollMonitoringTimer();
_scrollMonitoringTimer = Timer(const Duration(milliseconds: 100), () { _scrollMonitoringTimer = Timer(Durations.collectionScrollMonitoringTimerDelay, () {
widget.isScrollingNotifier.value = false; widget.isScrollingNotifier.value = false;
}); });
} }

View file

@ -1,5 +1,7 @@
import 'package:aves/utils/durations.dart';
import 'package:flushbar/flushbar.dart'; import 'package:flushbar/flushbar.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
mixin FeedbackMixin { mixin FeedbackMixin {
void showFeedback(BuildContext context, String message) { void showFeedback(BuildContext context, String message) {
@ -9,9 +11,9 @@ mixin FeedbackMixin {
borderRadius: 8, borderRadius: 8,
borderColor: Colors.white30, borderColor: Colors.white30,
borderWidth: 0.5, borderWidth: 0.5,
duration: const Duration(seconds: 2), duration: Durations.opToastDisplay * timeDilation,
flushbarPosition: FlushbarPosition.TOP, flushbarPosition: FlushbarPosition.TOP,
animationDuration: const Duration(milliseconds: 600), animationDuration: Durations.opToastAnimation,
).show(context); ).show(context);
} }
} }

View file

@ -7,6 +7,7 @@ import 'package:aves/model/image_entry.dart';
import 'package:aves/model/metadata_db.dart'; import 'package:aves/model/metadata_db.dart';
import 'package:aves/services/android_app_service.dart'; import 'package:aves/services/android_app_service.dart';
import 'package:aves/services/image_file_service.dart'; import 'package:aves/services/image_file_service.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/album/app_bar.dart'; import 'package:aves/widgets/album/app_bar.dart';
import 'package:aves/widgets/album/empty.dart'; import 'package:aves/widgets/album/empty.dart';
import 'package:aves/widgets/common/action_delegates/create_album_dialog.dart'; import 'package:aves/widgets/common/action_delegates/create_album_dialog.dart';
@ -18,6 +19,7 @@ import 'package:aves/widgets/filter_grid_page.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';
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:percent_indicator/circular_percent_indicator.dart'; import 'package:percent_indicator/circular_percent_indicator.dart';
@ -221,8 +223,6 @@ class SelectionActionDelegate with FeedbackMixin, PermissionAwareMixin {
OverlayEntry _opReportOverlayEntry; OverlayEntry _opReportOverlayEntry;
static const _overlayAnimationDuration = Duration(milliseconds: 300);
void _showOpReport<T extends ImageOpEvent>({ void _showOpReport<T extends ImageOpEvent>({
@required BuildContext context, @required BuildContext context,
@required List<ImageEntry> selection, @required List<ImageEntry> selection,
@ -260,7 +260,7 @@ class SelectionActionDelegate with FeedbackMixin, PermissionAwareMixin {
); );
} }
return AnimatedSwitcher( return AnimatedSwitcher(
duration: _overlayAnimationDuration, duration: Durations.collectionOpOverlayAnimation,
child: child, child: child,
); );
}); });
@ -270,7 +270,7 @@ class SelectionActionDelegate with FeedbackMixin, PermissionAwareMixin {
} }
Future<void> _hideOpReportOverlay() async { Future<void> _hideOpReportOverlay() async {
await Future.delayed(_overlayAnimationDuration); await Future.delayed(Durations.collectionOpOverlayAnimation * timeDilation);
_opReportOverlayEntry.remove(); _opReportOverlayEntry.remove();
_opReportOverlayEntry = null; _opReportOverlayEntry = null;
} }

View file

@ -1,5 +1,6 @@
import 'dart:math'; import 'dart:math';
import 'package:aves/utils/durations.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
@ -34,14 +35,11 @@ class _SweeperState extends State<Sweeper> with SingleTickerProviderStateMixin {
bool get isToggled => widget.toggledNotifier.value; bool get isToggled => widget.toggledNotifier.value;
static const opacityAnimationDurationMillis = 150;
static const sweepingDurationMillis = 650;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_angleAnimationController = AnimationController( _angleAnimationController = AnimationController(
duration: const Duration(milliseconds: sweepingDurationMillis), duration: Durations.sweepingAnimation,
vsync: this, vsync: this,
); );
final startAngle = widget.startAngle; final startAngle = widget.startAngle;
@ -86,7 +84,7 @@ class _SweeperState extends State<Sweeper> with SingleTickerProviderStateMixin {
return IgnorePointer( return IgnorePointer(
child: AnimatedOpacity( child: AnimatedOpacity(
opacity: isToggled && (_isAppearing || _angleAnimationController.status == AnimationStatus.forward) ? 1 : 0, opacity: isToggled && (_isAppearing || _angleAnimationController.status == AnimationStatus.forward) ? 1 : 0,
duration: const Duration(milliseconds: opacityAnimationDurationMillis), duration: Durations.sweeperOpacityAnimation,
child: ValueListenableBuilder<double>( child: ValueListenableBuilder<double>(
valueListenable: _angleAnimationController, valueListenable: _angleAnimationController,
builder: (context, value, child) { builder: (context, value, child) {
@ -113,7 +111,7 @@ class _SweeperState extends State<Sweeper> with SingleTickerProviderStateMixin {
if (isToggled) { if (isToggled) {
_isAppearing = true; _isAppearing = true;
setState(() {}); setState(() {});
await Future.delayed(Duration(milliseconds: (opacityAnimationDurationMillis * timeDilation).toInt())); await Future.delayed(Durations.sweeperOpacityAnimation * timeDilation);
_isAppearing = false; _isAppearing = false;
if (mounted) { if (mounted) {
_angleAnimationController.reset(); _angleAnimationController.reset();

View file

@ -7,6 +7,7 @@ import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/image_entry.dart'; import 'package:aves/model/image_entry.dart';
import 'package:aves/model/settings.dart'; import 'package:aves/model/settings.dart';
import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/album/collection_page.dart'; import 'package:aves/widgets/album/collection_page.dart';
import 'package:aves/widgets/album/thumbnail/raster.dart'; import 'package:aves/widgets/album/thumbnail/raster.dart';
import 'package:aves/widgets/album/thumbnail/vector.dart'; import 'package:aves/widgets/album/thumbnail/vector.dart';
@ -115,7 +116,8 @@ class FilterGridPage extends StatelessWidget {
return AnimationConfiguration.staggeredGrid( return AnimationConfiguration.staggeredGrid(
position: i, position: i,
columnCount: columnCount, columnCount: columnCount,
duration: const Duration(milliseconds: 375), duration: Durations.staggeredAnimation,
delay: Durations.staggeredAnimationDelay,
child: SlideAnimation( child: SlideAnimation(
verticalOffset: 50.0, verticalOffset: 50.0,
child: FadeInAnimation( child: FadeInAnimation(

View file

@ -5,6 +5,7 @@ import 'package:aves/model/collection_lens.dart';
import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/image_entry.dart'; import 'package:aves/model/image_entry.dart';
import 'package:aves/utils/change_notifier.dart'; import 'package:aves/utils/change_notifier.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/album/collection_page.dart'; import 'package:aves/widgets/album/collection_page.dart';
import 'package:aves/widgets/common/action_delegates/entry_action_delegate.dart'; import 'package:aves/widgets/common/action_delegates/entry_action_delegate.dart';
import 'package:aves/widgets/common/image_providers/thumbnail_provider.dart'; import 'package:aves/widgets/common/image_providers/thumbnail_provider.dart';
@ -73,7 +74,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
_horizontalPager = PageController(initialPage: _currentHorizontalPage); _horizontalPager = PageController(initialPage: _currentHorizontalPage);
_verticalPager = PageController(initialPage: _currentVerticalPage.value)..addListener(_onVerticalPageControllerChange); _verticalPager = PageController(initialPage: _currentVerticalPage.value)..addListener(_onVerticalPageControllerChange);
_overlayAnimationController = AnimationController( _overlayAnimationController = AnimationController(
duration: const Duration(milliseconds: 200), duration: Durations.fullscreenOverlayAnimation,
vsync: this, vsync: this,
); );
_topOverlayScale = CurvedAnimation( _topOverlayScale = CurvedAnimation(
@ -97,8 +98,8 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
); );
WidgetsBinding.instance.addObserver(this); WidgetsBinding.instance.addObserver(this);
_initVideoController(); _initVideoController();
_initOverlay();
_registerWidget(widget); _registerWidget(widget);
WidgetsBinding.instance.addPostFrameCallback((_) => _initOverlay());
} }
@override @override
@ -283,7 +284,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
Future<void> _goToVerticalPage(int page) { Future<void> _goToVerticalPage(int page) {
return _verticalPager.animateToPage( return _verticalPager.animateToPage(
page, page,
duration: Duration(milliseconds: (300 * timeDilation).toInt()), duration: Durations.fullscreenPageAnimation,
curve: Curves.easeInOut, curve: Curves.easeInOut,
); );
} }
@ -332,7 +333,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
Future<void> _initOverlay() async { Future<void> _initOverlay() async {
// wait for MaterialPageRoute.transitionDuration // wait for MaterialPageRoute.transitionDuration
// to show overlay after hero animation is complete // to show overlay after hero animation is complete
await Future.delayed(Duration(milliseconds: (300 * timeDilation).toInt())); await Future.delayed(ModalRoute.of(context).transitionDuration * timeDilation);
await _onOverlayVisibleChange(); await _onOverlayVisibleChange();
} }

View file

@ -1,6 +1,7 @@
import 'package:aves/model/collection_lens.dart'; import 'package:aves/model/collection_lens.dart';
import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/image_entry.dart'; import 'package:aves/model/image_entry.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/common/aves_filter_chip.dart'; import 'package:aves/widgets/common/aves_filter_chip.dart';
import 'package:aves/widgets/common/data_providers/media_query_data_provider.dart'; import 'package:aves/widgets/common/data_providers/media_query_data_provider.dart';
import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/common/icons.dart';
@ -8,7 +9,6 @@ import 'package:aves/widgets/fullscreen/info/basic_section.dart';
import 'package:aves/widgets/fullscreen/info/location_section.dart'; import 'package:aves/widgets/fullscreen/info/location_section.dart';
import 'package:aves/widgets/fullscreen/info/metadata_section.dart'; import 'package:aves/widgets/fullscreen/info/metadata_section.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
@ -177,7 +177,7 @@ class InfoPageState extends State<InfoPage> {
BackUpNotification().dispatch(context); BackUpNotification().dispatch(context);
_scrollController.animateTo( _scrollController.animateTo(
0, 0,
duration: Duration(milliseconds: (300 * timeDilation).toInt()), duration: Durations.fullscreenPageAnimation,
curve: Curves.easeInOut, curve: Curves.easeInOut,
); );
} }

View file

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:aves/model/image_entry.dart'; import 'package:aves/model/image_entry.dart';
import 'package:aves/services/android_app_service.dart'; import 'package:aves/services/android_app_service.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/utils/time_utils.dart'; import 'package:aves/utils/time_utils.dart';
import 'package:aves/widgets/common/fx/blurred.dart'; import 'package:aves/widgets/common/fx/blurred.dart';
import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/common/icons.dart';
@ -61,7 +62,7 @@ class VideoControlOverlayState extends State<VideoControlOverlay> with SingleTic
void initState() { void initState() {
super.initState(); super.initState();
_playPauseAnimation = AnimationController( _playPauseAnimation = AnimationController(
duration: const Duration(milliseconds: 300), duration: Durations.iconAnimation,
vsync: this, vsync: this,
); );
_registerWidget(widget); _registerWidget(widget);
@ -220,9 +221,7 @@ class VideoControlOverlayState extends State<VideoControlOverlay> with SingleTic
void _startTimer() { void _startTimer() {
if (controller.textureId == null) return; if (controller.textureId == null) return;
_progressTimer?.cancel(); _progressTimer?.cancel();
_progressTimer = Timer.periodic(const Duration(milliseconds: 300), (timer) { _progressTimer = Timer.periodic(Durations.videoProgressTimerInterval, (_) => controller.refreshVideoInfo());
controller.refreshVideoInfo();
});
} }
void _stopTimer() { void _stopTimer() {

View file

@ -1,6 +1,7 @@
import 'package:aves/main.dart'; import 'package:aves/main.dart';
import 'package:aves/model/settings.dart'; import 'package:aves/model/settings.dart';
import 'package:aves/model/terms.dart'; import 'package:aves/model/terms.dart';
import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/common/aves_logo.dart'; import 'package:aves/widgets/common/aves_logo.dart';
import 'package:aves/widgets/common/labeled_checkbox.dart'; import 'package:aves/widgets/common/labeled_checkbox.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -28,7 +29,8 @@ class _WelcomePageState extends State<WelcomePage> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: _toStaggeredList( children: _toStaggeredList(
duration: const Duration(milliseconds: 375), duration: Durations.staggeredAnimation,
delay: Durations.staggeredAnimationDelay,
childAnimationBuilder: (child) => SlideAnimation( childAnimationBuilder: (child) => SlideAnimation(
verticalOffset: 50.0, verticalOffset: 50.0,
child: FadeInAnimation( child: FadeInAnimation(