updates
This commit is contained in:
parent
981b4836f9
commit
ed910748cb
34 changed files with 2054 additions and 153 deletions
|
|
@ -7,11 +7,12 @@ import '../screens/connect_sheet.dart';
|
|||
import '../screens/home_screen.dart';
|
||||
import '../screens/now_playing_screen.dart';
|
||||
import '../screens/settings_screen.dart';
|
||||
import '../settings/settings_store.dart';
|
||||
import '../state/providers.dart';
|
||||
import '../theme/tokens.dart';
|
||||
import '../widgets/mini_player.dart';
|
||||
|
||||
/// Top-level shell: the three Ratune tabs (Home / Browse / Now Playing) with a
|
||||
/// Top-level shell: the three Timbre tabs (Home / Browse / Now Playing) with a
|
||||
/// bottom tab bar and a status bar, mirroring the terminal layout.
|
||||
class AppShell extends ConsumerStatefulWidget {
|
||||
const AppShell({super.key});
|
||||
|
|
@ -29,12 +30,39 @@ class _AppShellState extends ConsumerState<AppShell> {
|
|||
final _homeNavKey = GlobalKey<NavigatorState>();
|
||||
final _browseNavKey = GlobalKey<NavigatorState>();
|
||||
|
||||
// Seed the Browse view from the persisted default exactly once, when settings
|
||||
// finish loading. Guarded so a later change to the default (or a manual browse
|
||||
// selection) is never overridden mid-session.
|
||||
bool _browseSeeded = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
ref.listenManual<AppSettings>(settingsProvider, (prev, next) {
|
||||
if (_browseSeeded) return;
|
||||
_browseSeeded = true;
|
||||
ref.read(browseModeProvider.notifier).state = next.defaultBrowseMode;
|
||||
});
|
||||
}
|
||||
|
||||
GlobalKey<NavigatorState>? _navKeyForTab(int tab) => switch (tab) {
|
||||
0 => _homeNavKey,
|
||||
1 => _browseNavKey,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
/// Tap on the bottom tab bar. Selecting a different tab just switches; tapping
|
||||
/// the already-active tab resets it to its root — popping the nested detail
|
||||
/// stack (e.g. Album → Browse home) so the tab button doubles as "go back to
|
||||
/// the top", instead of being a no-op.
|
||||
void _selectTab(int tapped, int current) {
|
||||
if (tapped == current) {
|
||||
_navKeyForTab(tapped)?.currentState?.popUntil((r) => r.isFirst);
|
||||
} else {
|
||||
ref.read(selectedTabProvider.notifier).state = tapped;
|
||||
}
|
||||
}
|
||||
|
||||
/// Android system-back: pop the active tab's nested stack first, then fall
|
||||
/// back to Home, and only exit the app from the Home root.
|
||||
void _handleBack(int tab) {
|
||||
|
|
@ -88,8 +116,7 @@ class _AppShellState extends ConsumerState<AppShell> {
|
|||
_TabBar(
|
||||
tabs: _tabs,
|
||||
index: index,
|
||||
onSelect: (i) =>
|
||||
ref.read(selectedTabProvider.notifier).state = i,
|
||||
onSelect: (i) => _selectTab(i, index),
|
||||
),
|
||||
const _StatusBar(),
|
||||
],
|
||||
|
|
@ -201,10 +228,10 @@ class _StatusBar extends ConsumerWidget {
|
|||
color: TimbreColors.surface,
|
||||
child: Row(
|
||||
children: [
|
||||
// Left: connection status — tap to open the connect sheet.
|
||||
// Left: connection status — tap to open the server switcher.
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
onTap: () => showConnectSheet(context),
|
||||
onTap: () => showServerSheet(context),
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: TimbreSpacing.lg),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue