feat: reactive volume slider and slicker bottom bar with lowered height

This commit is contained in:
Kingkor Roy Tirtho 2023-06-10 22:15:23 +06:00
parent 6ae896441a
commit 9d14517202
4 changed files with 94 additions and 76 deletions

View File

@ -82,4 +82,8 @@ abstract class SpotubeIcons {
static const piped = FeatherIcons.cloud; static const piped = FeatherIcons.cloud;
static const magic = Icons.auto_fix_high_outlined; static const magic = Icons.auto_fix_high_outlined;
static const selectionCheck = Icons.checklist_rounded; static const selectionCheck = Icons.checklist_rounded;
static const volumeHigh = FeatherIcons.volume2;
static const volumeMedium = FeatherIcons.volume1;
static const volumeLow = FeatherIcons.volume;
static const volumeMute = FeatherIcons.volumeX;
} }

View File

@ -26,8 +26,8 @@ class PlayerTrackDetails extends HookConsumerWidget {
Container( Container(
padding: const EdgeInsets.all(6), padding: const EdgeInsets.all(6),
constraints: const BoxConstraints( constraints: const BoxConstraints(
maxWidth: 70, maxWidth: 80,
maxHeight: 70, maxHeight: 80,
), ),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),

View File

@ -71,61 +71,20 @@ class BottomPlayer extends HookConsumerWidget {
type: MaterialType.transparency, type: MaterialType.transparency,
textStyle: theme.textTheme.bodyMedium!, textStyle: theme.textTheme.bodyMedium!,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Expanded(child: PlayerTrackDetails(albumArt: albumArt)), Expanded(child: PlayerTrackDetails(albumArt: albumArt)),
// controls // controls
Flexible( Flexible(
flex: 3, flex: 3,
child: Padding(
padding: const EdgeInsets.only(top: 5),
child: PlayerControls(), child: PlayerControls(),
), ),
),
// add to saved tracks // add to saved tracks
Expanded( Column(
flex: 1,
child: Wrap(
alignment: WrapAlignment.center,
runAlignment: WrapAlignment.center,
children: [ children: [
Container(
height: 20,
constraints: const BoxConstraints(maxWidth: 200),
child: HookBuilder(builder: (context) {
final volumeState =
useStream(audioPlayer.volumeStream).data ??
audioPlayer.volume;
final volume = useState(volumeState);
useEffect(() {
if (volume.value != volumeState) {
volume.value = volumeState;
}
return null;
}, [volumeState]);
return Listener(
onPointerSignal: (event) async {
if (event is PointerScrollEvent) {
if (event.scrollDelta.dy > 0) {
final value = volume.value - .2;
audioPlayer.setVolume(value < 0 ? 0 : value);
} else {
final value = volume.value + .2;
audioPlayer.setVolume(value > 1 ? 1 : value);
}
}
},
child: Slider(
min: 0,
max: 1,
value: volume.value,
onChanged: (v) {
volume.value = v;
},
onChangeEnd: audioPlayer.setVolume,
),
);
}),
),
PlayerActions( PlayerActions(
extraActions: [ extraActions: [
IconButton( IconButton(
@ -152,9 +111,63 @@ class BottomPlayer extends HookConsumerWidget {
}, },
), ),
], ],
),
Container(
height: 40,
constraints: const BoxConstraints(maxWidth: 250),
child: HookBuilder(builder: (context) {
final volume =
useStream(audioPlayer.volumeStream).data ??
audioPlayer.volume;
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: Icon(
volume == 0
? SpotubeIcons.volumeMute
: volume <= 0.2
? SpotubeIcons.volumeLow
: volume <= 0.6
? SpotubeIcons.volumeMedium
: SpotubeIcons.volumeHigh,
size: 16,
),
onPressed: () {
if (volume == 0) {
audioPlayer.setVolume(1);
} else {
audioPlayer.setVolume(0);
}
},
),
Listener(
onPointerSignal: (event) async {
if (event is PointerScrollEvent) {
if (event.scrollDelta.dy > 0) {
final value = volume - .2;
audioPlayer
.setVolume(value < 0 ? 0 : value);
} else {
final value = volume + .2;
audioPlayer
.setVolume(value > 1 ? 1 : value);
}
}
},
child: Slider(
min: 0,
max: 1,
value: volume,
onChanged: audioPlayer.setVolume,
),
),
],
);
}),
) )
], ],
),
) )
], ],
), ),

View File

@ -48,5 +48,6 @@ ThemeData theme(Color seed, Brightness brightness) {
backgroundColor: scheme.onSurface, backgroundColor: scheme.onSurface,
contentTextStyle: TextStyle(color: scheme.surface), contentTextStyle: TextStyle(color: scheme.surface),
), ),
sliderTheme: SliderThemeData(overlayShape: SliderComponentShape.noOverlay),
); );
} }