From 169c294e62bcc63121a20010fd7857beefc4e336 Mon Sep 17 00:00:00 2001 From: mace Date: Sat, 12 Sep 2026 15:29:32 +0200 Subject: [PATCH] Mark article read on display in article view, including on boot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit markCurrentArticleRead() already marked the displayed article read immediately at each deliberate navigation point (entering article view, paging next/prev), but reloading the page while viewMode was already 'article' (persisted in localStorage) booted straight into article view without marking anything read — the article on screen stayed unread until the user paged forward/back at least once. Close that gap with a single explicit call in RssFeeds.vue's onMounted: once the initial fetch resolves, if we're already in article view, mark the now-displayed article read the same way toggleViewMode()/ nextArticle()/prevArticle() do. (A first attempt replaced the explicit call sites with a generic watch on the displayed article's id, but that also fired on unrelated changes to it — e.g. switching the feed filter while in article view resets currentIndex and reprojects feeds, so the watch would silently mark an article the user never viewed as read. Reverted to the explicit, call-site-scoped approach and added only the one boot-time call needed.) Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01K2sYVA7rh7N5RYmcCd2KDV --- vue/src/components/RssFeeds.vue | 6 ++++++ vue/src/composables/__tests__/viewModeBoot.spec.js | 4 ++++ vue/src/composables/useFeeds.js | 1 + 3 files changed, 11 insertions(+) diff --git a/vue/src/components/RssFeeds.vue b/vue/src/components/RssFeeds.vue index acf8fea..51d6523 100644 --- a/vue/src/components/RssFeeds.vue +++ b/vue/src/components/RssFeeds.vue @@ -17,6 +17,7 @@ const { disconnectObserver, setInitialLoad, showMessageForXSeconds, + markCurrentArticleRead, } = useFeeds() const unreadCount = computed(() => feeds.value.filter(f => !f.read).length) @@ -122,6 +123,11 @@ onBeforeUnmount(() => { onMounted(async () => { setInitialLoad(false) await fetchData() + // viewMode persists across reloads (see useFeeds.js) — if we're booting + // straight into article view, the article now on screen needs the same + // immediate mark-read that toggleViewMode()/nextArticle()/prevArticle() + // give it when reached by in-session navigation. + if (viewMode.value === 'article') markCurrentArticleRead() sync(true) setTimeout(function () { setInitialLoad(true) diff --git a/vue/src/composables/__tests__/viewModeBoot.spec.js b/vue/src/composables/__tests__/viewModeBoot.spec.js index 4aedde5..de5a8f1 100644 --- a/vue/src/composables/__tests__/viewModeBoot.spec.js +++ b/vue/src/composables/__tests__/viewModeBoot.spec.js @@ -57,6 +57,10 @@ describe('viewMode boot persistence', () => { expect(wrapper.find('.article-single').exists()).toBe(true) expect(wrapper.find('#article').exists()).toBe(false) + // The article shown right after reload must be marked read immediately — + // not only once the user pages forward/back at least once. + expect(axios.put).toHaveBeenCalledWith('/api/v1/article/read/1', null, expect.anything()) + wrapper.unmount() }) diff --git a/vue/src/composables/useFeeds.js b/vue/src/composables/useFeeds.js index 49ffd2d..b81ddf3 100644 --- a/vue/src/composables/useFeeds.js +++ b/vue/src/composables/useFeeds.js @@ -593,6 +593,7 @@ export function useFeeds() { currentIndex, toggleViewMode, leaveArticleView, + markCurrentArticleRead, layout, toggleLayout, nextArticle,