Files
plezy/lib/providers/hidden_libraries_provider.dart
edde746 4eaf4423a1 refactor: share focus chrome and simplify the TV picker and browse paths
Focus chrome was implemented twice, once in the focusable wrapper and once
in the focus builders; both now go through FocusChrome. TvColorPicker's
channel row was a copy of TvNumberSpinner and is now that widget in compact
density.

Also trims unused helpers and fields and simplifies the Jellyfin browse
paths.
2026-07-26 06:09:49 +02:00

90 lines
3.2 KiB
Dart

import 'package:flutter/foundation.dart';
import '../mixins/disposable_change_notifier_mixin.dart';
import '../services/storage_service.dart';
/// Provider for managing hidden library state across the app.
/// This ensures that when a library is hidden/unhidden in one screen,
/// all other screens are automatically updated.
class HiddenLibrariesProvider extends ChangeNotifier with DisposableChangeNotifierMixin {
StorageService? _storageService;
final String? profileId;
Set<String> _hiddenLibraryKeys = {};
bool _isInitialized = false;
Future<void>? _initFuture;
HiddenLibrariesProvider({this._storageService, this.profileId}) {
// Start initialization eagerly to reduce race conditions
_initFuture = _initialize();
}
/// Ensures the provider is initialized. Call this before accessing hidden
/// libraries in contexts where you need the actual persisted values.
Future<void> ensureInitialized() => _initFuture ?? _initialize();
/// Check if the provider has completed initialization
bool get isInitialized => _isInitialized;
/// Get an unmodifiable copy of hidden library keys
Set<String> get hiddenLibraryKeys => Set.unmodifiable(_hiddenLibraryKeys);
/// Initialize the provider by loading hidden libraries from storage
Future<void> _initialize() async {
if (_isInitialized) return;
await _loadFromStorage();
_isInitialized = true;
safeNotifyListeners();
}
Future<void> _loadFromStorage() async {
final storage = _storageService ??= await StorageService.getInstance();
final scopedProfileId = profileId;
_hiddenLibraryKeys = scopedProfileId == null
? storage.getHiddenLibraries()
: storage.getHiddenLibrariesForProfile(scopedProfileId);
}
Future<void> _saveToStorage() async {
final storage = _storageService ??= await StorageService.getInstance();
final scopedProfileId = profileId;
if (scopedProfileId == null) {
await storage.saveHiddenLibraries(_hiddenLibraryKeys);
} else {
await storage.saveHiddenLibrariesForProfile(scopedProfileId, _hiddenLibraryKeys);
}
}
/// Hide a library by its key
/// Updates both in-memory state and persistent storage
Future<void> hideLibrary(String libraryKey) async {
if (!_isInitialized) await _initialize();
if (!_hiddenLibraryKeys.contains(libraryKey)) {
_hiddenLibraryKeys = Set.from(_hiddenLibraryKeys)..add(libraryKey);
await _saveToStorage();
safeNotifyListeners();
}
}
/// Unhide a library by its key
/// Updates both in-memory state and persistent storage
Future<void> unhideLibrary(String libraryKey) async {
if (!_isInitialized) await _initialize();
if (_hiddenLibraryKeys.contains(libraryKey)) {
_hiddenLibraryKeys = Set.from(_hiddenLibraryKeys)..remove(libraryKey);
await _saveToStorage();
safeNotifyListeners();
}
}
/// Check if a specific library is hidden
@visibleForTesting
bool isLibraryHidden(String libraryKey) => _hiddenLibraryKeys.contains(libraryKey);
/// Refresh hidden libraries from storage
/// Useful if storage was modified outside the provider
Future<void> refresh() async {
await _loadFromStorage();
_isInitialized = true;
safeNotifyListeners();
}
}