mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-28 14:58:59 +02:00
fix(navigation): open download queue from snackbar actions
This commit is contained in:
@@ -30,6 +30,7 @@ import 'package:spotiflac_android/utils/clickable_metadata.dart';
|
||||
import 'package:spotiflac_android/widgets/cached_cover_image.dart';
|
||||
import 'package:spotiflac_android/widgets/motion_header_banner.dart';
|
||||
import 'package:spotiflac_android/widgets/cross_extension_share_sheet.dart';
|
||||
import 'package:spotiflac_android/widgets/view_queue_snackbar_action.dart';
|
||||
|
||||
class _ArtistCache {
|
||||
static final _cache = TtlCache<_CacheEntry>(const Duration(minutes: 10));
|
||||
@@ -1055,10 +1056,7 @@ class _ArtistScreenState extends ConsumerState<ArtistScreen>
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(message),
|
||||
action: SnackBarAction(
|
||||
label: context.l10n.snackbarViewQueue,
|
||||
onPressed: () {},
|
||||
),
|
||||
action: buildViewQueueSnackBarAction(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import 'package:spotiflac_android/widgets/error_card.dart';
|
||||
import 'package:spotiflac_android/widgets/in_library_badge.dart';
|
||||
import 'package:spotiflac_android/widgets/preview_button.dart';
|
||||
import 'package:spotiflac_android/widgets/settings_group.dart';
|
||||
import 'package:spotiflac_android/widgets/view_queue_snackbar_action.dart';
|
||||
|
||||
part 'home_tab_helpers.dart';
|
||||
part 'home_tab_widgets.dart';
|
||||
@@ -1077,10 +1078,7 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
ScaffoldMessenger.of(this.context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(queueSnackbarMessage),
|
||||
action: SnackBarAction(
|
||||
label: l10n.snackbarViewQueue,
|
||||
onPressed: () {},
|
||||
),
|
||||
action: buildViewQueueSnackBarAction(this.context),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1109,10 +1107,7 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
ScaffoldMessenger.of(this.context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(queueSnackbarMessage),
|
||||
action: SnackBarAction(
|
||||
label: l10n.snackbarViewQueue,
|
||||
onPressed: () {},
|
||||
),
|
||||
action: buildViewQueueSnackBarAction(this.context),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -105,6 +105,10 @@ class _MainShellState extends ConsumerState<MainShell>
|
||||
duration: const Duration(milliseconds: 180),
|
||||
value: 1,
|
||||
);
|
||||
ShellNavigationService.registerTabSelectionHandler(
|
||||
owner: this,
|
||||
handler: _onShellTabRequested,
|
||||
);
|
||||
ShellNavigationService.syncState(
|
||||
currentTabIndex: _currentIndex,
|
||||
showRepoTab: false,
|
||||
@@ -433,6 +437,7 @@ class _MainShellState extends ConsumerState<MainShell>
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
ShellNavigationService.unregisterTabSelectionHandler(this);
|
||||
_shareSubscription?.cancel();
|
||||
_pageController.dispose();
|
||||
_tabJumpTransitionController.dispose();
|
||||
@@ -452,6 +457,19 @@ class _MainShellState extends ConsumerState<MainShell>
|
||||
ref.read(trackProvider.notifier).clear();
|
||||
}
|
||||
|
||||
void _onShellTabRequested(ShellTab tab) {
|
||||
final showStore = ref.read(
|
||||
settingsProvider.select((s) => s.showExtensionStore),
|
||||
);
|
||||
final index = switch (tab) {
|
||||
ShellTab.home => 0,
|
||||
ShellTab.library => 1,
|
||||
ShellTab.repository => showStore ? 2 : null,
|
||||
ShellTab.settings => showStore ? 3 : 2,
|
||||
};
|
||||
if (index != null) _onNavTap(index);
|
||||
}
|
||||
|
||||
void _onNavTap(int index) {
|
||||
if (index == 0 && _currentIndex == 0) {
|
||||
_resetHomeToMain();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
enum ShellTab { home, library, repository, settings }
|
||||
|
||||
class ShellNavigationService {
|
||||
static final GlobalKey<NavigatorState> homeTabNavigatorKey =
|
||||
GlobalKey<NavigatorState>();
|
||||
@@ -10,6 +12,29 @@ class ShellNavigationService {
|
||||
|
||||
static int _currentTabIndex = 0;
|
||||
static bool _showRepoTab = false;
|
||||
static Object? _tabSelectionOwner;
|
||||
static ValueChanged<ShellTab>? _tabSelectionHandler;
|
||||
|
||||
static void registerTabSelectionHandler({
|
||||
required Object owner,
|
||||
required ValueChanged<ShellTab> handler,
|
||||
}) {
|
||||
_tabSelectionOwner = owner;
|
||||
_tabSelectionHandler = handler;
|
||||
}
|
||||
|
||||
static void unregisterTabSelectionHandler(Object owner) {
|
||||
if (!identical(_tabSelectionOwner, owner)) return;
|
||||
_tabSelectionOwner = null;
|
||||
_tabSelectionHandler = null;
|
||||
}
|
||||
|
||||
static bool requestTab(ShellTab tab) {
|
||||
final handler = _tabSelectionHandler;
|
||||
if (handler == null) return false;
|
||||
handler(tab);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void syncState({
|
||||
required int currentTabIndex,
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:spotiflac_android/l10n/l10n.dart';
|
||||
import 'package:spotiflac_android/services/shell_navigation_service.dart';
|
||||
|
||||
SnackBarAction buildViewQueueSnackBarAction(BuildContext context) {
|
||||
return SnackBarAction(
|
||||
label: context.l10n.snackbarViewQueue,
|
||||
onPressed: () {
|
||||
ShellNavigationService.requestTab(ShellTab.library);
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:spotiflac_android/l10n/app_localizations.dart';
|
||||
import 'package:spotiflac_android/services/shell_navigation_service.dart';
|
||||
import 'package:spotiflac_android/widgets/view_queue_snackbar_action.dart';
|
||||
|
||||
void main() {
|
||||
group('ShellNavigationService tab requests', () {
|
||||
test('forwards a named tab request to the registered shell', () {
|
||||
final owner = Object();
|
||||
ShellTab? requestedTab;
|
||||
addTearDown(
|
||||
() => ShellNavigationService.unregisterTabSelectionHandler(owner),
|
||||
);
|
||||
|
||||
ShellNavigationService.registerTabSelectionHandler(
|
||||
owner: owner,
|
||||
handler: (tab) => requestedTab = tab,
|
||||
);
|
||||
|
||||
expect(ShellNavigationService.requestTab(ShellTab.library), isTrue);
|
||||
expect(requestedTab, ShellTab.library);
|
||||
});
|
||||
|
||||
test('does not remove a newer shell handler', () {
|
||||
final oldOwner = Object();
|
||||
final currentOwner = Object();
|
||||
ShellTab? requestedTab;
|
||||
addTearDown(
|
||||
() =>
|
||||
ShellNavigationService.unregisterTabSelectionHandler(currentOwner),
|
||||
);
|
||||
|
||||
ShellNavigationService.registerTabSelectionHandler(
|
||||
owner: oldOwner,
|
||||
handler: (_) {},
|
||||
);
|
||||
ShellNavigationService.registerTabSelectionHandler(
|
||||
owner: currentOwner,
|
||||
handler: (tab) => requestedTab = tab,
|
||||
);
|
||||
|
||||
ShellNavigationService.unregisterTabSelectionHandler(oldOwner);
|
||||
|
||||
expect(ShellNavigationService.requestTab(ShellTab.settings), isTrue);
|
||||
expect(requestedTab, ShellTab.settings);
|
||||
});
|
||||
|
||||
test('reports when no shell can handle the request', () {
|
||||
final owner = Object();
|
||||
ShellNavigationService.registerTabSelectionHandler(
|
||||
owner: owner,
|
||||
handler: (_) {},
|
||||
);
|
||||
ShellNavigationService.unregisterTabSelectionHandler(owner);
|
||||
|
||||
expect(ShellNavigationService.requestTab(ShellTab.library), isFalse);
|
||||
});
|
||||
|
||||
testWidgets('View Queue snackbar action requests the Library tab', (
|
||||
tester,
|
||||
) async {
|
||||
final owner = Object();
|
||||
ShellTab? requestedTab;
|
||||
addTearDown(
|
||||
() => ShellNavigationService.unregisterTabSelectionHandler(owner),
|
||||
);
|
||||
ShellNavigationService.registerTabSelectionHandler(
|
||||
owner: owner,
|
||||
handler: (tab) => requestedTab = tab,
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
home: Scaffold(
|
||||
body: Builder(
|
||||
builder: (context) => buildViewQueueSnackBarAction(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.tap(find.text('View Queue'));
|
||||
|
||||
expect(requestedTab, ShellTab.library);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user