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.
90 lines
3.2 KiB
Dart
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();
|
|
}
|
|
}
|