Skip to content

Commit 2aa3c54

Browse files
committed
link the animation to the actual refresh process
1 parent 4460b25 commit 2aa3c54

2 files changed

Lines changed: 81 additions & 12 deletions

File tree

lib/schedule/ui/viewmodels/weekly_schedule_view_model.dart

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ class WeeklyScheduleViewModel extends BaseViewModel {
328328
currentDateStart,
329329
currentDateEnd,
330330
force: true,
331+
awaitRefresh: true,
331332
);
332333
}
333334

@@ -361,6 +362,7 @@ class WeeklyScheduleViewModel extends BaseViewModel {
361362
DateTime end, {
362363
bool force = false,
363364
bool applyToVisibleState = true,
365+
bool awaitRefresh = false,
364366
}) async {
365367
if (_isDisposed) return;
366368

@@ -417,6 +419,7 @@ class WeeklyScheduleViewModel extends BaseViewModel {
417419
end,
418420
visibleUpdateRequestId: visibleUpdateRequestId,
419421
applyToVisibleState: applyToVisibleState,
422+
awaitRefresh: awaitRefresh,
420423
origin: applyToVisibleState
421424
? ScheduleRefreshOrigin.userBrowsing
422425
: ScheduleRefreshOrigin.foregroundMaintenance,
@@ -434,6 +437,7 @@ class WeeklyScheduleViewModel extends BaseViewModel {
434437
DateTime end, {
435438
int? visibleUpdateRequestId,
436439
bool applyToVisibleState = true,
440+
bool awaitRefresh = false,
437441
ScheduleRefreshOrigin origin = ScheduleRefreshOrigin.userBrowsing,
438442
}) async {
439443
final task = PerformanceTelemetry.instance.startTask(
@@ -470,27 +474,32 @@ class WeeklyScheduleViewModel extends BaseViewModel {
470474
}
471475

472476
final nowValue = now;
473-
final shouldForceFetch = cachedSchedule.entries.isEmpty &&
474-
scheduleSourceProvider.currentScheduleSource.canQuery();
477+
final shouldForceFetch = awaitRefresh ||
478+
(cachedSchedule.entries.isEmpty &&
479+
scheduleSourceProvider.currentScheduleSource.canQuery());
475480
final isStale = shouldForceFetch || _isWindowStale(start, end, nowValue);
476481

477482
if (!isStale) {
478483
unawaited(task.finish());
479484
return false;
480485
}
481486

482-
unawaited(
483-
_refreshScheduleInBackground(
484-
start,
485-
end,
486-
cancellationToken,
487-
task,
488-
visibleUpdateRequestId: visibleUpdateRequestId,
489-
applyToVisibleState: applyToVisibleState,
490-
origin: origin,
491-
),
487+
final refreshFuture = _refreshScheduleInBackground(
488+
start,
489+
end,
490+
cancellationToken,
491+
task,
492+
visibleUpdateRequestId: visibleUpdateRequestId,
493+
applyToVisibleState: applyToVisibleState,
494+
origin: origin,
492495
);
493496

497+
if (awaitRefresh) {
498+
await refreshFuture;
499+
} else {
500+
unawaited(refreshFuture);
501+
}
502+
494503
return true;
495504
}
496505

test/schedule/ui/viewmodels/weekly_schedule_background_refresh_test.dart

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,66 @@ void main() {
183183

184184
expect(viewModel.isUpdating, isFalse);
185185
});
186+
187+
test(
188+
'refreshVisibleWeek awaits network refresh before completing',
189+
() async {
190+
final provider = _BlockingScheduleProvider();
191+
final sourceProvider = _FakeScheduleSourceProvider();
192+
final viewModel = WeeklyScheduleViewModel(provider, sourceProvider);
193+
194+
final weekStart = DateTime(2026, 2, 9);
195+
final weekEnd = DateTime(2026, 2, 16);
196+
197+
viewModel.currentDateStart = weekStart;
198+
viewModel.currentDateEnd = weekEnd;
199+
200+
var refreshCompleted = false;
201+
final refreshFuture = viewModel.refreshVisibleWeek().then((_) {
202+
refreshCompleted = true;
203+
});
204+
205+
// Let microtasks run but the blocking provider hasn't completed yet.
206+
await Future<void>.delayed(const Duration(milliseconds: 50));
207+
expect(refreshCompleted, isFalse,
208+
reason: 'refreshVisibleWeek should not complete until network '
209+
'request finishes');
210+
211+
// Now complete the network request.
212+
provider.complete(
213+
ScheduleQueryResult(Schedule(), const []),
214+
);
215+
await refreshFuture;
216+
expect(refreshCompleted, isTrue);
217+
},
218+
);
219+
220+
test(
221+
'refreshVisibleWeek forces fetch even when cache is fresh',
222+
() async {
223+
final entries = <ScheduleEntry>[
224+
_entry(DateTime(2026, 2, 9), 'Mon'),
225+
];
226+
final provider = _CountingScheduleProvider(entries);
227+
final sourceProvider = _FakeScheduleSourceProvider();
228+
final viewModel = WeeklyScheduleViewModel(provider, sourceProvider);
229+
230+
final weekStart = DateTime(2026, 2, 9);
231+
final weekEnd = DateTime(2026, 2, 16);
232+
233+
// Initial load populates cache and marks window as fresh.
234+
await viewModel.updateSchedule(weekStart, weekEnd, force: true);
235+
expect(provider.updatedScheduleRequests, 1);
236+
237+
viewModel.currentDateStart = weekStart;
238+
viewModel.currentDateEnd = weekEnd;
239+
240+
// Pull-to-refresh should fetch again even though cache is fresh.
241+
await viewModel.refreshVisibleWeek();
242+
expect(provider.updatedScheduleRequests, 2,
243+
reason: 'pull-to-refresh must bypass staleness gate');
244+
},
245+
);
186246
}
187247

188248
ScheduleEntry _entry(DateTime start, String suffix) {

0 commit comments

Comments
 (0)