fixes: nav bar scroll & highlight + minor

This commit is contained in:
Thibault Deckers 2022-05-19 11:51:13 +09:00
parent 98e54f9dff
commit d4a545ad2a
6 changed files with 63 additions and 84 deletions

View file

@ -32,7 +32,6 @@ class BugReport extends StatefulWidget {
}
class _BugReportState extends State<BugReport> with FeedbackMixin {
final ScrollController _infoScrollController = ScrollController();
late Future<String> _infoLoader;
bool _showInstructions = false;
@ -90,29 +89,13 @@ class _BugReportState extends State<BugReport> with FeedbackMixin {
constraints: const BoxConstraints(maxHeight: 100),
margin: const EdgeInsets.symmetric(vertical: 8),
clipBehavior: Clip.antiAlias,
child: Theme(
data: Theme.of(context).copyWith(
scrollbarTheme: ScrollbarThemeData(
thumbVisibility: MaterialStateProperty.all(true),
radius: const Radius.circular(16),
crossAxisMargin: 6,
mainAxisMargin: 6,
interactive: true,
),
),
child: Scrollbar(
// when using `Scrollbar.isAlwaysShown`, a controller must be provided
// and used by both the `Scrollbar` and the `Scrollable`, but
// as of Flutter v2.8.1, `SelectableText` does not allow passing the `scrollController`
// so we wrap it in a `SingleChildScrollView`
controller: _infoScrollController,
child: SingleChildScrollView(
padding: const EdgeInsetsDirectional.only(start: 8, top: 4, end: 16, bottom: 4),
controller: _infoScrollController,
// to show a scroll bar, we would need to provide a scroll controller
// to both the `Scrollable` and the `Scrollbar`, but
// as of Flutter v3.0.0, `SelectableText` does not allow passing the `scrollController`
child: SelectableText(info),
),
),
),
);
},
),

View file

@ -127,14 +127,22 @@ class _CollectionPageState extends State<CollectionPage> {
),
),
floatingActionButton: appMode == AppMode.pickMultipleMediaExternal && hasSelection
? FloatingActionButton(
? TooltipTheme(
data: TooltipTheme.of(context).copyWith(
preferBelow: false,
),
child: FloatingActionButton(
tooltip: context.l10n.collectionPickPageTitle,
onPressed: () {
final items = context.read<Selection<AvesEntry>>().selectedItems;
final uris = items.map((entry) => entry.uri).toList();
ViewerService.pick(uris);
},
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16)),
),
child: const Icon(AIcons.apply),
),
)
: null,
drawer: AppDrawer(currentCollection: _collection),

View file

@ -3,7 +3,6 @@ import 'dart:math';
import 'package:aves/widgets/common/basic/draggable_scrollbar.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class FloatingNavBar extends StatefulWidget {
final ScrollController? scrollController;
@ -28,11 +27,8 @@ class _FloatingNavBarState extends State<FloatingNavBar> with SingleTickerProvid
late AnimationController _controller;
late Animation<Offset> _offsetAnimation;
double? _lastOffset;
double _delta = 0;
bool _isDragging = false;
static const double _deltaThreshold = 50;
@override
void initState() {
super.initState();
@ -73,7 +69,6 @@ class _FloatingNavBarState extends State<FloatingNavBar> with SingleTickerProvid
void _registerWidget(FloatingNavBar widget) {
_lastOffset = null;
_delta = 0;
widget.scrollController?.addListener(_onScrollChange);
_subscriptions.add(widget.events.listen(_onDraggableScrollBarEvent));
}
@ -98,25 +93,19 @@ class _FloatingNavBarState extends State<FloatingNavBar> with SingleTickerProvid
if (scrollController == null) return;
final offset = scrollController.offset;
_delta += offset - (_lastOffset ?? offset);
final delta = offset - (_lastOffset ?? offset);
_lastOffset = offset;
if (_isDragging) return;
final after = scrollController.position.extentAfter;
double? newValue;
final childHeight = widget.childHeight;
if (after < childHeight && scrollController.position.userScrollDirection == ScrollDirection.reverse) {
_controller.value = min(_controller.value, after / childHeight);
_delta = 0;
return;
}
if (_delta.abs() > _deltaThreshold) {
if (_delta > 0) {
_hide();
} else {
_show();
final after = scrollController.position.extentAfter;
if (after < childHeight && delta > 0) {
newValue = min(_controller.value, after / childHeight);
} else if (!_isDragging || delta > 0) {
newValue = _controller.value + delta / childHeight;
}
if (newValue != null) {
_controller.value = newValue.clamp(0.0, 1.0);
}
}
@ -124,22 +113,10 @@ class _FloatingNavBarState extends State<FloatingNavBar> with SingleTickerProvid
switch (event) {
case DraggableScrollBarEvent.dragStart:
_isDragging = true;
_hide();
break;
case DraggableScrollBarEvent.dragEnd:
_isDragging = false;
_show();
break;
}
}
void _show() {
_controller.reverse();
_delta = 0;
}
void _hide() {
_controller.forward();
_delta = 0;
}
}

