From 92a44faac3b1d6dbfeab803f342ccfc6b1b7219a Mon Sep 17 00:00:00 2001 From: Yusuf Suleman Date: Sat, 4 Apr 2026 13:08:27 -0500 Subject: [PATCH] =?UTF-8?q?fix:=20three=20Reader=20bugs=20=E2=80=94=20imag?= =?UTF-8?q?e=20overflow,=20load=20more,=20refresh=20read=20state?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #22 Image overflow: added .frame(maxWidth: .infinity) before .frame(height: 180) on AsyncImage to constrain width within card. Card's .clipShape already clips corners. #23 Load more not triggering: added loadMoreIfNeeded(for:) that fires onAppear for entries 5 from the bottom. No longer relies solely on the bottom sentinel Color.clear which could be missed. Also increased sentinel height from 1pt to 40pt. #24 Refresh not updating read state: flushDeferredReads() now called before vm.refresh() in .refreshable. Deferred marks are synced to API before re-fetching, so the server returns correct read states. Also clears markedByScroll set. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Features/Reader/Views/EntryListView.swift | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/ios/Platform/Platform/Features/Reader/Views/EntryListView.swift b/ios/Platform/Platform/Features/Reader/Views/EntryListView.swift index 68d34bb..4d9f001 100644 --- a/ios/Platform/Platform/Features/Reader/Views/EntryListView.swift +++ b/ios/Platform/Platform/Features/Reader/Views/EntryListView.swift @@ -66,6 +66,9 @@ struct EntryListView: View { } } .refreshable { + // Flush any deferred read marks before refreshing + flushDeferredReads() + markedByScroll.removeAll() await vm.refresh() } .navigationDestination(for: ReaderEntry.self) { entry in @@ -176,6 +179,7 @@ struct EntryListView: View { entryContextMenu(entry: entry, vm: vm) } ) + .onAppear { loadMoreIfNeeded(for: entry) } } loadMoreTrigger @@ -201,6 +205,7 @@ struct EntryListView: View { entryContextMenu(entry: entry, vm: vm) } ) + .onAppear { loadMoreIfNeeded(for: entry) } Divider() .padding(.leading, 36) @@ -212,14 +217,25 @@ struct EntryListView: View { } } + // Trigger loadMore when an entry near the bottom appears + private func loadMoreIfNeeded(for entry: ReaderEntry) { + let entries = vm.entries + guard entries.count >= 5 else { return } + let threshold = entries[entries.count - 5].id + if entry.id == threshold { + Task { await vm.loadMore() } + } + } + private var loadMoreTrigger: some View { Group { if vm.isLoadingMore { ProgressView() .padding() - } else { + } else if vm.entries.count > 0 { + // Fallback trigger at the very bottom Color.clear - .frame(height: 1) + .frame(height: 40) .onAppear { Task { await vm.loadMore() } } @@ -242,6 +258,7 @@ struct EntryCardView: View { image .resizable() .aspectRatio(contentMode: .fill) + .frame(maxWidth: .infinity) .frame(height: 180) .clipped() default: