diff --git a/flutter_client/lib/app.dart b/flutter_client/lib/app.dart index 2c9a5160..40f4ce8c 100644 --- a/flutter_client/lib/app.dart +++ b/flutter_client/lib/app.dart @@ -1,5 +1,8 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'cache/cache_filler.dart'; import 'cache/metadata_prefetcher.dart'; @@ -77,6 +80,14 @@ class _MinstrelAppState extends ConsumerState { // probe → offlineProvider. Read here to start the poller; S4 // gates system-playlist play + Shuffle-all on it. ref.read(offlineProvider); + // POST_NOTIFICATIONS (Android 13+) is denied-by-default until + // requested; without it the media notification is silently + // suppressed on physical devices. One-shot, post-first-frame so + // it never blocks launch; no-op on <13 / once already decided. + if (Platform.isAndroid) { + // ignore: unawaited_futures + Permission.notification.request(); + } }); } diff --git a/flutter_client/lib/player/now_playing_screen.dart b/flutter_client/lib/player/now_playing_screen.dart index 95817b8f..9301e477 100644 --- a/flutter_client/lib/player/now_playing_screen.dart +++ b/flutter_client/lib/player/now_playing_screen.dart @@ -222,6 +222,14 @@ class _NowPlayingScreenState extends ConsumerState { _displayedDominant = null; _pendingPreloadId = null; }); + // Session was torn down (#52 idle/dismiss) while the full + // player was open. Don't strand the user on an empty + // "Nothing playing." screen — minimize back (the mini bar is + // already gone too). maybePop is a no-op if this is somehow + // the root route. + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) Navigator.of(context).maybePop(); + }); } return; } diff --git a/flutter_client/pubspec.yaml b/flutter_client/pubspec.yaml index 0c425aeb..30c98a22 100644 --- a/flutter_client/pubspec.yaml +++ b/flutter_client/pubspec.yaml @@ -25,6 +25,9 @@ dependencies: # Lucide icon set (design system mandates Lucide, not Material). # Icons exposed as LucideIcons. IconData usable in Icon(). flutter_lucide: ^1.11.0 + # Runtime POST_NOTIFICATIONS request (Android 13+ denies-by-default + # until asked; the media notification is suppressed without it). + permission_handler: ^12.0.1 google_fonts: ^8.1.0 # 10.x conflicts with flutter_secure_storage 10.x on win32. Hold at 8.3.1 # until either lib bumps win32 to 6.x.