summaryrefslogtreecommitdiffstats
path: root/lib/presentation/screens/media
diff options
context:
space:
mode:
Diffstat (limited to 'lib/presentation/screens/media')
-rw-r--r--lib/presentation/screens/media/media.dart55
-rw-r--r--lib/presentation/screens/media/media_player.dart68
-rw-r--r--lib/presentation/screens/media/media_player_controls.dart201
-rw-r--r--lib/presentation/screens/media/play_list_table.dart244
-rw-r--r--lib/presentation/screens/media/radio_player.dart4
-rw-r--r--lib/presentation/screens/media/radio_player_controls.dart146
-rw-r--r--lib/presentation/screens/media/radio_preset_table.dart172
7 files changed, 530 insertions, 360 deletions
diff --git a/lib/presentation/screens/media/media.dart b/lib/presentation/screens/media/media.dart
index b7ce9e1..e2ba927 100644
--- a/lib/presentation/screens/media/media.dart
+++ b/lib/presentation/screens/media/media.dart
@@ -1,7 +1,7 @@
import 'package:flutter_ics_homescreen/export.dart';
import 'package:flutter_ics_homescreen/presentation/screens/media/media_player.dart';
import 'package:flutter_ics_homescreen/presentation/screens/media/radio_player.dart';
-import 'widgets/media_volume_bar.dart';
+import 'package:flutter_ics_homescreen/data/data_providers/play_controller.dart';
import 'media_nav_notifier.dart';
import 'player_navigation.dart';
@@ -50,6 +50,21 @@ class MediaPage extends StatelessWidget {
}
}
+class MediaPlayingStateNotifier extends Notifier<bool> {
+ @override
+ bool build() {
+ return false;
+ }
+
+ set(bool value) {
+ state = value;
+ }
+}
+
+final mediaPlayingStateProvider =
+ NotifierProvider<MediaPlayingStateNotifier, bool>(
+ MediaPlayingStateNotifier.new);
+
class Media extends ConsumerStatefulWidget {
const Media({super.key});
@@ -58,22 +73,44 @@ class Media extends ConsumerStatefulWidget {
}
class _MediaState extends ConsumerState<Media> {
- //late MediaNavState selectedNav;
-
- //@override
- //initState() {
- // selectedNav = ref.read(mediaNavStateProvider);
- // super.initState();
- //}
+ @override
+ void initState() {
+ // Set initial source so external control (like the volume bar button)
+ // will work from the start.
+ var navState = ref.read(mediaNavStateProvider);
+ switch (navState) {
+ case MediaNavState.fm:
+ ref.read(playControllerProvider).setSource(PlaySource.radio);
+ break;
+ case MediaNavState.media:
+ default:
+ ref.read(playControllerProvider).setSource(PlaySource.media);
+ break;
+ }
+ super.initState();
+ }
onPressed(MediaNavState type) {
setState(() {
if (type == MediaNavState.fm) {
ref.read(mediaNavStateProvider.notifier).set(MediaNavState.fm);
+ ref.read(playControllerProvider).setSource(PlaySource.radio);
+
+ bool mediaPlaying = false;
+ if (ref.read(mediaPlayerStateProvider).playState == PlayState.playing) {
+ ref.read(mpdClientProvider).pause();
+ mediaPlaying = true;
+ }
+ ref.read(mediaPlayingStateProvider.notifier).set(mediaPlaying);
ref.read(radioClientProvider).start();
} else if (type == MediaNavState.media) {
ref.read(mediaNavStateProvider.notifier).set(MediaNavState.media);
+ ref.read(playControllerProvider).setSource(PlaySource.media);
+
ref.read(radioClientProvider).stop();
+ if (ref.read(mediaPlayingStateProvider)) {
+ ref.read(mpdClientProvider).play();
+ }
}
});
}
@@ -103,11 +140,13 @@ class _MediaState extends ConsumerState<Media> {
: Container(),
),
),
+ /*
if (navState == MediaNavState.media || navState == MediaNavState.fm)
const Padding(
padding: EdgeInsets.symmetric(horizontal: 144, vertical: 23.5),
child: CustomVolumeSlider(),
),
+ */
],
),
);
diff --git a/lib/presentation/screens/media/media_player.dart b/lib/presentation/screens/media/media_player.dart
index d7486c7..0dab346 100644
--- a/lib/presentation/screens/media/media_player.dart
+++ b/lib/presentation/screens/media/media_player.dart
@@ -3,38 +3,31 @@ import 'media_player_controls.dart';
import 'play_list_table.dart';
import 'segmented_buttons.dart';
-class MediaPlayer extends StatefulWidget {
+class MediaPlayer extends ConsumerStatefulWidget {
const MediaPlayer({super.key});
@override
- State<MediaPlayer> createState() => _MediaPlayerState();
+ ConsumerState<MediaPlayer> createState() => _MediaPlayerState();
}
-class _MediaPlayerState extends State<MediaPlayer> {
- String selectedNav = "Bluetooth";
- List<String> navItems = ["Bluetooth", "SD", "USB"];
-
- late String songName = "Feel Good Inc.";
-
- String tableName = "2000’s Dance Hits";
- List<PlayListModel> playList = [
- PlayListModel(songName: "Feel Good Inc.", albumName: "Gorillaz"),
- PlayListModel(
- songName: "Hips Don’t Lie", albumName: "Shakira, Wyclef Jean"),
- PlayListModel(songName: "AG1", albumName: "Paid Advertisement"),
- PlayListModel(songName: "Hey Ya!", albumName: "Outkast"),
- PlayListModel(songName: "One, Two, Step", albumName: "Ciara, Missy Elliot"),
- PlayListModel(songName: "Don’t Trust Me", albumName: "3OH!3"),
- ];
- String selectedPlayListSongName = "Feel Good Inc.";
+class _MediaPlayerState extends ConsumerState<MediaPlayer> {
+ String selectedNav = "USB";
+ List<String> navItems = ["USB", "SD", "Bluetooth"];
@override
Widget build(BuildContext context) {
- double albumArtSize = 460;
+ double albumArtSize = 400;
+ final playlistPosition = ref.watch(mediaPlayerStateProvider
+ .select((mediaplayer) => mediaplayer.playlistPosition));
+ final playlistArt = ref.watch(playlistArtProvider);
+ Uint8List art = Uint8List(0);
+ if (playlistArt.containsKey(playlistPosition)) {
+ art = playlistArt[playlistPosition]!;
+ }
+
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
- //const PlayerNavigation(),
SegmentedButtons(
navItems: navItems,
selectedNav: selectedNav,
@@ -45,11 +38,20 @@ class _MediaPlayerState extends State<MediaPlayer> {
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
- Image.asset(
- "assets/AlbumArtMedia.png",
- width: albumArtSize,
- height: albumArtSize,
- )
+ art.isNotEmpty
+ ? Image.memory(art,
+ width: albumArtSize,
+ height: albumArtSize,
+ fit: BoxFit.contain)
+ : Container(
+ width: albumArtSize,
+ height: albumArtSize,
+ color: AGLDemoColors.jordyBlueColor.withOpacity(0.2),
+ child: Icon(
+ Icons.music_note,
+ size: albumArtSize,
+ color: AGLDemoColors.jordyBlueColor,
+ ))
],
),
const SizedBox(
@@ -58,19 +60,11 @@ class _MediaPlayerState extends State<MediaPlayer> {
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
- MediaPlayerControls(
- songName: songName,
- songLengthStart: "-1:23",
- songLengthStop: "5:03"),
+ MediaPlayerControls(),
const SizedBox(
- height: 72,
- ),
- PlayListTable(
- playList: playList,
- selectedPlayListSongName: selectedPlayListSongName,
- tableName: tableName,
- type: "media",
+ height: 12,
),
+ PlayListTable(),
],
)
],
diff --git a/lib/presentation/screens/media/media_player_controls.dart b/lib/presentation/screens/media/media_player_controls.dart
index 518b669..26cdfce 100644
--- a/lib/presentation/screens/media/media_player_controls.dart
+++ b/lib/presentation/screens/media/media_player_controls.dart
@@ -1,40 +1,49 @@
import 'package:flutter_ics_homescreen/core/utils/helpers.dart';
import 'package:flutter_ics_homescreen/export.dart';
-import 'package:flutter_ics_homescreen/presentation/screens/media/widgets/gradient_progress_indicator.dart';
+import 'package:flutter_ics_homescreen/presentation/screens/settings/settings_screens/audio_settings/widget/slider_widgets.dart';
-class MediaPlayerControls extends StatefulWidget {
- const MediaPlayerControls(
- {super.key,
- required this.songName,
- required this.songLengthStart,
- required this.songLengthStop});
+// Time to string helper, returns HH:MM:SS or MM:SS as appropriate
+String timeToString(Duration time) {
+ String result = "";
+ if (time > const Duration(minutes: 59, seconds: 59)) {
+ result = time.toString().split('.').first.padLeft(8, "0");
+ } else {
+ result = time.toString().substring(2, 7);
+ }
+ return result;
+}
- final String songName;
- final String songLengthStart;
- final String songLengthStop;
+class MediaPlayerControls extends ConsumerStatefulWidget {
+ const MediaPlayerControls({super.key});
@override
- State<MediaPlayerControls> createState() => _MediaPlayerControlsState();
+ ConsumerState<MediaPlayerControls> createState() =>
+ _MediaPlayerControlsState();
}
-class _MediaPlayerControlsState extends State<MediaPlayerControls> {
- late String songName;
- late String songLengthStart;
- late String songLengthStop;
- final String albumName = "Gorillaz";
-
- int songProgress = 20;
-
- @override
- void initState() {
- songName = widget.songName;
- songLengthStart = widget.songLengthStart;
- songLengthStop = widget.songLengthStop;
- super.initState();
- }
+class _MediaPlayerControlsState extends ConsumerState<MediaPlayerControls> {
+ //@override
+ //void initState() {
+ // super.initState();
+ //}
@override
Widget build(BuildContext context) {
+ var currentSong = ref.watch(
+ mediaPlayerStateProvider.select((mediaplayer) => mediaplayer.song));
+ var songPosition = ref.watch(mediaPlayerPositionProvider);
+
+ String songName = "";
+ String songDetail = "";
+ String songPositionString = "00:00";
+ String songLengthString = "00:00";
+ if (currentSong != null) {
+ songName = currentSong.title;
+ songDetail = currentSong.artist;
+ songLengthString = timeToString(currentSong.duration);
+ }
+ songPositionString = timeToString(songPosition);
+
return Material(
color: Colors.transparent,
child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
@@ -46,42 +55,25 @@ class _MediaPlayerControlsState extends State<MediaPlayerControls> {
shadows: [Helpers.dropShadowRegular],
fontSize: 44),
),
- MediaPlayerControlsubDetails(
- albumName: albumName,
+ MediaPlayerControlsDetails(
+ songDetail: songDetail,
),
Column(children: [
- GradientProgressIndicator(
- percent: songProgress,
- type: "media",
- gradient: LinearGradient(
- begin: Alignment.centerLeft,
- end: Alignment.centerRight,
- colors: [
- AGLDemoColors.jordyBlueColor,
- AGLDemoColors.jordyBlueColor.withOpacity(0.8),
- ]),
- backgroundColor: AGLDemoColors.gradientBackgroundDarkColor,
- ),
- // const LinearProgressIndicator(
- // backgroundColor: AGLDemoColors.gradientBackgroundDarkColor,
- // color: Colors.white70,
- // minHeight: 8,
- // value: 0.7,
- // ),
+ const MediaPlayerControlsSlider(),
Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
- songLengthStart,
+ songPositionString,
style: TextStyle(
color: Colors.white,
fontSize: 26,
shadows: [Helpers.dropShadowRegular]),
),
Text(
- songLengthStop,
+ songLengthString,
style: TextStyle(
color: Colors.white,
fontSize: 26,
@@ -91,23 +83,23 @@ class _MediaPlayerControlsState extends State<MediaPlayerControls> {
),
),
]),
- const MediaPlayerActions(),
+ const MediaPlayerControlsActions(),
]),
);
}
}
-class MediaPlayerControlsubDetails extends StatefulWidget {
- const MediaPlayerControlsubDetails({super.key, required this.albumName});
- final String albumName;
+class MediaPlayerControlsDetails extends StatefulWidget {
+ const MediaPlayerControlsDetails({super.key, required this.songDetail});
+ final String songDetail;
@override
- State<MediaPlayerControlsubDetails> createState() =>
- _MediaPlayerControlsubDetailsState();
+ State<MediaPlayerControlsDetails> createState() =>
+ _MediaPlayerControlsDetailsState();
}
-class _MediaPlayerControlsubDetailsState
- extends State<MediaPlayerControlsubDetails> {
+class _MediaPlayerControlsDetailsState
+ extends State<MediaPlayerControlsDetails> {
bool isShuffleEnabled = false;
bool isRepeatEnabled = false;
@override
@@ -116,7 +108,7 @@ class _MediaPlayerControlsubDetailsState
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
- widget.albumName,
+ widget.songDetail,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w400,
@@ -158,25 +150,98 @@ class _MediaPlayerControlsubDetailsState
}
}
-class MediaPlayerActions extends StatefulWidget {
- const MediaPlayerActions({super.key});
+class MediaPlayerControlsSlider extends ConsumerStatefulWidget {
+ const MediaPlayerControlsSlider({super.key});
+
+ @override
+ ConsumerState<MediaPlayerControlsSlider> createState() =>
+ MediaPlayerControlsSliderState();
+}
+
+class MediaPlayerControlsSliderState
+ extends ConsumerState<MediaPlayerControlsSlider> {
+ //late Duration songPosition;
+
+ //@override
+ //void initState() {
+ // songPosition = ref.read(mediaPlayerPositionProvider);
+ // super.initState();
+ //}
+
+ @override
+ Widget build(BuildContext context) {
+ var currentSong = ref.watch(
+ mediaPlayerStateProvider.select((mediaplayer) => mediaplayer.song));
+ var songPosition = ref.watch(mediaPlayerPositionProvider);
+
+ Duration songLength = Duration.zero;
+ if (currentSong != null) {
+ songLength = currentSong.duration;
+ }
+
+ return Container(
+ height: 80,
+ child: SliderTheme(
+ data: SliderThemeData(
+ overlayShape: SliderComponentShape.noOverlay,
+ valueIndicatorShape: SliderComponentShape.noOverlay,
+ activeTickMarkColor: Colors.transparent,
+ inactiveTickMarkColor: Colors.transparent,
+ inactiveTrackColor: AGLDemoColors.periwinkleColor,
+ thumbShape: const PolygonSliderThumb(sliderValue: 3, thumbRadius: 23),
+ //trackHeight: 5,
+ ),
+ child: Slider(
+ max: songLength.inMilliseconds.toDouble(),
+ value: songPosition.inMilliseconds.toDouble(),
+ onChangeStart: (double value) {
+ // Disable timer so position will not change while control is
+ // being dragged. It will be re-enabled via the playback state
+ // update from MPD.
+ ref.read(mediaPlayerPositionProvider.notifier).pause();
+ },
+ onChanged: (double newValue) {
+ setState(() {
+ ref
+ .read(mediaPlayerPositionProvider.notifier)
+ .set(Duration(milliseconds: newValue.toInt()));
+ });
+ },
+ onChangeEnd: (double newValue) {
+ ref.read(mpdClientProvider).seek(newValue.toInt());
+ },
+ ),
+ ),
+ );
+ }
+}
+
+class MediaPlayerControlsActions extends ConsumerStatefulWidget {
+ const MediaPlayerControlsActions({super.key});
@override
- State<MediaPlayerActions> createState() => _MediaPlayerActionsState();
+ ConsumerState<MediaPlayerControlsActions> createState() =>
+ _MediaPlayerControlsActionsState();
}
-class _MediaPlayerActionsState extends State<MediaPlayerActions> {
+class _MediaPlayerControlsActionsState
+ extends ConsumerState<MediaPlayerControlsActions> {
bool isPressed = false;
- bool isPlaying = true;
@override
Widget build(BuildContext context) {
+ bool isPlaying = ref.watch(mediaPlayerStateProvider
+ .select((mediaplayer) => mediaplayer.playState)) ==
+ PlayState.playing;
+
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
InkWell(
customBorder: const CircleBorder(),
- onTap: () {},
+ onTap: () {
+ ref.read(mpdClientProvider).previous();
+ },
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SvgPicture.asset(
@@ -191,7 +256,11 @@ class _MediaPlayerActionsState extends State<MediaPlayerActions> {
customBorder: const CircleBorder(),
onTap: () {
setState(() {
- isPlaying = !isPlaying;
+ if (isPlaying) {
+ ref.read(mpdClientProvider).pause();
+ } else {
+ ref.read(mpdClientProvider).play();
+ }
});
},
onTapDown: (details) {
@@ -221,7 +290,9 @@ class _MediaPlayerActionsState extends State<MediaPlayerActions> {
),
InkWell(
customBorder: const CircleBorder(),
- onTap: () {},
+ onTap: () {
+ ref.read(mpdClientProvider).next();
+ },
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SvgPicture.asset(
diff --git a/lib/presentation/screens/media/play_list_table.dart b/lib/presentation/screens/media/play_list_table.dart
index 369bb9c..71d2fc9 100644
--- a/lib/presentation/screens/media/play_list_table.dart
+++ b/lib/presentation/screens/media/play_list_table.dart
@@ -2,38 +2,29 @@ import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter_ics_homescreen/core/utils/helpers.dart';
import 'package:flutter_ics_homescreen/export.dart';
-class PlayListTable extends StatefulWidget {
- const PlayListTable(
- {super.key,
- required this.type,
- required this.tableName,
- required this.playList,
- required this.selectedPlayListSongName});
- final String type;
- final String tableName;
- final List<PlayListModel> playList;
- final String selectedPlayListSongName;
+class PlayListTable extends ConsumerStatefulWidget {
+ PlayListTable({super.key});
@override
- State<PlayListTable> createState() => _PlayListTableState();
+ ConsumerState<PlayListTable> createState() => _PlayListTableState();
}
-class _PlayListTableState extends State<PlayListTable> {
+class _PlayListTableState extends ConsumerState<PlayListTable> {
bool isAudioSettingsEnabled = false;
- late String tableName;
- late List<PlayListModel> playList;
- late String selectedPlayListSongName;
- @override
- void initState() {
- tableName = widget.tableName;
- playList = widget.playList;
- selectedPlayListSongName = widget.selectedPlayListSongName;
- super.initState();
- }
+ //@override
+ //void initState() {
+ // super.initState();
+ //}
@override
Widget build(BuildContext context) {
+ final controller = ScrollController();
+ var playlist = ref.watch(playlistProvider);
+ var selectedPosition = ref.watch(mediaPlayerStateProvider
+ .select((mediaplayer) => mediaplayer.playlistPosition));
+ late String tableName = "USB";
+
return Material(
color: Colors.transparent,
child: Column(
@@ -51,19 +42,18 @@ class _PlayListTableState extends State<PlayListTable> {
fontWeight: FontWeight.w400,
fontSize: 40),
),
- if (widget.type == "media")
- InkWell(
- customBorder: const CircleBorder(),
- onTap: () {},
- child: Opacity(
- opacity: 0.5,
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: SvgPicture.asset(
- "assets/AppleMusic.svg",
- width: 32,
- )),
- )),
+ InkWell(
+ customBorder: const CircleBorder(),
+ onTap: () {},
+ child: Opacity(
+ opacity: 0.5,
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: SvgPicture.asset(
+ "assets/AppleMusic.svg",
+ width: 32,
+ )),
+ )),
],
),
InkWell(
@@ -81,77 +71,119 @@ class _PlayListTableState extends State<PlayListTable> {
)))
],
),
- SizedBox(
- height: 325,
- child: SingleChildScrollView(
- child: Column(
- children: playList.map((index) {
- return Container(
- height: 100,
- margin: const EdgeInsets.symmetric(vertical: 4),
- decoration: BoxDecoration(
- border: Border(
- left: selectedPlayListSongName == index.songName
- ? const BorderSide(
- color: Colors.white, width: 4)
- : BorderSide.none),
- gradient: LinearGradient(
- colors: selectedPlayListSongName == index.songName
- ? [
- AGLDemoColors.neonBlueColor,
- AGLDemoColors.neonBlueColor
- .withOpacity(0.15)
- ]
- : [
- Colors.black,
- Colors.black.withOpacity(0.20)
- ])),
- child: InkWell(
- onTap: () {
- setState(() {
- selectedPlayListSongName = index.songName;
- });
- },
- child: Padding(
- padding: const EdgeInsets.symmetric(
- vertical: 17, horizontal: 24),
- child: Row(
- children: [
- Expanded(
- flex: 6,
- child: AutoSizeText(
- index.songName,
- maxLines: 1,
- style: TextStyle(
- color: Colors.white,
- fontSize: 40,
- shadows: [Helpers.dropShadowRegular]),
- )),
- Expanded(
- flex: 4,
- child: Text(
- index.albumName,
- style: TextStyle(
- color: Colors.white,
- fontSize: 26,
- shadows: [Helpers.dropShadowRegular]),
- ))
- ],
- ),
- ),
- ),
- );
- }).toList()),
- ),
- ),
+ Padding(
+ padding: const EdgeInsets.only(right: 12),
+ child: SizedBox(
+ height: 500,
+ child: RawScrollbar(
+ controller: controller,
+ thickness: 32,
+ thumbVisibility: true,
+ radius: const Radius.circular(10),
+ thumbColor: AGLDemoColors.periwinkleColor,
+ minThumbLength: 60,
+ interactive: true,
+ child: ScrollConfiguration(
+ behavior: ScrollConfiguration.of(context).copyWith(
+ scrollbars: false,
+ overscroll: false,
+ ),
+ child: CustomScrollView(
+ controller: controller,
+ physics: const ClampingScrollPhysics(),
+ slivers: <Widget>[
+ SliverList.separated(
+ itemCount: playlist.length,
+ itemBuilder: (_, int index) {
+ return Container(
+ height: 92,
+ margin:
+ const EdgeInsets.only(right: 44),
+ decoration: BoxDecoration(
+ border: Border(
+ left: selectedPosition ==
+ playlist[index].position
+ ? const BorderSide(
+ color: Colors.white,
+ width: 4)
+ : BorderSide.none),
+ gradient: LinearGradient(
+ colors: selectedPosition ==
+ playlist[index].position
+ ? [
+ AGLDemoColors
+ .neonBlueColor,
+ AGLDemoColors
+ .neonBlueColor
+ .withOpacity(0.15)
+ ]
+ : [
+ Colors.black,
+ Colors.black
+ .withOpacity(0.20)
+ ])),
+ child: InkWell(
+ onTap: () {
+ setState(() {
+ selectedPosition =
+ playlist[index].position;
+ ref
+ .read(mpdClientProvider)
+ .pickTrack(
+ playlist[index].position);
+ });
+ },
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 17, horizontal: 24),
+ child: Column(
+ children: [
+ Expanded(
+ flex: 6,
+ child: Align(
+ alignment: Alignment
+ .centerLeft,
+ child: AutoSizeText(
+ playlist[index].title,
+ maxLines: 1,
+ style: TextStyle(
+ color:
+ Colors.white,
+ fontSize: 40,
+ shadows: [
+ Helpers
+ .dropShadowRegular
+ ]),
+ ))),
+ Expanded(
+ flex: 4,
+ child: Align(
+ alignment: Alignment
+ .centerLeft,
+ child: Text(
+ playlist[index]
+ .artist,
+ style: TextStyle(
+ color:
+ Colors.white,
+ fontSize: 22,
+ shadows: [
+ Helpers
+ .dropShadowRegular
+ ]),
+ )))
+ ],
+ ),
+ ),
+ ),
+ );
+ },
+ separatorBuilder: (_, __) {
+ return SizedBox(height: 8);
+ },
+ ),
+ ]))))),
],
));
}
}
-
-class PlayListModel {
- final String songName;
- final String albumName;
-
- PlayListModel({required this.songName, required this.albumName});
-}
diff --git a/lib/presentation/screens/media/radio_player.dart b/lib/presentation/screens/media/radio_player.dart
index 4531c7b..f6695f1 100644
--- a/lib/presentation/screens/media/radio_player.dart
+++ b/lib/presentation/screens/media/radio_player.dart
@@ -34,8 +34,8 @@ class _RadioPlayerState extends ConsumerState<RadioPlayer> {
@override
Widget build(BuildContext context) {
- double fmSignalHeight = 460;
- double fmSignalWidth = 460;
+ double fmSignalHeight = 400;
+ double fmSignalWidth = 400;
return Container(
padding: const EdgeInsets.only(left: 7, right: 7),
diff --git a/lib/presentation/screens/media/radio_player_controls.dart b/lib/presentation/screens/media/radio_player_controls.dart
index bfa8da6..acc8291 100644
--- a/lib/presentation/screens/media/radio_player_controls.dart
+++ b/lib/presentation/screens/media/radio_player_controls.dart
@@ -10,6 +10,12 @@ class RadioPlayerControls extends ConsumerWidget {
var freqCurrent =
ref.watch(radioStateProvider.select((radio) => radio.freqCurrent));
String currentString = (freqCurrent / 1000000.0).toStringAsFixed(1);
+ var freqMin =
+ ref.watch(radioStateProvider.select((radio) => radio.freqMin));
+ String freqMinString = (freqMin / 1000000.0).toStringAsFixed(1);
+ var freqMax =
+ ref.watch(radioStateProvider.select((radio) => radio.freqMax));
+ String freqMaxString = (freqMax / 1000000.0).toStringAsFixed(1);
return Material(
color: Colors.transparent,
@@ -24,16 +30,40 @@ class RadioPlayerControls extends ConsumerWidget {
shadows: [Helpers.dropShadowRegular],
fontSize: 44),
),
- const RadioPlayerControlsSubDetails(),
- const RadioPlayerControlsSlider(),
+ const RadioPlayerControlsActions(),
+ Column(children: [
+ const RadioPlayerControlsSlider(),
+ Padding(
+ padding: const EdgeInsets.symmetric(vertical: 5),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ freqMinString,
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: 26,
+ shadows: [Helpers.dropShadowRegular]),
+ ),
+ Text(
+ freqMaxString,
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: 26,
+ shadows: [Helpers.dropShadowRegular]),
+ )
+ ],
+ ),
+ ),
+ ]),
],
),
);
}
}
-class RadioPlayerControlsSubDetails extends ConsumerWidget {
- const RadioPlayerControlsSubDetails({super.key});
+class RadioPlayerControlsActions extends ConsumerWidget {
+ const RadioPlayerControlsActions({super.key});
onPressed({required WidgetRef ref, required String type}) {
if (type == "tuneLeft") {
@@ -174,78 +204,40 @@ class RadioPlayerControlsSliderState
ref.watch(radioStateProvider.select((radio) => radio.freqCurrent)) /
1000000.0;
- String minString = (freqMin / 1000000.0).toStringAsFixed(1);
- String maxString = (freqMax / 1000000.0).toStringAsFixed(1);
-
- return Padding(
- padding: const EdgeInsets.symmetric(horizontal: 64),
- child: Container(
- decoration: const ShapeDecoration(
- color: AGLDemoColors.buttonFillEnabledColor,
- shape: StadiumBorder(
- side: BorderSide(
- color: Color(0xFF5477D4),
- width: 0.5,
- )),
- ),
- height: 160,
- child: Row(
- children: [
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 20),
- child: Text(
- minString,
- style: TextStyle(
- color: Colors.white,
- fontSize: 32,
- shadows: [Helpers.dropShadowRegular]),
- )),
- Expanded(
- child: SliderTheme(
- data: SliderThemeData(
- overlayShape: SliderComponentShape.noOverlay,
- valueIndicatorShape: SliderComponentShape.noOverlay,
- activeTickMarkColor: Colors.transparent,
- inactiveTickMarkColor: Colors.transparent,
- inactiveTrackColor: AGLDemoColors.backgroundInsetColor,
- thumbShape: const PolygonSliderThumb(
- sliderValue: 3, thumbRadius: 23),
- //trackHeight: 5,
- ),
- child: Slider(
- divisions: (freqMax - freqMin) ~/ freqStep,
- min: freqMin / 1000000.0,
- max: freqMax / 1000000.0,
- value: currentFreq,
- onChangeStart: (double value) {
- ref.read(radioClientProvider).scanStop();
- },
- onChanged: (double value) {
- setState(() {
- ref
- .read(radioStateProvider.notifier)
- .updateFrequency((value * 1000000.0).toInt());
- });
- },
- onChangeEnd: (double value) {
- ref
- .read(radioStateProvider.notifier)
- .setFrequency((value * 1000000.0).toInt());
- },
- ),
- ),
- ),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 20),
- child: Text(
- maxString,
- style: TextStyle(
- color: Colors.white,
- fontSize: 32,
- shadows: [Helpers.dropShadowRegular]),
- )),
- ],
- ),
- ));
+ return Container(
+ height: 80,
+ child: SliderTheme(
+ data: SliderThemeData(
+ overlayShape: SliderComponentShape.noOverlay,
+ valueIndicatorShape: SliderComponentShape.noOverlay,
+ activeTickMarkColor: Colors.transparent,
+ inactiveTickMarkColor: Colors.transparent,
+ inactiveTrackColor: AGLDemoColors.periwinkleColor,
+ thumbShape: const PolygonSliderThumb(sliderValue: 3, thumbRadius: 23),
+ //trackHeight: 5,
+ ),
+ child: Slider(
+ divisions: (freqMax - freqMin) ~/ freqStep,
+ min: freqMin / 1000000.0,
+ max: freqMax / 1000000.0,
+ value: currentFreq,
+ onChangeStart: (double value) {
+ ref.read(radioClientProvider).scanStop();
+ },
+ onChanged: (double value) {
+ setState(() {
+ ref
+ .read(radioStateProvider.notifier)
+ .updateFrequency((value * 1000000.0).toInt());
+ });
+ },
+ onChangeEnd: (double value) {
+ ref
+ .read(radioStateProvider.notifier)
+ .setFrequency((value * 1000000.0).toInt());
+ },
+ ),
+ ),
+ );
}
}
diff --git a/lib/presentation/screens/media/radio_preset_table.dart b/lib/presentation/screens/media/radio_preset_table.dart
index 816bcb9..97affb8 100644
--- a/lib/presentation/screens/media/radio_preset_table.dart
+++ b/lib/presentation/screens/media/radio_preset_table.dart
@@ -38,6 +38,8 @@ class _RadioPresetTableState extends ConsumerState<RadioPresetTable> {
@override
Widget build(BuildContext context) {
+ final controller = ScrollController();
+
return Material(
color: Colors.transparent,
child: Column(
@@ -72,72 +74,112 @@ class _RadioPresetTableState extends ConsumerState<RadioPresetTable> {
)))
],
),
- SizedBox(
- height: 325,
- child: SingleChildScrollView(
- child: Column(
- children: presets.map((index) {
- return Container(
- height: 100,
- margin: const EdgeInsets.symmetric(vertical: 4),
- decoration: BoxDecoration(
- border: Border(
- left: selectedPreset == index.name
- ? const BorderSide(
- color: Colors.white, width: 4)
- : BorderSide.none),
- gradient: LinearGradient(
- colors: selectedPreset == index.name
- ? [
- AGLDemoColors.neonBlueColor,
- AGLDemoColors.neonBlueColor
- .withOpacity(0.15)
- ]
- : [
- Colors.black,
- Colors.black.withOpacity(0.20)
- ])),
- child: InkWell(
- onTap: () {
- ref
- .read(radioClientProvider)
- .setFrequency(index.frequency);
- setState(() {
- selectedPreset = index.name;
- });
- },
- child: Padding(
- padding: const EdgeInsets.symmetric(
- vertical: 17, horizontal: 24),
- child: Row(
- children: [
- Expanded(
- flex: 6,
- child: AutoSizeText(
- index.name,
- maxLines: 1,
- style: TextStyle(
- color: Colors.white,
- fontSize: 40,
- shadows: [Helpers.dropShadowRegular]),
- )),
- Expanded(
- flex: 4,
- child: Text(
- frequencyToString(index.frequency),
- style: TextStyle(
- color: Colors.white,
- fontSize: 26,
- shadows: [Helpers.dropShadowRegular]),
- ))
- ],
+ Padding(
+ padding: const EdgeInsets.only(right: 12),
+ child: SizedBox(
+ height: 500,
+ child: RawScrollbar(
+ controller: controller,
+ thickness: 32,
+ thumbVisibility: true,
+ radius: const Radius.circular(10),
+ thumbColor: AGLDemoColors.periwinkleColor,
+ minThumbLength: 60,
+ interactive: true,
+ child: ScrollConfiguration(
+ behavior: ScrollConfiguration.of(context).copyWith(
+ scrollbars: false,
+ overscroll: false,
),
- ),
- ),
- );
- }).toList()),
- ),
- ),
+ child: CustomScrollView(
+ controller: controller,
+ physics: const ClampingScrollPhysics(),
+ slivers: <Widget>[
+ SliverList.separated(
+ itemCount: presets.length,
+ itemBuilder: (_, int index) {
+ return Container(
+ height: 92,
+ margin: const EdgeInsets.only(right: 44),
+ decoration: BoxDecoration(
+ border: Border(
+ left: selectedPreset ==
+ presets[index].name
+ ? const BorderSide(
+ color: Colors.white,
+ width: 4)
+ : BorderSide.none),
+ gradient: LinearGradient(
+ colors: selectedPreset ==
+ presets[index].name
+ ? [
+ AGLDemoColors.neonBlueColor,
+ AGLDemoColors.neonBlueColor
+ .withOpacity(0.15)
+ ]
+ : [
+ Colors.black,
+ Colors.black
+ .withOpacity(0.20)
+ ])),
+ child: InkWell(
+ onTap: () {
+ ref
+ .read(radioClientProvider)
+ .setFrequency(
+ presets[index].frequency);
+ setState(() {
+ selectedPreset = presets[index].name;
+ });
+ },
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 17, horizontal: 24),
+ child: Row(
+ children: [
+ Expanded(
+ flex: 6,
+ child: AutoSizeText(
+ presets[index].name,
+ maxLines: 1,
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: 32,
+ shadows: [
+ Helpers
+ .dropShadowRegular
+ ]),
+ )),
+ Expanded(
+ flex: 4,
+ child: Align(
+ alignment:
+ Alignment.centerRight,
+ child: Text(
+ frequencyToString(
+ presets[index]
+ .frequency),
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: 24,
+ shadows: [
+ Helpers
+ .dropShadowRegular
+ ]),
+ )))
+ ],
+ ),
+ ),
+ ),
+ );
+ },
+ separatorBuilder: (_, __) {
+ return SizedBox(height: 8);
+ },
+ ),
+ ])),
+ ),
+ )),
],
));
}