@@ -15,8 +15,16 @@ part 'command_palette_bloc.freezed.dart';
1515class CommandPaletteBloc
1616 extends Bloc <CommandPaletteEvent , CommandPaletteState > {
1717 CommandPaletteBloc () : super (CommandPaletteState .initial ()) {
18+ // Register individual event handlers for clarity
19+ on < _SearchChanged > (_onSearchChanged);
20+ on < _PerformSearch > (_onPerformSearch);
21+ on < _NewSearchStream > (_onNewSearchStream);
22+ on < _ResultsChanged > (_onResultsChanged);
23+ on < _TrashChanged > (_onTrashChanged);
24+ on < _WorkspaceChanged > (_onWorkspaceChanged);
25+ on < _ClearSearch > (_onClearSearch);
26+
1827 _initTrash ();
19- _dispatch ();
2028 }
2129
2230 Timer ? _debounceOnChanged;
@@ -32,122 +40,6 @@ class CommandPaletteBloc
3240 return super .close ();
3341 }
3442
35- void _dispatch () {
36- on < CommandPaletteEvent > ((event, emit) async {
37- event.when (
38- searchChanged: _debounceOnSearchChanged,
39- trashChanged: (trash) async {
40- if (trash != null ) {
41- return emit (state.copyWith (trash: trash));
42- }
43-
44- final trashOrFailure = await _trashService.readTrash ();
45- final trashRes = trashOrFailure.fold (
46- (trash) => trash,
47- (error) => null ,
48- );
49-
50- if (trashRes != null ) {
51- emit (state.copyWith (trash: trashRes.items));
52- }
53- },
54- performSearch: (search) async {
55- if (search.isNotEmpty && search != state.query) {
56- _oldQuery = state.query;
57- emit (state.copyWith (query: search, isLoading: true ));
58- unawaited (
59- SearchBackendService .performSearch (
60- search,
61- workspaceId: _workspaceId,
62- ).then (
63- (result) {
64- result.onSuccess (
65- (stream) async {
66- if (! isClosed) {
67- add (
68- CommandPaletteEvent .newSearchStream (stream: stream),
69- );
70- }
71- },
72- );
73- },
74- ),
75- );
76- } else {
77- emit (
78- state.copyWith (
79- query: null ,
80- isLoading: false ,
81- resultItems: [],
82- resultSummaries: [],
83- ),
84- );
85- }
86- },
87- newSearchStream: (SearchResponseStream stream) {
88- if (state.searchResponseStream != null ) {
89- state.searchResponseStream! .dispose ();
90- }
91-
92- emit (state.copyWith (searchId: stream.searchId));
93- stream.listen (
94- onData: (SearchResponsePB response) {
95- if (! isClosed) {
96- add (CommandPaletteEvent .resultsChanged (response: response));
97- }
98- },
99- );
100- },
101- resultsChanged: (SearchResponsePB response) {
102- if (state.query != _oldQuery) {
103- emit (
104- state.copyWith (
105- resultItems: [],
106- resultSummaries: [],
107- isLoading: response.isLoading,
108- ),
109- );
110- _oldQuery = state.query;
111- }
112-
113- if (state.searchId != response.searchId) {
114- return ;
115- }
116-
117- emit (
118- state.copyWith (
119- resultItems: response.result.items,
120- resultSummaries: response.result.summaries,
121- isLoading: response.isLoading,
122- ),
123- );
124- },
125- workspaceChanged: (workspaceId) {
126- _workspaceId = workspaceId;
127- emit (
128- state.copyWith (
129- resultItems: [],
130- resultSummaries: [],
131- query: '' ,
132- isLoading: false ,
133- ),
134- );
135- },
136- clearSearch: () {
137- emit (
138- state.copyWith (
139- resultItems: [],
140- resultSummaries: [],
141- query: '' ,
142- isLoading: false ,
143- searchId: null ,
144- ),
145- );
146- },
147- );
148- });
149- }
150-
15143 Future <void > _initTrash () async {
15244 _trashListener.start (
15345 trashUpdated: (trashOrFailed) {
@@ -158,53 +50,188 @@ class CommandPaletteBloc
15850
15951 final trashOrFailure = await _trashService.readTrash ();
16052 final trash = trashOrFailure.toNullable ();
161-
16253 add (CommandPaletteEvent .trashChanged (trash: trash? .items));
16354 }
16455
165- void _debounceOnSearchChanged (String value) {
56+ // Handler for debouncing search changes
57+ FutureOr <void > _onSearchChanged (
58+ _SearchChanged event,
59+ Emitter <CommandPaletteState > emit,
60+ ) {
16661 _debounceOnChanged? .cancel ();
16762 _debounceOnChanged = Timer (
16863 const Duration (milliseconds: 300 ),
169- () => _performSearch (value),
64+ () {
65+ if (! isClosed) {
66+ add (CommandPaletteEvent .performSearch (search: event.search));
67+ }
68+ },
69+ );
70+ }
71+
72+ // Handler for performing search
73+ FutureOr <void > _onPerformSearch (
74+ _PerformSearch event,
75+ Emitter <CommandPaletteState > emit,
76+ ) async {
77+ if (event.search.isNotEmpty && event.search != state.query) {
78+ _oldQuery = state.query;
79+ emit (state.copyWith (query: event.search, isLoading: true ));
80+
81+ // Fire off the search asynchronously without waiting for its result
82+ unawaited (
83+ SearchBackendService .performSearch (
84+ event.search,
85+ workspaceId: _workspaceId,
86+ ).then (
87+ (result) {
88+ result.onSuccess ((stream) async {
89+ if (! isClosed) {
90+ add (CommandPaletteEvent .newSearchStream (stream: stream));
91+ }
92+ });
93+ },
94+ ),
95+ );
96+ } else {
97+ emit (
98+ state.copyWith (
99+ query: null ,
100+ isLoading: false ,
101+ resultItems: [],
102+ resultSummaries: [],
103+ ),
104+ );
105+ }
106+ }
107+
108+ // Handler to listen and forward search stream events
109+ FutureOr <void > _onNewSearchStream (
110+ _NewSearchStream event,
111+ Emitter <CommandPaletteState > emit,
112+ ) {
113+ // Dispose previous stream if exists
114+ state.searchResponseStream? .dispose ();
115+ emit (
116+ state.copyWith (
117+ searchId: event.stream.searchId,
118+ searchResponseStream: event.stream,
119+ ),
120+ );
121+
122+ // Listen to the stream and add incoming results as events
123+ event.stream.listen (
124+ onData: (SearchResponsePB response) {
125+ if (! isClosed) {
126+ add (CommandPaletteEvent .resultsChanged (response: response));
127+ }
128+ },
170129 );
171130 }
172131
173- void _performSearch (String value) =>
174- add (CommandPaletteEvent .performSearch (search: value));
132+ // Handler for results update events
133+ FutureOr <void > _onResultsChanged (
134+ _ResultsChanged event,
135+ Emitter <CommandPaletteState > emit,
136+ ) async {
137+ // If the query has been updated since the last search, clear previous results
138+ if (state.query != _oldQuery) {
139+ emit (
140+ state.copyWith (
141+ resultItems: [],
142+ resultSummaries: [],
143+ isLoading: event.response.isLoading,
144+ ),
145+ );
146+ _oldQuery = state.query;
147+ }
148+
149+ if (state.searchId != event.response.searchId) {
150+ return ;
151+ }
152+
153+ emit (
154+ state.copyWith (
155+ resultItems: event.response.result.items,
156+ resultSummaries: event.response.result.summaries,
157+ isLoading: event.response.isLoading,
158+ ),
159+ );
160+ }
161+
162+ // Handler for trash update events
163+ FutureOr <void > _onTrashChanged (
164+ _TrashChanged event,
165+ Emitter <CommandPaletteState > emit,
166+ ) async {
167+ if (event.trash != null ) {
168+ emit (state.copyWith (trash: event.trash! ));
169+ } else {
170+ final trashOrFailure = await _trashService.readTrash ();
171+ final trashRes = trashOrFailure.fold ((trash) => trash, (error) => null );
172+ if (trashRes != null ) {
173+ emit (state.copyWith (trash: trashRes.items));
174+ }
175+ }
176+ }
177+
178+ // Handler for workspace changes
179+ FutureOr <void > _onWorkspaceChanged (
180+ _WorkspaceChanged event,
181+ Emitter <CommandPaletteState > emit,
182+ ) {
183+ _workspaceId = event.workspaceId;
184+ emit (
185+ state.copyWith (
186+ resultItems: [],
187+ resultSummaries: [],
188+ query: '' ,
189+ isLoading: false ,
190+ ),
191+ );
192+ }
193+
194+ // Handler for clearing the search state
195+ FutureOr <void > _onClearSearch (
196+ _ClearSearch event,
197+ Emitter <CommandPaletteState > emit,
198+ ) {
199+ emit (
200+ state.copyWith (
201+ resultItems: [],
202+ resultSummaries: [],
203+ query: '' ,
204+ isLoading: false ,
205+ searchId: null ,
206+ ),
207+ );
208+ }
175209}
176210
177211@freezed
178212class CommandPaletteEvent with _$CommandPaletteEvent {
179213 const factory CommandPaletteEvent .searchChanged ({required String search}) =
180214 _SearchChanged ;
181-
182215 const factory CommandPaletteEvent .performSearch ({required String search}) =
183216 _PerformSearch ;
184-
185217 const factory CommandPaletteEvent .newSearchStream ({
186218 required SearchResponseStream stream,
187219 }) = _NewSearchStream ;
188-
189220 const factory CommandPaletteEvent .resultsChanged ({
190221 required SearchResponsePB response,
191222 }) = _ResultsChanged ;
192-
193223 const factory CommandPaletteEvent .trashChanged ({
194224 @Default (null ) List <TrashPB >? trash,
195225 }) = _TrashChanged ;
196-
197226 const factory CommandPaletteEvent .workspaceChanged ({
198227 @Default (null ) String ? workspaceId,
199228 }) = _WorkspaceChanged ;
200-
201229 const factory CommandPaletteEvent .clearSearch () = _ClearSearch ;
202230}
203231
204232@freezed
205233class CommandPaletteState with _$CommandPaletteState {
206234 const CommandPaletteState ._();
207-
208235 const factory CommandPaletteState ({
209236 @Default (null ) String ? query,
210237 @Default ([]) List <SearchResponseItemPB > resultItems,
0 commit comments