@@ -625,6 +625,8 @@ class MusifyAudioHandler extends BaseAudioHandler {
625625 }
626626
627627 try {
628+ if (offlineMode.value) return ;
629+
628630 final baseSong = _getCurrentSongForRecommendations ();
629631 if (baseSong == null ) {
630632 logger.log ('No valid song for recommendations' );
@@ -691,6 +693,8 @@ class MusifyAudioHandler extends BaseAudioHandler {
691693 if (nextRecommendedSong != null ) {
692694 return ;
693695 }
696+ // Do not prefetch recommendations while in offline mode
697+ if (offlineMode.value) return ;
694698
695699 Future .microtask (() async {
696700 try {
@@ -1078,6 +1082,9 @@ class MusifyAudioHandler extends BaseAudioHandler {
10781082 }
10791083
10801084 void _preloadUpcomingSongs () {
1085+ // Don't attempt to preload while offline mode is enabled
1086+ if (offlineMode.value) return ;
1087+
10811088 Future .microtask (() async {
10821089 try {
10831090 final songsToPreload = < Map > [];
@@ -1132,15 +1139,21 @@ class MusifyAudioHandler extends BaseAudioHandler {
11321139 String ? preloadUrl;
11331140
11341141 try {
1135- // fetchSongStreamUrl handles caching, freshness checks, and validation
1136- preloadUrl = await fetchSongStreamUrl (ytid, nextSong['isLive' ] ?? false )
1137- .timeout (
1138- const Duration (seconds: 8 ),
1139- onTimeout: () {
1140- logger.log ('Preload timeout for song $ytid ' );
1141- return null ;
1142- },
1143- );
1142+ // Don't attempt to fetch remote streams while offline mode is enabled
1143+ if (offlineMode.value) {
1144+ logger.log ('Offline mode enabled; skipping preload for $ytid ' );
1145+ preloadUrl = null ;
1146+ } else {
1147+ // fetchSongStreamUrl handles caching, freshness checks, and validation
1148+ preloadUrl = await fetchSongStreamUrl (ytid, nextSong['isLive' ] ?? false )
1149+ .timeout (
1150+ const Duration (seconds: 8 ),
1151+ onTimeout: () {
1152+ logger.log ('Preload timeout for song $ytid ' );
1153+ return null ;
1154+ },
1155+ );
1156+ }
11441157 } catch (e, stackTrace) {
11451158 logger.log (
11461159 'Error preloading song $ytid ' ,
@@ -1341,6 +1354,20 @@ class MusifyAudioHandler extends BaseAudioHandler {
13411354 return null ;
13421355 }
13431356
1357+ // If offline mode is enabled, do NOT fall back to online streams.
1358+ // This prevents network requests while the user explicitly requested
1359+ // offline-only operation.
1360+ try {
1361+ if (offlineMode.value) {
1362+ logger.log (
1363+ 'Offline mode enabled and offline file missing for ${songData ['ytid' ]}. Not falling back to online.' ,
1364+ );
1365+ return null ;
1366+ }
1367+ } catch (_) {
1368+ // If offlineMode isn't available for some reason, continue with fallback.
1369+ }
1370+
13441371 logger.log (
13451372 'Offline file missing for ${songData ['ytid' ]}, switching to online' ,
13461373 );
@@ -1450,10 +1477,24 @@ class MusifyAudioHandler extends BaseAudioHandler {
14501477 );
14511478
14521479 if (isOffline) {
1480+ // If offline mode is explicitly enabled, do not attempt any online
1481+ // fallback — respect the user's offline-only preference.
1482+ try {
1483+ if (offlineMode.value) {
1484+ return false ;
1485+ }
1486+ } catch (_) {
1487+ // If offlineMode isn't accessible, fallthrough to attempt fallback.
1488+ }
1489+
14531490 return _attemptOfflineFallback (song, mediaId: mediaId);
14541491 }
14551492
14561493 if (allowOnlineRetry) {
1494+ if (offlineMode.value) {
1495+ _lastError = e.toString ();
1496+ return false ;
1497+ }
14571498 final songId = song['ytid' ]? .toString ();
14581499 if (songId != null && songId.isNotEmpty) {
14591500 final cacheKey = 'song_${songId }_${audioQualitySetting .value }_url' ;
@@ -1491,6 +1532,9 @@ class MusifyAudioHandler extends BaseAudioHandler {
14911532 }
14921533
14931534 Future <bool > _attemptOfflineFallback (Map song, {String ? mediaId}) async {
1535+ // Do not attempt any network calls when offline mode is enabled.
1536+ if (offlineMode.value) return false ;
1537+
14941538 final onlineUrl = await fetchSongStreamUrl (
14951539 song['ytid' ],
14961540 song['isLive' ] ?? false ,
0 commit comments