Skip to content

Commit 674c4f2

Browse files
committed
FIX: Remove duplicate _notifyQueueChanged call on non-current-song queue removal to prevent redundant UI rebuilds, move wasCurrentSong queue notification after player stop for correct UI state during track transition
1 parent 9a5510d commit 674c4f2

3 files changed

Lines changed: 104 additions & 104 deletions

File tree

lib/core/utils/audio_player_service.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ class AudioPlayerService {
159159

160160
if (isYoutube) {
161161
final prefs = await SharedPreferences.getInstance();
162-
final useYoutube = prefs.getBool('use_youtube_service') ?? true;
162+
final useYoutube = prefs.getBool('use_youtube_service') ?? false;
163163
if (!useYoutube) {
164164
throw StateError('YouTube streaming disabled by user');
165165
}
@@ -1144,7 +1144,6 @@ class AudioPlayerService {
11441144

11451145
_queue = List.unmodifiable(newQueue);
11461146
_prefetchedForIndex = null;
1147-
_notifyQueueChanged();
11481147

11491148
int newIndex = _currentIndex;
11501149
if (wasCurrentSong) {
@@ -1154,6 +1153,7 @@ class AudioPlayerService {
11541153
++_playToken;
11551154
await _player.stop();
11561155
_trackLoading.add(false);
1156+
_notifyQueueChanged();
11571157

11581158
if (newIndex >= 0 && newIndex < newQueue.length) {
11591159
_currentIndex = newIndex;

lib/features/home/home_screen.dart

Lines changed: 88 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,26 @@ class _HomeScreenState extends State<HomeScreen> {
1919
int _index = 0;
2020
int _searchScreenVersion = 0;
2121

22+
bool _useYoutube = false;
23+
bool _useSaavn = false;
24+
25+
@override
26+
void initState() {
27+
super.initState();
28+
_loadStreamingPrefs();
29+
}
30+
31+
Future<void> _loadStreamingPrefs() async {
32+
final prefs = await SharedPreferences.getInstance();
33+
if (!mounted) return;
34+
setState(() {
35+
_useYoutube = prefs.getBool('use_youtube_service') ?? false;
36+
_useSaavn = prefs.getBool('use_saavn_service') ?? false;
37+
});
38+
}
39+
2240
void _onMusicServiceChanged(bool _) {
41+
_loadStreamingPrefs();
2342
setState(() {
2443
_searchScreenVersion++;
2544
});
@@ -45,105 +64,83 @@ class _HomeScreenState extends State<HomeScreen> {
4564
kBottomNavigationBarHeight +
4665
miniGapAboveNav;
4766

48-
return FutureBuilder<Map<String, bool>>(
49-
future: SharedPreferences.getInstance().then(
50-
(prefs) => {
51-
'use_youtube_service': prefs.getBool('use_youtube_service') ?? false,
52-
'use_saavn_service': prefs.getBool('use_saavn_service') ?? false,
53-
},
54-
),
55-
builder: (context, snapshot) {
56-
final useYoutube = snapshot.data?['use_youtube_service'] ?? false;
57-
final useSaavn = snapshot.data?['use_saavn_service'] ?? false;
58-
final isLocalMode = !useYoutube && !useSaavn;
67+
final isLocalMode = !_useYoutube && !_useSaavn;
5968

60-
final tabs = <Widget>[
61-
SearchScreen(key: ValueKey('search_$_searchScreenVersion')),
62-
isLocalMode
63-
? const _DisabledLibraryPlaceholder()
64-
: const LibraryScreen(),
65-
SettingsScreen(onMusicServiceChanged: _onMusicServiceChanged),
66-
];
69+
final tabs = <Widget>[
70+
SearchScreen(key: ValueKey('search_$_searchScreenVersion')),
71+
isLocalMode ? const _DisabledLibraryPlaceholder() : const LibraryScreen(),
72+
SettingsScreen(onMusicServiceChanged: _onMusicServiceChanged),
73+
];
6774

68-
int displayIndex = _index;
69-
if (displayIndex >= tabs.length) displayIndex = 0;
75+
int displayIndex = _index;
76+
if (displayIndex >= tabs.length) displayIndex = 0;
7077

71-
return Scaffold(
72-
extendBody: true,
73-
body: Stack(
74-
children: [
75-
IndexedStack(
76-
index: displayIndex,
77-
children: List<Widget>.generate(
78-
tabs.length,
79-
(i) => RepaintBoundary(
80-
child: TickerMode(
81-
enabled: i == displayIndex,
82-
child: tabs[i],
83-
),
84-
),
85-
),
86-
),
87-
Positioned(
88-
left: 0,
89-
right: 0,
90-
bottom: miniPlayerBottom,
91-
child: const MiniPlayer(),
78+
return Scaffold(
79+
extendBody: true,
80+
body: Stack(
81+
children: [
82+
IndexedStack(
83+
index: displayIndex,
84+
children: List<Widget>.generate(
85+
tabs.length,
86+
(i) => RepaintBoundary(
87+
child: TickerMode(enabled: i == displayIndex, child: tabs[i]),
9288
),
93-
],
94-
),
95-
bottomNavigationBar: Padding(
96-
padding: EdgeInsets.fromLTRB(
97-
12,
98-
0,
99-
12,
100-
navBottomPadding + bottomInset,
10189
),
102-
child: ClipRRect(
103-
borderRadius: BorderRadius.circular(24),
104-
child: Container(
105-
color: Colors.white.withValues(alpha: 0.08),
106-
child: BottomNavigationBar(
107-
backgroundColor: Colors.transparent,
108-
elevation: 0,
109-
currentIndex: displayIndex,
110-
onTap: (i) {
111-
if (i == displayIndex) return;
112-
setState(() => _index = i);
113-
},
114-
items: [
115-
BottomNavigationBarItem(
116-
icon: Icon(
117-
themeProvider.useGlassTheme
118-
? CupertinoIcons.search
119-
: Icons.search,
120-
),
121-
label: 'Search',
122-
),
123-
BottomNavigationBarItem(
124-
icon: Icon(
125-
themeProvider.useGlassTheme
126-
? CupertinoIcons.music_albums
127-
: Icons.library_music,
128-
color: isLocalMode ? Colors.white24 : null,
129-
),
130-
label: 'Library',
131-
),
132-
BottomNavigationBarItem(
133-
icon: Icon(
134-
themeProvider.useGlassTheme
135-
? CupertinoIcons.settings
136-
: Icons.settings,
137-
),
138-
label: 'Settings',
139-
),
140-
],
90+
),
91+
Positioned(
92+
left: 0,
93+
right: 0,
94+
bottom: miniPlayerBottom,
95+
child: const MiniPlayer(),
96+
),
97+
],
98+
),
99+
bottomNavigationBar: Padding(
100+
padding: EdgeInsets.fromLTRB(12, 0, 12, navBottomPadding + bottomInset),
101+
child: ClipRRect(
102+
borderRadius: BorderRadius.circular(24),
103+
child: Container(
104+
color: Colors.white.withValues(alpha: 0.08),
105+
child: BottomNavigationBar(
106+
backgroundColor: Colors.transparent,
107+
elevation: 0,
108+
currentIndex: displayIndex,
109+
onTap: (i) {
110+
if (i == displayIndex) return;
111+
setState(() => _index = i);
112+
},
113+
items: [
114+
BottomNavigationBarItem(
115+
icon: Icon(
116+
themeProvider.useGlassTheme
117+
? CupertinoIcons.search
118+
: Icons.search,
119+
),
120+
label: 'Search',
141121
),
142-
),
122+
BottomNavigationBarItem(
123+
icon: Icon(
124+
themeProvider.useGlassTheme
125+
? CupertinoIcons.music_albums
126+
: Icons.library_music,
127+
color: isLocalMode ? Colors.white24 : null,
128+
),
129+
label: 'Library',
130+
),
131+
BottomNavigationBarItem(
132+
icon: Icon(
133+
themeProvider.useGlassTheme
134+
? CupertinoIcons.settings
135+
: Icons.settings,
136+
),
137+
label: 'Settings',
138+
),
139+
],
143140
),
144141
),
145-
);
146-
},
142+
),
143+
),
147144
);
148145
}
149146
}

lib/features/search/search_screen.dart

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ class _SearchScreenState extends State<SearchScreen>
174174
final useYoutube = prefs.getBool('use_youtube_service') ?? false;
175175
final useSaavn = prefs.getBool('use_saavn_service') ?? false;
176176
final query = _controller.text.trim();
177+
178+
Future<List<LocalAudioTrack>>? localAudiosFuture;
179+
177180
setState(() {
178181
_servicesReady = true;
179182
_useYoutubeService = useYoutube;
@@ -184,10 +187,7 @@ class _SearchScreenState extends State<SearchScreen>
184187
_homeSectionsFuture = null;
185188
_searchFuture = null;
186189
_localAudiosFuture = _loadLocalAudiosWithPermission();
187-
_localAudiosFuture.then((tracks) {
188-
if (!mounted) return;
189-
setState(() => _localAudios = tracks);
190-
});
190+
localAudiosFuture = _localAudiosFuture;
191191
} else {
192192
_searchFuture = _performSearch(_quickPicksQuery, forceRefresh: true);
193193
_homeSectionsFuture = useYoutube
@@ -198,15 +198,18 @@ class _SearchScreenState extends State<SearchScreen>
198198
_searchFuture = null;
199199
} else {
200200
_lastQuery = query;
201-
if (!useYoutube && !useSaavn) {
202-
setState(() {
203-
_searchFuture = _searchLocalAudios(query);
204-
});
205-
} else {
206-
_searchFuture = _performSearch(query, forceRefresh: true);
207-
}
201+
_searchFuture = (!useYoutube && !useSaavn)
202+
? _searchLocalAudios(query)
203+
: _performSearch(query, forceRefresh: true);
208204
}
209205
});
206+
207+
if (localAudiosFuture != null) {
208+
final tracks = await localAudiosFuture!;
209+
if (!mounted) return;
210+
setState(() => _localAudios = tracks);
211+
}
212+
210213
if (useYoutube || useSaavn) {
211214
await _searchFuture?.catchError((_) => <SaavnSong>[]);
212215
}

0 commit comments

Comments
 (0)