aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorScott Murray <scott.murray@konsulko.com>2023-12-31 16:24:51 -0500
committerScott Murray <scott.murray@konsulko.com>2024-01-03 18:23:52 -0500
commit4742fde5c48726357cc8db06d237e9db6c3df608 (patch)
treedcca2b3e3c6cb3a4a46b7ae603f64fa9ce5a086c /lib
parentfcd868bd73d35bd79074f3425317152565aeb275 (diff)
Initial radio implementation
Notable changes: - Add radio gRPC API protobuf definitation and generated files. - Reworked existing single gRPC APIs library to split it into per-API libraries to avoid name collision issues. - Add radio gRPC client class and associated radio state class and RiverPod providers. - Split media controls and play list table classes into media player and radio specific versions to facilitate customization and wiring up their appropriate backends in a straightforward fashion. Some potential rationalization of styling widgets may be done as a follow up to avoid some duplication. - Added radio configuration and presets loading. The presets will be populated with the contents of a radio-presets.yaml file from the configured location, the default location is the /etc/xdg/AGL/ics-homescreen directory. - Implemented FM radio player against the radio gRPC API. For the sake of expediency, no attempt has been made to make the player able to handle AM band support. - Reworked media page navigation state so that active player is restored when coming back to the page. Logic has been added to start/stop the radio on navigating to or leaving the FM radio sub-page. This will potentially be reworked before CES to work with the pause/stop button present on the other pages. - Started pruning down global exports.dart a bit to remove files only used in a specific page/hierarchy, starting with media. Bug-AGL: SPEC-5029 Change-Id: I1ae0aca4a7a8218e69e4286c863f01509a1cccb7 Signed-off-by: Scott Murray <scott.murray@konsulko.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/data/data_providers/app_config_provider.dart72
-rw-r--r--lib/data/data_providers/app_launcher.dart36
-rw-r--r--lib/data/data_providers/app_provider.dart19
-rw-r--r--lib/data/data_providers/audio_notifier.dart8
-rw-r--r--lib/data/data_providers/radio_client.dart161
-rw-r--r--lib/data/data_providers/radio_notifier.dart31
-rw-r--r--lib/data/data_providers/radio_presets_provider.dart49
-rw-r--r--lib/data/data_providers/val_client.dart7
-rw-r--r--lib/data/data_providers/vehicle_notifier.dart2
-rw-r--r--lib/data/models/audio_state.dart (renamed from lib/data/models/audio.dart)24
-rw-r--r--lib/data/models/radio_state.dart100
-rw-r--r--lib/export.dart11
-rw-r--r--lib/presentation/common_widget/custom_bottom_bar.dart2
-rw-r--r--lib/presentation/common_widget/volume_and_fan_control.dart2
-rw-r--r--lib/presentation/router/routes/routes.dart4
-rw-r--r--lib/presentation/screens/media/media.dart (renamed from lib/presentation/screens/media_player/media_player.dart)57
-rw-r--r--lib/presentation/screens/media/media_nav_notifier.dart18
-rw-r--r--lib/presentation/screens/media/media_player.dart (renamed from lib/presentation/screens/media_player/media_content.dart)15
-rw-r--r--lib/presentation/screens/media/media_player_controls.dart235
-rw-r--r--lib/presentation/screens/media/play_list_table.dart (renamed from lib/presentation/screens/media_player/play_list_table.dart)1
-rw-r--r--lib/presentation/screens/media/player_navigation.dart (renamed from lib/presentation/screens/media_player/player_navigation.dart)30
-rw-r--r--lib/presentation/screens/media/radio_player.dart (renamed from lib/presentation/screens/media_player/fm_player.dart)49
-rw-r--r--lib/presentation/screens/media/radio_player_controls.dart251
-rw-r--r--lib/presentation/screens/media/radio_preset_table.dart151
-rw-r--r--lib/presentation/screens/media/segmented_buttons.dart (renamed from lib/presentation/screens/media_player/segmented_buttons.dart)0
-rw-r--r--lib/presentation/screens/media/widgets/gradient_progress_indicator.dart (renamed from lib/presentation/screens/media_player/widgets/gradient_progress_indicator.dart)0
-rw-r--r--lib/presentation/screens/media/widgets/media_volume_bar.dart (renamed from lib/presentation/screens/media_player/widgets/media_volume_bar.dart)37
-rw-r--r--lib/presentation/screens/media_player/media_controls.dart413
-rw-r--r--lib/presentation/screens/media_player/my_media.dart0
-rw-r--r--lib/presentation/screens/settings/settings_screens/audio_settings/widget/slider_widgets.dart14
-rw-r--r--lib/presentation/screens/splash/widget/splash_content.dart3
31 files changed, 1232 insertions, 570 deletions
diff --git a/lib/data/data_providers/app_config_provider.dart b/lib/data/data_providers/app_config_provider.dart
index 7e0ddc6..a60a462 100644
--- a/lib/data/data_providers/app_config_provider.dart
+++ b/lib/data/data_providers/app_config_provider.dart
@@ -35,14 +35,40 @@ class KuksaConfig {
}
}
+class RadioConfig {
+ final String hostname;
+ final int port;
+ final String presets;
+
+ static String defaultHostname = 'localhost';
+ static int defaultPort = 50053;
+ static String defaultPresets =
+ '/etc/xdg/AGL/ics-homescreen/radio-presets.yaml';
+
+ RadioConfig(
+ {required this.hostname, required this.port, required this.presets});
+
+ static RadioConfig defaultConfig() {
+ return RadioConfig(
+ hostname: RadioConfig.defaultHostname,
+ port: RadioConfig.defaultPort,
+ presets: RadioConfig.defaultPresets);
+ }
+}
+
class AppConfig {
final bool disableBkgAnimation;
final bool randomHybridAnimation;
final KuksaConfig kuksaConfig;
+ final RadioConfig radioConfig;
static String configFilePath = '/etc/xdg/AGL/ics-homescreen.yaml';
- AppConfig({required this.disableBkgAnimation, required this.randomHybridAnimation, required this.kuksaConfig});
+ AppConfig(
+ {required this.disableBkgAnimation,
+ required this.randomHybridAnimation,
+ required this.kuksaConfig,
+ required this.radioConfig});
static KuksaConfig parseKuksaConfig(YamlMap kuksaMap) {
try {
@@ -64,7 +90,7 @@ class AppConfig {
debugPrint("Reading authorization token $s");
try {
token = File(s).readAsStringSync();
- } on Exception catch (_) {
+ } catch (_) {
print("ERROR: Could not read authorization token file $token");
token = "";
}
@@ -89,7 +115,7 @@ class AppConfig {
}
try {
ca_cert = File(ca_path).readAsBytesSync();
- } on Exception catch (_) {
+ } catch (_) {
print("ERROR: Could not read CA certificate file $ca_path");
ca_cert = [];
}
@@ -107,10 +133,33 @@ class AppConfig {
use_tls: use_tls,
ca_certificate: ca_cert,
tls_server_name: tls_server_name);
- } on Exception catch (_) {
+ } catch (_) {
return KuksaConfig.defaultConfig();
}
}
+
+ static RadioConfig parseRadioConfig(YamlMap radioMap) {
+ try {
+ String hostname = RadioConfig.defaultHostname;
+ if (radioMap.containsKey('hostname')) {
+ hostname = radioMap['hostname'];
+ }
+
+ int port = RadioConfig.defaultPort;
+ if (radioMap.containsKey('port')) {
+ port = radioMap['port'];
+ }
+
+ String presets = RadioConfig.defaultPresets;
+ if (radioMap.containsKey('presets')) {
+ hostname = radioMap['presets'];
+ }
+
+ return RadioConfig(hostname: hostname, port: port, presets: presets);
+ } catch (_) {
+ return RadioConfig.defaultConfig();
+ }
+ }
}
final appConfigProvider = Provider((ref) {
@@ -133,6 +182,13 @@ final appConfigProvider = Provider((ref) {
tls_server_name: "");
}
+ RadioConfig radioConfig;
+ if (yamlMap.containsKey('radio')) {
+ radioConfig = AppConfig.parseRadioConfig(yamlMap['radio']);
+ } else {
+ radioConfig = RadioConfig.defaultConfig();
+ }
+
bool disableBkgAnimation = disableBkgAnimationDefault;
if (yamlMap.containsKey('disable-bg-animation')) {
var value = yamlMap['disable-bg-animation'];
@@ -152,11 +208,13 @@ final appConfigProvider = Provider((ref) {
return AppConfig(
disableBkgAnimation: disableBkgAnimation,
randomHybridAnimation: randomHybridAnimation,
- kuksaConfig: kuksaConfig);
- } on Exception catch (_) {
+ kuksaConfig: kuksaConfig,
+ radioConfig: radioConfig);
+ } catch (_) {
return AppConfig(
disableBkgAnimation: false,
randomHybridAnimation: false,
- kuksaConfig: KuksaConfig.defaultConfig());
+ kuksaConfig: KuksaConfig.defaultConfig(),
+ radioConfig: RadioConfig.defaultConfig());
}
});
diff --git a/lib/data/data_providers/app_launcher.dart b/lib/data/data_providers/app_launcher.dart
index b0199d3..8762643 100644
--- a/lib/data/data_providers/app_launcher.dart
+++ b/lib/data/data_providers/app_launcher.dart
@@ -1,5 +1,6 @@
import 'package:flutter_ics_homescreen/export.dart';
-import 'package:protos/protos.dart';
+import 'package:protos/applauncher-api.dart';
+import 'package:protos/agl-shell-api.dart';
class AppLauncher {
final Ref ref;
@@ -9,20 +10,18 @@ class AppLauncher {
late ClientChannel appLauncherChannel;
late AppLauncherClient appLauncher;
- List<String> appStack = [ 'homescreen' ];
+ List<String> appStack = ['homescreen'];
AppLauncher({required this.ref}) {
- aglShellChannel =
- ClientChannel('localhost',
- port: 14005,
- options: ChannelOptions(credentials: ChannelCredentials.insecure()));
+ aglShellChannel = ClientChannel('localhost',
+ port: 14005,
+ options: ChannelOptions(credentials: ChannelCredentials.insecure()));
aglShell = AglShellManagerServiceClient(aglShellChannel);
- appLauncherChannel =
- ClientChannel('localhost',
- port: 50052,
- options: ChannelOptions(credentials: ChannelCredentials.insecure()));
+ appLauncherChannel = ClientChannel('localhost',
+ port: 50052,
+ options: ChannelOptions(credentials: ChannelCredentials.insecure()));
appLauncher = AppLauncherClient(appLauncherChannel);
}
@@ -58,13 +57,23 @@ class AppLauncher {
debugPrint("Got app:");
debugPrint("$info");
// Existing icons are currently not usable, so leave blank for now
- apps.add(AppLauncherInfo(id: info.id, name: info.name, icon: "", internal: false));
+ apps.add(AppLauncherInfo(
+ id: info.id, name: info.name, icon: "", internal: false));
}
apps.sort((a, b) => a.name.compareTo(b.name));
// Add built-in app widgets
- apps.insert(0, AppLauncherInfo(id: "clock", name: "Clock", icon: "clock.svg", internal: true));
- apps.insert(0, AppLauncherInfo(id: "weather", name: "Weather", icon: "weather.svg", internal: true));
+ apps.insert(
+ 0,
+ AppLauncherInfo(
+ id: "clock", name: "Clock", icon: "clock.svg", internal: true));
+ apps.insert(
+ 0,
+ AppLauncherInfo(
+ id: "weather",
+ name: "Weather",
+ icon: "weather.svg",
+ internal: true));
ref.read(appLauncherListProvider.notifier).update(apps);
} catch (e) {
@@ -104,5 +113,4 @@ class AppLauncher {
}
}
}
-
}
diff --git a/lib/data/data_providers/app_provider.dart b/lib/data/data_providers/app_provider.dart
index 1670eba..ad3dd22 100644
--- a/lib/data/data_providers/app_provider.dart
+++ b/lib/data/data_providers/app_provider.dart
@@ -4,8 +4,10 @@ import 'package:flutter_ics_homescreen/data/data_providers/time_notifier.dart';
import 'package:flutter_ics_homescreen/data/data_providers/units_notifier.dart';
import 'package:flutter_ics_homescreen/data/data_providers/audio_notifier.dart';
import 'package:flutter_ics_homescreen/data/data_providers/users_notifier.dart';
+import 'package:flutter_ics_homescreen/data/data_providers/radio_notifier.dart';
import 'package:flutter_ics_homescreen/data/data_providers/val_client.dart';
import 'package:flutter_ics_homescreen/data/data_providers/app_launcher.dart';
+import 'package:flutter_ics_homescreen/data/data_providers/radio_client.dart';
import 'package:flutter_ics_homescreen/export.dart';
import '../models/users.dart';
@@ -16,7 +18,7 @@ enum AppState {
dashboard,
hvac,
apps,
- mediaPlayer,
+ media,
settings,
splash,
dateTime,
@@ -48,7 +50,14 @@ final appLauncherProvider = Provider((ref) {
return AppLauncher(ref: ref);
});
-final appLauncherListProvider = NotifierProvider<AppLauncherList, List<AppLauncherInfo>>(AppLauncherList.new);
+final appLauncherListProvider =
+ NotifierProvider<AppLauncherList, List<AppLauncherInfo>>(
+ AppLauncherList.new);
+
+final radioClientProvider = Provider((ref) {
+ RadioConfig config = ref.watch(appConfigProvider).radioConfig;
+ return RadioClient(config: config, ref: ref);
+});
final vehicleProvider =
NotifierProvider<VehicleNotifier, Vehicle>(VehicleNotifier.new);
@@ -62,7 +71,10 @@ final unitStateProvider = StateNotifierProvider<UnitsNotifier, Units>((ref) {
});
final audioStateProvider =
- NotifierProvider<AudioNotifier, Audio>(AudioNotifier.new);
+ NotifierProvider<AudioStateNotifier, AudioState>(AudioStateNotifier.new);
+
+final radioStateProvider =
+ NotifierProvider<RadioStateNotifier, RadioState>(RadioStateNotifier.new);
final usersProvider = StateNotifierProvider<UsersNotifier, Users>((ref) {
return UsersNotifier(Users.initial());
@@ -77,4 +89,3 @@ final currentTimeProvider =
StateNotifierProvider<CurrentTimeNotifier, DateTime>((ref) {
return CurrentTimeNotifier();
});
-
diff --git a/lib/data/data_providers/audio_notifier.dart b/lib/data/data_providers/audio_notifier.dart
index 32ab409..a601095 100644
--- a/lib/data/data_providers/audio_notifier.dart
+++ b/lib/data/data_providers/audio_notifier.dart
@@ -1,10 +1,10 @@
import 'package:flutter_ics_homescreen/export.dart';
-import 'package:protos/protos.dart';
+import 'package:protos/val-api.dart';
-class AudioNotifier extends Notifier<Audio> {
+class AudioStateNotifier extends Notifier<AudioState> {
@override
- Audio build() {
- return Audio.initial();
+ AudioState build() {
+ return AudioState.initial();
}
void resetToDefaults() {
diff --git a/lib/data/data_providers/radio_client.dart b/lib/data/data_providers/radio_client.dart
new file mode 100644
index 0000000..2cde65e
--- /dev/null
+++ b/lib/data/data_providers/radio_client.dart
@@ -0,0 +1,161 @@
+import 'package:flutter_ics_homescreen/export.dart';
+import 'package:protos/radio-api.dart' as api;
+
+class RadioClient {
+ final RadioConfig config;
+ final Ref ref;
+ late api.ClientChannel channel;
+ late api.RadioClient stub;
+
+ RadioClient({required this.config, required this.ref}) {
+ debugPrint(
+ "Connecting to radio service at ${config.hostname}:${config.port}");
+ api.ChannelCredentials creds = const api.ChannelCredentials.insecure();
+ channel = api.ClientChannel(config.hostname,
+ port: config.port, options: api.ChannelOptions(credentials: creds));
+ stub = api.RadioClient(channel);
+ }
+
+ void run() async {
+ getBandParameters();
+
+ try {
+ var responseStream = stub.getStatusEvents(api.StatusRequest());
+ await for (var event in responseStream) {
+ handleStatusEvent(event);
+ }
+ } catch (e) {
+ print(e);
+ }
+ }
+
+ void getBandParameters() async {
+ try {
+ var response = await stub.getBandParameters(
+ api.GetBandParametersRequest(band: api.Band.BAND_FM));
+ ref.read(radioStateProvider.notifier).updateBandParameters(
+ freqMin: response.min,
+ freqMax: response.max,
+ freqStep: response.step);
+
+ // Get initial frequency
+ var freqResponse = await stub.getFrequency(api.GetFrequencyRequest());
+ ref
+ .read(radioStateProvider.notifier)
+ .updateFrequency(freqResponse.frequency);
+ } catch (e) {
+ print(e);
+ }
+ }
+
+ void handleStatusEvent(api.StatusResponse response) {
+ switch (response.whichStatus()) {
+ case api.StatusResponse_Status.frequency:
+ var status = response.frequency;
+ ref.read(radioStateProvider.notifier).updateFrequency(status.frequency);
+ break;
+ case api.StatusResponse_Status.play:
+ var status = response.play;
+ ref.read(radioStateProvider.notifier).updatePlaying(status.playing);
+ break;
+ case api.StatusResponse_Status.scan:
+ var status = response.scan;
+ if (status.stationFound) {
+ ref.read(radioStateProvider.notifier).updateScanning(false);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ void start() async {
+ try {
+ var response = await stub.start(api.StartRequest());
+ } catch (e) {
+ print(e);
+ }
+ }
+
+ void stop() async {
+ try {
+ var response = await stub.stop(api.StopRequest());
+ } catch (e) {
+ print(e);
+ }
+ }
+
+ void setFrequency(int frequency) async {
+ var radioState = ref.read(radioStateProvider);
+ if ((frequency < radioState.freqMin) ||
+ (frequency > radioState.freqMax) ||
+ ((frequency - radioState.freqMin) % radioState.freqStep) != 0) {
+ debugPrint("setFrequency: invalid frequency $frequency!");
+ return;
+ }
+ try {
+ var response = await stub
+ .setFrequency(api.SetFrequencyRequest(frequency: frequency));
+ } catch (e) {
+ print(e);
+ }
+ }
+
+ void tuneForward() async {
+ var radioState = ref.read(radioStateProvider);
+ if (radioState.freqCurrent < radioState.freqMax) {
+ int frequency = radioState.freqCurrent + radioState.freqStep;
+ if (frequency > radioState.freqMax) {
+ frequency = radioState.freqMax;
+ }
+ try {
+ var response = await stub
+ .setFrequency(api.SetFrequencyRequest(frequency: frequency));
+ } catch (e) {
+ print(e);
+ }
+ }
+ }
+
+ void tuneBackward() async {
+ var radioState = ref.read(radioStateProvider);
+ if (radioState.freqCurrent > radioState.freqMin) {
+ int frequency = radioState.freqCurrent - radioState.freqStep;
+ if (frequency < radioState.freqMin) {
+ frequency = radioState.freqMin;
+ }
+ try {
+ var response = await stub
+ .setFrequency(api.SetFrequencyRequest(frequency: frequency));
+ } catch (e) {
+ print(e);
+ }
+ }
+ }
+
+ void scanForward() async {
+ try {
+ var response = await stub.scanStart(api.ScanStartRequest(
+ direction: api.ScanDirection.SCAN_DIRECTION_FORWARD));
+ } catch (e) {
+ print(e);
+ }
+ }
+
+ void scanBackward() async {
+ try {
+ var response = await stub.scanStart(api.ScanStartRequest(
+ direction: api.ScanDirection.SCAN_DIRECTION_BACKWARD));
+ } catch (e) {
+ print(e);
+ }
+ }
+
+ void scanStop() async {
+ try {
+ var response = await stub.scanStop(api.ScanStopRequest());
+ } catch (e) {
+ print(e);
+ }
+ }
+}
diff --git a/lib/data/data_providers/radio_notifier.dart b/lib/data/data_providers/radio_notifier.dart
new file mode 100644
index 0000000..90e0df5
--- /dev/null
+++ b/lib/data/data_providers/radio_notifier.dart
@@ -0,0 +1,31 @@
+import 'package:flutter_ics_homescreen/export.dart';
+
+class RadioStateNotifier extends Notifier<RadioState> {
+ @override
+ RadioState build() {
+ return RadioState.initial();
+ }
+
+ void updateBandParameters(
+ {required int freqMin, required freqMax, required freqStep}) {
+ state =
+ state.copyWith(freqMin: freqMin, freqMax: freqMax, freqStep: freqStep);
+ }
+
+ void updateFrequency(int frequency) {
+ state = state.copyWith(freqCurrent: frequency);
+ }
+
+ void setFrequency(int frequency) {
+ state = state.copyWith(freqCurrent: frequency);
+ ref.read(radioClientProvider).setFrequency(frequency);
+ }
+
+ void updatePlaying(bool playing) {
+ state = state.copyWith(playing: playing);
+ }
+
+ void updateScanning(bool scanning) {
+ state = state.copyWith(scanning: scanning);
+ }
+}
diff --git a/lib/data/data_providers/radio_presets_provider.dart b/lib/data/data_providers/radio_presets_provider.dart
new file mode 100644
index 0000000..9ee68ac
--- /dev/null
+++ b/lib/data/data_providers/radio_presets_provider.dart
@@ -0,0 +1,49 @@
+import 'dart:io';
+import 'package:flutter_ics_homescreen/export.dart';
+import 'package:yaml/yaml.dart';
+
+class RadioPreset {
+ final int frequency;
+ final String name;
+
+ RadioPreset({required this.frequency, required this.name});
+}
+
+class RadioPresets {
+ final List<RadioPreset> fmPresets;
+
+ RadioPresets({required this.fmPresets});
+}
+
+final radioPresetsProvider = Provider((ref) {
+ final presetsFilename = ref.read(appConfigProvider).radioConfig.presets;
+ if (presetsFilename.isEmpty) {
+ return RadioPresets(fmPresets: []);
+ }
+ try {
+ print("Reading radio presets $presetsFilename");
+ var presetsFile = File(presetsFilename);
+ String content = presetsFile.readAsStringSync();
+ final dynamic yamlMap = loadYaml(content);
+
+ List<RadioPreset> presets = [];
+ if (yamlMap.containsKey('fm')) {
+ dynamic list = yamlMap['fm'];
+ if (list is YamlList) {
+ for (var element in list) {
+ if ((element is YamlMap) &&
+ element.containsKey('frequency') &&
+ element.containsKey('name')) {
+ presets.add(RadioPreset(
+ frequency: element['frequency'].toInt(),
+ name: element['name'].toString()));
+ }
+ }
+ }
+ }
+ return RadioPresets(fmPresets: presets);
+ } catch (_) {
+ debugPrint("Exception reading presets!");
+ return RadioPresets(fmPresets: []);
+ }
+});
diff --git a/lib/data/data_providers/val_client.dart b/lib/data/data_providers/val_client.dart
index 28bb480..db962ee 100644
--- a/lib/data/data_providers/val_client.dart
+++ b/lib/data/data_providers/val_client.dart
@@ -1,5 +1,5 @@
import 'package:flutter_ics_homescreen/export.dart';
-import 'package:protos/protos.dart';
+import 'package:protos/val-api.dart';
class ValClient {
final KuksaConfig config;
@@ -9,7 +9,7 @@ class ValClient {
late String authorization;
ValClient({required this.config, required this.ref}) {
- debugPrint("Using ${config.hostname}:${config.port}");
+ debugPrint("Connecting to KUKSA.val at ${config.hostname}:${config.port}");
ChannelCredentials creds;
if (config.use_tls && config.ca_certificate.isNotEmpty) {
print("Using TLS");
@@ -25,11 +25,10 @@ class ValClient {
}
channel = ClientChannel(config.hostname,
port: config.port, options: ChannelOptions(credentials: creds));
- debugPrint('Start Listen on port: ${config.port}');
stub = VALClient(channel);
}
- void startListen() async {
+ void run() async {
List<String> fewSignals = VSSPath().getSignalsList();
var request = SubscribeRequest();
Map<String, String> metadata = {};
diff --git a/lib/data/data_providers/vehicle_notifier.dart b/lib/data/data_providers/vehicle_notifier.dart
index 78c5328..6fafb8c 100644
--- a/lib/data/data_providers/vehicle_notifier.dart
+++ b/lib/data/data_providers/vehicle_notifier.dart
@@ -3,7 +3,7 @@
import 'dart:async';
import 'package:flutter_ics_homescreen/export.dart';
-import 'package:protos/protos.dart';
+import 'package:protos/val-api.dart';
class VehicleNotifier extends Notifier<Vehicle> {
@override
diff --git a/lib/data/models/audio.dart b/lib/data/models/audio_state.dart
index 65490f9..cfa550b 100644
--- a/lib/data/models/audio.dart
+++ b/lib/data/models/audio_state.dart
@@ -3,13 +3,13 @@ import 'dart:convert';
import 'package:flutter_ics_homescreen/export.dart';
@immutable
-class Audio {
+class AudioState {
final double volume;
final double balance;
final double fade;
final double treble;
final double bass;
- const Audio({
+ const AudioState({
required this.volume,
required this.balance,
required this.fade,
@@ -17,22 +17,21 @@ class Audio {
required this.bass,
});
- const Audio.initial()
+ const AudioState.initial()
: volume = 5.0,
balance = 5.0,
fade = 5.0,
treble = 5.0,
bass = 5.0;
-
- Audio copyWith({
+ AudioState copyWith({
double? volume,
double? balance,
double? fade,
double? treble,
double? bass,
}) {
- return Audio(
+ return AudioState(
volume: volume ?? this.volume,
balance: balance ?? this.balance,
fade: fade ?? this.fade,
@@ -51,8 +50,8 @@ class Audio {
};
}
- factory Audio.fromMap(Map<String, dynamic> map) {
- return Audio(
+ factory AudioState.fromMap(Map<String, dynamic> map) {
+ return AudioState(
volume: map['volume']?.toDouble() ?? 0.0,
balance: map['balance']?.toDouble() ?? 0.0,
fade: map['fade']?.toDouble() ?? 0.0,
@@ -63,18 +62,19 @@ class Audio {
String toJson() => json.encode(toMap());
- factory Audio.fromJson(String source) => Audio.fromMap(json.decode(source));
+ factory AudioState.fromJson(String source) =>
+ AudioState.fromMap(json.decode(source));
@override
String toString() {
- return 'Audio(volume: $volume, balance: $balance, fade: $fade, treble: $treble, bass: $bass)';
+ return 'AudioState(volume: $volume, balance: $balance, fade: $fade, treble: $treble, bass: $bass)';
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
-
- return other is Audio &&
+
+ return other is AudioState &&
other.volume == volume &&
other.balance == balance &&
other.fade == fade &&
diff --git a/lib/data/models/radio_state.dart b/lib/data/models/radio_state.dart
new file mode 100644
index 0000000..dd307d9
--- /dev/null
+++ b/lib/data/models/radio_state.dart
@@ -0,0 +1,100 @@
+import 'dart:convert';
+
+import 'package:flutter_ics_homescreen/export.dart';
+
+@immutable
+class RadioState {
+ final int freqMin;
+ final int freqMax;
+ final int freqStep;
+ final int freqCurrent;
+ final bool playing;
+ final bool scanning;
+ const RadioState(
+ {required this.freqMin,
+ required this.freqMax,
+ required this.freqStep,
+ required this.freqCurrent,
+ required this.playing,
+ required this.scanning});
+
+ const RadioState.initial()
+ : freqMin = 8790000,
+ freqMax = 1083000,
+ freqStep = 20000,
+ freqCurrent = 8790000,
+ playing = false,
+ scanning = false;
+
+ RadioState copyWith(
+ {int? freqMin,
+ int? freqMax,
+ int? freqStep,
+ int? freqCurrent,
+ bool? playing,
+ bool? scanning}) {
+ return RadioState(
+ freqMin: freqMin ?? this.freqMin,
+ freqMax: freqMax ?? this.freqMax,
+ freqStep: freqStep ?? this.freqStep,
+ freqCurrent: freqCurrent ?? this.freqCurrent,
+ playing: playing ?? this.playing,
+ scanning: scanning ?? this.scanning,
+ );
+ }
+
+ Map<String, dynamic> toMap() {
+ return {
+ 'freqMin': freqMin,
+ 'freqMax': freqMax,
+ 'freqStep': freqStep,
+ 'freqCurrent': freqCurrent,
+ 'playing': playing,
+ 'scanning': scanning,
+ };
+ }
+
+ factory RadioState.fromMap(Map<String, dynamic> map) {
+ return RadioState(
+ freqMin: map['freqMin']?.toInt().toUnsigned() ?? 0,
+ freqMax: map['freqMax']?.toInt().toUnsigned() ?? 0,
+ freqStep: map['freqStep']?.toInt().toUnsigned() ?? 0,
+ freqCurrent: map['freqCurrent']?.toInt().toUnsigned() ?? 0,
+ playing: map['playing']?.toBool() ?? false,
+ scanning: map['scanning']?.toBool() ?? false,
+ );
+ }
+
+ String toJson() => json.encode(toMap());
+
+ factory RadioState.fromJson(String source) =>
+ RadioState.fromMap(json.decode(source));
+
+ @override
+ String toString() {
+ return 'RadioState(freqMin: $freqMin, freqMax: $freqMax, freqStep: $freqStep, freqCurrent: $freqCurrent, playing: $playing, scanning: $scanning)';
+ }
+
+ @override
+ bool operator ==(Object other) {
+ if (identical(this, other)) return true;
+
+ return other is RadioState &&
+ other.freqMin == freqMin &&
+ other.freqMax == freqMax &&
+ other.freqStep == freqStep &&
+ other.freqCurrent == freqCurrent &&
+ other.playing == playing &&
+ other.scanning == scanning;
+ }
+
+ @override
+ int get hashCode {
+ return freqMin.hashCode ^
+ freqMax.hashCode ^
+ freqStep.hashCode ^
+ freqCurrent.hashCode ^
+ playing.hashCode ^
+ scanning.hashCode;
+ }
+}
diff --git a/lib/export.dart b/lib/export.dart
index 1e07f3f..a5c5626 100644
--- a/lib/export.dart
+++ b/lib/export.dart
@@ -8,7 +8,8 @@ export 'data/theme/theme.dart';
//Models
export 'data/models/vehicle.dart';
export 'data/models/units.dart';
-export 'data/models/audio.dart';
+export 'data/models/audio_state.dart';
+export 'data/models/radio_state.dart';
export 'data/models/connections_signals.dart';
export 'data/models/hybrid.dart';
@@ -25,7 +26,7 @@ export 'presentation/screens/dashboard/widgets/child_lock.dart';
export 'presentation/screens/dashboard/widgets/hybrid_mode.dart';
export 'presentation/common_widget/custom_bottom_bar.dart';
export 'presentation/common_widget/custom_top_bar.dart';
-export 'presentation/screens/media_player/media_player.dart';
+export 'presentation/screens/media/media.dart';
export 'presentation/screens/hvac/hvac.dart';
export 'presentation/screens/settings/settings.dart';
export 'presentation/screens/settings/widgets/settings_list_tile.dart';
@@ -44,13 +45,7 @@ export 'package:flutter_ics_homescreen/presentation/screens/settings/settings_sc
export 'presentation/screens/apps/apps.dart';
export 'presentation/screens/splash/splash.dart';
export 'presentation/screens/splash/widget/splash_content.dart';
-//export 'presentation/screens/apps/apps_content.dart';
export 'presentation/screens/hvac/hvac_content.dart';
-export 'presentation/screens/media_player/media_controls.dart';
-export 'presentation/screens/media_player/play_list_table.dart';
-export 'presentation/screens/media_player/player_navigation.dart';
-export 'presentation/screens/media_player/segmented_buttons.dart';
-export 'presentation/screens/media_player/media_content.dart';
export 'presentation/screens/hvac/widgets/climate_controls.dart';
export 'presentation/screens/hvac/widgets/fan_focus.dart';
export 'presentation/screens/hvac/widgets/fan_speed_controls.dart';
diff --git a/lib/presentation/common_widget/custom_bottom_bar.dart b/lib/presentation/common_widget/custom_bottom_bar.dart
index 61a7e20..19c56b9 100644
--- a/lib/presentation/common_widget/custom_bottom_bar.dart
+++ b/lib/presentation/common_widget/custom_bottom_bar.dart
@@ -35,7 +35,7 @@ class CustomBottomBarState extends ConsumerState<CustomBottomBar> {
case "HVAC":
status = AppState.hvac;
case "Media":
- status = AppState.mediaPlayer;
+ status = AppState.media;
case "Settings":
status = AppState.settings;
case "Apps":
diff --git a/lib/presentation/common_widget/volume_and_fan_control.dart b/lib/presentation/common_widget/volume_and_fan_control.dart
index 051e360..b38e303 100644
--- a/lib/presentation/common_widget/volume_and_fan_control.dart
+++ b/lib/presentation/common_widget/volume_and_fan_control.dart
@@ -20,7 +20,7 @@ class VolumeFanControl extends ConsumerWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Visibility.maintain(
- visible: state == AppState.mediaPlayer ? false : true,
+ visible: state == AppState.media ? false : true,
child: const VolumeBar()),
SizedBox(
height: gapSize,
diff --git a/lib/presentation/router/routes/routes.dart b/lib/presentation/router/routes/routes.dart
index 57e50d2..45a1a14 100644
--- a/lib/presentation/router/routes/routes.dart
+++ b/lib/presentation/router/routes/routes.dart
@@ -17,8 +17,8 @@ List<Page<dynamic>> onGenerateAppViewPages(
return [HvacPage.page()];
case AppState.apps:
return [AppsPage.page()];
- case AppState.mediaPlayer:
- return [MediaPlayerPage.page()];
+ case AppState.media:
+ return [MediaPage.page()];
case AppState.settings:
return [SettingsPage.page()];
case AppState.splash:
diff --git a/lib/presentation/screens/media_player/media_player.dart b/lib/presentation/screens/media/media.dart
index 3126ac1..b7ce9e1 100644
--- a/lib/presentation/screens/media_player/media_player.dart
+++ b/lib/presentation/screens/media/media.dart
@@ -1,13 +1,14 @@
-import 'package:flutter_ics_homescreen/presentation/screens/media_player/fm_player.dart';
-
-import '/export.dart';
+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 'media_nav_notifier.dart';
+import 'player_navigation.dart';
-class MediaPlayerPage extends StatelessWidget {
- const MediaPlayerPage({super.key});
+class MediaPage extends StatelessWidget {
+ const MediaPage({super.key});
- static Page<void> page() =>
- const MaterialPage<void>(child: MediaPlayerPage());
+ static Page<void> page() => const MaterialPage<void>(child: MediaPage());
@override
Widget build(BuildContext context) {
Size size = MediaQuery.sizeOf(context);
@@ -21,7 +22,7 @@ class MediaPlayerPage extends StatelessWidget {
// // decoration:
// // BoxDecoration(gradient: AGLDemoColors.gradientBackgroundColor),
// child: SvgPicture.asset(
- // 'assets/MediaPlayerBackground.svg',
+ // 'assets/Media.svg',
// alignment: Alignment.center,
// fit: BoxFit.cover,
// //width: 200,
@@ -42,31 +43,45 @@ class MediaPlayerPage extends StatelessWidget {
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 50, horizontal: 50),
- child: MediaPlayerBackground(),
+ child: Media(),
)
- //const MediaPlayer(),
],
);
}
}
-class MediaPlayerBackground extends StatefulWidget {
- const MediaPlayerBackground({super.key});
+class Media extends ConsumerStatefulWidget {
+ const Media({super.key});
@override
- State<MediaPlayerBackground> createState() => _MediaPlayerBackgroundState();
+ ConsumerState<Media> createState() => _MediaState();
}
-class _MediaPlayerBackgroundState extends State<MediaPlayerBackground> {
- String selectedNav = "My Media";
- onPressed(type) {
+class _MediaState extends ConsumerState<Media> {
+ //late MediaNavState selectedNav;
+
+ //@override
+ //initState() {
+ // selectedNav = ref.read(mediaNavStateProvider);
+ // super.initState();
+ //}
+
+ onPressed(MediaNavState type) {
setState(() {
- selectedNav = type;
+ if (type == MediaNavState.fm) {
+ ref.read(mediaNavStateProvider.notifier).set(MediaNavState.fm);
+ ref.read(radioClientProvider).start();
+ } else if (type == MediaNavState.media) {
+ ref.read(mediaNavStateProvider.notifier).set(MediaNavState.media);
+ ref.read(radioClientProvider).stop();
+ }
});
}
@override
Widget build(BuildContext context) {
+ var navState = ref.watch(mediaNavStateProvider);
+
return SingleChildScrollView(
child: Column(
children: [
@@ -81,14 +96,14 @@ class _MediaPlayerBackgroundState extends State<MediaPlayerBackground> {
Padding(
padding: const EdgeInsets.symmetric(horizontal: 80),
child: SingleChildScrollView(
- child: selectedNav == "My Media"
+ child: navState == MediaNavState.media
? const MediaPlayer()
- : selectedNav == "FM"
- ? const FMPlayer()
+ : navState == MediaNavState.fm
+ ? const RadioPlayer()
: Container(),
),
),
- if (selectedNav == "My Media" || selectedNav == "FM")
+ 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_nav_notifier.dart b/lib/presentation/screens/media/media_nav_notifier.dart
new file mode 100644
index 0000000..6f93850
--- /dev/null
+++ b/lib/presentation/screens/media/media_nav_notifier.dart
@@ -0,0 +1,18 @@
+import 'package:flutter_ics_homescreen/export.dart';
+
+enum MediaNavState { media, fm, am, xm }
+
+class MediaNavStateNotifier extends Notifier<MediaNavState> {
+ @override
+ MediaNavState build() {
+ return MediaNavState.media;
+ }
+
+ set(MediaNavState value) {
+ state = value;
+ }
+}
+
+final mediaNavStateProvider =
+ NotifierProvider<MediaNavStateNotifier, MediaNavState>(
+ MediaNavStateNotifier.new);
diff --git a/lib/presentation/screens/media_player/media_content.dart b/lib/presentation/screens/media/media_player.dart
index 0625c9c..d7486c7 100644
--- a/lib/presentation/screens/media_player/media_content.dart
+++ b/lib/presentation/screens/media/media_player.dart
@@ -1,4 +1,7 @@
import 'package:flutter_ics_homescreen/export.dart';
+import 'media_player_controls.dart';
+import 'play_list_table.dart';
+import 'segmented_buttons.dart';
class MediaPlayer extends StatefulWidget {
const MediaPlayer({super.key});
@@ -31,7 +34,7 @@ class _MediaPlayerState extends State<MediaPlayer> {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
- // const PlayerNavigation(),
+ //const PlayerNavigation(),
SegmentedButtons(
navItems: navItems,
selectedNav: selectedNav,
@@ -55,12 +58,10 @@ class _MediaPlayerState extends State<MediaPlayer> {
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
- MediaControls(
- songName: songName,
- songLengthStart: "-1:23",
- songLengthStop: "5:03",
- type: "media",
- ),
+ MediaPlayerControls(
+ songName: songName,
+ songLengthStart: "-1:23",
+ songLengthStop: "5:03"),
const SizedBox(
height: 72,
),
diff --git a/lib/presentation/screens/media/media_player_controls.dart b/lib/presentation/screens/media/media_player_controls.dart
new file mode 100644
index 0000000..518b669
--- /dev/null
+++ b/lib/presentation/screens/media/media_player_controls.dart
@@ -0,0 +1,235 @@
+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';
+
+class MediaPlayerControls extends StatefulWidget {
+ const MediaPlayerControls(
+ {super.key,
+ required this.songName,
+ required this.songLengthStart,
+ required this.songLengthStop});
+
+ final String songName;
+ final String songLengthStart;
+ final String songLengthStop;
+
+ @override
+ State<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();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Material(
+ color: Colors.transparent,
+ child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
+ Text(
+ songName,
+ style: TextStyle(
+ color: Colors.white,
+ fontWeight: FontWeight.w400,
+ shadows: [Helpers.dropShadowRegular],
+ fontSize: 44),
+ ),
+ MediaPlayerControlsubDetails(
+ albumName: albumName,
+ ),
+ 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,
+ // ),
+ Padding(
+ padding: const EdgeInsets.symmetric(vertical: 5),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ songLengthStart,
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: 26,
+ shadows: [Helpers.dropShadowRegular]),
+ ),
+ Text(
+ songLengthStop,
+ style: TextStyle(
+ color: Colors.white,
+ fontSize: 26,
+ shadows: [Helpers.dropShadowRegular]),
+ )
+ ],
+ ),
+ ),
+ ]),
+ const MediaPlayerActions(),
+ ]),
+ );
+ }
+}
+
+class MediaPlayerControlsubDetails extends StatefulWidget {
+ const MediaPlayerControlsubDetails({super.key, required this.albumName});
+ final String albumName;
+
+ @override
+ State<MediaPlayerControlsubDetails> createState() =>
+ _MediaPlayerControlsubDetailsState();
+}
+
+class _MediaPlayerControlsubDetailsState
+ extends State<MediaPlayerControlsubDetails> {
+ bool isShuffleEnabled = false;
+ bool isRepeatEnabled = false;
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ widget.albumName,
+ style: TextStyle(
+ color: Colors.white,
+ fontWeight: FontWeight.w400,
+ fontSize: 40,
+ shadows: [Helpers.dropShadowRegular]),
+ ),
+ Row(
+ children: [
+ InkWell(
+ customBorder: const CircleBorder(),
+ onTap: () {
+ setState(() {
+ isShuffleEnabled = !isShuffleEnabled;
+ });
+ },
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: SvgPicture.asset(
+ "assets/${isShuffleEnabled ? "ShufflePressed.svg" : "Shuffle.svg"}",
+ width: 48,
+ ))),
+ InkWell(
+ customBorder: const CircleBorder(),
+ onTap: () {
+ setState(() {
+ isRepeatEnabled = !isRepeatEnabled;
+ });
+ },
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: SvgPicture.asset(
+ "assets/${isRepeatEnabled ? "RepeatPressed.svg" : "Repeat.svg"}",
+ width: 48,
+ ))),
+ ],
+ )
+ ],
+ );
+ }
+}
+
+class MediaPlayerActions extends StatefulWidget {
+ const MediaPlayerActions({super.key});
+
+ @override
+ State<MediaPlayerActions> createState() => _MediaPlayerActionsState();
+}
+
+class _MediaPlayerActionsState extends State<MediaPlayerActions> {
+ bool isPressed = false;
+ bool isPlaying = true;
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ InkWell(
+ customBorder: const CircleBorder(),
+ onTap: () {},
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: SvgPicture.asset(
+ "assets/SkipPrevious.svg",
+ width: 48,
+ ),
+ )),
+ const SizedBox(
+ width: 120,
+ ),
+ InkWell(
+ customBorder: const CircleBorder(),
+ onTap: () {
+ setState(() {
+ isPlaying = !isPlaying;
+ });
+ },
+ onTapDown: (details) {
+ setState(() {
+ isPressed = true;
+ });
+ },
+ onTapUp: (details) {
+ isPressed = false;
+ },
+ child: Container(
+ width: 64,
+ height: 64,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color:
+ isPressed ? Colors.white : AGLDemoColors.periwinkleColor,
+ boxShadow: [Helpers.boxDropShadowRegular]),
+ child: Icon(
+ isPlaying ? Icons.pause : Icons.play_arrow,
+ color: AGLDemoColors.resolutionBlueColor,
+ size: 60,
+ ),
+ )),
+ const SizedBox(
+ width: 120,
+ ),
+ InkWell(
+ customBorder: const CircleBorder(),
+ onTap: () {},
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: SvgPicture.asset(
+ "assets/SkipNext.svg",
+ width: 48,
+ ),
+ )),
+ ],
+ );
+ }
+}
diff --git a/lib/presentation/screens/media_player/play_list_table.dart b/lib/presentation/screens/media/play_list_table.dart
index e5c1292..369bb9c 100644
--- a/lib/presentation/screens/media_player/play_list_table.dart
+++ b/lib/presentation/screens/media/play_list_table.dart
@@ -23,6 +23,7 @@ class _PlayListTableState extends State<PlayListTable> {
late String tableName;
late List<PlayListModel> playList;
late String selectedPlayListSongName;
+
@override
void initState() {
tableName = widget.tableName;
diff --git a/lib/presentation/screens/media_player/player_navigation.dart b/lib/presentation/screens/media/player_navigation.dart
index 8e09e53..70a9906 100644
--- a/lib/presentation/screens/media_player/player_navigation.dart
+++ b/lib/presentation/screens/media/player_navigation.dart
@@ -1,19 +1,30 @@
import 'package:flutter_ics_homescreen/core/utils/helpers.dart';
import 'package:flutter_ics_homescreen/export.dart';
+import 'media_nav_notifier.dart';
-class PlayerNavigation extends StatefulWidget {
+class PlayerNavigation extends ConsumerStatefulWidget {
const PlayerNavigation({super.key, required this.onPressed});
final Function onPressed;
@override
- State<PlayerNavigation> createState() => _PlayerNavigationState();
+ ConsumerState<PlayerNavigation> createState() => _PlayerNavigationState();
}
-class _PlayerNavigationState extends State<PlayerNavigation> {
+class _PlayerNavigationState extends ConsumerState<PlayerNavigation> {
List<String> navItems = ["My Media", "FM", "AM", "XM"];
- String selectedNav = "My Media";
+ Map<MediaNavState, String> navStateMap = {
+ MediaNavState.media: "My Media",
+ MediaNavState.fm: "FM",
+ MediaNavState.am: "AM",
+ MediaNavState.xm: "XM"
+ };
+ //String selectedNav = "My Media";
+
@override
Widget build(BuildContext context) {
+ var navState = ref.watch(mediaNavStateProvider);
+ var selectedNav = navStateMap[navState];
+
return Row(
children: navItems
.map((e) => Expanded(
@@ -35,9 +46,16 @@ class _PlayerNavigationState extends State<PlayerNavigation> {
child: InkWell(
onTap: () {
setState(() {
- selectedNav = e;
+ if (e == "My Media" || e == "FM") {
+ selectedNav = e;
+ }
});
- widget.onPressed(selectedNav);
+ if (e == "My Media" || e == "FM") {
+ for (MapEntry<MediaNavState, String> me
+ in navStateMap.entries) {
+ if (me.value == e) widget.onPressed(me.key);
+ }
+ }
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 7),
diff --git a/lib/presentation/screens/media_player/fm_player.dart b/lib/presentation/screens/media/radio_player.dart
index 31a22ae..4531c7b 100644
--- a/lib/presentation/screens/media_player/fm_player.dart
+++ b/lib/presentation/screens/media/radio_player.dart
@@ -1,25 +1,37 @@
+import 'package:flutter_ics_homescreen/data/data_providers/radio_presets_provider.dart';
import 'package:flutter_ics_homescreen/export.dart';
+import 'radio_player_controls.dart';
+import 'radio_preset_table.dart';
+import 'segmented_buttons.dart';
-class FMPlayer extends StatefulWidget {
- const FMPlayer({super.key});
+class RadioPlayer extends ConsumerStatefulWidget {
+ const RadioPlayer({super.key});
@override
- State<FMPlayer> createState() => _FMPlayerState();
+ ConsumerState<RadioPlayer> createState() => _RadioPlayerState();
}
-class _FMPlayerState extends State<FMPlayer> {
+class _RadioPlayerState extends ConsumerState<RadioPlayer> {
String selectedNav = "Standard";
List<String> navItems = [
"Standard",
"HD",
];
String tableName = "Presets";
- List<PlayListModel> playList = [
- PlayListModel(songName: "93.1 The Mountain", albumName: "93.1"),
- PlayListModel(songName: "Mix 94.1", albumName: "94.1 MHz"),
- PlayListModel(songName: "96.3 KKLZ", albumName: "96.3 MHz"),
- ];
- String selectedPlayListSongName = "93.1 The Mountain";
+ late List<RadioPreset> presets;
+ late String selectedPreset;
+
+ @override
+ void initState() {
+ presets = ref.read(radioPresetsProvider).fmPresets;
+ if (presets.isNotEmpty) {
+ selectedPreset = presets.first.name;
+ } else {
+ selectedPreset = "";
+ }
+ super.initState();
+ }
+
@override
Widget build(BuildContext context) {
double fmSignalHeight = 460;
@@ -52,21 +64,14 @@ class _FMPlayerState extends State<FMPlayer> {
),
Column(
children: [
- const MediaControls(
- songName: "87.9",
- songLengthStart: "87.9 MHz",
- songLengthStop: "87.9 MHz",
- type: "fm",
- ),
+ const RadioPlayerControls(),
const SizedBox(
height: 70,
),
- PlayListTable(
- playList: playList,
- selectedPlayListSongName: selectedPlayListSongName,
- tableName: tableName,
- type: "fm",
- ),
+ RadioPresetTable(
+ presets: presets,
+ selectedPreset: selectedPreset,
+ tableName: tableName),
],
)
],
diff --git a/lib/presentation/screens/media/radio_player_controls.dart b/lib/presentation/screens/media/radio_player_controls.dart
new file mode 100644
index 0000000..bfa8da6
--- /dev/null
+++ b/lib/presentation/screens/media/radio_player_controls.dart
@@ -0,0 +1,251 @@
+import 'package:flutter_ics_homescreen/core/utils/helpers.dart';
+import 'package:flutter_ics_homescreen/export.dart';
+import 'package:flutter_ics_homescreen/presentation/screens/settings/settings_screens/audio_settings/widget/slider_widgets.dart';
+
+class RadioPlayerControls extends ConsumerWidget {
+ const RadioPlayerControls({super.key});
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ var freqCurrent =
+ ref.watch(radioStateProvider.select((radio) => radio.freqCurrent));
+ String currentString = (freqCurrent / 1000000.0).toStringAsFixed(1);
+
+ return Material(
+ color: Colors.transparent,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ Text(
+ currentString,
+ style: TextStyle(
+ color: Colors.white,
+ fontWeight: FontWeight.w400,
+ shadows: [Helpers.dropShadowRegular],
+ fontSize: 44),
+ ),
+ const RadioPlayerControlsSubDetails(),
+ const RadioPlayerControlsSlider(),
+ ],
+ ),
+ );
+ }
+}
+
+class RadioPlayerControlsSubDetails extends ConsumerWidget {
+ const RadioPlayerControlsSubDetails({super.key});
+
+ onPressed({required WidgetRef ref, required String type}) {
+ if (type == "tuneLeft") {
+ ref.read(radioClientProvider).tuneBackward();
+ } else if (type == "tuneRight") {
+ ref.read(radioClientProvider).tuneForward();
+ } else if (type == "scanLeft") {
+ bool playing =
+ ref.read(radioStateProvider.select((radio) => radio.playing));
+ if (playing) {
+ ref.read(radioClientProvider).scanBackward();
+ }
+ } else if (type == "scanRight") {
+ bool playing =
+ ref.read(radioStateProvider.select((radio) => radio.playing));
+ if (playing) {
+ ref.read(radioClientProvider).scanForward();
+ }
+ }
+ }
+
+ @override
+ Widget build(BuildContext context, WidgetRef ref) {
+ return Padding(
+ padding: const EdgeInsets.only(bottom: 5),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ Text(
+ "Tune",
+ style: TextStyle(
+ color: Colors.white,
+ fontWeight: FontWeight.w400,
+ fontSize: 40,
+ shadows: [Helpers.dropShadowRegular]),
+ ),
+ const SizedBox(
+ width: 25,
+ ),
+ InkWell(
+ customBorder: const CircleBorder(),
+ onTap: () {
+ onPressed(ref: ref, type: "tuneLeft");
+ },
+ child: const Padding(
+ padding: EdgeInsets.all(8.0),
+ child: Icon(
+ Icons.arrow_back,
+ size: 48,
+ color: AGLDemoColors.periwinkleColor,
+ ))),
+ const SizedBox(
+ width: 25,
+ ),
+ InkWell(
+ customBorder: const CircleBorder(),
+ onTap: () {
+ onPressed(ref: ref, type: "tuneRight");
+ },
+ child: const Padding(
+ padding: EdgeInsets.all(8.0),
+ child: Icon(
+ Icons.arrow_forward,
+ color: AGLDemoColors.periwinkleColor,
+ size: 48,
+ ))),
+ ],
+ ),
+ Row(
+ children: [
+ Text(
+ "Scan",
+ style: TextStyle(
+ color: Colors.white,
+ fontWeight: FontWeight.w400,
+ fontSize: 40,
+ shadows: [Helpers.dropShadowRegular]),
+ ),
+ const SizedBox(
+ width: 25,
+ ),
+ InkWell(
+ customBorder: const CircleBorder(),
+ onTap: () {
+ onPressed(ref: ref, type: "scanLeft");
+ },
+ child: const Padding(
+ padding: EdgeInsets.all(8.0),
+ child: Icon(
+ Icons.arrow_back,
+ color: AGLDemoColors.periwinkleColor,
+ size: 48,
+ ))),
+ const SizedBox(
+ width: 25,
+ ),
+ InkWell(
+ customBorder: const CircleBorder(),
+ onTap: () {
+ onPressed(ref: ref, type: "scanRight");
+ },
+ child: const Padding(
+ padding: EdgeInsets.all(8.0),
+ child: Icon(
+ Icons.arrow_forward,
+ color: AGLDemoColors.periwinkleColor,
+ size: 48,
+ ))),
+ ],
+ )
+ ],
+ ),
+ );
+ }
+}
+
+class RadioPlayerControlsSlider extends ConsumerStatefulWidget {
+ const RadioPlayerControlsSlider({super.key});
+
+ @override
+ ConsumerState<RadioPlayerControlsSlider> createState() =>
+ RadioPlayerControlsSliderState();
+}
+
+class RadioPlayerControlsSliderState
+ extends ConsumerState<RadioPlayerControlsSlider> {
+ @override
+ Widget build(BuildContext context) {
+ var freqMin =
+ ref.watch(radioStateProvider.select((radio) => radio.freqMin));
+ var freqMax =
+ ref.watch(radioStateProvider.select((radio) => radio.freqMax));
+ var freqStep =
+ ref.watch(radioStateProvider.select((radio) => radio.freqStep));
+ var currentFreq =
+ 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]),
+ )),
+ ],
+ ),
+ ));
+ }
+}
diff --git a/lib/presentation/screens/media/radio_preset_table.dart b/lib/presentation/screens/media/radio_preset_table.dart
new file mode 100644
index 0000000..816bcb9
--- /dev/null
+++ b/lib/presentation/screens/media/radio_preset_table.dart
@@ -0,0 +1,151 @@
+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';
+import 'package:flutter_ics_homescreen/data/data_providers/radio_presets_provider.dart';
+
+class RadioPresetTable extends ConsumerStatefulWidget {
+ const RadioPresetTable(
+ {super.key,
+ required this.tableName,
+ required this.presets,
+ required this.selectedPreset});
+
+ final String tableName;
+ final List<RadioPreset> presets;
+ final String selectedPreset;
+
+ @override
+ ConsumerState<RadioPresetTable> createState() => _RadioPresetTableState();
+}
+
+class _RadioPresetTableState extends ConsumerState<RadioPresetTable> {
+ bool isAudioSettingsEnabled = false;
+ late String tableName;
+ late List<RadioPreset> presets;
+ late String selectedPreset;
+
+ @override
+ void initState() {
+ tableName = widget.tableName;
+ presets = widget.presets;
+ selectedPreset = widget.selectedPreset;
+ super.initState();
+ }
+
+ String frequencyToString(int frequency) {
+ return "${(frequency / 1000000.0).toStringAsFixed(1)} MHz";
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Material(
+ color: Colors.transparent,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ children: [
+ Text(
+ tableName,
+ style: const TextStyle(
+ color: Colors.white,
+ fontWeight: FontWeight.w400,
+ fontSize: 40),
+ ),
+ ],
+ ),
+ InkWell(
+ customBorder: const CircleBorder(),
+ onTap: () {
+ setState(() {
+ isAudioSettingsEnabled = !isAudioSettingsEnabled;
+ });
+ },
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: SvgPicture.asset(
+ "assets/${isAudioSettingsEnabled ? "AudioSettingsPressed.svg" : "AudioSettings.svg"}",
+ width: 48,
+ )))
+ ],
+ ),
+ 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]),
+ ))
+ ],
+ ),
+ ),
+ ),
+ );
+ }).toList()),
+ ),
+ ),
+ ],
+ ));
+ }
+}
+
+class PlayListModel {
+ final String songName;
+ final String albumName;
+
+ PlayListModel({required this.songName, required this.albumName});
+}
diff --git a/lib/presentation/screens/media_player/segmented_buttons.dart b/lib/presentation/screens/media/segmented_buttons.dart
index 5cc1d87..5cc1d87 100644
--- a/lib/presentation/screens/media_player/segmented_buttons.dart
+++ b/lib/presentation/screens/media/segmented_buttons.dart
diff --git a/lib/presentation/screens/media_player/widgets/gradient_progress_indicator.dart b/lib/presentation/screens/media/widgets/gradient_progress_indicator.dart
index 24aa244..24aa244 100644
--- a/lib/presentation/screens/media_player/widgets/gradient_progress_indicator.dart
+++ b/lib/presentation/screens/media/widgets/gradient_progress_indicator.dart
diff --git a/lib/presentation/screens/media_player/widgets/media_volume_bar.dart b/lib/presentation/screens/media/widgets/media_volume_bar.dart
index dd59ee0..bd3a4f1 100644
--- a/lib/presentation/screens/media_player/widgets/media_volume_bar.dart
+++ b/lib/presentation/screens/media/widgets/media_volume_bar.dart
@@ -23,7 +23,7 @@ class CustomVolumeSliderState extends ConsumerState<CustomVolumeSlider> {
});
}
- void _dercrease() {
+ void _decrease() {
_currentVal -= 10;
if (_currentVal < 0) {
_currentVal = 0;
@@ -34,6 +34,7 @@ class CustomVolumeSliderState extends ConsumerState<CustomVolumeSlider> {
}
double _currentVal = 50;
+
@override
Widget build(BuildContext context) {
final volumeValue =
@@ -61,7 +62,7 @@ class CustomVolumeSliderState extends ConsumerState<CustomVolumeSlider> {
child: InkWell(
customBorder: const CircleBorder(),
onTap: () {
- _dercrease();
+ _decrease();
},
child: const Padding(
padding: EdgeInsets.all(8.0),
@@ -72,22 +73,6 @@ class CustomVolumeSliderState extends ConsumerState<CustomVolumeSlider> {
))),
),
),
- // Padding(
- // padding: const EdgeInsets.only(left: 10.0),
- // child: SizedBox(
- // width: 50,
- // child: IconButton(
- // padding: EdgeInsets.zero,
- // onPressed: () {
- // _dercrease();
- // },
- // icon: const Icon(
- // CustomIcons.vol_min,
- // color: AGLDemoColors.periwinkleColor,
- // size: 48,
- // )),
- // ),
- // ),
Expanded(
child: SliderTheme(
data: SliderThemeData(
@@ -130,22 +115,6 @@ class CustomVolumeSliderState extends ConsumerState<CustomVolumeSlider> {
))),
),
),
- // Padding(
- // padding: const EdgeInsets.only(right: 10.0),
- // child: SizedBox(
- // width: 60,
- // child: IconButton(
- // padding: EdgeInsets.zero,
- // onPressed: () {
- // _increase();
- // },
- // icon: const Icon(
- // CustomIcons.vol_max,
- // color: AGLDemoColors.periwinkleColor,
- // size: 48,
- // )),
- // ),
- // ),
],
),
),
diff --git a/lib/presentation/screens/media_player/media_controls.dart b/lib/presentation/screens/media_player/media_controls.dart
deleted file mode 100644
index 0686187..0000000
--- a/lib/presentation/screens/media_player/media_controls.dart
+++ /dev/null
@@ -1,413 +0,0 @@
-import 'package:flutter_ics_homescreen/core/utils/helpers.dart';
-import 'package:flutter_ics_homescreen/export.dart';
-import 'package:flutter_ics_homescreen/presentation/screens/media_player/widgets/gradient_progress_indicator.dart';
-
-class MediaControls extends StatefulWidget {
- const MediaControls(
- {super.key,
- required this.type,
- required this.songName,
- required this.songLengthStart,
- required this.songLengthStop});
-
- final String type;
- final String songName;
- final String songLengthStart;
- final String songLengthStop;
-
- @override
- State<MediaControls> createState() => _MediaControlsState();
-}
-
-class _MediaControlsState extends State<MediaControls> {
- 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();
- }
-
- @override
- Widget build(BuildContext context) {
- return Material(
- color: Colors.transparent,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.stretch,
- children: [
- Text(
- songName,
- style: TextStyle(
- color: Colors.white,
- fontWeight: FontWeight.w400,
- shadows: [Helpers.dropShadowRegular],
- fontSize: 44),
- ),
- if (widget.type == "media")
- MediaControlSubDetails(
- albumName: albumName,
- )
- else if (widget.type == "fm")
- const FMPlayerSubDetails(),
- if (widget.type == "media")
- 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,
- // ),
- Padding(
- padding: const EdgeInsets.symmetric(vertical: 5),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text(
- songLengthStart,
- style: TextStyle(
- color: Colors.white,
- fontSize: 26,
- shadows: [Helpers.dropShadowRegular]),
- ),
- Text(
- songLengthStop,
- style: TextStyle(
- color: Colors.white,
- fontSize: 26,
- shadows: [Helpers.dropShadowRegular]),
- )
- ],
- ),
- ),
- ])
- else if (widget.type == "fm")
- FMPlayerSlider(
- minHertz: songLengthStart,
- maxHertz: songLengthStop,
- songProgress: songProgress,
- ),
- if (widget.type == "media") const MediaPlayerActions()
- ],
- ),
- );
- }
-}
-
-class MediaControlSubDetails extends StatefulWidget {
- const MediaControlSubDetails({super.key, required this.albumName});
- final String albumName;
-
- @override
- State<MediaControlSubDetails> createState() => _MediaControlSubDetailsState();
-}
-
-class _MediaControlSubDetailsState extends State<MediaControlSubDetails> {
- bool isShuffleEnabled = false;
- bool isRepeatEnabled = false;
- @override
- Widget build(BuildContext context) {
- return Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text(
- widget.albumName,
- style: TextStyle(
- color: Colors.white,
- fontWeight: FontWeight.w400,
- fontSize: 40,
- shadows: [Helpers.dropShadowRegular]),
- ),
- Row(
- children: [
- InkWell(
- customBorder: const CircleBorder(),
- onTap: () {
- setState(() {
- isShuffleEnabled = !isShuffleEnabled;
- });
- },
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: SvgPicture.asset(
- "assets/${isShuffleEnabled ? "ShufflePressed.svg" : "Shuffle.svg"}",
- width: 48,
- ))),
- InkWell(
- customBorder: const CircleBorder(),
- onTap: () {
- setState(() {
- isRepeatEnabled = !isRepeatEnabled;
- });
- },
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: SvgPicture.asset(
- "assets/${isRepeatEnabled ? "RepeatPressed.svg" : "Repeat.svg"}",
- width: 48,
- ))),
- ],
- )
- ],
- );
- }
-}
-
-class FMPlayerSubDetails extends StatefulWidget {
- const FMPlayerSubDetails({
- super.key,
- });
-
- @override
- State<FMPlayerSubDetails> createState() => _FMPlayerSubDetailsState();
-}
-
-class _FMPlayerSubDetailsState extends State<FMPlayerSubDetails> {
- onPressed({required String type}) {}
- @override
- Widget build(BuildContext context) {
- return Padding(
- padding: const EdgeInsets.only(bottom: 5),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Row(
- children: [
- Text(
- "Tune",
- style: TextStyle(
- color: Colors.white,
- fontWeight: FontWeight.w400,
- fontSize: 40,
- shadows: [Helpers.dropShadowRegular]),
- ),
- const SizedBox(
- width: 25,
- ),
- InkWell(
- customBorder: const CircleBorder(),
- onTap: () {
- onPressed(type: "scanLeft");
- },
- child: const Padding(
- padding: EdgeInsets.all(8.0),
- child: Icon(
- Icons.arrow_back,
- size: 48,
- color: AGLDemoColors.periwinkleColor,
- ))),
- const SizedBox(
- width: 25,
- ),
- InkWell(
- customBorder: const CircleBorder(),
- onTap: () {
- onPressed(type: "scanRight");
- },
- child: const Padding(
- padding: EdgeInsets.all(8.0),
- child: Icon(
- Icons.arrow_forward,
- color: AGLDemoColors.periwinkleColor,
- size: 48,
- ))),
- ],
- ),
- Row(
- children: [
- Text(
- "Scan",
- style: TextStyle(
- color: Colors.white,
- fontWeight: FontWeight.w400,
- fontSize: 40,
- shadows: [Helpers.dropShadowRegular]),
- ),
- const SizedBox(
- width: 25,
- ),
- InkWell(
- customBorder: const CircleBorder(),
- onTap: () {
- onPressed(type: "scanLeft");
- },
- child: const Padding(
- padding: EdgeInsets.all(8.0),
- child: Icon(
- Icons.arrow_back,
- color: AGLDemoColors.periwinkleColor,
- size: 48,
- ))),
- const SizedBox(
- width: 25,
- ),
- InkWell(
- customBorder: const CircleBorder(),
- onTap: () {
- onPressed(type: "scanRight");
- },
- child: const Padding(
- padding: EdgeInsets.all(8.0),
- child: Icon(
- Icons.arrow_forward,
- color: AGLDemoColors.periwinkleColor,
- size: 48,
- ))),
- ],
- )
- ],
- ),
- );
- }
-}
-
-class MediaPlayerActions extends StatefulWidget {
- const MediaPlayerActions({super.key});
-
- @override
- State<MediaPlayerActions> createState() => _MediaPlayerActionsState();
-}
-
-class _MediaPlayerActionsState extends State<MediaPlayerActions> {
- bool isPressed = false;
- bool isPlaying = true;
-
- @override
- Widget build(BuildContext context) {
- return Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- InkWell(
- customBorder: const CircleBorder(),
- onTap: () {},
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: SvgPicture.asset(
- "assets/SkipPrevious.svg",
- width: 48,
- ),
- )),
- const SizedBox(
- width: 120,
- ),
- InkWell(
- customBorder: const CircleBorder(),
- onTap: () {
- setState(() {
- isPlaying = !isPlaying;
- });
- },
- onTapDown: (details) {
- setState(() {
- isPressed = true;
- });
- },
- onTapUp: (details) {
- isPressed = false;
-
- },
- child: Container(
- width: 64,
- height: 64,
- decoration: BoxDecoration(
- shape: BoxShape.circle,
- color:
- isPressed ? Colors.white : AGLDemoColors.periwinkleColor,
- boxShadow: [Helpers.boxDropShadowRegular]),
- child: Icon(
- isPlaying ? Icons.pause : Icons.play_arrow,
- color: AGLDemoColors.resolutionBlueColor,
- size: 60,
- ),
- )),
- const SizedBox(
- width: 120,
- ),
- InkWell(
- customBorder: const CircleBorder(),
- onTap: () {},
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: SvgPicture.asset(
- "assets/SkipNext.svg",
- width: 48,
- ),
- )),
- ],
- );
- }
-}
-
-class FMPlayerSlider extends StatefulWidget {
- const FMPlayerSlider(
- {super.key,
- required this.minHertz,
- required this.maxHertz,
- required this.songProgress});
- final String minHertz;
- final String maxHertz;
- final int songProgress;
-
- @override
- State<FMPlayerSlider> createState() => _FMPlayerSliderState();
-}
-
-class _FMPlayerSliderState extends State<FMPlayerSlider> {
- @override
- Widget build(BuildContext context) {
- return Row(
- children: [
- Text(
- widget.minHertz,
- style: TextStyle(
- color: Colors.white,
- fontSize: 26,
- shadows: [Helpers.dropShadowRegular]),
- ),
- Expanded(
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 40),
- child: GradientProgressIndicator(
- percent: widget.songProgress,
- height: 10,
- type: "fm",
- gradient: LinearGradient(
- begin: Alignment.centerLeft,
- end: Alignment.centerRight,
- colors: [
- AGLDemoColors.jordyBlueColor,
- AGLDemoColors.jordyBlueColor.withOpacity(0.8),
- ]),
- backgroundColor: AGLDemoColors.gradientBackgroundDarkColor,
- ),
- ),
- ),
- Text(
- widget.maxHertz,
- style: TextStyle(
- color: Colors.white,
- fontSize: 26,
- shadows: [Helpers.dropShadowRegular]),
- )
- ],
- );
- }
-}
diff --git a/lib/presentation/screens/media_player/my_media.dart b/lib/presentation/screens/media_player/my_media.dart
deleted file mode 100644
index e69de29..0000000
--- a/lib/presentation/screens/media_player/my_media.dart
+++ /dev/null
diff --git a/lib/presentation/screens/settings/settings_screens/audio_settings/widget/slider_widgets.dart b/lib/presentation/screens/settings/settings_screens/audio_settings/widget/slider_widgets.dart
index fefd9ed..6988caa 100644
--- a/lib/presentation/screens/settings/settings_screens/audio_settings/widget/slider_widgets.dart
+++ b/lib/presentation/screens/settings/settings_screens/audio_settings/widget/slider_widgets.dart
@@ -74,7 +74,7 @@ class CustomBalanceState extends ConsumerState<CustomBalanceSlider> {
onTap: () {
_decrease();
},
- child: Text(
+ child: const Text(
'LEFT',
style: TextStyle(
fontSize: 18,
@@ -127,7 +127,7 @@ class CustomBalanceState extends ConsumerState<CustomBalanceSlider> {
onTap: () {
_increase();
},
- child: Text(
+ child: const Text(
'RIGHT',
style: TextStyle(
fontSize: 18,
@@ -217,14 +217,14 @@ class CustomFaderState extends ConsumerState<CustomFaderSlider> {
onTap: () {
_decrease();
},
- child: Text(
+ child: const Text(
'REAR',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: AGLDemoColors.periwinkleColor,
),
- )),
+ )),
),
SizedBox(
width: 584,
@@ -246,9 +246,7 @@ class CustomFaderState extends ConsumerState<CustomFaderSlider> {
max: 10,
value: faderValue,
onChanged: (newValue) {
- ref
- .read(audioStateProvider.notifier)
- .setFade(newValue);
+ ref.read(audioStateProvider.notifier).setFade(newValue);
_currentVal = newValue;
},
onChangeEnd: (value) {
@@ -270,7 +268,7 @@ class CustomFaderState extends ConsumerState<CustomFaderSlider> {
onTap: () {
_increase();
},
- child: Text(
+ child: const Text(
'FRONT',
style: TextStyle(
fontSize: 18,
diff --git a/lib/presentation/screens/splash/widget/splash_content.dart b/lib/presentation/screens/splash/widget/splash_content.dart
index d93be4f..29d8d6c 100644
--- a/lib/presentation/screens/splash/widget/splash_content.dart
+++ b/lib/presentation/screens/splash/widget/splash_content.dart
@@ -66,7 +66,8 @@ class SplashContentState extends ConsumerState<SplashContent>
@override
void didChangeDependencies() {
- ref.read(valClientProvider).startListen();
+ ref.read(valClientProvider).run();
+ ref.read(radioClientProvider).run();
super.didChangeDependencies();
}