Files
yommi_ff/lib/providers/m3u_provider.dart

60 lines
1.9 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/foundation.dart' show debugPrint;
import '../models/stream_entry.dart';
import '../services/m3u_service.dart';
final m3uServiceProvider = Provider<M3UService>((ref) => M3UService());
final channelListProvider =
StateNotifierProvider<ChannelListNotifier, AsyncValue<List<StreamEntry>>>(
(ref) {
final svc = ref.watch(m3uServiceProvider);
return ChannelListNotifier(svc);
});
final selectedChannelProvider = StateProvider<StreamEntry?>((ref) => null);
class ChannelListNotifier extends StateNotifier<AsyncValue<List<StreamEntry>>> {
final M3UService _svc;
ChannelListNotifier(this._svc) : super(const AsyncValue.data([]));
Future<void> fetch(String url, {bool force = false}) async {
// If not forcing, try to load a persistent cache first and return it immediately
if (!force) {
try {
final cached = await _svc.loadFromCache(url);
if (cached != null) {
state = AsyncValue.data(cached);
// Refresh in background to get fresh results
_refreshInBackground(url);
return;
}
} catch (e) {
// ignore cache read errors and fall back to network fetch
debugPrint('Cache read failed during fetch: $e');
}
}
state = const AsyncValue.loading();
try {
final entries = await _svc.fetch(url, forceRefresh: force);
state = AsyncValue.data(entries);
} catch (e, st) {
state = AsyncValue.error(e, st);
}
}
Future<void> _refreshInBackground(String url) async {
try {
final entries = await _svc.fetch(url, forceRefresh: true);
// Only update state if still not error or older content
state = AsyncValue.data(entries);
} catch (e) {
debugPrint('Background refresh failed: $e');
// keep cached data; don't overwrite with error
}
}
Future<void> refresh(String url) async => fetch(url, force: true);
}