@@ -5,7 +5,6 @@ import 'package:appflowy/workspace/application/settings/ai/local_llm_listener.da
55import 'package:appflowy_backend/dispatch/dispatch.dart' ;
66import 'package:appflowy_backend/log.dart' ;
77import 'package:appflowy_backend/protobuf/flowy-ai/entities.pb.dart' ;
8- import 'package:appflowy_result/appflowy_result.dart' ;
98import 'package:easy_localization/easy_localization.dart' ;
109import 'package:protobuf/protobuf.dart' ;
1110import 'package:universal_platform/universal_platform.dart' ;
@@ -21,12 +20,14 @@ class AIModelStateNotifier {
2120 final bool _isDesktop;
2221 final LocalAIStateListener ? _localAIListener;
2322 final AIModelSwitchListener _aiModelSwitchListener;
23+
2424 LocalAIPB ? _localAIState;
2525 AvailableModelsPB ? _availableModels;
2626
27- // callbacks
27+ // Callbacks
2828 void Function (AiType , bool , String )? onChanged;
2929 void Function (AvailableModelsPB )? onAvailableModelsChanged;
30+
3031 String hintText () {
3132 final aiType = getCurrentAiType ();
3233 if (aiType.isLocal) {
@@ -38,22 +39,16 @@ class AIModelStateNotifier {
3839 }
3940
4041 AiType getCurrentAiType () {
41- // On non-desktop platforms, always return cloud type
42- if (! _isDesktop) {
43- return AiType .cloud;
44- }
45-
46- return _availableModels? .selectedModel.isLocal == true
42+ // On non-desktop platforms, always return cloud type.
43+ if (! _isDesktop) return AiType .cloud;
44+ return (_availableModels? .selectedModel.isLocal ?? false )
4745 ? AiType .local
4846 : AiType .cloud;
4947 }
5048
5149 bool isEditable () {
52- // On non-desktop platforms, always editable (cloud-only)
53- if (! _isDesktop) {
54- return true ;
55- }
56-
50+ // On non-desktop platforms, always editable.
51+ if (! _isDesktop) return true ;
5752 return getCurrentAiType ().isLocal
5853 ? _localAIState? .state == RunningStatePB .Running
5954 : true ;
@@ -64,7 +59,11 @@ class AIModelStateNotifier {
6459 }
6560
6661 Future <void > init () async {
67- await _loadAvailableModels ();
62+ // Load both available models and local state concurrently.
63+ await Future .wait ([
64+ _loadAvailableModels (),
65+ _loadLocalAIState (),
66+ ]);
6867 }
6968
7069 Future <void > _loadAvailableModels () async {
@@ -76,8 +75,20 @@ class AIModelStateNotifier {
7675 onAvailableModelsChanged? .call (models);
7776 _notifyStateChanged ();
7877 },
79- (err) {
80- Log .error ("Failed to get available models: $err " );
78+ (err) => Log .error ("Failed to get available models: $err " ),
79+ );
80+ }
81+
82+ Future <void > _loadLocalAIState () async {
83+ final result = await AIEventGetLocalAIState ().send ();
84+ result.fold (
85+ (state) {
86+ _localAIState = state;
87+ _notifyStateChanged ();
88+ },
89+ (error) {
90+ Log .error ("Failed to get local AI state: $error " );
91+ _notifyStateChanged ();
8192 },
8293 );
8394 }
@@ -89,12 +100,11 @@ class AIModelStateNotifier {
89100 this .onChanged = onChanged;
90101 this .onAvailableModelsChanged = onAvailableModelsChanged;
91102
92- // Only start local AI listener on desktop platforms
103+ // Only start local AI listener on desktop platforms.
93104 if (_isDesktop) {
94105 _localAIListener? .start (
95106 stateCallback: (state) {
96107 _localAIState = state;
97-
98108 if (state.state == RunningStatePB .Running ||
99109 state.state == RunningStatePB .Stopped ) {
100110 _loadAvailableModels ();
@@ -111,18 +121,8 @@ class AIModelStateNotifier {
111121 _availableModels = updatedModels;
112122 onAvailableModelsChanged? .call (updatedModels);
113123 }
114-
115124 if (model.isLocal && _isDesktop) {
116- AIEventGetLocalAIState ().send ().fold (
117- (localAIState) {
118- _localAIState = localAIState;
119- _notifyStateChanged ();
120- },
121- (error) {
122- Log .error ("Failed to get local AI state: $error " );
123- _notifyStateChanged ();
124- },
125- );
125+ _loadLocalAIState ();
126126 } else {
127127 _notifyStateChanged ();
128128 }
0 commit comments