UI for displaying article note modals

This commit is contained in:
Jackson Harper
2023-04-07 16:39:48 +08:00
parent be4fea153a
commit 1ef73388aa
11 changed files with 189 additions and 37 deletions

View File

@ -1,5 +1,6 @@
#if os(iOS)
import CoreData
import MarkdownUI
import Models
import Services
import SwiftUI
@ -10,6 +11,11 @@
@Environment(\.presentationMode) private var presentationMode
@StateObject var viewModel = NotebookViewModel()
@State var showAnnotationModal = false
@State var errorAlertMessage: String?
@State var showErrorAlertMessage = false
@State var noteAnnotation = ""
let itemObjectID: NSManagedObjectID
@Binding var hasHighlightMutations: Bool
@State var setLabelsHighlight: Highlight?
@ -17,12 +23,12 @@
var emptyView: some View {
Text(LocalText.highlightCardNoHighlightsOnPage)
.multilineTextAlignment(.center)
.multilineTextAlignment(.leading)
.padding(16)
}
var innerBody: some View {
(viewModel.highlightItems.count > 0 ? AnyView(listView) : AnyView(emptyView))
listView
.navigationTitle("Notebook")
.listStyle(PlainListStyle())
#if os(iOS)
@ -46,35 +52,80 @@
#endif
}
var noteSection: some View {
HStack {
// let isEmpty = viewModel.noteItem.annotation.isEmpty
Spacer(minLength: 6)
if let note = viewModel.noteItem, let annotation = note.annotation, !annotation.isEmpty {
Markdown(annotation)
.lineSpacing(6)
.accentColor(.appGraySolid)
.foregroundColor(.appGrayTextContrast)
.font(.appSubheadline)
.padding(12)
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color.appButtonBackground)
.cornerRadius(8)
} else {
Text("Add Notes...")
.lineSpacing(6)
.accentColor(.appGraySolid)
.foregroundColor(.appGrayText)
.font(.appSubheadline)
.padding(12)
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color.appButtonBackground)
.cornerRadius(8)
}
}
.onTapGesture {
// annotation = highlightParams.annotation
showAnnotationModal = true
}
}
var listView: some View {
List {
Section {
ForEach(viewModel.highlightItems) { highlightParams in
HighlightsListCard(
viewModel: self.viewModel,
highlightParams: highlightParams,
hasHighlightMutations: $hasHighlightMutations,
onSaveAnnotation: {
viewModel.updateAnnotation(
highlightID: highlightParams.highlightID,
annotation: $0,
dataService: dataService
)
},
onDeleteHighlight: {
hasHighlightMutations = true
viewModel.deleteHighlight(
highlightID: highlightParams.highlightID,
dataService: dataService
)
},
onSetLabels: { highlightID in
setLabelsHighlight = Highlight.lookup(byID: highlightID, inContext: dataService.viewContext)
}
)
.listRowSeparator(.hidden)
Section("Article Notes") {
noteSection
.listRowSeparator(.hidden, edges: .bottom)
}
Section("Highlights") {
if viewModel.highlightItems.count > 0 {
ForEach(Array(viewModel.highlightItems.enumerated()), id: \.offset) { idx, highlightParams in
HighlightsListCard(
viewModel: self.viewModel,
highlightParams: highlightParams,
hasHighlightMutations: $hasHighlightMutations,
onSaveAnnotation: {
viewModel.updateAnnotation(
highlightID: highlightParams.highlightID,
annotation: $0,
dataService: dataService
)
},
onDeleteHighlight: {
hasHighlightMutations = true
viewModel.deleteHighlight(
highlightID: highlightParams.highlightID,
dataService: dataService
)
},
onSetLabels: { highlightID in
setLabelsHighlight = Highlight.lookup(byID: highlightID, inContext: dataService.viewContext)
}
)
.listRowSeparator(.hidden, edges: idx == 0 ? .bottom : .all)
}
} else {
emptyView
.listRowSeparator(.hidden, edges: .bottom)
}
}
Spacer(minLength: 120)
.listRowSeparator(.hidden, edges: .all)
}.sheet(item: $setLabelsHighlight) { highlight in
ApplyLabelsView(mode: .highlight(highlight), isSearchFocused: false, onSave: { selectedLabels in
hasHighlightMutations = true
@ -83,6 +134,20 @@
labels: selectedLabels,
dataService: dataService)
})
}.sheet(isPresented: $showAnnotationModal) {
HighlightAnnotationSheet(
annotation: $noteAnnotation,
onSave: {
// onSaveAnnotation(annotation)
showAnnotationModal = false
hasHighlightMutations = true
},
onCancel: {
showAnnotationModal = false
},
errorAlertMessage: $errorAlertMessage,
showErrorAlertMessage: $showErrorAlertMessage
)
}
}

View File

@ -17,7 +17,7 @@ struct HighlightListItemParams: Identifiable {
struct NoteItemParams: Identifiable {
let id = UUID()
let highlightID: String
let annotation: String
let annotation: String?
}
@MainActor final class NotebookViewModel: ObservableObject {
@ -79,7 +79,6 @@ struct NoteItemParams: Identifiable {
}
private func loadHighlights(item: LinkedItem) {
let notes = item.highlights.asArray(of: Highlight.self).filter { $0.type == "NOTE" }
let unsortedHighlights = item.highlights.asArray(of: Highlight.self)
.filter { $0.type == "HIGHLIGHT" && $0.serverSyncStatus != ServerSyncStatus.needsDeletion.rawValue }
@ -100,5 +99,10 @@ struct NoteItemParams: Identifiable {
createdBy: $0.createdByMe ? nil : InternalUserProfile.makeSingle($0.createdBy)
)
}
noteItem = item.highlights.asArray(of: Highlight.self)
.filter { $0.type == "NOTE" && $0.serverSyncStatus != ServerSyncStatus.needsDeletion.rawValue }
.first
.map { NoteItemParams(highlightID: $0.unwrappedID, annotation: $0.annotation) }
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "Hotpot.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View File

@ -0,0 +1,24 @@
{
"images" : [
{
"filename" : "notebook.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#000000" viewBox="0 0 256 256"><path d="M184,112a8,8,0,0,1-8,8H112a8,8,0,0,1,0-16h64A8,8,0,0,1,184,112Zm-8,24H112a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Zm48-88V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48ZM48,208H72V48H48Zm160,0V48H88V208H208Z"></path></svg>

After

Width:  |  Height:  |  Size: 363 B

View File

@ -14,7 +14,7 @@ struct WebReaderContainerView: View {
@State private var showLabelsModal = false
@State private var showHighlightLabelsModal = false
@State private var showTitleEdit = false
@State private var showHighlightsView = false
@State private var showNotebookView = false
@State private var hasPerformedHighlightMutations = false
@State var showHighlightAnnotationModal = false
@State private var navBarVisibilityRatio = 1.0
@ -61,7 +61,7 @@ struct WebReaderContainerView: View {
lastScrollPercentage = percent
}
func onHighlightListViewDismissal() {
func onNotebookViewDismissal() {
// Reload the web view if mutation happened in highlights list modal
guard hasPerformedHighlightMutations else { return }
@ -205,7 +205,7 @@ struct WebReaderContainerView: View {
let hasLabels = item.labels?.count != 0
return Group {
Button(
action: { showHighlightsView = true },
action: { showNotebookView = true },
label: { Label("Notebook", systemImage: "highlighter") }
)
Button(
@ -261,14 +261,13 @@ struct WebReaderContainerView: View {
}
var navBar: some View {
HStack(alignment: .center) {
HStack(alignment: .center, spacing: 15) {
#if os(iOS)
Button(
action: { self.presentationMode.wrappedValue.dismiss() },
label: {
Image(systemName: "chevron.backward")
.font(.appNavbarIcon)
// .foregroundColor(.appGrayTextContrast)
.padding()
}
)
@ -285,6 +284,14 @@ struct WebReaderContainerView: View {
)
.padding(.horizontal)
.scaleEffect(navBarVisibilityRatio)
Button(
action: { showNotebookView.toggle() },
label: {
Image("notebook", bundle: Bundle.module)
}
)
.padding(.horizontal)
.scaleEffect(navBarVisibilityRatio)
#if os(macOS)
Spacer()
#endif
@ -297,7 +304,6 @@ struct WebReaderContainerView: View {
Image(systemName: "ellipsis")
.resizable(resizingMode: Image.ResizingMode.stretch)
.aspectRatio(contentMode: .fit)
// .foregroundColor(.appGrayTextContrast)
.frame(width: 20, height: 20)
.scaleEffect(navBarVisibilityRatio)
.padding()
@ -344,7 +350,7 @@ struct WebReaderContainerView: View {
})
}
#if os(iOS)
.sheet(isPresented: $showHighlightsView, onDismiss: onHighlightListViewDismissal) {
.sheet(isPresented: $showNotebookView, onDismiss: onNotebookViewDismissal) {
NotebookView(
itemObjectID: item.objectID,
hasHighlightMutations: $hasPerformedHighlightMutations

View File

@ -0,0 +1,24 @@
{
"images" : [
{
"filename" : "notebook.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#000000" viewBox="0 0 256 256"><path d="M184,112a8,8,0,0,1-8,8H112a8,8,0,0,1,0-16h64A8,8,0,0,1,184,112Zm-8,24H112a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Zm48-88V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48ZM48,208H72V48H48Zm160,0V48H88V208H208Z"></path></svg>

After

Width:  |  Height:  |  Size: 363 B

View File

@ -13,7 +13,7 @@
// Highlights List Card
"highlightCardHighlightByOther" = "Highlight by ";
"highlightCardNoHighlightsOnPage" = "You have not added any highlights or notes to this page.";
"highlightCardNoHighlightsOnPage" = "You have not added any highlights to this page.";
// Labels View
"labelsViewAssignNameColor" = "Assign a name and color.";