View file

@ -15,19 +15,26 @@ import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class AppBottomNavBar extends StatelessWidget {
class AppBottomNavBar extends StatefulWidget {
final Stream<DraggableScrollBarEvent> events;
// collection loaded in the `CollectionPage`, if any
final CollectionLens? currentCollection;
static double get height => kBottomNavigationBarHeight + AvesFloatingBar.margin.vertical;
const AppBottomNavBar({
super.key,
required this.events,
this.currentCollection,
});
static double get height => kBottomNavigationBarHeight + AvesFloatingBar.margin.vertical;
@override
State<AppBottomNavBar> createState() => _AppBottomNavBarState();
}
class _AppBottomNavBarState extends State<AppBottomNavBar> {
String? _lastRoute;
@override
Widget build(BuildContext context) {
@ -68,8 +75,8 @@ class AppBottomNavBar extends StatelessWidget {
},
child: FloatingNavBar(
scrollController: PrimaryScrollController.of(context),
events: events,
childHeight: height + context.select<MediaQueryData, double>((mq) => mq.effectiveBottomPadding),
events: widget.events,
childHeight: AppBottomNavBar.height + context.select<MediaQueryData, double>((mq) => mq.effectiveBottomPadding),
child: SafeArea(
child: child,
),
@ -78,13 +85,16 @@ class AppBottomNavBar extends StatelessWidget {
}
int _getCurrentIndex(BuildContext context, List<AvesBottomNavItem> items) {
final currentRoute = context.currentRouteName;
// current route may be null during navigation
final currentRoute = context.currentRouteName ?? _lastRoute;
_lastRoute = currentRoute;
final currentItem = items.firstWhereOrNull((item) {
if (currentRoute != item.route) return false;
if (item.route != CollectionPage.routeName) return true;
final currentFilters = currentCollection?.filters;
final currentFilters = widget.currentCollection?.filters;
if (currentFilters == null || currentFilters.length > 1) return false;
return currentFilters.firstOrNull == item.filter;
});

View file

@ -203,6 +203,7 @@ class _EntryGoogleMapState<T> extends State<EntryGoogleMap<T>> with WidgetsBindi
myLocationEnabled: false,
myLocationButtonEnabled: false,
markers: {
// TODO TLAD workaround for dot location marker not showing the last value until this is fixed: https://github.com/flutter/flutter/issues/103686
...markers,
if (dotLocation != null && _dotMarkerBitmap != null)
Marker(

View file

@ -7,14 +7,14 @@ packages:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "39.0.0"
version: "40.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
version: "4.1.0"
archive:
dependency: transitive
description:
@ -296,7 +296,7 @@ packages:
name: ffi
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
version: "1.2.1"
fijkplayer:
dependency: "direct main"
description:
@ -319,35 +319,35 @@ packages:
name: firebase_core
url: "https://pub.dartlang.org"
source: hosted
version: "1.16.0"
version: "1.17.0"
firebase_core_platform_interface:
dependency: transitive
description:
name: firebase_core_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "4.3.0"
version: "4.4.0"
firebase_core_web:
dependency: transitive
description:
name: firebase_core_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.3"
version: "1.6.4"
firebase_crashlytics:
dependency: transitive
description:
name: firebase_crashlytics
url: "https://pub.dartlang.org"
source: hosted
version: "2.7.2"
version: "2.8.0"
firebase_crashlytics_platform_interface:
dependency: transitive
description:
name: firebase_crashlytics_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "3.2.5"
version: "3.2.6"
flex_color_picker:
dependency: "direct main"
description:
@ -449,7 +449,7 @@ packages:
name: frontend_server_client
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
version: "2.1.3"
fuchsia_remote_debug_protocol:
dependency: transitive
description: flutter
@ -517,7 +517,7 @@ packages:
name: http_parser
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
version: "4.0.1"
image:
dependency: transitive
description:
@ -657,7 +657,7 @@ packages:
name: overlay_support
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.1"
version: "2.0.0"
package_config:
dependency: transitive
description:
@ -769,7 +769,7 @@ packages:
name: percent_indicator
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.1"
version: "4.2.2"
permission_handler:
dependency: "direct main"
description:
@ -1259,7 +1259,7 @@ packages:
name: win32
url: "https://pub.dartlang.org"
source: hosted
version: "2.5.2"
version: "2.6.1"
wkt_parser:
dependency: transitive
description:
@ -1287,7 +1287,7 @@ packages:
name: yaml
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
version: "3.1.1"
sdks:
dart: ">=2.17.0 <3.0.0"
flutter: ">=2.10.0"
flutter: ">=2.12.0"