From 8af7efb6cea7f2579b2a85934498494dd4bbd2e2 Mon Sep 17 00:00:00 2001 From: zarzet <42882290+zarzet@users.noreply.github.com> Date: Mon, 19 Oct 2026 00:52:20 +0700 Subject: [PATCH] refactor(providers): move UI-declared providers to lib/providers The listening summary and system volume providers lived in UI files. They move verbatim to lib/providers with the same names; the old files re-export them so tests and other importers are unchanged. --- .../listening_statistics_provider.dart | 14 ++++++++ lib/providers/system_volume_provider.dart | 35 +++++++++++++++++++ lib/screens/listening_statistics_screen.dart | 13 ++----- lib/widgets/player_volume_control.dart | 32 ++--------------- 4 files changed, 53 insertions(+), 41 deletions(-) create mode 100644 lib/providers/listening_statistics_provider.dart create mode 100644 lib/providers/system_volume_provider.dart diff --git a/lib/providers/listening_statistics_provider.dart b/lib/providers/listening_statistics_provider.dart new file mode 100644 index 00000000..98c4a83c --- /dev/null +++ b/lib/providers/listening_statistics_provider.dart @@ -0,0 +1,14 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:spotiflac_android/services/listening_statistics.dart'; + +final listeningSummaryProvider = FutureProvider.autoDispose + .family((ref, period) async { + await listeningRecorder.flush(); + final now = DateTime.now(); + final tomorrow = DateTime(now.year, now.month, now.day + 1); + final start = period.days == 0 + ? DateTime(period.year) + : DateTime(now.year, now.month, now.day - period.days + 1); + final end = period.days == 0 ? DateTime(period.year + 1) : tomorrow; + return ListeningStatisticsStore.instance.load(start, end); + }); diff --git a/lib/providers/system_volume_provider.dart b/lib/providers/system_volume_provider.dart new file mode 100644 index 00000000..d53b088d --- /dev/null +++ b/lib/providers/system_volume_provider.dart @@ -0,0 +1,35 @@ +import 'dart:async'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:spotiflac_android/services/music_playback_deck.dart'; +import 'package:spotiflac_android/services/system_volume_service.dart'; +import 'package:volume_controller/volume_controller.dart'; + +final usbVolumeProvider = StreamProvider.autoDispose((ref) { + final events = StreamController(); + void changed() => events.add(usbHardwareVolume.value); + usbHardwareVolume.addListener(changed); + changed(); + ref.onDispose(() { + usbHardwareVolume.removeListener(changed); + unawaited(events.close()); + }); + return events.stream; +}); + +/// A single shared subscription for the visible player, including hardware +/// volume-button changes. This controls system volume, not ReplayGain gain. +final systemVolumeProvider = StreamProvider.autoDispose( + (ref) => SystemVolumeService.instance.changes, +); + +final systemVolumeWriterProvider = Provider Function(double)>(( + ref, +) { + return (value) { + if (usbHardwareVolume.value != null) return setUsbHardwareVolume(value); + final volume = VolumeController.instance; + volume.showSystemUI = false; + return volume.setVolume(value.clamp(0, 1)); + }; +}); diff --git a/lib/screens/listening_statistics_screen.dart b/lib/screens/listening_statistics_screen.dart index 514f9a46..78946fd9 100644 --- a/lib/screens/listening_statistics_screen.dart +++ b/lib/screens/listening_statistics_screen.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:spotiflac_android/l10n/l10n.dart'; +import 'package:spotiflac_android/providers/listening_statistics_provider.dart'; import 'package:spotiflac_android/providers/settings_provider.dart'; import 'package:spotiflac_android/screens/listening_rewind_screen.dart'; import 'package:spotiflac_android/services/listening_statistics.dart'; @@ -22,17 +23,7 @@ import 'package:spotiflac_android/widgets/app_sliver_header.dart'; import 'package:spotiflac_android/widgets/player_artwork.dart'; import 'package:spotiflac_android/widgets/settings_group.dart'; -final listeningSummaryProvider = FutureProvider.autoDispose - .family((ref, period) async { - await listeningRecorder.flush(); - final now = DateTime.now(); - final tomorrow = DateTime(now.year, now.month, now.day + 1); - final start = period.days == 0 - ? DateTime(period.year) - : DateTime(now.year, now.month, now.day - period.days + 1); - final end = period.days == 0 ? DateTime(period.year + 1) : tomorrow; - return ListeningStatisticsStore.instance.load(start, end); - }); +export 'package:spotiflac_android/providers/listening_statistics_provider.dart'; class ListeningStatisticsScreen extends ConsumerStatefulWidget { const ListeningStatisticsScreen({super.key}); diff --git a/lib/widgets/player_volume_control.dart b/lib/widgets/player_volume_control.dart index b005a394..c8e11531 100644 --- a/lib/widgets/player_volume_control.dart +++ b/lib/widgets/player_volume_control.dart @@ -4,43 +4,15 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:spotiflac_android/l10n/l10n.dart'; +import 'package:spotiflac_android/providers/system_volume_provider.dart'; import 'package:spotiflac_android/theme/mornye_theme.dart'; import 'package:spotiflac_android/widgets/app_icon.dart'; import 'package:spotiflac_android/widgets/app_slider.dart'; import 'package:spotiflac_android/widgets/mornye_player_slider.dart'; import 'package:spotiflac_android/utils/logger.dart'; -import 'package:volume_controller/volume_controller.dart'; import 'package:spotiflac_android/services/music_playback_deck.dart'; -import 'package:spotiflac_android/services/system_volume_service.dart'; -final usbVolumeProvider = StreamProvider.autoDispose((ref) { - final events = StreamController(); - void changed() => events.add(usbHardwareVolume.value); - usbHardwareVolume.addListener(changed); - changed(); - ref.onDispose(() { - usbHardwareVolume.removeListener(changed); - unawaited(events.close()); - }); - return events.stream; -}); - -/// A single shared subscription for the visible player, including hardware -/// volume-button changes. This controls system volume, not ReplayGain gain. -final systemVolumeProvider = StreamProvider.autoDispose( - (ref) => SystemVolumeService.instance.changes, -); - -final systemVolumeWriterProvider = Provider Function(double)>(( - ref, -) { - return (value) { - if (usbHardwareVolume.value != null) return setUsbHardwareVolume(value); - final volume = VolumeController.instance; - volume.showSystemUI = false; - return volume.setVolume(value.clamp(0, 1)); - }; -}); +export 'package:spotiflac_android/providers/system_volume_provider.dart'; /// System (or USB hardware) volume slider for the player and USB settings. /// Mornye draws its glass slider between speaker glyphs; Material draws the