mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-09-29 12:52:13 +02:00
fix(navigation): preserve compact state and active icon colors
This commit is contained in:
@@ -8,8 +8,8 @@ import 'package:spotiflac_android/theme/mornye_theme.dart';
|
||||
import 'package:spotiflac_android/widgets/mini_player.dart';
|
||||
import 'package:spotiflac_android/widgets/mornye_chrome.dart';
|
||||
|
||||
/// Only deliberate vertical drags change the chrome. Horizontal artwork rows,
|
||||
/// programmatic scrolling and edge bounce must not minimize the navigation.
|
||||
/// Deliberate vertical drags minimize the chrome until the page returns to its
|
||||
/// top. Horizontal rows, programmatic scrolling and bounce must not minimize it.
|
||||
class MornyeChromeController extends ValueNotifier<bool> {
|
||||
MornyeChromeController() : super(false);
|
||||
|
||||
@@ -30,16 +30,22 @@ class MornyeChromeController extends ValueNotifier<bool> {
|
||||
notification is ScrollEndNotification) {
|
||||
_distance = 0;
|
||||
}
|
||||
if (notification is! ScrollUpdateNotification ||
|
||||
notification.dragDetails == null) {
|
||||
return false;
|
||||
}
|
||||
if (notification is! ScrollUpdateNotification) return false;
|
||||
final metrics = notification.metrics;
|
||||
if (metrics.pixels <= metrics.minScrollExtent + 12) {
|
||||
// The Library list can reach its start while its outer header is still
|
||||
// collapsed. Restore the tabs only when both scroll positions return.
|
||||
final outer = notification.context
|
||||
?.findAncestorStateOfType<NestedScrollViewState>()
|
||||
?.outerController;
|
||||
if (outer != null &&
|
||||
outer.positions.any((p) => p.pixels > p.minScrollExtent + 12)) {
|
||||
return false;
|
||||
}
|
||||
expand();
|
||||
return false;
|
||||
}
|
||||
if (metrics.outOfRange) return false;
|
||||
if (metrics.outOfRange || notification.dragDetails == null) return false;
|
||||
final delta = notification.scrollDelta ?? 0;
|
||||
if (delta == 0) return false;
|
||||
if (_distance.sign != delta.sign) _distance = 0;
|
||||
@@ -47,8 +53,6 @@ class MornyeChromeController extends ValueNotifier<bool> {
|
||||
if (_distance >= 28) {
|
||||
value = true;
|
||||
_distance = 0;
|
||||
} else if (_distance <= -18) {
|
||||
expand();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -199,13 +203,9 @@ class MornyeBottomBar extends ConsumerWidget {
|
||||
width: size,
|
||||
height: size,
|
||||
),
|
||||
color: Color.lerp(
|
||||
index == selectedIndex
|
||||
? scheme.primary
|
||||
: inactiveIconColor,
|
||||
scheme.primary,
|
||||
amount,
|
||||
),
|
||||
color: index == selectedIndex
|
||||
? scheme.primary
|
||||
: inactiveIconColor,
|
||||
icon: Opacity(
|
||||
opacity: amount == 0 ? 0 : 1,
|
||||
child: destinations[index].icon,
|
||||
|
||||
@@ -136,8 +136,14 @@ void main() {
|
||||
) async {
|
||||
final activeTab = ValueNotifier(0);
|
||||
addTearDown(activeTab.dispose);
|
||||
await pumpShell(tester, blur: blur, activeTab: activeTab);
|
||||
final primary = MornyeTheme.build(Brightness.light).colorScheme.primary;
|
||||
await pumpShell(
|
||||
tester,
|
||||
blur: blur,
|
||||
activeTab: activeTab,
|
||||
brightness: Brightness.dark,
|
||||
);
|
||||
final scheme = MornyeTheme.build(Brightness.dark).colorScheme;
|
||||
final primary = scheme.primary;
|
||||
Color? iconColor(String key, IconData data) {
|
||||
final icon = find.descendant(
|
||||
of: find.byKey(ValueKey(key)),
|
||||
@@ -186,11 +192,11 @@ void main() {
|
||||
2 => Icons.grid_view,
|
||||
_ => Icons.home,
|
||||
}),
|
||||
index == 3 ? isNot(primary) : primary,
|
||||
index == 3 ? scheme.onSurface : primary,
|
||||
);
|
||||
expect(
|
||||
iconColor('mornye-compact-search', Icons.search),
|
||||
index == 3 ? primary : isNot(primary),
|
||||
index == 3 ? primary : scheme.onSurface,
|
||||
);
|
||||
final movingIcon = switch (index) {
|
||||
1 => Icons.music_note,
|
||||
@@ -221,6 +227,14 @@ void main() {
|
||||
{index == 3 ? 0 : index, 3},
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
iconColor('mornye-compact-leading', movingIcon),
|
||||
index == 3 ? scheme.onSurface : primary,
|
||||
);
|
||||
expect(
|
||||
iconColor('mornye-compact-search', Icons.search),
|
||||
index == 3 ? primary : scheme.onSurface,
|
||||
);
|
||||
expect(
|
||||
tester.widget<IconButton>(leading).tooltip,
|
||||
index == 3 ? 'Home' : label,
|
||||
@@ -608,7 +622,7 @@ void main() {
|
||||
}
|
||||
|
||||
testWidgets(
|
||||
'scrolling up expands; programmatic and horizontal movement do not collapse',
|
||||
'compact tabs survive upward scrolling until the page returns to the top',
|
||||
(tester) async {
|
||||
await pumpShell(tester);
|
||||
scroll.jumpTo(500);
|
||||
@@ -622,11 +636,14 @@ void main() {
|
||||
expect(chrome.value, isTrue);
|
||||
await tester.drag(find.byType(ListView), const Offset(0, 90));
|
||||
await tester.pumpAndSettle();
|
||||
expect(chrome.value, isTrue);
|
||||
await tester.drag(find.byType(ListView), const Offset(0, 900));
|
||||
await tester.pumpAndSettle();
|
||||
expect(chrome.value, isFalse);
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets('Library inner scrolling expands before the header returns', (
|
||||
testWidgets('Library keeps compact tabs until the outer header returns', (
|
||||
tester,
|
||||
) async {
|
||||
await pumpShell(
|
||||
@@ -651,6 +668,9 @@ void main() {
|
||||
expect(chrome.value, isTrue);
|
||||
await tester.drag(find.byType(ListView), const Offset(0, 100));
|
||||
await tester.pumpAndSettle();
|
||||
expect(chrome.value, isTrue);
|
||||
await tester.drag(find.byType(ListView), const Offset(0, 900));
|
||||
await tester.pumpAndSettle();
|
||||
expect(chrome.value, isFalse);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user