Use sets for selected/unselected labels to eliminate duplicate IDs in selection
This commit is contained in:
@ -255,10 +255,10 @@ public struct ShareExtensionView: View {
|
||||
}
|
||||
|
||||
func onLabelTap(label: LinkedItemLabel, textChip _: TextChip) {
|
||||
if let selectedIndex = labelsViewModel.selectedLabels.firstIndex(of: label) {
|
||||
labelsViewModel.selectedLabels.remove(at: selectedIndex)
|
||||
if labelsViewModel.selectedLabels.contains(label) {
|
||||
labelsViewModel.selectedLabels.remove(label)
|
||||
} else {
|
||||
labelsViewModel.selectedLabels.append(label)
|
||||
labelsViewModel.selectedLabels.insert(label)
|
||||
}
|
||||
|
||||
if let linkedItem = viewModel.linkedItem {
|
||||
@ -435,7 +435,7 @@ public struct ShareExtensionView: View {
|
||||
labelsSection
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
previousLabels = self.labelsViewModel.selectedLabels
|
||||
previousLabels = Array(self.labelsViewModel.selectedLabels)
|
||||
viewState = .editingLabels
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,9 +59,9 @@ struct ApplyLabelsView: View {
|
||||
Button(
|
||||
action: {
|
||||
if isSelected(label) {
|
||||
viewModel.selectedLabels.removeAll(where: { $0.id == label.id })
|
||||
viewModel.selectedLabels.remove(label)
|
||||
} else {
|
||||
viewModel.selectedLabels.append(label)
|
||||
viewModel.selectedLabels.insert(label)
|
||||
}
|
||||
},
|
||||
label: {
|
||||
@ -138,10 +138,11 @@ struct ApplyLabelsView: View {
|
||||
switch mode {
|
||||
case let .item(feedItem):
|
||||
viewModel.saveItemLabelChanges(itemID: feedItem.unwrappedID, dataService: dataService)
|
||||
onSave?(Array(viewModel.selectedLabels))
|
||||
case .highlight:
|
||||
onSave?(viewModel.selectedLabels)
|
||||
onSave?(Array(viewModel.selectedLabels))
|
||||
case .list:
|
||||
onSave?(viewModel.selectedLabels)
|
||||
onSave?(Array(viewModel.selectedLabels))
|
||||
}
|
||||
presentationMode.wrappedValue.dismiss()
|
||||
},
|
||||
|
||||
@ -6,8 +6,8 @@ import Views
|
||||
|
||||
@MainActor final class LabelsViewModel: ObservableObject {
|
||||
@Published var isLoading = false
|
||||
@Published var selectedLabels = [LinkedItemLabel]()
|
||||
@Published var unselectedLabels = [LinkedItemLabel]()
|
||||
@Published var selectedLabels = Set<LinkedItemLabel>()
|
||||
@Published var unselectedLabels = Set<LinkedItemLabel>()
|
||||
@Published var labels = [LinkedItemLabel]()
|
||||
@Published var showCreateLabelModal = false
|
||||
@Published var labelSearchFilter = ""
|
||||
@ -31,9 +31,9 @@ import Views
|
||||
let selLabels = initiallySelectedLabels ?? item?.sortedLabels ?? []
|
||||
for label in labels {
|
||||
if selLabels.contains(label) {
|
||||
selectedLabels.append(label)
|
||||
selectedLabels.insert(label)
|
||||
} else {
|
||||
unselectedLabels.append(label)
|
||||
unselectedLabels.insert(label)
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,9 +46,9 @@ import Views
|
||||
let selLabels = initiallySelectedLabels ?? item?.sortedLabels ?? []
|
||||
for label in self.labels {
|
||||
if selLabels.contains(label) {
|
||||
self.selectedLabels.append(label)
|
||||
self.selectedLabels.insert(label)
|
||||
} else {
|
||||
self.unselectedLabels.append(label)
|
||||
self.unselectedLabels.insert(label)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -71,9 +71,9 @@ import Views
|
||||
let selLabels = highlight.labels ?? []
|
||||
for label in labels {
|
||||
if selLabels.contains(label) {
|
||||
selectedLabels.append(label)
|
||||
selectedLabels.insert(label)
|
||||
} else {
|
||||
unselectedLabels.append(label)
|
||||
unselectedLabels.insert(label)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,7 +89,7 @@ import Views
|
||||
}
|
||||
|
||||
setLabels(fetchedLabels ?? [])
|
||||
unselectedLabels = fetchedLabels ?? []
|
||||
unselectedLabels = Set(fetchedLabels ?? [])
|
||||
}
|
||||
|
||||
func fetchLabelsFromNetwork(dataService: DataService) async {
|
||||
@ -101,7 +101,7 @@ import Views
|
||||
}
|
||||
|
||||
setLabels(fetchedLabels)
|
||||
unselectedLabels = fetchedLabels
|
||||
unselectedLabels = Set(fetchedLabels)
|
||||
}
|
||||
|
||||
func createLabel(dataService: DataService, name: String, color: Color, description: String?) {
|
||||
@ -118,7 +118,7 @@ import Views
|
||||
|
||||
if let label = dataService.viewContext.object(with: labelObjectID) as? LinkedItemLabel {
|
||||
labels.insert(label, at: 0)
|
||||
selectedLabels.insert(label, at: 0)
|
||||
selectedLabels.insert(label)
|
||||
}
|
||||
|
||||
isLoading = false
|
||||
@ -128,8 +128,6 @@ import Views
|
||||
func deleteLabel(dataService: DataService, labelID: String, name: String) {
|
||||
dataService.removeLabel(labelID: labelID, name: name)
|
||||
labels.removeAll { $0.name == name }
|
||||
selectedLabels.removeAll { $0.name == name }
|
||||
unselectedLabels.removeAll { $0.name == name }
|
||||
}
|
||||
|
||||
func saveItemLabelChanges(itemID: String, dataService: DataService) {
|
||||
@ -139,14 +137,4 @@ import Views
|
||||
func saveHighlightLabelChanges(highlightID: String, dataService: DataService) {
|
||||
dataService.setLabelsForHighlight(highlightID: highlightID, labelIDs: selectedLabels.map(\.unwrappedID))
|
||||
}
|
||||
|
||||
func addLabelToItem(_ label: LinkedItemLabel) {
|
||||
selectedLabels.insert(label, at: 0)
|
||||
unselectedLabels.removeAll { $0.name == label.name }
|
||||
}
|
||||
|
||||
func removeLabelFromItem(_ label: LinkedItemLabel) {
|
||||
unselectedLabels.insert(label, at: 0)
|
||||
selectedLabels.removeAll { $0.name == label.name }
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,6 +100,7 @@ struct WebReader: PlatformViewRepresentable {
|
||||
(webView as? OmnivoreWebView)?.updateTextContrast()
|
||||
(webView as? OmnivoreWebView)?.updateMaxWidthPercentage()
|
||||
(webView as? OmnivoreWebView)?.updateLineHeight()
|
||||
(webView as? OmnivoreWebView)?.updateLabels(labelsJSON: item.labelsJSONString)
|
||||
}
|
||||
|
||||
if showNavBarActionID != context.coordinator.previousShowNavBarActionID {
|
||||
|
||||
@ -295,7 +295,11 @@ struct WebReaderContainerView: View {
|
||||
Button(LocalText.cancelGeneric, role: .cancel, action: {})
|
||||
}
|
||||
.sheet(isPresented: $showLabelsModal) {
|
||||
ApplyLabelsView(mode: .item(item), isSearchFocused: false, onSave: { _ in showLabelsModal = false })
|
||||
ApplyLabelsView(mode: .item(item), isSearchFocused: false, onSave: { labels in
|
||||
showLabelsModal = false
|
||||
item.labels = NSSet(array: labels)
|
||||
readerSettingsChangedTransactionID = UUID()
|
||||
})
|
||||
}
|
||||
.sheet(isPresented: $showTitleEdit) {
|
||||
LinkedItemMetadataEditView(item: item)
|
||||
|
||||
@ -54,6 +54,7 @@ extension DataService {
|
||||
send(mutation, to: path, headers: headers) { result in
|
||||
let data = try? result.get()
|
||||
let syncStatus: ServerSyncStatus = data == nil ? .needsUpdate : .isNSync
|
||||
print("DATA: ", data)
|
||||
|
||||
context.perform {
|
||||
guard let linkedItem = LinkedItem.lookup(byID: itemID, inContext: context) else { return }
|
||||
|
||||
@ -105,6 +105,14 @@ public final class OmnivoreWebView: WKWebView {
|
||||
}
|
||||
}
|
||||
|
||||
public func updateLabels(labelsJSON: String) {
|
||||
do {
|
||||
try dispatchEvent(.updateLabels(labels: labelsJSON))
|
||||
} catch {
|
||||
showErrorInSnackbar("Error updating labels")
|
||||
}
|
||||
}
|
||||
|
||||
public func shareOriginalItem() {
|
||||
do {
|
||||
try dispatchEvent(.share)
|
||||
@ -379,6 +387,7 @@ public enum WebViewDispatchEvent {
|
||||
case copyHighlight
|
||||
case dismissHighlight
|
||||
case speakingSection(anchorIdx: String)
|
||||
case updateLabels(labels: String)
|
||||
|
||||
var script: String {
|
||||
get throws {
|
||||
@ -421,6 +430,8 @@ public enum WebViewDispatchEvent {
|
||||
return "dismissHighlight"
|
||||
case .speakingSection:
|
||||
return "speakingSection"
|
||||
case .updateLabels:
|
||||
return "updateLabels"
|
||||
}
|
||||
}
|
||||
|
||||
@ -441,6 +452,8 @@ public enum WebViewDispatchEvent {
|
||||
return "event.isDark = '\(isDark)';"
|
||||
case let .updateFontFamily(family: family):
|
||||
return "event.fontFamily = '\(family)';"
|
||||
case let .updateLabels(labels):
|
||||
return "event.labels = \(labels);"
|
||||
case let .saveAnnotation(annotation: annotation):
|
||||
let encoder = JSONEncoder()
|
||||
if let encoded = try? encoder.encode(annotation) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -50,8 +50,14 @@ const mutation = async (name, input) => {
|
||||
}
|
||||
|
||||
const App = () => {
|
||||
const [labels, setLabels] = React.useState(window.omnivoreArticle.labels)
|
||||
applyStoredTheme(false)
|
||||
|
||||
document.addEventListener('updateLabels', (event) => {
|
||||
console.log("updating labels: ", event.labels)
|
||||
setLabels(event.labels)
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
@ -68,7 +74,7 @@ const App = () => {
|
||||
>
|
||||
<ArticleContainer
|
||||
article={window.omnivoreArticle}
|
||||
labels={window.omnivoreArticle.labels}
|
||||
labels={labels}
|
||||
isAppleAppEmbed={true}
|
||||
highlightBarDisabled={!window.enableHighlightBar}
|
||||
highlightsBaseURL="https://example.com"
|
||||
|
||||
Reference in New Issue
Block a user