Skip to content

Commit f9db776

Browse files
committed
refactor(bottom_actions_row): convert BottomActionsRow to StatefulWidget for better state management
1 parent 53fff08 commit f9db776

File tree

1 file changed

+70
-43
lines changed

1 file changed

+70
-43
lines changed

lib/widgets/now_playing/bottom_actions_row.dart

Lines changed: 70 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import 'package:musify/utilities/mediaitem.dart';
3232
import 'package:musify/widgets/queue_list_view.dart';
3333
import 'package:musify/widgets/song_bar.dart';
3434

35-
class BottomActionsRow extends StatelessWidget {
35+
class BottomActionsRow extends StatefulWidget {
3636
const BottomActionsRow({
3737
super.key,
3838
required this.audioId,
@@ -47,16 +47,48 @@ class BottomActionsRow extends StatelessWidget {
4747
final bool isLargeScreen;
4848
final dynamic lyricsController;
4949

50+
@override
51+
State<BottomActionsRow> createState() => _BottomActionsRowState();
52+
}
53+
54+
class _BottomActionsRowState extends State<BottomActionsRow> {
55+
late final ValueNotifier<bool> _songLikeStatus;
56+
late final ValueNotifier<bool> _songOfflineStatus;
57+
58+
@override
59+
void initState() {
60+
super.initState();
61+
_songLikeStatus = ValueNotifier<bool>(isSongAlreadyLiked(widget.audioId));
62+
_songOfflineStatus = ValueNotifier<bool>(
63+
isSongAlreadyOffline(widget.audioId),
64+
);
65+
}
66+
67+
@override
68+
void didUpdateWidget(BottomActionsRow oldWidget) {
69+
super.didUpdateWidget(oldWidget);
70+
if (oldWidget.audioId != widget.audioId) {
71+
_songLikeStatus.value = isSongAlreadyLiked(widget.audioId);
72+
_songOfflineStatus.value = isSongAlreadyOffline(widget.audioId);
73+
}
74+
}
75+
76+
@override
77+
void dispose() {
78+
_songLikeStatus.dispose();
79+
_songOfflineStatus.dispose();
80+
super.dispose();
81+
}
82+
5083
@override
5184
Widget build(BuildContext context) {
5285
final colorScheme = Theme.of(context).colorScheme;
53-
final songLikeStatus = ValueNotifier<bool>(isSongAlreadyLiked(audioId));
54-
final songOfflineStatus = ValueNotifier<bool>(
55-
isSongAlreadyOffline(audioId),
56-
);
86+
final l10n = context.l10n!;
5787

5888
final screenWidth = MediaQuery.sizeOf(context).width;
59-
final responsiveIconSize = screenWidth < 360 ? iconSize * 0.85 : iconSize;
89+
final responsiveIconSize = screenWidth < 360
90+
? widget.iconSize * 0.85
91+
: widget.iconSize;
6092

6193
return StreamBuilder<List<Map>>(
6294
stream: audioHandler.queueAsMapStream,
@@ -70,31 +102,30 @@ class BottomActionsRow extends StatelessWidget {
70102
activeIcon: FluentIcons.cloud_off_24_filled,
71103
colorScheme: colorScheme,
72104
size: responsiveIconSize,
73-
statusNotifier: songOfflineStatus,
74-
onPressed: audioId == null
105+
statusNotifier: _songOfflineStatus,
106+
onPressed: widget.audioId == null
75107
? null
76-
: () => _toggleOffline(songOfflineStatus, audioId, metadata),
77-
tooltip: 'Offline',
108+
: () => _toggleOffline(
109+
_songOfflineStatus,
110+
widget.audioId,
111+
widget.metadata,
112+
),
113+
tooltip: l10n.makeOffline,
78114
),
79115
_buildSleepTimerButton(context, colorScheme, responsiveIconSize),
80-
];
81-
82-
if (!offlineMode.value) {
83-
actions.add(
116+
if (!offlineMode.value)
84117
_buildSimpleActionButton(
85118
context: context,
86119
icon: FluentIcons.album_add_24_regular,
87120
colorScheme: colorScheme,
88121
size: responsiveIconSize,
89-
onPressed: () =>
90-
showAddToPlaylistDialog(context, mediaItemToMap(metadata)),
91-
tooltip: 'Add to playlist',
122+
onPressed: () => showAddToPlaylistDialog(
123+
context,
124+
mediaItemToMap(widget.metadata),
125+
),
126+
tooltip: l10n.addToPlaylist,
92127
),
93-
);
94-
}
95-
96-
if (queue.isNotEmpty && !isLargeScreen) {
97-
actions.add(
128+
if (queue.isNotEmpty && !widget.isLargeScreen)
98129
_buildSimpleActionButton(
99130
context: context,
100131
icon: FluentIcons.apps_list_24_filled,
@@ -104,37 +135,33 @@ class BottomActionsRow extends StatelessWidget {
104135
context,
105136
const QueueWidget(isBottomSheet: true),
106137
),
107-
tooltip: 'Queue',
138+
tooltip: l10n.queue,
139+
),
140+
if (!offlineMode.value) ...[
141+
_buildSimpleActionButton(
142+
context: context,
143+
icon: FluentIcons.text_quote_24_regular,
144+
colorScheme: colorScheme,
145+
size: responsiveIconSize,
146+
onPressed: widget.lyricsController.flipcard,
147+
tooltip: l10n.lyrics,
108148
),
109-
);
110-
}
111-
112-
if (!offlineMode.value) {
113-
actions.addAll([
114149
_buildActionButton(
115150
context: context,
116151
icon: FluentIcons.heart_24_regular,
117152
activeIcon: FluentIcons.heart_24_filled,
118153
colorScheme: colorScheme,
119154
size: responsiveIconSize,
120-
statusNotifier: songLikeStatus,
155+
statusNotifier: _songLikeStatus,
121156
activeColor: colorScheme.primary,
122157
onPressed: () {
123-
updateSongLikeStatus(audioId, !songLikeStatus.value);
124-
songLikeStatus.value = !songLikeStatus.value;
158+
updateSongLikeStatus(widget.audioId, !_songLikeStatus.value);
159+
_songLikeStatus.value = !_songLikeStatus.value;
125160
},
126-
tooltip: 'Like',
161+
tooltip: l10n.likedSongs,
127162
),
128-
_buildSimpleActionButton(
129-
context: context,
130-
icon: FluentIcons.text_quote_24_regular,
131-
colorScheme: colorScheme,
132-
size: responsiveIconSize,
133-
onPressed: lyricsController.flipcard,
134-
tooltip: 'Lyrics',
135-
),
136-
]);
137-
}
163+
],
164+
];
138165

139166
return Container(
140167
padding: const EdgeInsets.all(8),
@@ -228,7 +255,7 @@ class BottomActionsRow extends StatelessWidget {
228255
: colorScheme.onSurfaceVariant,
229256
),
230257
iconSize: size,
231-
tooltip: 'Sleep timer',
258+
tooltip: context.l10n!.sleepTimer,
232259
style: IconButton.styleFrom(
233260
backgroundColor: isActive
234261
? colorScheme.primary.withValues(alpha: 0.15)

0 commit comments

Comments
 (0)