Files
plezy/lib/providers/shader_provider.dart
T

131 lines
4.6 KiB
Dart

import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import '../mixins/disposable_change_notifier_mixin.dart';
import '../models/shader_preset.dart';
import '../services/settings_service.dart';
import '../services/shader_asset_loader.dart';
class ShaderProvider extends ChangeNotifier with DisposableChangeNotifierMixin {
SettingsService? _settingsService;
ValueNotifier<String>? _savedPresetListenable;
ValueNotifier<List<Map<String, dynamic>>>? _customPresetsListenable;
ShaderPreset _savedPreset = ShaderPreset.none;
ShaderPreset _currentPreset = ShaderPreset.none;
List<ShaderPreset> _customPresets = [];
bool _initialized = false;
ShaderProvider() {
_initialize();
}
Future<void> _initialize() async {
final service = await SettingsService.getInstance();
if (_settingsService == service && _savedPresetListenable != null && _customPresetsListenable != null) {
_syncFromSettings();
return;
}
_savedPresetListenable?.removeListener(_onSettingsChanged);
_customPresetsListenable?.removeListener(_onSettingsChanged);
_settingsService = service;
_savedPresetListenable = service.listenable(SettingsService.globalShaderPreset)..addListener(_onSettingsChanged);
_customPresetsListenable = service.listenable(SettingsService.customShaderPresets)..addListener(_onSettingsChanged);
_syncFromSettings();
}
void _onSettingsChanged() => _syncFromSettings();
void _syncFromSettings() {
final service = _settingsService;
if (service == null) return;
final customData = service.read(SettingsService.customShaderPresets);
final customPresets = customData.map((json) => ShaderPreset.fromJson(json)).toList();
_customPresets = customPresets;
final presetId = service.read(SettingsService.globalShaderPreset);
_savedPreset = findPresetById(presetId) ?? ShaderPreset.none;
_currentPreset = _savedPreset;
_initialized = true;
safeNotifyListeners();
}
@override
void dispose() {
_savedPresetListenable?.removeListener(_onSettingsChanged);
_customPresetsListenable?.removeListener(_onSettingsChanged);
super.dispose();
}
bool get initialized => _initialized;
ShaderPreset get savedPreset => _savedPreset;
ShaderPreset get currentPreset => _currentPreset;
List<ShaderPreset> get allPresets => [...ShaderPreset.allPresets, ..._customPresets];
List<ShaderPreset> get customPresets => _customPresets;
bool get isShaderEnabled => _currentPreset.type != ShaderPresetType.none;
ShaderPreset? findPresetById(String id) {
return ShaderPreset.fromId(id) ?? _customPresets.firstWhereOrNull((p) => p.id == id);
}
Future<void> setPreset(ShaderPreset preset) async {
final service = _settingsService ?? await SettingsService.getInstance();
await service.write(SettingsService.globalShaderPreset, preset.id);
if (_savedPresetListenable == null) {
_savedPreset = preset;
_currentPreset = preset;
safeNotifyListeners();
}
}
/// Update the current preset without persisting (e.g. toggling off temporarily)
void setCurrentPreset(ShaderPreset preset) {
if (_currentPreset.id != preset.id) {
_currentPreset = preset;
notifyListeners();
}
}
/// Import a custom shader from a file path.
/// Copies the file to the custom shaders directory and creates a preset.
Future<ShaderPreset> importCustomShader(String filePath, String displayName) async {
final storedFileName = await ShaderAssetLoader.importCustomShader(filePath);
final id = 'custom_$storedFileName';
final preset = ShaderPreset(id: id, name: displayName, type: ShaderPresetType.custom, fileName: storedFileName);
_customPresets.add(preset);
await _saveCustomPresets();
return preset;
}
/// Delete a custom shader preset and its file.
Future<void> deleteCustomShader(ShaderPreset preset) async {
final wasActive = _currentPreset.id == preset.id || _savedPreset.id == preset.id;
if (preset.fileName != null) {
await ShaderAssetLoader.deleteCustomShader(preset.fileName!);
}
_customPresets.removeWhere((p) => p.id == preset.id);
await _saveCustomPresets();
// Reset to none if the deleted preset was active
if (wasActive) {
await setPreset(ShaderPreset.none);
}
}
Future<void> _saveCustomPresets() async {
final service = _settingsService ?? await SettingsService.getInstance();
final data = _customPresets.map((p) => p.toJson()).toList();
await service.write(SettingsService.customShaderPresets, data);
}
/// Reset to default (no shaders)
Future<void> reset() async {
await setPreset(ShaderPreset.none);
}
}