From 80c1d660cde17174086c52a35db6b8fbcae65e4c Mon Sep 17 00:00:00 2001 From: wangdl Date: Tue, 9 Jun 2026 20:49:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20#80=20=E6=A0=87=E8=AE=B0=E5=B7=B2?= =?UTF-8?q?=E8=AF=BB=20UI=20+=20=E4=B9=90=E8=A7=82=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- .../UserInterfaceState.xcuserstate | Bin 104569 -> 104569 bytes .../MaterialReader/MaterialReaderView.swift | 40 +++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/AIStudyApp/AIStudyApp.xcodeproj/project.xcworkspace/xcuserdata/Admin1.xcuserdatad/UserInterfaceState.xcuserstate b/AIStudyApp/AIStudyApp.xcodeproj/project.xcworkspace/xcuserdata/Admin1.xcuserdatad/UserInterfaceState.xcuserstate index dbf0672ba490ceb7bdef019af87a273179e9fd9e..d9f3afe1616d18985b03385a1e709d64a344e77f 100644 GIT binary patch delta 173 zcmV;e08;~2lVCsx zvmL=~Di-&YMZ)em04xA49?JkVfdMyx2M2)xHkVHo0X>teS{;*Zj31M*jP94V76GjW+JH-e1mu%Z bY8bbH7XcUn0ou2k7y*`j0jIYymH|itk~}{^ delta 167 zcmV;Y09gO|um<_C2Cy=~4+Mr4*nt5=fdu2C4o?-^lmEaMlUTr}0o$|xz=|psQZ=e^ zfd$ZBRBvQqc_3kQATlsIGdHuJ>)jazAXBIf0=Iz$0kaPq05u-P04*NJ21EcX04*NN z05yRDH-P~*fd>bdPZa?@lk+?ulTeHulgL^|lg~=1m$nuGtp?kGOMwLBlTm6Iw}BS{ V7y$v>x0)CMmVE)Kw=tFhNCJSpJ_Y~) diff --git a/AIStudyApp/AIStudyApp/Features/MaterialReader/MaterialReaderView.swift b/AIStudyApp/AIStudyApp/Features/MaterialReader/MaterialReaderView.swift index 8dfe539..58f0910 100644 --- a/AIStudyApp/AIStudyApp/Features/MaterialReader/MaterialReaderView.swift +++ b/AIStudyApp/AIStudyApp/Features/MaterialReader/MaterialReaderView.swift @@ -101,6 +101,7 @@ struct MaterialReaderView: View { @State private var hasRestoredPosition = false @State private var restoreBlockId: String? @State private var actualContentHeight: CGFloat = 1 + @State private var isMarkedRead = false private let title: String private let knowledgeBaseId: String? @@ -157,16 +158,26 @@ struct MaterialReaderView: View { .toolbarBackground(.hidden, for: .navigationBar) .toolbar { ToolbarItem(placement: .topBarTrailing) { - NavigationLink(value: Route.aiChat(context: ChatEntryContext( - scopeType: .material, - scopeId: vm.materialId, - scopeName: title, - parentKnowledgeBaseId: knowledgeBaseId, - createdFrom: "material_reader" - ))) { - Image(systemName: "bubble.left.and.bubble.right") - .font(.system(size: 16)) - .foregroundColor(Color.zxF05) + HStack(spacing: 16) { + Button { + markAsRead() + } label: { + Image(systemName: isMarkedRead ? "checkmark.circle.fill" : "checkmark.circle") + .font(.system(size: 16)) + .foregroundColor(isMarkedRead ? Color.green : Color.zxF05) + } + + NavigationLink(value: Route.aiChat(context: ChatEntryContext( + scopeType: .material, + scopeId: vm.materialId, + scopeName: title, + parentKnowledgeBaseId: knowledgeBaseId, + createdFrom: "material_reader" + ))) { + Image(systemName: "bubble.left.and.bubble.right") + .font(.system(size: 16)) + .foregroundColor(Color.zxF05) + } } } } @@ -293,6 +304,15 @@ struct MaterialReaderView: View { print("[READER] V1 session closed") } + /// Mark the current material as read — optimistic update + event push. + private func markAsRead() { + guard !isMarkedRead else { return } + isMarkedRead = true + sessionManager.markAsRead() + // V1 fallback + collector.markAsRead(materialId: vm.materialId) + } + /// Build a NoteAnchor from the current scroll position (for quick note). private func buildAnchor() -> NoteAnchor? { let pos = sessionManager.lastPosition ?? collector.lastPosition