Files
plezy/lib/services/favorite_channels_repository.dart
2026-05-01 01:20:36 +02:00

56 lines
2.3 KiB
Dart

import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/livetv_channel.dart';
/// Persistence boundary for the per-connection favorite-channel list shown
/// in the Live TV picker. Pulled out of `_JellyfinLiveTvSupport` so the
/// favorites round-trip can be exercised with an in-memory fake instead of
/// the platform `SharedPreferences` plugin.
///
/// The repo owns the *serialisation*; the call site owns the *key naming*
/// (which depends on connection id + machineId — backend-specific concerns
/// the repo shouldn't have to know about).
abstract class FavoriteChannelsRepository {
/// Reads channels for [key]. If absent, falls back to [legacyKey] one
/// time, migrating the value into [key] and clearing the legacy slot.
Future<List<FavoriteChannel>> read({required String key, required String legacyKey});
/// Replaces the channel list under [key].
Future<void> write(String key, List<FavoriteChannel> channels);
}
/// Production implementation. Holds no state; the platform plugin has its
/// own caching layer behind `SharedPreferences.getInstance()`.
class SharedPreferencesFavoriteChannelsRepository implements FavoriteChannelsRepository {
const SharedPreferencesFavoriteChannelsRepository();
@override
Future<List<FavoriteChannel>> read({required String key, required String legacyKey}) async {
final prefs = await SharedPreferences.getInstance();
var raw = prefs.getString(key);
if (raw == null) {
// Migrate from the legacy bare-machineId slot. Only the first user to
// read inherits it; the rest start empty (favorites were always
// user-scoped semantically — the legacy key just couldn't express it).
final legacy = prefs.getString(legacyKey);
if (legacy != null) {
await prefs.setString(key, legacy);
await prefs.remove(legacyKey);
raw = legacy;
}
}
if (raw == null || raw.isEmpty) return const [];
final decoded = jsonDecode(raw);
if (decoded is! List) return const [];
return decoded.whereType<Map<String, dynamic>>().map(FavoriteChannel.fromJson).toList();
}
@override
Future<void> write(String key, List<FavoriteChannel> channels) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(key, jsonEncode(channels.map((c) => c.toJson()).toList()));
}
}