Skip to content

Commit bd6c620

Browse files
committed
refactor: simplify recent changes
1 parent 29ea0cc commit bd6c620

2 files changed

Lines changed: 108 additions & 111 deletions

File tree

lib/screens/bottom_navigation_page.dart

Lines changed: 107 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -30,101 +30,110 @@ import 'package:musify/services/settings_manager.dart';
3030
import 'package:musify/widgets/mini_player.dart';
3131

3232
class BottomNavigationPage extends StatefulWidget {
33-
const BottomNavigationPage({
34-
required this.child,
35-
this.isOfflineMode = false,
36-
super.key,
37-
});
33+
const BottomNavigationPage({required this.child, super.key});
3834

3935
final StatefulNavigationShell child;
40-
final bool isOfflineMode;
4136

4237
@override
4338
State<BottomNavigationPage> createState() => _BottomNavigationPageState();
4439
}
4540

4641
class _BottomNavigationPageState extends State<BottomNavigationPage> {
42+
bool? _previousOfflineMode;
43+
4744
@override
4845
Widget build(BuildContext context) {
49-
return LayoutBuilder(
50-
builder: (context, constraints) {
51-
final isLargeScreen = MediaQuery.of(context).size.width >= 600;
52-
final items = _getNavigationItems;
46+
return ValueListenableBuilder<bool>(
47+
valueListenable: offlineMode,
48+
builder: (context, isOfflineMode, _) {
49+
// Handle offline mode changes
50+
if (_previousOfflineMode != null &&
51+
_previousOfflineMode != isOfflineMode) {
52+
SchedulerBinding.instance.addPostFrameCallback((_) {
53+
_handleOfflineModeChange(isOfflineMode);
54+
});
55+
}
56+
_previousOfflineMode = isOfflineMode;
57+
58+
return LayoutBuilder(
59+
builder: (context, constraints) {
60+
final isLargeScreen = MediaQuery.of(context).size.width >= 600;
61+
final items = _getNavigationItems(isOfflineMode);
5362

54-
return Scaffold(
55-
body: SafeArea(
56-
child: Row(
57-
children: [
58-
if (isLargeScreen)
59-
NavigationRail(
60-
labelType: NavigationRailLabelType.selected,
61-
destinations:
62-
items
63-
.map(
64-
(item) => NavigationRailDestination(
65-
icon: Icon(item.icon),
66-
selectedIcon: Icon(item.icon),
67-
label: Text(item.label),
68-
),
69-
)
70-
.toList(),
71-
selectedIndex: _getCurrentIndex,
72-
onDestinationSelected: _onTabTapped,
73-
),
74-
Expanded(
75-
child: Column(
76-
children: [
77-
Expanded(child: widget.child),
78-
StreamBuilder<MediaItem?>(
79-
stream: audioHandler.mediaItem.distinct((prev, curr) {
80-
if (prev == null || curr == null) return false;
81-
return prev.id == curr.id &&
82-
prev.title == curr.title &&
83-
prev.artist == curr.artist &&
84-
prev.artUri == curr.artUri;
85-
}),
86-
builder: (context, snapshot) {
87-
final metadata = snapshot.data;
88-
if (metadata == null) {
89-
return const SizedBox.shrink();
90-
}
91-
return MiniPlayer(metadata: metadata);
92-
},
63+
return Scaffold(
64+
body: SafeArea(
65+
child: Row(
66+
children: [
67+
if (isLargeScreen)
68+
NavigationRail(
69+
labelType: NavigationRailLabelType.selected,
70+
destinations:
71+
items
72+
.map(
73+
(item) => NavigationRailDestination(
74+
icon: Icon(item.icon),
75+
selectedIcon: Icon(item.selectedIcon),
76+
label: Text(item.label),
77+
),
78+
)
79+
.toList(),
80+
selectedIndex: _getCurrentIndex(items, isOfflineMode),
81+
onDestinationSelected:
82+
(index) => _onTabTapped(index, items),
9383
),
94-
],
95-
),
84+
Expanded(
85+
child: Column(
86+
children: [
87+
Expanded(child: widget.child),
88+
StreamBuilder<MediaItem?>(
89+
stream: audioHandler.mediaItem.distinct(
90+
_mediaItemEquals,
91+
),
92+
builder: (context, snapshot) {
93+
final metadata = snapshot.data;
94+
if (metadata == null) {
95+
return const SizedBox.shrink();
96+
}
97+
return MiniPlayer(metadata: metadata);
98+
},
99+
),
100+
],
101+
),
102+
),
103+
],
96104
),
97-
],
98-
),
99-
),
100-
bottomNavigationBar:
101-
!isLargeScreen
102-
? NavigationBar(
103-
selectedIndex: _getCurrentIndex,
104-
labelBehavior:
105-
languageSetting == const Locale('en', '')
106-
? NavigationDestinationLabelBehavior
107-
.onlyShowSelected
108-
: NavigationDestinationLabelBehavior.alwaysHide,
109-
onDestinationSelected: _onTabTapped,
110-
destinations:
111-
items
112-
.map(
113-
(item) => NavigationDestination(
114-
icon: Icon(item.icon),
115-
selectedIcon: Icon(item.icon),
116-
label: item.label,
117-
),
118-
)
119-
.toList(),
120-
)
121-
: null,
105+
),
106+
bottomNavigationBar:
107+
!isLargeScreen
108+
? NavigationBar(
109+
selectedIndex: _getCurrentIndex(items, isOfflineMode),
110+
labelBehavior:
111+
languageSetting == const Locale('en', '')
112+
? NavigationDestinationLabelBehavior
113+
.onlyShowSelected
114+
: NavigationDestinationLabelBehavior.alwaysHide,
115+
onDestinationSelected:
116+
(index) => _onTabTapped(index, items),
117+
destinations:
118+
items
119+
.map(
120+
(item) => NavigationDestination(
121+
icon: Icon(item.icon),
122+
selectedIcon: Icon(item.selectedIcon),
123+
label: item.label,
124+
),
125+
)
126+
.toList(),
127+
)
128+
: null,
129+
);
130+
},
122131
);
123132
},
124133
);
125134
}
126135

127-
List<_NavigationItem> get _getNavigationItems {
136+
List<_NavigationItem> _getNavigationItems(bool isOfflineMode) {
128137
final items = <_NavigationItem>[
129138
_NavigationItem(
130139
icon: FluentIcons.home_24_regular,
@@ -136,7 +145,7 @@ class _BottomNavigationPageState extends State<BottomNavigationPage> {
136145
];
137146

138147
// Only add search tab in online mode
139-
if (!widget.isOfflineMode) {
148+
if (!isOfflineMode) {
140149
items.add(
141150
_NavigationItem(
142151
icon: FluentIcons.search_24_regular,
@@ -149,8 +158,8 @@ class _BottomNavigationPageState extends State<BottomNavigationPage> {
149158
}
150159

151160
// Adjust indices based on whether search is included
152-
final libraryIndex = widget.isOfflineMode ? 1 : 2;
153-
final settingsIndex = widget.isOfflineMode ? 2 : 3;
161+
final libraryIndex = isOfflineMode ? 1 : 2;
162+
final settingsIndex = isOfflineMode ? 2 : 3;
154163

155164
items.addAll([
156165
_NavigationItem(
@@ -172,41 +181,27 @@ class _BottomNavigationPageState extends State<BottomNavigationPage> {
172181
return items;
173182
}
174183

175-
@override
176-
void didUpdateWidget(BottomNavigationPage oldWidget) {
177-
super.didUpdateWidget(oldWidget);
184+
void _handleOfflineModeChange(bool isOfflineMode) {
185+
if (!mounted) return;
178186

179-
// Handle offline mode transition
180-
if (oldWidget.isOfflineMode != widget.isOfflineMode) {
181-
_handleOfflineModeChange();
182-
}
183-
}
184-
185-
void _handleOfflineModeChange() {
186187
final currentRoute = GoRouterState.of(context).matchedLocation;
187188

188189
// If we're switching to offline mode and currently on search tab
189-
if (widget.isOfflineMode && currentRoute.startsWith('/search')) {
190+
if (isOfflineMode && currentRoute.startsWith('/search')) {
190191
// Navigate to home
191-
SchedulerBinding.instance.addPostFrameCallback((_) {
192-
if (mounted) {
193-
widget.child.goBranch(0);
194-
}
195-
});
192+
widget.child.goBranch(0);
196193
}
197194
}
198195

199-
void _onTabTapped(int index) {
200-
final items = _getNavigationItems;
196+
void _onTabTapped(int index, List<_NavigationItem> items) {
201197
if (index < items.length) {
202198
final item = items[index];
203199
// Use the shell navigation index instead of the route
204200
widget.child.goBranch(item.shellIndex);
205201
}
206202
}
207203

208-
int get _getCurrentIndex {
209-
final items = _getNavigationItems;
204+
int _getCurrentIndex(List<_NavigationItem> items, bool isOfflineMode) {
210205
final currentIndex = widget.child.currentIndex;
211206

212207
// Add bounds checking
@@ -222,16 +217,26 @@ class _BottomNavigationPageState extends State<BottomNavigationPage> {
222217
}
223218

224219
// Handle edge cases more robustly
225-
if (widget.isOfflineMode && currentIndex == 1) {
220+
if (isOfflineMode && currentIndex == 1) {
226221
return 0; // Search -> Home
227222
}
228223

229-
if (widget.isOfflineMode && currentIndex > 1) {
224+
if (isOfflineMode && currentIndex > 1) {
230225
return (currentIndex - 1).clamp(0, items.length - 1);
231226
}
232227

233228
return currentIndex.clamp(0, items.length - 1);
234229
}
230+
231+
static bool _mediaItemEquals(MediaItem? prev, MediaItem? curr) {
232+
if (prev == curr) return true;
233+
if (prev == null || curr == null) return false;
234+
235+
return prev.id == curr.id &&
236+
prev.title == curr.title &&
237+
prev.artist == curr.artist &&
238+
prev.artUri == curr.artUri;
239+
}
235240
}
236241

237242
class _NavigationItem {

lib/services/router_service.dart

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,7 @@ class NavigationManager {
4949
branches: _getRouteBranches(),
5050
pageBuilder: (context, state, navigationShell) {
5151
return getPage(
52-
child: ValueListenableBuilder<bool>(
53-
valueListenable: offlineMode,
54-
builder: (context, isOffline, _) {
55-
return BottomNavigationPage(
56-
isOfflineMode: isOffline,
57-
child: navigationShell,
58-
);
59-
},
60-
),
52+
child: BottomNavigationPage(child: navigationShell),
6153
state: state,
6254
);
6355
},

0 commit comments

Comments
 (0)