Адрес бэкенда хранится в shared_preferences и читается до runApp; switchApiBaseUrl сбрасывает токены и кэш старого сервера. Выход стирает refresh-токен и sqlite-кэш ответов. Экран настроек переделан под разделы.
33 lines
1.1 KiB
Dart
33 lines
1.1 KiB
Dart
import 'package:dio/dio.dart';
|
|
|
|
/// A value from the API, or the last one [CacheInterceptor] had on file for the
|
|
/// same endpoint+params when the live request failed. `fetchedAt` is null for
|
|
/// a live answer — that is the one bit a screen needs to decide whether to
|
|
/// show a `StaleBanner`. See `docs/ai/offline-cache.md`.
|
|
class Cached<T> {
|
|
const Cached(this.data, {this.fetchedAt});
|
|
|
|
final T data;
|
|
final DateTime? fetchedAt;
|
|
}
|
|
|
|
extension CachedResponseX<T> on Response<T> {
|
|
/// Wraps this response's data with the staleness [CacheInterceptor] recorded
|
|
/// in `extra['fetchedAt']`. A provider that wants offline support returns
|
|
/// `r.cached` instead of `r.data!`.
|
|
Cached<T> get cached =>
|
|
Cached(data as T, fetchedAt: extra['fetchedAt'] as DateTime?);
|
|
}
|
|
|
|
/// The oldest of several fetch times, or null if none of them is stale.
|
|
/// Screens with several cached providers show one banner for the lot rather
|
|
/// than one per tile.
|
|
DateTime? oldestFetch(Iterable<DateTime?> fetchedAt) {
|
|
DateTime? oldest;
|
|
for (final at in fetchedAt) {
|
|
if (at == null) continue;
|
|
if (oldest == null || at.isBefore(oldest)) oldest = at;
|
|
}
|
|
return oldest;
|
|
}
|