durations cleanup
This commit is contained in:
parent
ac1dc99cba
commit
3fe1d955d6
21 changed files with 99 additions and 57 deletions
|
@ -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)
|
||||||
''';
|
''';
|
||||||
|
|
||||||
|
|
|
@ -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
35
lib/utils/durations.dart
Normal 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;
|
||||||
|
}
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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: [
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,14 +53,14 @@ class _CreateAlbumDialogState extends State<CreateAlbumDialog> {
|
||||||
isExpanded: true,
|
isExpanded: true,
|
||||||
items: allVolumes
|
items: allVolumes
|
||||||
.map((volume) => DropdownMenuItem(
|
.map((volume) => DropdownMenuItem(
|
||||||
value: volume,
|
value: volume,
|
||||||
child: Text(
|
child: Text(
|
||||||
volume.description,
|
volume.description,
|
||||||
softWrap: false,
|
softWrap: false,
|
||||||
overflow: TextOverflow.fade,
|
overflow: TextOverflow.fade,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
.toList(),
|
.toList(),
|
||||||
value: selectedVolume,
|
value: selectedVolume,
|
||||||
onChanged: (volume) => setState(() => selectedVolume = volume),
|
onChanged: (volume) => setState(() => selectedVolume = volume),
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -321,18 +322,18 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
_showSystemUI();
|
_showSystemUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
// system UI
|
// system UI
|
||||||
|
|
||||||
static void _showSystemUI() => SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
|
static void _showSystemUI() => SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
|
||||||
|
|
||||||
static void _hideSystemUI() => SystemChrome.setEnabledSystemUIOverlays([]);
|
static void _hideSystemUI() => SystemChrome.setEnabledSystemUIOverlays([]);
|
||||||
|
|
||||||
// overlay
|
// overlay
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in a new issue