package upgrade, lints, gesture settings touch slop

This commit is contained in:
Thibault Deckers 2022-05-12 17:32:51 +09:00
parent 754b155576
commit 67b7842ec0
57 changed files with 211 additions and 165 deletions

View file

@ -17,7 +17,7 @@ jobs:
# Available versions may lag behind https://github.com/flutter/flutter.git
- uses: subosito/flutter-action@v2
with:
flutter-version: '2.10.5'
flutter-version: '3.0.0'
channel: 'stable'
- name: Clone the repository.

View file

@ -19,7 +19,7 @@ jobs:
# Available versions may lag behind https://github.com/flutter/flutter.git
- uses: subosito/flutter-action@v2
with:
flutter-version: '2.10.5'
flutter-version: '3.0.0'
channel: 'stable'
# Workaround for this Android Gradle Plugin issue (supposedly fixed in AGP 4.1):
@ -56,15 +56,15 @@ jobs:
rm release.keystore.asc
mkdir outputs
(cd scripts/; ./apply_flavor_play.sh)
flutter build appbundle -t lib/main_play.dart --flavor play --bundle-sksl-path shaders_2.10.5.sksl.json
flutter build appbundle -t lib/main_play.dart --flavor play --bundle-sksl-path shaders_3.0.0.sksl.json
cp build/app/outputs/bundle/playRelease/*.aab outputs
flutter build apk -t lib/main_play.dart --flavor play --bundle-sksl-path shaders_2.10.5.sksl.json
flutter build apk -t lib/main_play.dart --flavor play --bundle-sksl-path shaders_3.0.0.sksl.json
cp build/app/outputs/apk/play/release/*.apk outputs
(cd scripts/; ./apply_flavor_huawei.sh)
flutter build apk -t lib/main_huawei.dart --flavor huawei --bundle-sksl-path shaders_2.10.5.sksl.json
flutter build apk -t lib/main_huawei.dart --flavor huawei --bundle-sksl-path shaders_3.0.0.sksl.json
cp build/app/outputs/apk/huawei/release/*.apk outputs
(cd scripts/; ./apply_flavor_izzy.sh)
flutter build apk -t lib/main_izzy.dart --flavor izzy --split-per-abi --bundle-sksl-path shaders_2.10.5.sksl.json
flutter build apk -t lib/main_izzy.dart --flavor izzy --split-per-abi --bundle-sksl-path shaders_3.0.0.sksl.json
cp build/app/outputs/apk/izzy/release/*.apk outputs
rm $AVES_STORE_FILE
env:

View file

@ -14,7 +14,7 @@ All notable changes to this project will be documented in this file.
### Changed
- upgraded Flutter to stable v2.10.5
- upgraded Flutter to stable v3.0.0
## <a id="v1.6.4"></a>[v1.6.4] - 2022-04-19

View file

@ -11,6 +11,12 @@ analyzer:
linter:
rules:
# from 'flutter_lints', excluded
use_build_context_synchronously: false # no alternative
# from 'lints / recommended', excluded
no_leading_underscores_for_local_identifiers: false # useful for null checked variable variants
# from 'effective dart', excluded
avoid_classes_with_only_static_members: false # too strict
avoid_function_literals_in_foreach_calls: false # benefit?

View file

@ -55,7 +55,7 @@ extension ExtraAvesEntryImages on AvesEntry {
expectedContentLength: sizeBytes,
);
bool _isReady(Object providerKey) => imageCache!.statusForKey(providerKey).keepAlive;
bool _isReady(Object providerKey) => imageCache.statusForKey(providerKey).keepAlive;
List<ThumbnailProvider> get cachedThumbnails => EntryCache.thumbnailRequestExtents.map(_getThumbnailProviderKey).where(_isReady).map(ThumbnailProvider.new).toList();

View file

@ -239,7 +239,7 @@ class Settings extends ChangeNotifier {
if (_locale != null) {
preferredLocales.add(_locale);
} else {
preferredLocales.addAll(WidgetsBinding.instance!.window.locales);
preferredLocales.addAll(WidgetsBinding.instance.window.locales);
if (preferredLocales.isEmpty) {
// the `window` locales may be empty in a window-less service context
preferredLocales.addAll(_systemLocalesFallback);

View file

@ -335,6 +335,11 @@ class Constants {
license: 'Apache 2.0',
sourceUrl: 'https://github.com/jifalops/dart-latlong',
),
Dependency(
name: 'Path',
license: 'BSD 3-Clause',
sourceUrl: 'https://github.com/dart-lang/path',
),
Dependency(
name: 'PDF for Dart and Flutter',
license: 'Apache 2.0',

View file

@ -92,9 +92,9 @@ class _BugReportState extends State<BugReport> with FeedbackMixin {
clipBehavior: Clip.antiAlias,
child: Theme(
data: Theme.of(context).copyWith(
scrollbarTheme: const ScrollbarThemeData(
isAlwaysShown: true,
radius: Radius.circular(16),
scrollbarTheme: ScrollbarThemeData(
thumbVisibility: MaterialStateProperty.all(true),
radius: const Radius.circular(16),
crossAxisMargin: 6,
mainAxisMargin: 6,
interactive: true,
@ -171,7 +171,7 @@ class _BugReportState extends State<BugReport> with FeedbackMixin {
'Android build: ${androidInfo.display}',
'Device: ${androidInfo.manufacturer} ${androidInfo.model}',
'Mobile services: ${hasMobileServices ? 'ready' : 'not available'}',
'System locales: ${WidgetsBinding.instance!.window.locales.join(', ')}',
'System locales: ${WidgetsBinding.instance.window.locales.join(', ')}',
'Aves locale: ${settings.locale ?? 'system'} -> ${settings.appliedLocale}',
'Installer: $installer',
].join('\n');

View file

@ -80,7 +80,7 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
_newIntentChannel.receiveBroadcastStream().listen((event) => _onNewIntent(event as Map?));
_analysisCompletionChannel.receiveBroadcastStream().listen((event) => _onAnalysisCompletion());
_errorChannel.receiveBroadcastStream().listen((event) => _onError(event as String?));
WidgetsBinding.instance!.addObserver(this);
WidgetsBinding.instance.addObserver(this);
}
@override
@ -280,7 +280,7 @@ class _AvesAppState extends State<AvesApp> with WidgetsBindingObserver {
? 'profile'
: 'debug',
'has_mobile_services': hasMobileServices,
'locales': WidgetsBinding.instance!.window.locales.join(', '),
'locales': WidgetsBinding.instance.window.locales.join(', '),
'time_zone': '${now.timeZoneName} (${now.timeZoneOffset})',
});
_navigatorObservers = [

View file

@ -77,7 +77,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
);
_isSelectingNotifier.addListener(_onActivityChange);
_registerWidget(widget);
WidgetsBinding.instance!.addPostFrameCallback((_) => _onFilterChanged());
WidgetsBinding.instance.addPostFrameCallback((_) => _onFilterChanged());
}
@override

View file

@ -35,6 +35,7 @@ import 'package:aves/widgets/common/providers/tile_extent_controller_provider.da
import 'package:aves/widgets/common/thumbnail/decorated.dart';
import 'package:aves/widgets/common/tile_extent_controller.dart';
import 'package:aves/widgets/navigation/nav_bar/nav_bar.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:intl/intl.dart';
@ -389,7 +390,12 @@ class _CollectionScrollViewState extends State<_CollectionScrollView> {
primary: true,
// workaround to prevent scrolling the app bar away
// when there is no content and we use `SliverFillRemaining`
physics: collection.isEmpty ? const NeverScrollableScrollPhysics() : const SloppyScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
physics: collection.isEmpty
? const NeverScrollableScrollPhysics()
: SloppyScrollPhysics(
gestureSettings: context.select<MediaQueryData, DeviceGestureSettings>((mq) => mq.gestureSettings),
parent: const AlwaysScrollableScrollPhysics(),
),
cacheExtent: context.select<TileExtentController, double>((controller) => controller.effectiveExtentMax),
slivers: [
appBar,

View file

@ -61,7 +61,7 @@ class _CollectionPageState extends State<CollectionPage> {
_collection.removeFilter(TrashFilter.instance);
}
}));
WidgetsBinding.instance!.addPostFrameCallback((_) => _checkInitHighlight());
WidgetsBinding.instance.addPostFrameCallback((_) => _checkInitHighlight());
}
@override

View file

@ -1,3 +1,4 @@
// ignore_for_file: depend_on_referenced_packages
import 'package:flutter/material.dart';
import 'package:highlight/highlight.dart' show highlight, Node;

View file

@ -29,9 +29,9 @@ class MarkdownContainer extends StatelessWidget {
borderRadius: const BorderRadius.all(Radius.circular(16)),
child: Theme(
data: Theme.of(context).copyWith(
scrollbarTheme: const ScrollbarThemeData(
isAlwaysShown: true,
radius: Radius.circular(16),
scrollbarTheme: ScrollbarThemeData(
thumbVisibility: MaterialStateProperty.all(true),
radius: const Radius.circular(16),
crossAxisMargin: 6,
mainAxisMargin: 16,
interactive: true,

View file

@ -1,3 +1,4 @@
// ignore_for_file: depend_on_referenced_packages
import 'dart:math' as math;
import 'package:flutter/gestures.dart';

View file

@ -1,25 +1,30 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
// TODO TLAD merge with `MagnifierScrollerPhysics`
class SloppyScrollPhysics extends ScrollPhysics {
final DeviceGestureSettings? gestureSettings;
// in [0, 1]
// 0: most reactive but will not let Magnifier recognizers accept gestures
// 1: less reactive but gives the most leeway to Magnifier recognizers
final double touchSlopFactor;
const SloppyScrollPhysics({
required this.gestureSettings,
this.touchSlopFactor = 1,
ScrollPhysics? parent,
}) : super(parent: parent);
// in [0, 1]
// 0: most reactive but will not let other recognizers accept gestures
// 1: less reactive but gives the most leeway to other recognizers
final double touchSlopFactor;
@override
SloppyScrollPhysics applyTo(ScrollPhysics? ancestor) {
return SloppyScrollPhysics(
gestureSettings: gestureSettings,
touchSlopFactor: touchSlopFactor,
parent: buildParent(ancestor),
);
}
@override
double get dragStartDistanceMotionThreshold => kTouchSlop * touchSlopFactor;
double get dragStartDistanceMotionThreshold => (gestureSettings?.touchSlop ?? kTouchSlop) * touchSlopFactor;
}

View file

@ -6,7 +6,7 @@ class HighlightDecoration extends Decoration {
const HighlightDecoration({required this.color});
@override
_HighlightDecorationPainter createBoxPainter([VoidCallback? onChanged]) {
BoxPainter createBoxPainter([VoidCallback? onChanged]) {
return _HighlightDecorationPainter(this, onChanged);
}
}

View file

@ -45,7 +45,7 @@ class _GridItemTrackerState<T> extends State<GridItemTracker<T>> with WidgetsBin
}
Orientation get _windowOrientation {
final size = WidgetsBinding.instance!.window.physicalSize;
final size = WidgetsBinding.instance.window.physicalSize;
return size.width > size.height ? Orientation.landscape : Orientation.portrait;
}
@ -62,7 +62,7 @@ class _GridItemTrackerState<T> extends State<GridItemTracker<T>> with WidgetsBin
final highlightInfo = context.read<HighlightInfo>();
_subscriptions.add(highlightInfo.eventBus.on<TrackEvent<T>>().listen(_trackItem));
_lastOrientation = _windowOrientation;
WidgetsBinding.instance!.addObserver(this);
WidgetsBinding.instance.addObserver(this);
_saveLayoutMetrics();
}
@ -90,7 +90,7 @@ class _GridItemTrackerState<T> extends State<GridItemTracker<T>> with WidgetsBin
@override
void dispose() {
WidgetsBinding.instance!.removeObserver(this);
WidgetsBinding.instance.removeObserver(this);
_subscriptions
..forEach((sub) => sub.cancel())
..clear();
@ -168,7 +168,7 @@ class _GridItemTrackerState<T> extends State<GridItemTracker<T>> with WidgetsBin
}
if (pivotItem != null) {
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read<HighlightInfo>().trackItem(pivotItem, animate: false);
});
}

View file

@ -55,6 +55,8 @@ class _GridScaleGestureDetectorState<T> extends State<GridScaleGestureDetector<T
@override
Widget build(BuildContext context) {
final gestureSettings = context.select<MediaQueryData, DeviceGestureSettings>((mq) => mq.gestureSettings);
final child = GestureDetector(
// Horizontal/vertical drag gestures are interpreted as scaling
// if they are not handled by `onHorizontalDragStart`/`onVerticalDragStart`
@ -79,7 +81,8 @@ class _GridScaleGestureDetectorState<T> extends State<GridScaleGestureDetector<T
..onStart = _onScaleStart
..onUpdate = _onScaleUpdate
..onEnd = _onScaleEnd
..dragStartBehavior = DragStartBehavior.start;
..dragStartBehavior = DragStartBehavior.start
..gestureSettings = gestureSettings;
},
),
},
@ -195,7 +198,7 @@ class _GridScaleGestureDetectorState<T> extends State<GridScaleGestureDetector<T
_applyingScale = false;
} else {
// scroll to show the focal point thumbnail at its new position
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
final trackItem = _metadata!.item;
final highlightItem = widget.highlightItem?.call(trackItem) ?? trackItem;
context.read<HighlightInfo>().trackItem(trackItem, animate: false, highlightItem: highlightItem);
@ -263,7 +266,7 @@ class _ScaleOverlayState extends State<_ScaleOverlay> {
@override
void initState() {
super.initState();
WidgetsBinding.instance!.addPostFrameCallback((_) => setState(() => _init = true));
WidgetsBinding.instance.addPostFrameCallback((_) => setState(() => _init = true));
}
@override

View file

@ -139,7 +139,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
_subscriptions.add(covers.colorChangeStream.listen(_onCoverColorChange));
_subscriptions.add(settings.updateStream.where((event) => event.key == Settings.themeColorModeKey).listen((_) {
// delay so that contextual colors reflect the new settings
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_onCoverColorChange(null);
});
}));
@ -282,7 +282,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
onTapDown: onLongPress != null ? (details) => _tapPosition = details.globalPosition : null,
onTap: onTap != null
? () {
WidgetsBinding.instance!.addPostFrameCallback((_) => onTap!(filter));
WidgetsBinding.instance.addPostFrameCallback((_) => onTap!(filter));
setState(() => _tapped = true);
}
: null,

View file

@ -3,6 +3,7 @@ import 'package:aves/widgets/common/magnifier/pan/corner_hit_detector.dart';
import 'package:aves/widgets/common/magnifier/pan/gesture_detector_scope.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
class MagnifierGestureDetector extends StatefulWidget {
const MagnifierGestureDetector({
@ -39,6 +40,7 @@ class _MagnifierGestureDetectorState extends State<MagnifierGestureDetector> {
@override
Widget build(BuildContext context) {
final gestureSettings = context.select<MediaQueryData, DeviceGestureSettings>((mq) => mq.gestureSettings);
final gestures = <Type, GestureRecognizerFactory>{};
if (widget.onTapDown != null || widget.onTapUp != null) {
@ -63,9 +65,11 @@ class _MagnifierGestureDetectorState extends State<MagnifierGestureDetector> {
doubleTapDetails: doubleTapDetails,
),
(instance) {
instance.onStart = widget.onScaleStart != null ? (details) => widget.onScaleStart!(details, doubleTapDetails.value != null) : null;
instance.onUpdate = widget.onScaleUpdate;
instance.onEnd = widget.onScaleEnd;
instance
..onStart = widget.onScaleStart != null ? (details) => widget.onScaleStart!(details, doubleTapDetails.value != null) : null
..onUpdate = widget.onScaleUpdate
..onEnd = widget.onScaleEnd
..gestureSettings = gestureSettings;
},
);
}
@ -73,14 +77,16 @@ class _MagnifierGestureDetectorState extends State<MagnifierGestureDetector> {
gestures[DoubleTapGestureRecognizer] = GestureRecognizerFactoryWithHandlers<DoubleTapGestureRecognizer>(
() => DoubleTapGestureRecognizer(debugOwner: this),
(instance) {
instance.onDoubleTapCancel = () => doubleTapDetails.value = null;
instance.onDoubleTapDown = (details) => doubleTapDetails.value = details;
instance.onDoubleTap = widget.onDoubleTap != null
? () {
widget.onDoubleTap!(doubleTapDetails.value!);
doubleTapDetails.value = null;
}
: null;
final onDoubleTap = widget.onDoubleTap;
instance
..onDoubleTapCancel = _onDoubleTapCancel
..onDoubleTapDown = _onDoubleTapDown
..onDoubleTap = onDoubleTap != null
? () {
onDoubleTap(doubleTapDetails.value!);
doubleTapDetails.value = null;
}
: null;
},
);
@ -90,4 +96,8 @@ class _MagnifierGestureDetectorState extends State<MagnifierGestureDetector> {
child: widget.child,
);
}
void _onDoubleTapCancel() => doubleTapDetails.value = null;
void _onDoubleTapDown(TapDownDetails details) => doubleTapDetails.value = details;
}

View file

@ -11,12 +11,12 @@ class MagnifierGestureRecognizer extends ScaleGestureRecognizer {
final ValueNotifier<TapDownDetails?> doubleTapDetails;
MagnifierGestureRecognizer({
Object? debugOwner,
super.debugOwner,
required this.hitDetector,
required this.validateAxis,
this.touchSlopFactor = 2,
required this.doubleTapDetails,
}) : super(debugOwner: debugOwner);
});
Map<int, Offset> _pointerLocations = <int, Offset>{};
@ -128,14 +128,16 @@ class MagnifierGestureRecognizer extends ScaleGestureRecognizer {
final doubleTap = doubleTapDetails.value != null;
if (shouldMove || doubleTap) {
final pointerDeviceKind = event.kind;
final spanDelta = (_currentSpan! - _initialSpan!).abs();
final focalPointDelta = (_currentFocalPoint! - _initialFocalPoint!).distance;
// warning: do not compare `focalPointDelta` to `kPanSlop`
// `ScaleGestureRecognizer` uses `kPanSlop`, but `HorizontalDragGestureRecognizer` uses `kTouchSlop`
// `ScaleGestureRecognizer` uses `kPanSlop` (or platform settings, cf gestures/events.dart `computePanSlop`),
// but `HorizontalDragGestureRecognizer` uses `kTouchSlop` (or platform settings, cf gestures/events.dart `computeHitSlop`)
// and the magnifier recognizer may compete with the `HorizontalDragGestureRecognizer` from a containing `PageView`
// setting `touchSlopFactor` to 2 restores default `ScaleGestureRecognizer` behaviour as `kPanSlop = kTouchSlop * 2.0`
// setting `touchSlopFactor` in [0, 1] will allow this recognizer to accept the gesture before the one from `PageView`
if (spanDelta > kScaleSlop || focalPointDelta > kTouchSlop * touchSlopFactor) {
if (spanDelta > computeScaleSlop(pointerDeviceKind) || focalPointDelta > computeHitSlop(pointerDeviceKind, gestureSettings) * touchSlopFactor) {
acceptGesture(event.pointer);
}
}

View file

@ -3,8 +3,6 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
mixin CornerHitDetector on MagnifierControllerDelegate {
_AxisHit hitAxis() => _AxisHit(_hitCornersX(), _hitCornersY());
// the child width/height is not accurate for some image size & scale combos
// e.g. 3580.0 * 0.1005586592178771 yields 360.0
// but 4764.0 * 0.07556675062972293 yields 360.00000000000006
@ -53,17 +51,6 @@ mixin CornerHitDetector on MagnifierControllerDelegate {
}
}
class _AxisHit {
_AxisHit(this.hasHitX, this.hasHitY);
final _CornerHit hasHitX;
final _CornerHit hasHitY;
bool get hasHitAny => hasHitX.hasHitAny || hasHitY.hasHitAny;
bool get hasHitBoth => hasHitX.hasHitBoth && hasHitY.hasHitBoth;
}
class _CornerHit {
const _CornerHit(this.hasHitMin, this.hasHitMax);

View file

@ -1,29 +1,34 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/widgets.dart';
// `PageView` contains a `Scrollable` which sets up a `HorizontalDragGestureRecognizer`
// this recognizer will win in the gesture arena when the drag distance reaches `kTouchSlop`
// we cannot change that, but we can prevent the scrollable from panning until this threshold is reached
// and let other recognizers accept the gesture instead
// `PageView` contains a `Scrollable` which sets up a `HorizontalDragGestureRecognizer`.
// This recognizer will win in the gesture arena when the drag distance reaches
// `kTouchSlop` (or platform settings, cf gestures/events.dart `computeHitSlop`).
// We cannot change that, but we can prevent the scrollable from panning until this threshold is reached
// and let other recognizers accept the gesture instead.
class MagnifierScrollerPhysics extends ScrollPhysics {
const MagnifierScrollerPhysics({
this.touchSlopFactor = 1,
ScrollPhysics? parent,
}) : super(parent: parent);
final DeviceGestureSettings? gestureSettings;
// in [0, 1]
// 0: most reactive but will not let Magnifier recognizers accept gestures
// 1: less reactive but gives the most leeway to Magnifier recognizers
final double touchSlopFactor;
const MagnifierScrollerPhysics({
required this.gestureSettings,
this.touchSlopFactor = 1,
ScrollPhysics? parent,
}) : super(parent: parent);
@override
MagnifierScrollerPhysics applyTo(ScrollPhysics? ancestor) {
return MagnifierScrollerPhysics(
gestureSettings: gestureSettings,
touchSlopFactor: touchSlopFactor,
parent: buildParent(ancestor),
);
}
@override
double get dragStartDistanceMotionThreshold => kTouchSlop * touchSlopFactor;
double get dragStartDistanceMotionThreshold => (gestureSettings?.touchSlop ?? kTouchSlop) * touchSlopFactor;
}

View file

@ -73,7 +73,7 @@ class _EntryLeafletMapState<T> extends State<EntryLeafletMap<T>> with TickerProv
void initState() {
super.initState();
_registerWidget(widget);
WidgetsBinding.instance!.addPostFrameCallback((_) => _updateVisibleRegion());
WidgetsBinding.instance.addPostFrameCallback((_) => _updateVisibleRegion());
}
@override

View file

@ -25,12 +25,12 @@ class _DebugCacheSectionState extends State<DebugCacheSection> with AutomaticKee
Row(
children: [
Expanded(
child: Text('Image cache:\n\t${imageCache!.currentSize}/${imageCache!.maximumSize} items\n\t${formatFileSize('en_US', imageCache!.currentSizeBytes)}/${formatFileSize('en_US', imageCache!.maximumSizeBytes)}'),
child: Text('Image cache:\n\t${imageCache.currentSize}/${imageCache.maximumSize} items\n\t${formatFileSize('en_US', imageCache.currentSizeBytes)}/${formatFileSize('en_US', imageCache.maximumSizeBytes)}'),
),
const SizedBox(width: 8),
ElevatedButton(
onPressed: () {
imageCache!.clear();
imageCache.clear();
setState(() {});
},

View file

@ -66,7 +66,7 @@ class DebugSettingsSection extends StatelessWidget {
'hiddenFilters': toMultiline(settings.hiddenFilters),
'searchHistory': toMultiline(settings.searchHistory),
'locale': '${settings.locale}',
'systemLocales': '${WidgetsBinding.instance!.window.locales}',
'systemLocales': '${WidgetsBinding.instance.window.locales}',
'topEntryIds': '${settings.topEntryIds}',
},
),

View file

@ -68,9 +68,9 @@ class AvesDialog extends StatelessWidget {
if (hasScrollBar) {
child = Theme(
data: Theme.of(context).copyWith(
scrollbarTheme: const ScrollbarThemeData(
isAlwaysShown: true,
radius: Radius.circular(16),
scrollbarTheme: ScrollbarThemeData(
thumbVisibility: MaterialStateProperty.all(true),
radius: const Radius.circular(16),
crossAxisMargin: 4,
mainAxisMargin: 4,
interactive: true,

View file

@ -92,7 +92,7 @@ class _AvesSelectionDialogState<T> extends State<AvesSelectionDialog<T>> {
groupValue: _selectedValue,
onChanged: (v) {
if (needConfirmation) {
setState(() => _selectedValue = v!);
setState(() => _selectedValue = v as T);
} else {
Navigator.pop(context, v);
}

View file

@ -37,7 +37,7 @@ class _EditEntryLocationDialogState extends State<EditEntryLocationDialog> {
super.initState();
_latitudeFocusNode.addListener(_onLatLngFocusChange);
_longitudeFocusNode.addListener(_onLatLngFocusChange);
WidgetsBinding.instance!.addPostFrameCallback((_) => _setLocation(context, widget.entry.latLng));
WidgetsBinding.instance.addPostFrameCallback((_) => _setLocation(context, widget.entry.latLng));
}
@override

View file

@ -232,7 +232,7 @@ class _TileViewDialogState<S, G, L> extends State<TileViewDialog<S, G, L>> with
key: Key(value.toString()),
value: value,
groupValue: get(),
onChanged: (v) => setState(() => set(v!)),
onChanged: (v) => setState(() => set(v as T)),
title: Text(
title,
softWrap: false,

View file

@ -377,7 +377,7 @@ class _FilterSectionedContentState<T extends CollectionFilter> extends State<_Fi
@override
void initState() {
super.initState();
WidgetsBinding.instance!.addPostFrameCallback((_) => _checkInitHighlight());
WidgetsBinding.instance.addPostFrameCallback((_) => _checkInitHighlight());
}
@override

View file

@ -88,7 +88,7 @@ class _InteractiveFilterTileState<T extends CollectionFilter> extends State<Inte
// make sure the chip hero triggers, even when tapping on the list view details
setState(() => _heroTypeOverride = HeroType.always);
}
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.push(
context,
MaterialPageRoute(

View file

@ -53,7 +53,7 @@ class _HomePageState extends State<HomePage> {
void initState() {
super.initState();
_setup();
imageCache!.maximumSizeBytes = 512 * (1 << 20);
imageCache.maximumSizeBytes = 512 * (1 << 20);
}
@override

View file

@ -147,7 +147,7 @@ class _ContentState extends State<_Content> with SingleTickerProviderStateMixin
}
});
WidgetsBinding.instance!.addPostFrameCallback((_) => _onOverlayVisibleChange(animate: false));
WidgetsBinding.instance.addPostFrameCallback((_) => _onOverlayVisibleChange(animate: false));
}
@override

View file

@ -16,7 +16,7 @@ class FloatingNavBar extends StatefulWidget {
}) : super(key: key);
@override
_FloatingNavBarState createState() => _FloatingNavBarState();
State<FloatingNavBar> createState() => _FloatingNavBarState();
}
class _FloatingNavBarState extends State<FloatingNavBar> with SingleTickerProviderStateMixin {

View file

@ -211,7 +211,7 @@ class CollectionSearchDelegate {
}
Widget buildResults(BuildContext context) {
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
// `buildResults` is called in the build phase,
// so we post the call that will filter the collection
// and possibly trigger a rebuild here
@ -249,7 +249,7 @@ class CollectionSearchDelegate {
// we post closing the search page after applying the filter selection
// so that hero animation target is ready in the `FilterBar`,
// even when the target is a child of an `AnimatedList`
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_goBack(context);
});
}

View file

@ -27,7 +27,7 @@ class _CrumbLineState extends State<CrumbLine> {
super.didUpdateWidget(oldWidget);
if (widget.directory.relativeDir.length > oldWidget.directory.relativeDir.length) {
// scroll to show last crumb
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
final extent = _controller.position.maxScrollExtent;
_controller.animateTo(
extent,

View file

@ -333,7 +333,7 @@ class StatsPage extends StatelessWidget {
// we post closing the search page after applying the filter selection
// so that hero animation target is ready in the `FilterBar`,
// even when the target is a child of an `AnimatedList`
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.pop(context);
});
}

View file

@ -7,6 +7,7 @@ import 'package:aves/widgets/common/magnifier/pan/scroll_physics.dart';
import 'package:aves/widgets/viewer/multipage/conductor.dart';
import 'package:aves/widgets/viewer/page_entry_builder.dart';
import 'package:aves/widgets/viewer/visual/entry_page_view.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -44,7 +45,10 @@ class _MultiEntryScrollerState extends State<MultiEntryScroller> with AutomaticK
key: const Key('horizontal-pageview'),
scrollDirection: Axis.horizontal,
controller: pageController,
physics: const MagnifierScrollerPhysics(parent: BouncingScrollPhysics()),
physics: MagnifierScrollerPhysics(
gestureSettings: context.select<MediaQueryData, DeviceGestureSettings>((mq) => mq.gestureSettings),
parent: const BouncingScrollPhysics(),
),
onPageChanged: widget.onPageChanged,
itemBuilder: (context, index) {
final mainEntry = entries[index];

View file

@ -10,8 +10,10 @@ import 'package:aves/widgets/common/magnifier/pan/scroll_physics.dart';
import 'package:aves/widgets/viewer/entry_horizontal_pager.dart';
import 'package:aves/widgets/viewer/info/info_page.dart';
import 'package:aves/widgets/viewer/notifications.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:screen_brightness/screen_brightness.dart';
class ViewerVerticalPageView extends StatefulWidget {
@ -136,7 +138,10 @@ class _ViewerVerticalPageViewState extends State<ViewerVerticalPageView> {
key: const Key('vertical-pageview'),
scrollDirection: Axis.vertical,
controller: widget.verticalPager,
physics: const MagnifierScrollerPhysics(parent: PageScrollPhysics()),
physics: MagnifierScrollerPhysics(
gestureSettings: context.select<MediaQueryData, DeviceGestureSettings>((mq) => mq.gestureSettings),
parent: const PageScrollPhysics(),
),
onPageChanged: widget.onVerticalPageChanged,
children: pages,
),

View file

@ -132,8 +132,8 @@ class _EntryViewerStackState extends State<EntryViewerStack> with FeedbackMixin,
);
_initEntryControllers(entry);
_registerWidget(widget);
WidgetsBinding.instance!.addObserver(this);
WidgetsBinding.instance!.addPostFrameCallback((_) => _initOverlay());
WidgetsBinding.instance.addObserver(this);
WidgetsBinding.instance.addPostFrameCallback((_) => _initOverlay());
}
@override
@ -150,7 +150,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with FeedbackMixin,
_overlayAnimationController.dispose();
_overlayVisible.removeListener(_onOverlayVisibleChange);
_verticalPager.removeListener(_onVerticalPageControllerChange);
WidgetsBinding.instance!.removeObserver(this);
WidgetsBinding.instance.removeObserver(this);
_unregisterWidget(widget);
super.dispose();
}
@ -395,7 +395,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with FeedbackMixin,
builder: (context, mqHeight, child) {
// when orientation change, the `PageController` offset is not updated right away
// and it does not trigger its listeners when it does, so we force a refresh in the next frame
WidgetsBinding.instance!.addPostFrameCallback((_) => _onVerticalPageControllerChange());
WidgetsBinding.instance.addPostFrameCallback((_) => _onVerticalPageControllerChange());
return AnimatedBuilder(
animation: _verticalScrollNotifier,
builder: (context, child) => Positioned(
@ -548,7 +548,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with FeedbackMixin,
if (_heroInfoNotifier.value != heroInfo) {
_heroInfoNotifier.value = heroInfo;
// we post closing the viewer page so that hero animation source is ready
WidgetsBinding.instance!.addPostFrameCallback((_) => pop());
WidgetsBinding.instance.addPostFrameCallback((_) => pop());
} else {
// viewer already has correct hero info, no need to rebuild
pop();

View file

@ -46,7 +46,7 @@ class _PanoramaPageState extends State<PanoramaPage> {
void initState() {
super.initState();
_overlayVisible.addListener(_onOverlayVisibleChange);
WidgetsBinding.instance!.addPostFrameCallback((_) => _initOverlay());
WidgetsBinding.instance.addPostFrameCallback((_) => _initOverlay());
}
@override

View file

@ -33,7 +33,7 @@ class _WelcomePageState extends State<WelcomePage> {
super.initState();
settings.setContextualDefaults();
_termsLoader = rootBundle.loadString(termsPath);
WidgetsBinding.instance!.addPostFrameCallback((_) => _initWelcomeSettings());
WidgetsBinding.instance.addPostFrameCallback((_) => _initWelcomeSettings());
}
// explicitly set consent values to current defaults

View file

@ -44,7 +44,7 @@ class _MarkerGeneratorWidgetState<T extends Key> extends State<MarkerGeneratorWi
}
void _checkNextFrame() {
WidgetsBinding.instance!.addPostFrameCallback((_) async {
WidgetsBinding.instance.addPostFrameCallback((_) async {
if (!mounted) return;
final waitingItems = _items.where((v) => v.isWaiting).toSet();
final readyItems = waitingItems.where((v) => widget.isReadyToRender(v.markerKey)).toSet();

View file

@ -3,11 +3,12 @@ version: 0.0.1
publish_to: none
environment:
sdk: ">=2.16.2 <3.0.0"
sdk: ">=2.17.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
collection:
# TODO TLAD as of 2022/02/22, null safe version is pre-release
custom_rounded_rectangle_border: '>=0.2.0-nullsafety.0'
equatable:

View file

@ -3,7 +3,7 @@ version: 0.0.1
publish_to: none
environment:
sdk: ">=2.16.2 <3.0.0"
sdk: ">=2.17.0 <3.0.0"
dependencies:
flutter:

View file

@ -3,7 +3,7 @@ version: 0.0.1
publish_to: none
environment:
sdk: ">=2.16.2 <3.0.0"
sdk: ">=2.17.0 <3.0.0"
dependencies:
flutter:

View file

@ -3,13 +3,14 @@ version: 0.0.1
publish_to: none
environment:
sdk: ">=2.16.2 <3.0.0"
sdk: ">=2.17.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
aves_report:
path: ../aves_report
collection:
firebase_core:
firebase_crashlytics:
stack_trace:

View file

@ -3,7 +3,7 @@ version: 0.0.1
publish_to: none
environment:
sdk: ">=2.16.2 <3.0.0"
sdk: ">=2.17.0 <3.0.0"
dependencies:
flutter:

View file

@ -67,7 +67,7 @@ class _EntryGoogleMapState<T> extends State<EntryGoogleMap<T>> with WidgetsBindi
@override
void initState() {
super.initState();
WidgetsBinding.instance!.addObserver(this);
WidgetsBinding.instance.addObserver(this);
_registerWidget(widget);
}
@ -82,7 +82,7 @@ class _EntryGoogleMapState<T> extends State<EntryGoogleMap<T>> with WidgetsBindi
void dispose() {
_unregisterWidget(widget);
_serviceMapController?.dispose();
WidgetsBinding.instance!.removeObserver(this);
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@ -255,7 +255,7 @@ class _EntryGoogleMapState<T> extends State<EntryGoogleMap<T>> with WidgetsBindi
} else {
// the visible region is sometimes uninitialized when queried right after creation,
// so we query it again next frame
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_updateVisibleRegion(zoom: zoom, rotation: rotation);
});
}

View file

@ -3,7 +3,7 @@ version: 0.0.1
publish_to: none
environment:
sdk: ">=2.16.2 <3.0.0"
sdk: ">=2.17.0 <3.0.0"
dependencies:
flutter:

View file

@ -273,7 +273,7 @@ class _EntryHmsMapState<T> extends State<EntryHmsMap<T>> {
} else {
// the visible region is sometimes uninitialized when queried right after creation,
// so we query it again next frame
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_updateVisibleRegion(zoom: zoom, rotation: rotation);
});
}

View file

@ -3,7 +3,7 @@ version: 0.0.1
publish_to: none
environment:
sdk: ">=2.16.2 <3.0.0"
sdk: ">=2.17.0 <3.0.0"
dependencies:
flutter:

View file

@ -7,28 +7,28 @@ packages:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "31.0.0"
version: "39.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.0"
version: "4.0.0"
archive:
dependency: transitive
description:
name: archive
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.6"
version: "3.1.11"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
version: "2.3.1"
async:
dependency: transitive
description:
@ -77,7 +77,7 @@ packages:
name: barcode
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.0"
version: "2.2.1"
boolean_selector:
dependency: transitive
description:
@ -113,13 +113,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.0"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.5"
clock:
dependency: transitive
description:
@ -133,7 +126,7 @@ packages:
name: collection
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
version: "1.16.0"
connectivity_plus:
dependency: "direct main"
description:
@ -196,7 +189,7 @@ packages:
name: coverage
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
version: "1.2.0"
crypto:
dependency: transitive
description:
@ -296,7 +289,7 @@ packages:
name: fake_async
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
version: "1.3.0"
ffi:
dependency: transitive
description:
@ -406,7 +399,7 @@ packages:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
version: "2.0.1"
flutter_localizations:
dependency: "direct main"
description: flutter
@ -432,7 +425,7 @@ packages:
name: flutter_plugin_android_lifecycle
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
version: "2.0.6"
flutter_staggered_animations:
dependency: "direct main"
description:
@ -489,7 +482,7 @@ packages:
name: google_maps_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.4"
version: "2.1.5"
google_maps_flutter_platform_interface:
dependency: transitive
description:
@ -552,7 +545,7 @@ packages:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
version: "0.6.4"
latlong2:
dependency: "direct main"
description:
@ -566,7 +559,7 @@ packages:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "2.0.0"
lists:
dependency: transitive
description:
@ -601,7 +594,7 @@ packages:
name: material_color_utilities
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.3"
version: "0.1.4"
material_design_icons_flutter:
dependency: "direct main"
description:
@ -729,12 +722,12 @@ packages:
source: hosted
version: "0.4.0"
path:
dependency: transitive
dependency: "direct main"
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
version: "1.8.1"
path_parsing:
dependency: transitive
description:
@ -748,28 +741,28 @@ packages:
name: path_provider_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
version: "2.1.6"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
version: "2.0.4"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
version: "2.0.6"
pdf:
dependency: "direct main"
description:
name: pdf
url: "https://pub.dartlang.org"
source: hosted
version: "3.7.4"
version: "3.8.0"
percent_indicator:
dependency: "direct main"
description:
@ -818,7 +811,7 @@ packages:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "4.4.0"
version: "5.0.0"
platform:
dependency: transitive
description:
@ -853,7 +846,7 @@ packages:
name: printing
url: "https://pub.dartlang.org"
source: hosted
version: "5.8.0"
version: "5.9.0"
process:
dependency: transitive
description:
@ -930,7 +923,7 @@ packages:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.13"
version: "2.0.15"
shared_preferences_android:
dependency: "direct main"
description:
@ -944,21 +937,21 @@ packages:
name: shared_preferences_ios
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.1.1"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.1.1"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
version: "2.0.4"
shared_preferences_platform_interface:
dependency: transitive
description:
@ -972,14 +965,14 @@ packages:
name: shared_preferences_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
version: "2.0.4"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
version: "2.1.1"
shelf:
dependency: transitive
description:
@ -1033,7 +1026,7 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.1"
version: "1.8.2"
sqflite:
dependency: "direct main"
description:
@ -1112,21 +1105,21 @@ packages:
name: test
url: "https://pub.dartlang.org"
source: hosted
version: "1.19.5"
version: "1.21.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.8"
version: "0.4.9"
test_core:
dependency: transitive
description:
name: test_core
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.9"
version: "0.4.13"
transparent_image:
dependency: "direct main"
description:
@ -1161,35 +1154,35 @@ packages:
name: url_launcher
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.0"
version: "6.1.2"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.16"
version: "6.0.17"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.15"
version: "6.0.16"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
version: "3.0.1"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
version: "3.0.1"
url_launcher_platform_interface:
dependency: transitive
description:
@ -1203,28 +1196,28 @@ packages:
name: url_launcher_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.9"
version: "2.0.11"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0"
version: "3.0.1"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "2.1.2"
vm_service:
dependency: transitive
description:
name: vm_service
url: "https://pub.dartlang.org"
source: hosted
version: "7.5.0"
version: "8.2.2"
watcher:
dependency: transitive
description:
@ -1280,7 +1273,7 @@ packages:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "5.3.1"
version: "5.4.1"
yaml:
dependency: transitive
description:
@ -1289,5 +1282,5 @@ packages:
source: hosted
version: "3.1.0"
sdks:
dart: ">=2.16.2 <3.0.0"
dart: ">=2.17.0 <3.0.0"
flutter: ">=2.10.0"

View file

@ -10,7 +10,7 @@ version: 1.6.4+70
publish_to: none
environment:
sdk: ">=2.16.2 <3.0.0"
sdk: ">=2.17.0 <3.0.0"
# following https://github.blog/2021-09-01-improving-git-protocol-security-github/
# dependency GitHub repos should be referenced via `https://`, not `git://`
@ -62,6 +62,7 @@ dependencies:
palette_generator:
# TODO TLAD as of 2022/02/22, latest version (v0.4.1) has this issue: https://github.com/zesage/panorama/issues/25
panorama: 0.4.0
path:
pdf:
percent_indicator:
permission_handler:

10
scripts/pub_upgrade_all.sh Executable file
View file

@ -0,0 +1,10 @@
#!/bin/bash
cd ..
flutter pub upgrade
cd plugins
for plugin in $(ls -d *); do
cd $plugin
flutter pub upgrade
cd ..
done