Skip to content

Commit

Permalink
fix(reading): avoid duplicate loading when changing article
Browse files Browse the repository at this point in the history
  • Loading branch information
casimir committed Jan 8, 2025
1 parent 4f8dd2e commit f8244e1
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 57 deletions.
7 changes: 0 additions & 7 deletions lib/pages/articles/article_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,6 @@ class _ArticleListState extends ConsumerState<ArticleListView> {
controller: _scroller,
itemCount: ref.watch(queryMetaProvider.selectAsync((it) => it.count)),
itemBuilder: (context, index) async {
if (index == 0) {
WidgetsBinding.instance.addPostFrameCallback((_) {
ref.read(queryMetaProvider.future).then((meta) {
ref.read(currentArticleProvider.notifier).maybeInit(meta.ids[0]);
});
});
}
return AsyncArticleItem(
articleId: await ref
.watch(queryMetaProvider.selectAsync((it) => it.ids[index])),
Expand Down
72 changes: 24 additions & 48 deletions lib/providers/article.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ class ArticleData extends _$ArticleData {
@override
Future<Article?> build(int articleId) async {
final stopwatch = Stopwatch()..start();

_watcher?.cancel();
_watch(articleId);
ref.onDispose(() => _watcher?.cancel());

final t1 = DB().managers.articles;
final ret =
await t1.filter((f) => f.id.equals(articleId)).getSingleOrNull();
Expand All @@ -35,75 +38,48 @@ class ArticleData extends _$ArticleData {
void _watch(int articleId) {
final q = DB().managers.articles.filter((f) => f.id.equals(articleId));
_watcher = q.watchSingleOrNull(distinct: false).listen((article) {
final stateArticle = state.maybeWhen(orElse: () => null, data: (a) => a);
if (state.isLoading || !state.hasValue) return;
final stateArticle = state.value;
if (stateArticle == null || article != stateArticle) {
state = AsyncValue.data(article);
}
});
ref.onDispose(() => _watcher?.cancel());
}
}

@riverpod
class CurrentArticle extends _$CurrentArticle {
int? _articleId;
StreamSubscription? _watcher;

@override
Future<Article?> build() async {
_watcher?.cancel();

_articleId ??=
var articleId =
ref.watch(settingsProvider.select((it) => it[Sk.selectedArticleId]));

if (_articleId == null) {
final meta = await ref.read(queryMetaProvider.future);
if (meta.ids.isNotEmpty) {
_articleId = meta.ids.first;
if (articleId != null) {
final db = DB();
final exists = await db.managers.articles
.filter((f) => f.id.equals(articleId))
.exists();
if (!exists) {
articleId = null;
}
}

if (_articleId != null) {
_watch();
return ref.watch(articleDataProvider(_articleId!).future);
}

return null;
}

void _watch() {
final q = DB().managers.articles.filter((f) => f.id.equals(_articleId!));
_watcher = q.watchSingleOrNull(distinct: false).listen((article) {
if (article == null) {
_articleId = null;
ref.invalidateSelf();
return;
if (articleId == null) {
final meta = await ref.read(queryMetaProvider.future);
if (meta.ids.isNotEmpty) {
articleId = meta.ids.first;
}
}

final stateArticle = state.maybeWhen(orElse: () => null, data: (a) => a);
if (stateArticle == null) {
state = AsyncValue.data(article);
} else if (article.id != stateArticle.id) {
change(article.id);
}
});
ref.onDispose(() => _watcher?.cancel());
return articleId != null
? ref.watch(articleDataProvider(articleId!).future)
: null;
}

void change(int articleId) {
if (_articleId == articleId) return;

_articleId = articleId;

ref.read(settingsProvider.notifier).set(Sk.selectedArticleId, articleId);
ref.invalidateSelf();
}

bool maybeInit(int articleId) {
if (_articleId != null && _articleId! > 0) return false;

change(articleId);
return true;
if (state.value?.id != articleId) {
ref.read(settingsProvider.notifier).set(Sk.selectedArticleId, articleId);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/providers/article.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f8244e1

Please sign in to comment.