From 9fe6c4b9263528fc3c9b5852cbcdd1c61b42a237 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 21 Nov 2023 09:10:48 +0800 Subject: [PATCH 1/3] Update extension labels quick picker --- .../Share/Views/ShareExtensionView.swift | 99 ++++++++++++------- .../App/Views/Home/HomeFeedViewIOS.swift | 50 +++++++++- .../Sources/Utils/UserDefaultKeys.swift | 1 + 3 files changed, 115 insertions(+), 35 deletions(-) diff --git a/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift b/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift index 84232e33d..055263fe0 100644 --- a/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift +++ b/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift @@ -82,9 +82,9 @@ public struct ShareExtensionView: View { } } .frame(width: 56, height: 56).overlay( - RoundedRectangle(cornerRadius: 14) + RoundedRectangle(cornerRadius: 5) .stroke(.white, lineWidth: 1) - ).cornerRadius(14) + ).cornerRadius(5) VStack(alignment: .leading) { Text(self.viewModel.url ?? "") .font(Font.system(size: 12)) @@ -117,21 +117,22 @@ public struct ShareExtensionView: View { Button(action: { NotificationCenter.default.post(name: Notification.Name("ShowAddNoteSheet"), object: nil) }, label: { - Text(hasNoteText ? viewModel.noteText : "Add note...") - .frame(minHeight: 50, alignment: .top) - .frame(maxWidth: .infinity, alignment: .leading) - .multilineTextAlignment(.leading) + VStack { + Text(hasNoteText ? viewModel.noteText : "Add note...") + .frame(maxWidth: .infinity, alignment: .topLeading) + .multilineTextAlignment(.leading) + Spacer() + } }) .foregroundColor(hasNoteText ? Color.appGrayTextContrast : Color.extensionTextSubtle ) .font(Font.system(size: 13, weight: .semibold)) - .frame(height: 50, alignment: .top) - .frame(maxWidth: .infinity, alignment: .leading) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading) .contentShape(Rectangle()) } - var labelsBox: some View { + var labelsButton: some View { Button(action: { NotificationCenter.default.post(name: Notification.Name("ShowEditLabelsSheet"), object: nil) }, label: { @@ -157,12 +158,37 @@ public struct ShareExtensionView: View { noteBox - labelsBox + labelsButton }.padding(15) + .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.extensionPanelBackground) .cornerRadius(14) } + var labelsBox: some View { + ScrollView(.vertical) { + LabelsMasonaryView(labels: labelsViewModel.labels, + selectedLabels: labelsViewModel.selectedLabels, + onLabelTap: { label, _ in + if labelsViewModel.selectedLabels.contains(label) { + labelsViewModel.selectedLabels += [label] + } else { + labelsViewModel.selectedLabels.removeAll { $0.unwrappedID == label.unwrappedID } + } + if let itemID = viewModel.linkedItem?.id { + labelsViewModel.saveItemLabelChanges( + itemID: itemID, + dataService: viewModel.services.dataService + ) + } + }) + } + .padding(.bottom, 15) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(Color.extensionPanelBackground) + .cornerRadius(14) + } + var moreMenuButton: some View { Menu { #if os(iOS) @@ -253,12 +279,7 @@ public struct ShareExtensionView: View { } var displayDismiss: Bool { - #if os(iOS) - if UIDevice.isIPhone { - return false - } - #endif - return true + true } public var body: some View { @@ -271,14 +292,25 @@ public struct ShareExtensionView: View { #endif } + @AppStorage(UserDefaultKey.visibleShareExtensionTab.rawValue) var visibleTab = "info" + var iOSBody: some View { VStack(alignment: .leading, spacing: 15) { titleBar .padding(.top, 15) - infoBox + TabView(selection: $visibleTab) { + infoBox + .tag("info") + .padding(.horizontal, 15) + labelsBox + .tag("labels") + .padding(.horizontal, 15) + } + .tabViewStyle(.page(indexDisplayMode: .never)) + .padding(.horizontal, -15) - Spacer(minLength: 1) + Spacer() HStack { #if os(macOS) @@ -286,23 +318,21 @@ public struct ShareExtensionView: View { .padding(.bottom, 15) #endif Spacer() - if displayDismiss { - Button(action: { - extensionContext?.completeRequest(returningItems: [], completionHandler: nil) - }, label: { - Text("Dismiss") - #if os(iOS) - .font(Font.system(size: 17, weight: .semibold)) - .tint(Color.appGrayText) - .padding(20) - #endif - }) + Button(action: { + extensionContext?.completeRequest(returningItems: [], completionHandler: nil) + }, label: { + Text("Dismiss") #if os(iOS) - .frame(height: 50) - .cornerRadius(24) + .font(Font.system(size: 17, weight: .semibold)) + .tint(Color.appGrayText) + .padding(20) #endif - .padding(.bottom, 15) - } + }) + #if os(iOS) + .frame(height: 50) + .cornerRadius(24) + #endif + .padding(.bottom, 15) Button(action: { viewModel.handleReadNowAction(extensionContext: extensionContext) }, label: { @@ -324,6 +354,9 @@ public struct ShareExtensionView: View { .background(Color.extensionBackground) .onAppear { viewModel.savePage(extensionContext: extensionContext) + Task { + await labelsViewModel.loadLabels(dataService: viewModel.services.dataService, initiallySelectedLabels: []) + } } } diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift index 3ecabf3b9..960adee61 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift @@ -63,6 +63,7 @@ struct AnimatingCellHeight: AnimatableModifier { listTitle: $listTitle, isListScrolled: $isListScrolled, prefersListLayout: $prefersListLayout, + isEditMode: $isEditMode, selection: $selection, viewModel: viewModel, showFeatureCards: showFeatureCards @@ -263,6 +264,7 @@ struct AnimatingCellHeight: AnimatableModifier { @Binding var listTitle: String @Binding var isListScrolled: Bool @Binding var prefersListLayout: Bool + @Binding var isEditMode: EditMode @Binding var selection: Set @ObservedObject var viewModel: HomeFeedViewModel @@ -291,6 +293,7 @@ struct AnimatingCellHeight: AnimatableModifier { listTitle: $listTitle, isListScrolled: $isListScrolled, prefersListLayout: $prefersListLayout, + isEditMode: $isEditMode, selection: $selection, viewModel: viewModel, showFeatureCards: showFeatureCards @@ -340,6 +343,7 @@ struct AnimatingCellHeight: AnimatableModifier { @Binding var listTitle: String @Binding var isListScrolled: Bool @Binding var prefersListLayout: Bool + @Binding var isEditMode: EditMode @State private var showHideFeatureAlert = false @Binding var selection: Set @@ -576,7 +580,7 @@ struct AnimatingCellHeight: AnimatableModifier { } } - ForEach(viewModel.items, id: \.self.unwrappedID) { item in + ForEach(Array(viewModel.items.enumerated()), id: \.1.unwrappedID) { idx, item in FeedCardNavigationLink( item: item, isInMultiSelectMode: viewModel.isInMultiSelectMode, @@ -608,6 +612,15 @@ struct AnimatingCellHeight: AnimatableModifier { swipeActionButton(action: action, item: item) } } + if idx > 0, + isEditMode != .active, + let savedAt = item.savedAt, + Calendar.current.isDateInToday(savedAt) || Calendar.current.isDateInYesterday(savedAt), + let previousSavedAt = viewModel.items[idx - 1].savedAt, + Calendar.current.isDate(previousSavedAt, equalTo: savedAt, toGranularity: .day) + { + dateSummaryCard(previousSavedAt) + } } } .padding(0) @@ -624,6 +637,40 @@ struct AnimatingCellHeight: AnimatableModifier { } } + func dateSummaryCard(_: Date) -> some View { + VStack(alignment: .center, spacing: 15) { + Text("3 articles saved today") + .frame(maxWidth: .infinity, alignment: .center) + .font(.body) + HStack { + Spacer() + HStack(spacing: 0) { + Button(action: {}, label: { + Text("Archive all") + .font(Font.system(size: 14)) + .padding(.horizontal, 10) + }) + .frame(height: 30) + .background(Color.blue) + Button(action: {}, label: { + Image(systemName: "chevron.down") + .resizable() + .scaledToFit() + .frame(width: 10, height: 10) + .padding(.leading, 7.5) + .padding(.trailing, 7.5) + .foregroundColor(Color.white) + }) + .frame(height: 30) + .background(Color(hex: "345BB8")) + } + .cornerRadius(2.5) + Spacer() + } + } + .padding(15) + } + func swipeActionButton(action: SwipeAction, item: LinkedItem) -> AnyView { switch action { case .pin: @@ -663,7 +710,6 @@ struct AnimatingCellHeight: AnimatableModifier { return AnyView(Button( action: { // viewModel.addLabel(dataService: dataService, item: item, label: "Inbox", color) - }, label: { Label("Move to Inbox", systemImage: "tray.fill") diff --git a/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift b/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift index 8d6ee7c77..cc5734cc6 100644 --- a/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift +++ b/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift @@ -33,4 +33,5 @@ public enum UserDefaultKey: String { case hideFeatureSection case justifyText case prefersHideStatusBarInReader + case visibleShareExtensionTab } From 03edf82dab57af28d906ef5c62324e74315c63fa Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 21 Nov 2023 09:37:45 +0800 Subject: [PATCH 2/3] Fix label picker selection --- .../App/AppExtensions/Share/Views/ShareExtensionView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift b/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift index 055263fe0..557124c08 100644 --- a/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift +++ b/apple/OmnivoreKit/Sources/App/AppExtensions/Share/Views/ShareExtensionView.swift @@ -170,7 +170,7 @@ public struct ShareExtensionView: View { LabelsMasonaryView(labels: labelsViewModel.labels, selectedLabels: labelsViewModel.selectedLabels, onLabelTap: { label, _ in - if labelsViewModel.selectedLabels.contains(label) { + if !labelsViewModel.selectedLabels.contains(label) { labelsViewModel.selectedLabels += [label] } else { labelsViewModel.selectedLabels.removeAll { $0.unwrappedID == label.unwrappedID } From 69709dd37af0bffee2b356f3aff841caadd46ae5 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 21 Nov 2023 10:38:52 +0800 Subject: [PATCH 3/3] Add Yunxi voice, comment out today buttons for now --- .../App/Views/Home/HomeFeedViewIOS.swift | 20 +++++++++---------- .../Services/AudioSession/Voices.swift | 1 + 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift index 960adee61..425d64458 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift @@ -580,7 +580,7 @@ struct AnimatingCellHeight: AnimatableModifier { } } - ForEach(Array(viewModel.items.enumerated()), id: \.1.unwrappedID) { idx, item in + ForEach(Array(viewModel.items.enumerated()), id: \.1.unwrappedID) { _, item in FeedCardNavigationLink( item: item, isInMultiSelectMode: viewModel.isInMultiSelectMode, @@ -612,15 +612,15 @@ struct AnimatingCellHeight: AnimatableModifier { swipeActionButton(action: action, item: item) } } - if idx > 0, - isEditMode != .active, - let savedAt = item.savedAt, - Calendar.current.isDateInToday(savedAt) || Calendar.current.isDateInYesterday(savedAt), - let previousSavedAt = viewModel.items[idx - 1].savedAt, - Calendar.current.isDate(previousSavedAt, equalTo: savedAt, toGranularity: .day) - { - dateSummaryCard(previousSavedAt) - } +// if idx > 0, +// isEditMode != .active, +// let savedAt = item.savedAt, +// Calendar.current.isDateInToday(savedAt) || Calendar.current.isDateInYesterday(savedAt), +// let previousSavedAt = viewModel.items[idx - 1].savedAt, +// Calendar.current.isDate(previousSavedAt, equalTo: savedAt, toGranularity: .day) +// { +// dateSummaryCard(previousSavedAt) +// } } } .padding(0) diff --git a/apple/OmnivoreKit/Sources/Services/AudioSession/Voices.swift b/apple/OmnivoreKit/Sources/Services/AudioSession/Voices.swift index e524cb08e..56750302f 100644 --- a/apple/OmnivoreKit/Sources/Services/AudioSession/Voices.swift +++ b/apple/OmnivoreKit/Sources/Services/AudioSession/Voices.swift @@ -101,6 +101,7 @@ public enum Voices { VoicePair(firstKey: "fr-FR-HenriNeural", secondKey: "fr-FR-DeniseNeural", firstName: "Henri", secondName: "Denise", language: "en-FR", category: .frFR), VoicePair(firstKey: "zh-CN-XiaochenNeural", secondKey: "zh-CN-XiaohanNeural", firstName: "Xiaochen", secondName: "Xiaohan", language: "zh-CN", category: .zhCN), VoicePair(firstKey: "zh-CN-XiaoxiaoNeural", secondKey: "zh-CN-YunyangNeural", firstName: "Xiaoxiao", secondName: "Yunyang", language: "zh-CN", category: .zhCN), + VoicePair(firstKey: "zh-CN-YunxiNeural", secondKey: "zh-CN-XiaoyiNeural", firstName: "Yunxi", secondName: "Xiaoyi", language: "zh-CN", category: .zhCN), VoicePair(firstKey: "es-ES-AlvaroNeural", secondKey: "es-ES-ElviraNeural", firstName: "Alvaro", secondName: "Elvira", language: "es-ES", category: .esES), VoicePair(firstKey: "de-CH-LeniNeural", secondKey: "de-DE-KatjaNeural", firstName: "Leni", secondName: "Katja", language: "de-DE", category: .deDE), VoicePair(firstKey: "de-DE-AmalaNeural", secondKey: "de-DE-BerndNeural", firstName: "Amala", secondName: "Bernd", language: "de-DE", category: .deDE),