refactor: migrate to riverpod 3
This commit is contained in:
@@ -208,12 +208,29 @@ class AnimationService {
|
||||
enum PageTransitionType { fade, slide, scale }
|
||||
|
||||
/// Provider for reduced motion preference
|
||||
final reducedMotionProvider = StateProvider<bool>((ref) => false);
|
||||
final reducedMotionProvider = NotifierProvider<ReducedMotionNotifier, bool>(
|
||||
ReducedMotionNotifier.new,
|
||||
);
|
||||
|
||||
/// Provider for animation performance settings
|
||||
final animationPerformanceProvider = StateProvider<AnimationPerformance>((ref) {
|
||||
return AnimationPerformance.adaptive;
|
||||
});
|
||||
final animationPerformanceProvider =
|
||||
NotifierProvider<AnimationPerformanceNotifier, AnimationPerformance>(
|
||||
AnimationPerformanceNotifier.new,
|
||||
);
|
||||
|
||||
class ReducedMotionNotifier extends Notifier<bool> {
|
||||
@override
|
||||
bool build() => false;
|
||||
|
||||
void set(bool value) => state = value;
|
||||
}
|
||||
|
||||
class AnimationPerformanceNotifier extends Notifier<AnimationPerformance> {
|
||||
@override
|
||||
AnimationPerformance build() => AnimationPerformance.adaptive;
|
||||
|
||||
void set(AnimationPerformance performance) => state = performance;
|
||||
}
|
||||
|
||||
/// Animation performance levels
|
||||
enum AnimationPerformance {
|
||||
@@ -225,8 +242,8 @@ enum AnimationPerformance {
|
||||
|
||||
/// Provider for managing animation settings
|
||||
final animationSettingsProvider =
|
||||
StateNotifierProvider<AnimationSettingsNotifier, AnimationSettings>(
|
||||
(ref) => AnimationSettingsNotifier(),
|
||||
NotifierProvider<AnimationSettingsNotifier, AnimationSettings>(
|
||||
AnimationSettingsNotifier.new,
|
||||
);
|
||||
|
||||
class AnimationSettings {
|
||||
@@ -253,8 +270,9 @@ class AnimationSettings {
|
||||
}
|
||||
}
|
||||
|
||||
class AnimationSettingsNotifier extends StateNotifier<AnimationSettings> {
|
||||
AnimationSettingsNotifier() : super(const AnimationSettings());
|
||||
class AnimationSettingsNotifier extends Notifier<AnimationSettings> {
|
||||
@override
|
||||
AnimationSettings build() => const AnimationSettings();
|
||||
|
||||
void setReduceMotion(bool reduce) {
|
||||
state = state.copyWith(reduceMotion: reduce);
|
||||
|
||||
@@ -20,9 +20,11 @@ class SettingsService {
|
||||
static const String _voiceHoldToTalkKey = 'voice_hold_to_talk';
|
||||
static const String _voiceAutoSendKey = 'voice_auto_send_final';
|
||||
// Realtime transport preference
|
||||
static const String _socketTransportModeKey = 'socket_transport_mode'; // 'auto' or 'ws'
|
||||
static const String _socketTransportModeKey =
|
||||
'socket_transport_mode'; // 'auto' or 'ws'
|
||||
// Quick pill visibility selections (max 2)
|
||||
static const String _quickPillsKey = 'quick_pills'; // StringList of identifiers e.g. ['web','image','tools']
|
||||
static const String _quickPillsKey =
|
||||
'quick_pills'; // StringList of identifiers e.g. ['web','image','tools']
|
||||
// Chat input behavior
|
||||
static const String _sendOnEnterKey = 'send_on_enter';
|
||||
|
||||
@@ -335,9 +337,14 @@ class AppSettings {
|
||||
highContrast: highContrast ?? this.highContrast,
|
||||
largeText: largeText ?? this.largeText,
|
||||
darkMode: darkMode ?? this.darkMode,
|
||||
defaultModel: defaultModel is _DefaultValue ? this.defaultModel : defaultModel as String?,
|
||||
omitProviderInModelName: omitProviderInModelName ?? this.omitProviderInModelName,
|
||||
voiceLocaleId: voiceLocaleId is _DefaultValue ? this.voiceLocaleId : voiceLocaleId as String?,
|
||||
defaultModel: defaultModel is _DefaultValue
|
||||
? this.defaultModel
|
||||
: defaultModel as String?,
|
||||
omitProviderInModelName:
|
||||
omitProviderInModelName ?? this.omitProviderInModelName,
|
||||
voiceLocaleId: voiceLocaleId is _DefaultValue
|
||||
? this.voiceLocaleId
|
||||
: voiceLocaleId as String?,
|
||||
voiceHoldToTalk: voiceHoldToTalk ?? this.voiceHoldToTalk,
|
||||
voiceAutoSendFinal: voiceAutoSendFinal ?? this.voiceAutoSendFinal,
|
||||
socketTransportMode: socketTransportMode ?? this.socketTransportMode,
|
||||
@@ -363,7 +370,7 @@ class AppSettings {
|
||||
other.voiceAutoSendFinal == voiceAutoSendFinal &&
|
||||
other.sendOnEnter == sendOnEnter &&
|
||||
_listEquals(other.quickPills, quickPills);
|
||||
// socketTransportMode intentionally not included in == to avoid frequent rebuilds
|
||||
// socketTransportMode intentionally not included in == to avoid frequent rebuilds
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -397,18 +404,27 @@ bool _listEquals(List<String> a, List<String> b) {
|
||||
}
|
||||
|
||||
/// Provider for app settings
|
||||
final appSettingsProvider =
|
||||
StateNotifierProvider<AppSettingsNotifier, AppSettings>(
|
||||
(ref) => AppSettingsNotifier(),
|
||||
);
|
||||
final appSettingsProvider = NotifierProvider<AppSettingsNotifier, AppSettings>(
|
||||
AppSettingsNotifier.new,
|
||||
);
|
||||
|
||||
class AppSettingsNotifier extends StateNotifier<AppSettings> {
|
||||
AppSettingsNotifier() : super(const AppSettings()) {
|
||||
_loadSettings();
|
||||
class AppSettingsNotifier extends Notifier<AppSettings> {
|
||||
bool _initialized = false;
|
||||
|
||||
@override
|
||||
AppSettings build() {
|
||||
if (!_initialized) {
|
||||
_initialized = true;
|
||||
Future.microtask(_loadSettings);
|
||||
}
|
||||
return const AppSettings();
|
||||
}
|
||||
|
||||
Future<void> _loadSettings() async {
|
||||
final settings = await SettingsService.loadSettings();
|
||||
if (!ref.mounted) {
|
||||
return;
|
||||
}
|
||||
state = settings;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,17 @@ class SharedPayload {
|
||||
}
|
||||
|
||||
/// Holds a pending shared payload until the app is ready (e.g., authed + model loaded)
|
||||
final pendingSharedPayloadProvider = StateProvider<SharedPayload?>((_) => null);
|
||||
final pendingSharedPayloadProvider =
|
||||
NotifierProvider<PendingSharedPayloadNotifier, SharedPayload?>(
|
||||
PendingSharedPayloadNotifier.new,
|
||||
);
|
||||
|
||||
class PendingSharedPayloadNotifier extends Notifier<SharedPayload?> {
|
||||
@override
|
||||
SharedPayload? build() => null;
|
||||
|
||||
void set(SharedPayload? payload) => state = payload;
|
||||
}
|
||||
|
||||
/// Initializes listening to OS share intents and handles them
|
||||
final shareReceiverInitializerProvider = Provider<void>((ref) {
|
||||
@@ -45,7 +55,7 @@ final shareReceiverInitializerProvider = Provider<void>((ref) {
|
||||
model != null &&
|
||||
isOnChatRoute) {
|
||||
_processPayload(ref, pending);
|
||||
ref.read(pendingSharedPayloadProvider.notifier).state = null;
|
||||
ref.read(pendingSharedPayloadProvider.notifier).set(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +80,7 @@ final shareReceiverInitializerProvider = Provider<void>((ref) {
|
||||
final dynamic media = await handler.getInitialSharedMedia();
|
||||
final payload = _toPayload(media);
|
||||
if (payload.hasAnything) {
|
||||
ref.read(pendingSharedPayloadProvider.notifier).state = payload;
|
||||
ref.read(pendingSharedPayloadProvider.notifier).set(payload);
|
||||
maybeProcessPending();
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -83,7 +93,7 @@ final shareReceiverInitializerProvider = Provider<void>((ref) {
|
||||
try {
|
||||
final payload = _toPayload(media);
|
||||
if (payload.hasAnything) {
|
||||
ref.read(pendingSharedPayloadProvider.notifier).state = payload;
|
||||
ref.read(pendingSharedPayloadProvider.notifier).set(payload);
|
||||
maybeProcessPending();
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -178,10 +188,10 @@ Future<void> _processPayload(Ref ref, SharedPayload payload) async {
|
||||
// Prefill text in the composer (do not auto-send) and request focus
|
||||
final text = payload.text?.trim();
|
||||
if (text != null && text.isNotEmpty) {
|
||||
ref.read(prefilledInputTextProvider.notifier).state = text;
|
||||
ref.read(prefilledInputTextProvider.notifier).set(text);
|
||||
// Bump focus trigger to ensure input focuses after navigation/build
|
||||
final current = ref.read(inputFocusTriggerProvider);
|
||||
ref.read(inputFocusTriggerProvider.notifier).state = current + 1;
|
||||
ref.read(inputFocusTriggerProvider.notifier).set(current + 1);
|
||||
}
|
||||
// Do NOT create a server chat here. The chat is created on first send
|
||||
// (with server syncing + title generation) in chat_providers.dart.
|
||||
|
||||
Reference in New Issue
Block a user