diff --git a/apple/OmnivoreKit/Sources/App/Views/LinkedItemMetadataEditView.swift b/apple/OmnivoreKit/Sources/App/Views/LinkedItemMetadataEditView.swift index 11cbb47d4..55291ce5f 100644 --- a/apple/OmnivoreKit/Sources/App/Views/LinkedItemMetadataEditView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/LinkedItemMetadataEditView.swift @@ -3,7 +3,7 @@ import Services import SwiftUI import Views -@MainActor final class LinkedItemTitleEditViewModel: ObservableObject { +@MainActor final class LinkedItemMetadataEditViewModel: ObservableObject { @Published var title = "" @Published var description = "" @Published var author = "" @@ -28,9 +28,15 @@ import Views struct LinkedItemMetadataEditView: View { @EnvironmentObject var dataService: DataService @Environment(\.presentationMode) private var presentationMode - @StateObject var viewModel = LinkedItemTitleEditViewModel() + @StateObject var viewModel = LinkedItemMetadataEditViewModel() let item: LinkedItem + let onSave: ((String, String) -> Void)? + + init(item: LinkedItem, onSave: ((String, String) -> Void)? = nil) { + self.item = item + self.onSave = onSave + } var editForm: some View { ScrollView(showsIndicators: false) { @@ -96,6 +102,9 @@ struct LinkedItemMetadataEditView: View { Button( action: { viewModel.submit(dataService: dataService, item: item) + if let onSave = self.onSave { + onSave(viewModel.title, viewModel.description) + } presentationMode.wrappedValue.dismiss() }, label: { Text(LocalText.genericSave).foregroundColor(.appGrayTextContrast) } diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift index 848fb6233..d0de7d863 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift @@ -101,6 +101,7 @@ struct WebReader: PlatformViewRepresentable { (webView as? OmnivoreWebView)?.updateMaxWidthPercentage() (webView as? OmnivoreWebView)?.updateLineHeight() (webView as? OmnivoreWebView)?.updateLabels(labelsJSON: item.labelsJSONString) + (webView as? OmnivoreWebView)?.updateTitle(title: item.title ?? "") } if showNavBarActionID != context.coordinator.previousShowNavBarActionID { diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift index 584f1c284..94ec9d6cc 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift @@ -309,7 +309,11 @@ struct WebReaderContainerView: View { }) } .sheet(isPresented: $showTitleEdit) { - LinkedItemMetadataEditView(item: item) + LinkedItemMetadataEditView(item: item, onSave: { title, _ in + item.title = title + // We dont need to update description because its never rendered in this view + readerSettingsChangedTransactionID = UUID() + }) } .sheet(isPresented: $showHighlightsView, onDismiss: onHighlightListViewDismissal) { HighlightsListView( diff --git a/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift b/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift index 7405e4777..6b603f9e4 100644 --- a/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift +++ b/apple/OmnivoreKit/Sources/Views/Article/OmnivoreWebView.swift @@ -105,6 +105,14 @@ public final class OmnivoreWebView: WKWebView { } } + public func updateTitle(title: String) { + do { + try dispatchEvent(.updateTitle(title: title)) + } catch { + showErrorInSnackbar("Error updating title") + } + } + public func updateLabels(labelsJSON: String) { do { try dispatchEvent(.updateLabels(labels: labelsJSON)) @@ -388,6 +396,7 @@ public enum WebViewDispatchEvent { case dismissHighlight case speakingSection(anchorIdx: String) case updateLabels(labels: String) + case updateTitle(title: String) var script: String { get throws { @@ -432,6 +441,8 @@ public enum WebViewDispatchEvent { return "speakingSection" case .updateLabels: return "updateLabels" + case .updateTitle: + return "updateTitle" } } @@ -454,6 +465,14 @@ public enum WebViewDispatchEvent { return "event.fontFamily = '\(family)';" case let .updateLabels(labels): return "event.labels = \(labels);" + case let .updateTitle(title): + let encoder = JSONEncoder() + if let encoded = try? encoder.encode(title) { + let str = String(decoding: encoded, as: UTF8.self) + return "event.title = \(str);" + } else { + throw BasicError.message(messageText: "Unable to serialize title.") + } case let .saveAnnotation(annotation: annotation): let encoder = JSONEncoder() if let encoded = try? encoder.encode(annotation) { diff --git a/packages/appreader/src/index.jsx b/packages/appreader/src/index.jsx index edbbdd32b..cd95c928e 100644 --- a/packages/appreader/src/index.jsx +++ b/packages/appreader/src/index.jsx @@ -50,12 +50,29 @@ const mutation = async (name, input) => { } const App = () => { - const [labels, setLabels] = React.useState(window.omnivoreArticle.labels) applyStoredTheme(false) + const useForceUpdate = () => { + const [, setState] = React.useState(); + return () => setState({}); + } + + const forceUpdate = useForceUpdate(); + document.addEventListener('updateLabels', (event) => { console.log("updating labels: ", event.labels) - setLabels(event.labels) + const updated = window.omnivoreArticle + updated.labels = event.labels + window.omnivoreArticle = updated + forceUpdate(); + }) + + document.addEventListener('updateTitle', (event) => { + console.log("updating title: ", event.title) + const updated = window.omnivoreArticle + updated.title = event.title + window.omnivoreArticle = updated + forceUpdate(); }) return ( @@ -74,7 +91,7 @@ const App = () => { >