@@ -9,12 +9,10 @@ pub struct QueryInner<T> {
99 key : String ,
1010 /// The current data (if any successful fetch has occurred)
1111 pub data : Option < T > ,
12- /// Whether a fetch is currently in progress
13- pub is_loading : bool ,
14- /// The last error (if any)
15- pub error : Option < Rc < anyhow:: Error > > ,
1612 /// Timestamp of the last successful fetch
1713 pub last_fetched_at : Option < SystemTime > ,
14+ /// The last error (if any) - stored as Rc for signal emission
15+ pub error : Option < Rc < anyhow:: Error > > ,
1816 query_fn : Option <
1917 Box < dyn Fn ( ) -> std:: pin:: Pin < Box < dyn std:: future:: Future < Output = anyhow:: Result < T > > > > > ,
2018 > ,
@@ -27,6 +25,8 @@ pub struct QueryInner<T> {
2725
2826 retry_strategy : Option < Box < dyn Fn ( u32 ) -> Option < Duration > > > ,
2927 retry_count : u32 ,
28+
29+ refetch_strategy : Option < Rc < dyn Fn ( & Query < T > ) + ' static > > ,
3030}
3131
3232impl < T > QueryInner < T > {
@@ -42,7 +42,6 @@ impl<T> QueryInner<T> {
4242 Self {
4343 key,
4444 data : None ,
45- is_loading : false ,
4645 error : None ,
4746 last_fetched_at : None ,
4847 query_fn,
@@ -52,6 +51,7 @@ impl<T> QueryInner<T> {
5251 timeout,
5352 retry_strategy : None ,
5453 retry_count : 0 ,
54+ refetch_strategy : None ,
5555 }
5656 }
5757
@@ -213,7 +213,7 @@ where
213213 }
214214
215215 /// Strategy: Execute fetch immediately
216- pub fn immediate ( ) -> impl FnOnce ( & Query < T > ) {
216+ pub fn immediate ( ) -> impl Fn ( & Query < T > ) {
217217 |query : & Query < T > | {
218218 query. fetch ( ) ;
219219 }
@@ -222,9 +222,7 @@ where
222222 /// Strategy: Debounce fetch calls
223223 /// Waits for `duration` after the last call before executing.
224224 /// If another call arrives before the timer fires, the timer resets.
225- ///
226- /// State is managed internally by the strategy and not stored in Query.
227- pub fn debounce ( duration : Duration ) -> impl FnOnce ( & Query < T > ) {
225+ pub fn debounce ( duration : Duration ) -> impl Fn ( & Query < T > ) {
228226 // Strategy state: managed by the closure itself
229227 let debounce_state: Rc < RefCell < Option < glib:: SourceId > > > = Rc :: new ( RefCell :: new ( None ) ) ;
230228
@@ -259,9 +257,7 @@ where
259257 /// Executes at most once per `interval`.
260258 /// If `trailing` is true, a trailing fetch will be scheduled after the interval
261259 /// if calls arrived during the throttle period.
262- ///
263- /// State is managed internally by the strategy and not stored in Query.
264- pub fn throttle ( interval : Duration , trailing : bool ) -> impl FnOnce ( & Query < T > ) {
260+ pub fn throttle ( interval : Duration , trailing : bool ) -> impl Fn ( & Query < T > ) {
265261 // Strategy state: managed by the closure itself
266262 let throttle_state: Rc < RefCell < ( Option < Instant > , Option < glib:: SourceId > ) > > =
267263 Rc :: new ( RefCell :: new ( ( None , None ) ) ) ;
@@ -353,8 +349,8 @@ where
353349 if let Some ( interval) = options. refetch_interval {
354350 let weak = Rc :: downgrade ( & inner) ;
355351 let source_id = glib:: timeout_add_seconds_local ( interval, move || {
356- if let Some ( query ) = Self :: from_weak ( & weak) {
357- query . fetch ( ) ;
352+ if let Some ( inner ) = weak. upgrade ( ) {
353+ Self { inner } . fetch ( ) ;
358354 }
359355 glib:: ControlFlow :: Continue
360356 } ) ;
@@ -363,15 +359,6 @@ where
363359 query
364360 }
365361
366- fn from_strong ( strong : & Rc < RefCell < QueryInner < T > > > ) -> Self {
367- Self {
368- inner : strong. clone ( ) ,
369- }
370- }
371- fn from_weak ( weak : & std:: rc:: Weak < RefCell < QueryInner < T > > > ) -> Option < Self > {
372- weak. upgrade ( ) . map ( |inner| Self { inner } )
373- }
374-
375362 /// Execute a fetch operation and handle the result
376363 async fn execute_fetch ( inner : & Rc < RefCell < QueryInner < T > > > ) {
377364 let key = { inner. borrow ( ) . key . clone ( ) } ;
@@ -407,7 +394,6 @@ where
407394 match result {
408395 Ok ( _data) => {
409396 inner. borrow_mut ( ) . data = Some ( _data. clone ( ) ) ;
410- inner. borrow_mut ( ) . is_loading = false ;
411397 inner. borrow_mut ( ) . error = None ;
412398 query_obj. set_is_loading ( false ) ;
413399 query_obj. set_is_success ( true ) ;
@@ -421,13 +407,12 @@ where
421407 }
422408 Err ( error) => {
423409 if inner. borrow ( ) . retry_strategy . is_some ( ) {
424- Self :: from_strong ( inner) . retry ( ) ;
410+ Self { inner : inner. clone ( ) } . retry ( ) ;
425411 return ;
426412 }
427413 let rc_error = Rc :: new ( error) ;
428414 let error_msg = rc_error. to_string ( ) ;
429415 // Keep the previous data, just mark as error
430- inner. borrow_mut ( ) . is_loading = false ;
431416 inner. borrow_mut ( ) . error = Some ( rc_error) ;
432417 query_obj. set_is_loading ( false ) ;
433418 query_obj. set_is_error ( true ) ;
@@ -451,11 +436,10 @@ where
451436 handle. abort ( ) ;
452437 }
453438
454- // Set loading inner , but preserve any previous data
439+ // Set loading state , but preserve any previous data
455440 query_obj. set_is_loading ( true ) ;
456441 query_obj. set_is_error ( false ) ;
457442 query_obj. set_is_success ( false ) ;
458- self . inner . borrow_mut ( ) . is_loading = true ;
459443 self . inner . borrow_mut ( ) . last_fetched_at = Some ( SystemTime :: now ( ) ) ;
460444
461445 let inner = self . inner . clone ( ) ;
@@ -468,21 +452,21 @@ where
468452 self . inner . borrow_mut ( ) . fetch_task_handle = Some ( handle) ;
469453 }
470454
471- /// Refetch with immediate strategy (for backward compatibility)
472- pub fn refetch ( & self ) {
473- self . refetch_with ( Self :: immediate ( ) ) ;
455+ /// Set the refetch strategy for this query.
456+ /// The strategy is a closure that determines when and how to execute the fetch.
457+ /// Common strategies are `Query::immediate`, `Query::debounce`, and `Query::throttle`.
458+ pub fn set_refetch_strategy ( & self , strategy : impl Fn ( & Query < T > ) + ' static ) {
459+ self . inner . borrow_mut ( ) . refetch_strategy = Some ( Rc :: new ( strategy) ) ;
474460 }
475461
476- /// Refetch with a specific strategy
477- ///
478- /// # Example
479- /// ```
480- /// query.refetch_with(Query::immediate());
481- /// query.refetch_with(Query::debounce(Duration::from_millis(300)));
482- /// query.refetch_with(Query::throttle(Duration::from_secs(1), true));
483- /// ```
484- pub fn refetch_with ( & self , strategy : impl FnOnce ( & Query < T > ) ) {
485- strategy ( self ) ;
462+ /// Refetch using the configured strategy (or immediate if none set)
463+ pub fn refetch ( & self ) {
464+ let strategy = self . inner . borrow ( ) . refetch_strategy . clone ( ) ;
465+ if let Some ( strategy) = strategy {
466+ strategy ( self ) ;
467+ } else {
468+ self . fetch ( ) ;
469+ }
486470 }
487471
488472 pub fn retry ( & self ) {
@@ -547,12 +531,6 @@ where
547531 } )
548532 }
549533
550- /// Bind a widget property to the query inner
551- pub fn bind_to_widget < W : IsA < gtk:: Widget > > ( & self , widget : & W , property : & str ) {
552- let query_obj = { self . inner . borrow ( ) . query_obj . clone ( ) } ;
553- query_obj. bind_property ( property, widget, property) . build ( ) ;
554- }
555-
556534 pub fn data ( & self ) -> Option < T > {
557535 self . inner . borrow ( ) . data . clone ( )
558536 }
0 commit comments