Merge pull request #3104 from omnivore-app/fix/macos-update-extension

Fix build on MacOS
This commit is contained in:
Jackson Harper
2023-11-16 16:06:08 +08:00
committed by GitHub
101 changed files with 536 additions and 524 deletions

View File

@ -7,4 +7,5 @@ graphql_gen:
extension_gen:
pushd ../pkg/extension/ && yarn build-prod && popd
cp -r ../pkg/extension/dist/* Sources/SafariExtension/Resources/.
mv Sources/SafariExtension/Resources/images/extension-transparent/* Sources/SafariExtension/Resources/images/extension/.
cat ../pkg/extension/dist/manifest.json | jq '.background.persistent = false' | jq '.permissions = ["activeTab", "storage", "nativeMessaging", "https://*/**", "http://*/**"]' > Sources/SafariExtension/Resources/manifest.json

View File

@ -14,7 +14,6 @@
042F48DC26DFD10E00BF98FC /* iOSLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 042F48DB26DFD10E00BF98FC /* iOSLaunchTests.swift */; };
045B1681279147E7005047F7 /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 045B1680279147E7005047F7 /* FirebaseMessaging */; };
0465B9BE26CDD35F005558CD /* MainApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D81BE98F0CB588F5FC577A13 /* MainApp.swift */; };
046C5CD526A3F89A00AC5349 /* icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 046C5CD426A3F89A00AC5349 /* icon.icns */; };
046C5CDF26A3F89A00AC5349 /* ShareExtension-Mac.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 046C5CD226A3F89A00AC5349 /* ShareExtension-Mac.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
046C5CE626A3FE8C00AC5349 /* App in Frameworks */ = {isa = PBXBuildFile; productRef = 046C5CE526A3FE8C00AC5349 /* App */; };
047AD6F22724C934004FD5CF /* App in Frameworks */ = {isa = PBXBuildFile; productRef = 047AD6F12724C934004FD5CF /* App */; };
@ -34,12 +33,8 @@
260BBE4168E3C57D6D2E225D /* App in Frameworks */ = {isa = PBXBuildFile; productRef = 7DD0EF4D497D71D248C7B0DF /* App */; };
4214F6EF2714D2260096B644 /* SafariExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 42FF1B16271154A700B38C38 /* SafariExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4214F6F22714D28E0096B644 /* SafariExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 42FF1B20271154A700B38C38 /* SafariExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4225D59227164F82002A680F /* fonts in Resources */ = {isa = PBXBuildFile; fileRef = 4225D59127164F82002A680F /* fonts */; };
4225D59327164F82002A680F /* fonts in Resources */ = {isa = PBXBuildFile; fileRef = 4225D59127164F82002A680F /* fonts */; };
42321E852714E6B00056429F /* scripts in Resources */ = {isa = PBXBuildFile; fileRef = 42321E822714E6B00056429F /* scripts */; };
42321E862714E6B00056429F /* scripts in Resources */ = {isa = PBXBuildFile; fileRef = 42321E822714E6B00056429F /* scripts */; };
42321E872714E6B00056429F /* styles in Resources */ = {isa = PBXBuildFile; fileRef = 42321E832714E6B00056429F /* styles */; };
42321E882714E6B00056429F /* styles in Resources */ = {isa = PBXBuildFile; fileRef = 42321E832714E6B00056429F /* styles */; };
42321E892714E6B00056429F /* views in Resources */ = {isa = PBXBuildFile; fileRef = 42321E842714E6B00056429F /* views */; };
42321E8A2714E6B00056429F /* views in Resources */ = {isa = PBXBuildFile; fileRef = 42321E842714E6B00056429F /* views */; };
42704E7328E6BDB000C8C73E /* SnapshotHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42704E7228E6BDAF00C8C73E /* SnapshotHelper.swift */; };
@ -192,7 +187,6 @@
042F48DB26DFD10E00BF98FC /* iOSLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSLaunchTests.swift; sourceTree = "<group>"; };
042F48DD26DFD10E00BF98FC /* iOSUITests.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = iOSUITests.plist; sourceTree = "<group>"; };
046C5CD226A3F89A00AC5349 /* ShareExtension-Mac.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "ShareExtension-Mac.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
046C5CD426A3F89A00AC5349 /* icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icon.icns; sourceTree = "<group>"; };
046C5CDB26A3F89A00AC5349 /* ShareExtensionMac.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = ShareExtensionMac.plist; sourceTree = "<group>"; };
046C5CDC26A3F89A00AC5349 /* ShareExtensionMac.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtensionMac.entitlements; sourceTree = "<group>"; };
047AA41F297A17FB00F0BEBF /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = "<group>"; };
@ -215,9 +209,7 @@
082449FB9F5F3730EE0D8D3F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
0BE7F7C593222747A96AA4E7 /* Omnivore.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Omnivore.plist; sourceTree = "<group>"; };
1A39D8FDA25447FDBF07E24B /* Omnivore.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Omnivore.app; sourceTree = BUILT_PRODUCTS_DIR; };
4225D59127164F82002A680F /* fonts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = fonts; sourceTree = "<group>"; };
42321E822714E6B00056429F /* scripts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = scripts; sourceTree = "<group>"; };
42321E832714E6B00056429F /* styles */ = {isa = PBXFileReference; lastKnownFileType = folder; path = styles; sourceTree = "<group>"; };
42321E842714E6B00056429F /* views */ = {isa = PBXFileReference; lastKnownFileType = folder; path = views; sourceTree = "<group>"; };
42704E7228E6BDAF00C8C73E /* SnapshotHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SnapshotHelper.swift; sourceTree = "<group>"; };
42E2BFB128E458E0007F29B2 /* AppStoreScreenshots.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AppStoreScreenshots.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@ -473,9 +465,7 @@
42FF1AEC271154A600B38C38 /* Resources */ = {
isa = PBXGroup;
children = (
4225D59127164F82002A680F /* fonts */,
42321E822714E6B00056429F /* scripts */,
42321E832714E6B00056429F /* styles */,
42321E842714E6B00056429F /* views */,
42FF1AED271154A600B38C38 /* _locales */,
42FF1AEE271154A600B38C38 /* images */,
@ -511,7 +501,6 @@
B330B55BAF36E624637EE3BE /* ShareExtension */ = {
isa = PBXGroup;
children = (
046C5CD426A3F89A00AC5349 /* icon.icns */,
FF9F2334402E6B10A665F1A7 /* ShareExtensionViewController.swift */,
04E9706E26BDE47D002A523D /* ShareExtension.js */,
);
@ -878,7 +867,6 @@
buildActionMask = 2147483647;
files = (
04E9707226BDE5F1002A523D /* ShareExtension.js in Resources */,
046C5CD526A3F89A00AC5349 /* icon.icns in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -909,9 +897,7 @@
buildActionMask = 2147483647;
files = (
42321E892714E6B00056429F /* views in Resources */,
42321E872714E6B00056429F /* styles in Resources */,
42321E852714E6B00056429F /* scripts in Resources */,
4225D59227164F82002A680F /* fonts in Resources */,
42FF1B37271154A700B38C38 /* images in Resources */,
42FF1B39271154A700B38C38 /* manifest.json in Resources */,
42FF1B35271154A700B38C38 /* _locales in Resources */,
@ -923,9 +909,7 @@
buildActionMask = 2147483647;
files = (
42321E8A2714E6B00056429F /* views in Resources */,
42321E882714E6B00056429F /* styles in Resources */,
42321E862714E6B00056429F /* scripts in Resources */,
4225D59327164F82002A680F /* fonts in Resources */,
42FF1B38271154A700B38C38 /* images in Resources */,
42FF1B3A271154A700B38C38 /* manifest.json in Resources */,
42FF1B36271154A700B38C38 /* _locales in Resources */,

View File

@ -24,7 +24,9 @@ public struct AddNoteSheet: View {
public init(viewModel: ShareExtensionViewModel) {
_viewModel = StateObject(wrappedValue: viewModel)
UITextView.appearance().textContainerInset = UIEdgeInsets(top: 8, left: 4, bottom: 10, right: 4)
#if os(iOS)
UITextView.appearance().textContainerInset = UIEdgeInsets(top: 8, left: 4, bottom: 10, right: 4)
#endif
}
func saveNote() {
@ -41,6 +43,7 @@ public struct AddNoteSheet: View {
}
.background(Color.extensionBackground)
.navigationTitle("Add Note")
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
.navigationBarItems(leading: Button(action: {
dismiss()
@ -53,6 +56,10 @@ public struct AddNoteSheet: View {
}, label: {
Text("Save").bold()
}))
}.navigationViewStyle(StackNavigationViewStyle())
#endif
}
#if os(iOS)
.navigationViewStyle(StackNavigationViewStyle())
#endif
}
}

View File

@ -26,17 +26,11 @@ public struct EditInfoSheet: View {
public init(viewModel: ShareExtensionViewModel) {
_viewModel = StateObject(wrappedValue: viewModel)
UITextView.appearance().textContainerInset = UIEdgeInsets(top: 8, left: 4, bottom: 10, right: 4)
#if os(iOS)
UITextView.appearance().textContainerInset = UIEdgeInsets(top: 8, left: 4, bottom: 10, right: 4)
#endif
}
// func saveInfo() {
// if let linkedItem = viewModel.linkedItem {
// _ = viewModel.services.dataService.updateLinkedItemTitleAndDescription(itemID: linkedItem.unwrappedID, title: title, description: description, author: author)
// } else {
// // Maybe we shouldn't even allow this UI without linkeditem existing
// }
// }
public var body: some View {
if let item = viewModel.linkedItem {
LinkedItemMetadataEditView(item: item) { title, _ in

View File

@ -14,6 +14,7 @@ import Views
@MainActor
public struct EditLabelsSheet: View {
@State var text = ""
@State var isLabelsEntryFocused = false
@Environment(\.dismiss) private var dismiss
@EnvironmentObject var dataService: DataService
@ -29,8 +30,9 @@ public struct EditLabelsSheet: View {
public init(viewModel: ShareExtensionViewModel, labelsViewModel: LabelsViewModel) {
_viewModel = StateObject(wrappedValue: viewModel)
_labelsViewModel = StateObject(wrappedValue: labelsViewModel)
UITextView.appearance().textContainerInset = UIEdgeInsets(top: 5, left: 2, bottom: 5, right: 2)
#if os(iOS)
UITextView.appearance().textContainerInset = UIEdgeInsets(top: 5, left: 2, bottom: 5, right: 2)
#endif
}
@MainActor
@ -55,6 +57,7 @@ public struct EditLabelsSheet: View {
VStack {
LabelsEntryView(
searchTerm: $labelsViewModel.labelSearchFilter,
isFocused: $isLabelsEntryFocused,
viewModel: labelsViewModel
)
.padding(.horizontal, 10)
@ -95,7 +98,9 @@ public struct EditLabelsSheet: View {
}
.listStyle(.plain)
.background(Color.extensionBackground)
}
Spacer()
}.frame(maxHeight: .infinity)
}
public var body: some View {
@ -104,6 +109,7 @@ public struct EditLabelsSheet: View {
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.extensionBackground)
.navigationTitle("Set Labels")
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
.navigationBarItems(trailing: Button(action: {
if let linkedItem = viewModel.linkedItem, let linkedItemId = linkedItem.id {
@ -116,11 +122,14 @@ public struct EditLabelsSheet: View {
}, label: {
Text("Done").bold()
}))
#endif
}
.navigationViewStyle(StackNavigationViewStyle())
#if os(iOS)
.navigationViewStyle(StackNavigationViewStyle())
#endif
.environmentObject(viewModel.services.dataService)
.task {
await labelsViewModel.loadLabelsFromStore(dataService: viewModel.services.dataService)
}
.task {
await labelsViewModel.loadLabelsFromStore(dataService: viewModel.services.dataService)
}
}
}

View File

@ -9,6 +9,8 @@ import Foundation
import SwiftUI
struct MiniShareExtensionView: View {
@StateObject var viewModel: ShareExtensionViewModel
@StateObject var labelsViewModel: LabelsViewModel
let extensionContext: NSExtensionContext?
@State var showToast = true

View File

@ -20,7 +20,8 @@ public struct ShareExtensionView: View {
@State var showAddNoteModal = false
enum FocusField: Hashable {
case titleEditor
case noteEditor
case labelEditor
}
enum ViewState {
@ -39,6 +40,10 @@ public struct ShareExtensionView: View {
_viewModel = StateObject(wrappedValue: viewModel)
_labelsViewModel = StateObject(wrappedValue: labelsViewModel)
self.extensionContext = extensionContext
#if os(iOS)
UITextView.appearance().textContainerInset = UIEdgeInsets(top: 8, left: 4, bottom: 10, right: 4)
#endif
}
private func localImage(from url: URL) -> Image? {
@ -100,7 +105,7 @@ public struct ShareExtensionView: View {
Image(systemName: "checkmark.circle")
.frame(width: 15, height: 15)
.foregroundColor(.appGreenSuccess)
// .opacity(isSynced ? 1.0 : 0.0)
.opacity(isSynced ? 1.0 : 0.0)
}
}
@ -160,14 +165,16 @@ public struct ShareExtensionView: View {
var moreMenuButton: some View {
Menu {
Button(action: {
NotificationCenter.default.post(name: Notification.Name("ShowEditInfoSheet"), object: nil)
}, label: {
Label(
"Edit Info",
systemImage: "info.circle"
)
})
#if os(iOS)
Button(action: {
NotificationCenter.default.post(name: Notification.Name("ShowEditInfoSheet"), object: nil)
}, label: {
Label(
"Edit Info",
systemImage: "info.circle"
)
})
#endif
Button(action: {
if let linkedItem = self.viewModel.linkedItem {
self.viewModel.setLinkArchived(dataService: self.viewModel.services.dataService,
@ -237,14 +244,34 @@ public struct ShareExtensionView: View {
Text("Saved to Omnivore")
.font(Font.system(size: 22, weight: .bold))
.frame(maxWidth: .infinity, alignment: .leading)
Spacer()
moreMenuButton
closeButton
#if os(iOS)
Spacer()
moreMenuButton
closeButton
#endif
}
}
var displayDismiss: Bool {
#if os(iOS)
if UIDevice.isIPhone {
return false
}
#endif
return true
}
public var body: some View {
#if os(iOS)
iOSBody
.environmentObject(viewModel.services.dataService)
#else
macOSBody
.environmentObject(viewModel.services.dataService)
#endif
}
var iOSBody: some View {
VStack(alignment: .leading, spacing: 15) {
titleBar
.padding(.top, 15)
@ -254,32 +281,44 @@ public struct ShareExtensionView: View {
Spacer(minLength: 1)
HStack {
#if os(macOS)
moreMenuButton
.padding(.bottom, 15)
#endif
Spacer()
if UIDevice.isIPad {
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
})
#if os(iOS)
.frame(height: 50)
.cornerRadius(24)
.padding(.bottom, 15)
#endif
.padding(.bottom, 15)
}
Button(action: {
viewModel.handleReadNowAction(extensionContext: extensionContext)
}, label: {
Text("Read Now")
#if os(iOS)
.font(Font.system(size: 17, weight: .semibold))
.tint(Color.white)
.padding(20)
#endif
})
#if os(iOS)
.frame(height: 50)
.background(Color.blue)
.cornerRadius(24)
.padding(.bottom, 15)
#endif
.padding(.bottom, 15)
}.frame(maxWidth: .infinity)
}.padding(.horizontal, 15)
.background(Color.extensionBackground)
@ -287,4 +326,108 @@ public struct ShareExtensionView: View {
viewModel.savePage(extensionContext: extensionContext)
}
}
@State var labelsSearch = ZWSP
@State var isLabelsEntryFocused = false
func save() {
if !viewModel.noteText.isEmpty {
viewModel.saveNote()
}
if let itemID = viewModel.linkedItem?.id {
labelsViewModel.saveItemLabelChanges(itemID: itemID, dataService: viewModel.services.dataService)
}
}
var macOSBody: some View {
VStack(alignment: .leading, spacing: 0) {
HStack(spacing: 10) {
Text("Saved to Omnivore")
.font(Font.system(size: 17))
Image(systemName: "checkmark.circle")
.foregroundColor(.appGreenSuccess)
.opacity(isSynced ? 1.0 : 0.0)
Spacer()
}.padding(15)
Divider()
ZStack(alignment: .topLeading) {
TextEditor(text: $viewModel.noteText)
.frame(maxWidth: .infinity)
.font(Font.system(size: 14))
.accentColor(.blue)
#if os(macos)
.introspectTextView { textView in
textView.textContainerInset = NSSize(width: 10, height: 10)
}
#endif
.focused($focusedField, equals: .noteEditor)
if viewModel.noteText.isEmpty {
Text("Notes")
.fontWeight(.light)
.font(Font.system(size: 14))
.foregroundColor(.black.opacity(0.25))
.padding(.leading, 15)
.padding(.top, 10)
.allowsHitTesting(false)
}
}
Divider()
ZStack(alignment: .topLeading) {
LabelsEntryView(searchTerm: $labelsSearch, isFocused: $isLabelsEntryFocused, viewModel: labelsViewModel)
.frame(maxWidth: .infinity)
.padding(.horizontal, 8)
.focused($focusedField, equals: .labelEditor)
if labelsViewModel.selectedLabels.isEmpty, labelsSearch == ZWSP {
Text("Type to add labels")
.fontWeight(.light)
.font(Font.system(size: 14))
.foregroundColor(.black.opacity(0.25))
.padding(.leading, 15)
.padding(.top, 10)
.allowsHitTesting(false)
}
}
Divider()
HStack {
moreMenuButton
.padding(.bottom, 15)
Spacer()
Button(action: {
save()
extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
}, label: {
Text("Dismiss")
})
.padding(.bottom, 15)
Button(action: {
save()
viewModel.handleReadNowAction(extensionContext: extensionContext)
}, label: {
Text("Read Now")
})
.padding(.bottom, 15)
}.padding(15)
}.frame(maxWidth: .infinity)
.background(Color.isDarkMode ? Color.systemBackground : Color.white)
.onAppear {
if let extensionContext = extensionContext {
viewModel.savePage(extensionContext: extensionContext)
}
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
focusedField = .labelEditor
}
Task {
await labelsViewModel.loadLabels(dataService: viewModel.services.dataService, initiallySelectedLabels: [])
}
}
}
}

View File

@ -106,7 +106,6 @@ import Views
.contextMenu {
menuItems(item)
}
Divider().padding(5)
}
if viewModel.isLoading {

View File

@ -36,6 +36,7 @@ struct ApplyLabelsView: View {
@EnvironmentObject var dataService: DataService
@Environment(\.presentationMode) private var presentationMode
@StateObject var viewModel = LabelsViewModel()
@State var isLabelsEntryFocused = false
enum ViewState {
case mainView
@ -52,6 +53,7 @@ struct ApplyLabelsView: View {
VStack {
LabelsEntryView(
searchTerm: $viewModel.labelSearchFilter,
isFocused: $isLabelsEntryFocused,
viewModel: viewModel
)
.padding(.horizontal, 10)
@ -62,67 +64,60 @@ struct ApplyLabelsView: View {
}
List {
Section {
ForEach(viewModel.labels.applySearchFilter(viewModel.labelSearchFilter), id: \.self) { label in
Button(
action: {
if isSelected(label) {
if let idx = viewModel.selectedLabels.firstIndex(of: label) {
viewModel.selectedLabels.remove(at: idx)
}
} else {
viewModel.labelSearchFilter = ZWSP
viewModel.selectedLabels.append(label)
ForEach(viewModel.labels.applySearchFilter(viewModel.labelSearchFilter), id: \.self) { label in
Button(
action: {
if isSelected(label) {
if let idx = viewModel.selectedLabels.firstIndex(of: label) {
viewModel.selectedLabels.remove(at: idx)
}
},
label: {
HStack {
TextChip(feedItemLabel: label).allowsHitTesting(false)
Spacer()
if isSelected(label) {
Image(systemName: "checkmark")
}
}
.contentShape(Rectangle())
} else {
viewModel.labelSearchFilter = ZWSP
viewModel.selectedLabels.append(label)
}
)
.padding(.vertical, 5)
.frame(maxWidth: .infinity, alignment: .leading)
#if os(macOS)
.buttonStyle(PlainButtonStyle())
#endif
}
},
label: {
HStack {
TextChip(feedItemLabel: label).allowsHitTesting(false)
Spacer()
if isSelected(label) {
Image(systemName: "checkmark")
}
}
.contentShape(Rectangle())
}
)
.padding(.vertical, 5)
.frame(maxWidth: .infinity, alignment: .leading)
#if os(macOS)
.buttonStyle(PlainButtonStyle())
#endif
}
if !viewModel.labelSearchFilter.isEmpty, viewModel.labelSearchFilter != ZWSP {
createLabelButton
}
}
.listStyle(.plain)
.background(Color.extensionBackground)
Spacer()
.frame(maxHeight: .infinity)
}
.navigationTitle(mode.navTitle)
.background(Color.extensionBackground)
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
cancelButton
}
ToolbarItem(placement: .navigationBarTrailing) {
saveItemChangesButton
}
}
#else
.toolbar {
ToolbarItemGroup {
cancelButton
saveItemChangesButton
}
}
#endif
.sheet(isPresented: $viewModel.showCreateLabelModal) {
CreateLabelView(viewModel: viewModel, newLabelName: viewModel.labelSearchFilter)
}
.onAppear {
Task {
switch mode {
case let .item(feedItem):
await viewModel.loadLabels(dataService: dataService, item: feedItem)
case let .highlight(highlight):
await viewModel.loadLabels(dataService: dataService, highlight: highlight)
case let .list(labels):
await viewModel.loadLabels(dataService: dataService, initiallySelectedLabels: labels)
}
}
}
}
var createLabelButton: some View {
@ -176,32 +171,29 @@ struct ApplyLabelsView: View {
}
var body: some View {
Group {
#if os(iOS)
NavigationView {
if viewModel.labels.isEmpty, viewModel.isLoading {
EmptyView()
} else {
innerBody
#if os(iOS)
NavigationView {
innerBody
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
cancelButton
}
ToolbarItem(placement: .navigationBarTrailing) {
saveItemChangesButton
}
}
}
#elseif os(macOS)
innerBody
.toolbar {
ToolbarItemGroup {
cancelButton
saveItemChangesButton
}
}
#elseif os(macOS)
innerBody
.frame(minWidth: 400, minHeight: 600)
#endif
}
.onAppear {
Task {
switch mode {
case let .item(feedItem):
await viewModel.loadLabels(dataService: dataService, item: feedItem)
case let .highlight(highlight):
await viewModel.loadLabels(dataService: dataService, highlight: highlight)
case let .list(labels):
await viewModel.loadLabels(dataService: dataService, initiallySelectedLabels: labels)
}
}
}
.frame(minWidth: 400, minHeight: 600)
#endif
}
}
@ -210,8 +202,11 @@ extension Sequence where Element == LinkedItemLabel {
if searchFilter.isEmpty || searchFilter == ZWSP {
return map { $0 } // return the identity of the sequence
}
let index = searchFilter.index(searchFilter.startIndex, offsetBy: 1)
let trimmed = searchFilter.suffix(from: index).lowercased()
return filter { ($0.name ?? "").lowercased().contains(trimmed) }
if searchFilter.starts(with: ZWSP) {
let index = searchFilter.index(searchFilter.startIndex, offsetBy: 1)
let trimmed = searchFilter.suffix(from: index).lowercased()
return filter { ($0.name ?? "").lowercased().contains(trimmed) }
}
return filter { ($0.name ?? "").lowercased().contains(searchFilter.lowercased()) }
}
}

View File

@ -29,7 +29,6 @@ import SwiftUI
highlight: Highlight? = nil,
initiallySelectedLabels: [LinkedItemLabel]? = nil
) async {
isLoading = true
let selLabels = initiallySelectedLabels ?? item?.sortedLabels ?? highlight?.sortedLabels ?? []
await loadLabelsFromStore(dataService: dataService)
@ -42,7 +41,6 @@ import SwiftUI
unselectedLabels.insert(label)
}
}
isLoading = false
Task.detached(priority: .userInitiated) {
if let labelIDs = try? await dataService.labels() {
@ -59,7 +57,6 @@ import SwiftUI
self.unselectedLabels.insert(label)
}
}
self.isLoading = false
}
}
}

View File

@ -25,38 +25,54 @@ private struct LabelEntry: Entry {
@MainActor
public struct LabelsEntryView: View {
@Binding var searchTerm: String
@Binding var isFocused: Bool
@State var viewModel: LabelsViewModel
@EnvironmentObject var dataService: DataService
let entries: [Entry]
#if os(macOS)
@State var popoverIndex = -1
@State var presentPopover = false
#endif
@State private var totalHeight = CGFloat.zero
@FocusState private var textFieldFocused: Bool
public init(
searchTerm: Binding<String>,
isFocused: Binding<Bool>,
viewModel: LabelsViewModel
) {
self._searchTerm = searchTerm
self.viewModel = viewModel
self._isFocused = isFocused
self.viewModel = viewModel
self.entries = Array(viewModel.selectedLabels.map { LabelEntry(label: $0) })
}
func onTextSubmit() {
let index = searchTerm.index(searchTerm.startIndex, offsetBy: 1)
let trimmed = searchTerm.suffix(from: index).lowercased()
func getSearchTermText() -> String {
if searchTerm.starts(with: ZWSP) {
let index = searchTerm.index(searchTerm.startIndex, offsetBy: 1)
let trimmed = searchTerm.suffix(from: index)
return String(trimmed)
}
return searchTerm
}
func onTextSubmit() {
let trimmed = getSearchTermText()
if trimmed.count < 1 {
return
}
if let label = viewModel.labels.first(where: { $0.name?.lowercased() == trimmed }) {
let lowercased = trimmed.lowercased()
if let label = viewModel.labels.first(where: { $0.name?.lowercased() == lowercased }) {
if !viewModel.selectedLabels.contains(label) {
viewModel.selectedLabels.append(label)
}
searchTerm = ZWSP
reset()
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
textFieldFocused = true
}
@ -67,27 +83,58 @@ public struct LabelsEntryView: View {
color: Gradient.randomColor(str: trimmed, offset: 1),
description: nil
)
searchTerm = ZWSP
reset()
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
textFieldFocused = true
}
}
}
var textFieldString: NSAttributedString {
#if os(iOS)
NSAttributedString(
string: searchTerm,
attributes: [
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14)
]
)
#else
NSAttributedString(
string: searchTerm,
attributes: [
NSAttributedString.Key.font: NSFont.systemFont(ofSize: 14)
]
)
#endif
}
func reset() {
searchTerm = ZWSP
#if os(macOS)
popoverIndex = -1
presentPopover = false
#endif
}
var deletableTextField: some View {
let str = NSAttributedString(
string: searchTerm,
attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14)]
)
// Round it up to avoid jitter when typing
let textWidth = max(25.0, Double(Int(str.size().width + 1)))
let result = TextField("", text: $searchTerm)
let textWidth = max(25.0, Double(Int(textFieldString.size().width + 28)))
var result = AnyView(TextField("", text: $searchTerm)
.id("deletableTextField")
.frame(alignment: .topLeading)
.frame(height: 25)
.frame(width: textWidth)
.padding(5)
.padding(.trailing, 5)
.padding(.vertical, 5)
.padding(EdgeInsets(top: 0, leading: 6, bottom: 0, trailing: 6))
.cornerRadius(5)
.accentColor(.blue)
.font(Font.system(size: 14))
.multilineTextAlignment(.leading)
#if os(macOS)
.textFieldStyle(.plain)
.background(Color.clear)
#endif
.onChange(of: searchTerm, perform: { _ in
if searchTerm.count >= 64 {
searchTerm = String(searchTerm.prefix(64))
@ -95,56 +142,108 @@ public struct LabelsEntryView: View {
if searchTerm.isEmpty {
if viewModel.selectedLabels.count > 0 {
viewModel.selectedLabels.removeLast()
searchTerm = ZWSP
reset()
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
textFieldFocused = true
}
} else {
searchTerm = ZWSP
reset()
}
}
})
.onSubmit {
onTextSubmit()
.onSubmit {
#if os(iOS)
onTextSubmit()
#else
if popoverIndex == -1 || popoverIndex >= partialMatches.count {
onTextSubmit()
} else if popoverIndex >= 0, popoverIndex < partialMatches.count {
let matched = partialMatches[popoverIndex]
viewModel.selectedLabels.append(matched)
reset()
}
#endif
}
.submitScope())
#if os(macOS)
if #available(macOS 14.0, *) {
result = AnyView(result
.onKeyPress(.downArrow) {
popoverIndex = ((popoverIndex + 1) % (partialMatches.count + 1))
return .handled
}
.onKeyPress(.upArrow) {
popoverIndex -= 1
return .handled
}
.onKeyPress(.tab) {
popoverIndex = ((popoverIndex + 1) % (partialMatches.count + 1))
return .handled
})
}
return result
#endif
return AnyView(result)
}
// func onTextDelete() -> Bool { if searchTerm.isEmpty {
// if lastSelected {
// if viewModel.selectedLabels.count > 0 {
// viewModel.selectedLabels.removeLast()
// DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
// textFieldFocused = true
// }
// }
// } else {
// lastSelected = true
// }
// return true
// }
// return false
// }
public var body: some View {
// HStack(spacing: 0) {
VStack {
GeometryReader { geometry in
self.generateLabelsContent(in: geometry)
}
}.padding(0)
.frame(height: totalHeight)
.frame(maxWidth: .infinity)
.background(Color.extensionPanelBackground)
.cornerRadius(8)
#if os(macOS)
.onHover { isHovered in
DispatchQueue.main.async {
if isHovered {
NSCursor.iBeam.push()
} else {
NSCursor.pop()
}
}
}
#endif
.cornerRadius(8)
.onAppear {
textFieldFocused = true
}
.onTapGesture {
textFieldFocused = true
}
.transaction { $0.animation = nil }
.onChange(of: textFieldFocused) { self.isFocused = $0 }
}
var partialMatches: [LinkedItemLabel] {
viewModel.labels.applySearchFilter(searchTerm)
}
#if os(macOS)
private var createLabelButton: some View {
let count = partialMatches.count
return Button {
viewModel.createLabel(
dataService: dataService,
name: searchTerm,
color: Gradient.randomColor(str: searchTerm, offset: 1),
description: nil
)
reset()
} label: {
Text("Create new label")
.padding(6)
}
.background(popoverIndex == count ? Color.blue : Color.clear)
.frame(maxWidth: .infinity, alignment: .leading)
.cornerRadius(4)
.buttonStyle(.borderless)
.cornerRadius(4)
}
#endif
private func generateLabelsContent(in geom: GeometryProxy) -> some View {
var width = CGFloat.zero
var height = CGFloat.zero
@ -183,6 +282,37 @@ public struct LabelsEntryView: View {
height = 0
return result
}).focused($textFieldFocused)
#if os(macOS)
.onChange(of: searchTerm) { _ in
presentPopover = !searchTerm.isEmpty && searchTerm != ZWSP && partialMatches.count < 14
if popoverIndex >= partialMatches.count + 1 {
popoverIndex = partialMatches.count + 1
}
}
.popover(isPresented: $presentPopover, arrowEdge: .top) {
VStack(alignment: .leading, spacing: 4) {
ForEach(Array(partialMatches.enumerated()), id: \.offset) { idx, label in
if let name = label.name {
Button {
reset()
viewModel.selectedLabels.append(label)
} label: {
Text(name)
.padding(6)
.frame(maxWidth: .infinity, alignment: .leading)
}
.background(idx == popoverIndex ? Color.blue : Color.clear)
.frame(maxWidth: .infinity, alignment: .leading)
.cornerRadius(4)
.buttonStyle(.borderless)
.cornerRadius(4)
}
}
createLabelButton
}.padding(4)
}
#endif
}.background(viewHeightReader($totalHeight))
}

View File

@ -138,7 +138,7 @@ struct LinkedItemMetadataEditView: View {
)
}
}
.frame(minWidth: 400, minHeight: 600)
.frame(minWidth: 400, minHeight: 400)
}
#endif
}

View File

@ -499,7 +499,9 @@ struct WebReaderContainerView: View {
showErrorAlertMessage: $showErrorAlertMessage
)
}
.navigationViewStyle(StackNavigationViewStyle())
#if os(iOS)
.navigationViewStyle(StackNavigationViewStyle())
#endif
}
.sheet(isPresented: $showHighlightLabelsModal) {
if let highlight = Highlight.lookup(byID: self.annotation, inContext: self.dataService.viewContext) {

View File

@ -89,6 +89,7 @@ struct WelcomeView: View {
.sheet(isPresented: $showPrivacyModal) {
NavigationView {
BasicWebAppView.privacyPolicyWebView(baseURL: dataService.appEnvironment.webAppBaseURL)
#if os(iOS)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(
@ -101,11 +102,24 @@ struct WelcomeView: View {
)
}
}
#else
.toolbar {
Button(
action: {
showPrivacyModal = false
},
label: {
Text(LocalText.genericClose)
}
)
}
#endif
}
}
.sheet(isPresented: $showTermsModal) {
NavigationView {
BasicWebAppView.termsConditionsWebView(baseURL: dataService.appEnvironment.webAppBaseURL)
#if os(iOS)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button(
@ -118,6 +132,18 @@ struct WelcomeView: View {
)
}
}
#else
.toolbar {
Button(
action: {
showTermsModal = false
},
label: {
Text(LocalText.genericClose)
}
)
}
#endif
}
}
.sheet(isPresented: $showAboutPage) {

View File

@ -66,7 +66,7 @@ public struct LibraryItemCard: View {
labels
}
if let note = item.noteText {
if let note = item.noteText, !note.isEmpty {
HStack(alignment: .top, spacing: 10) {
avatarImage
.frame(width: 20, height: 20)

View File

@ -1,38 +0,0 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0xA8",
"green" : "0xEB",
"red" : "0xFB"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x4C",
"green" : "0x4D",
"red" : "0x4F"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 569 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 919 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 729 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 899 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1023 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 615 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1018 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 732 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 940 B

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16px" height="16px">
<path fill="black" d="M15.9 7.801c0 .507-.123 1.12-.248 1.656v.004l-.001.003a2.87 2.87 0 0 1-2.793 2.186h-.036c-1.625 0-2.649-1.334-2.649-2.828v-2.14l-1.21 1.794-.067.055a1.404 1.404 0 0 1-1.793 0l-.065-.053-1.248-1.82v4.414H4.6V6.268c0-.91 1.078-1.439 1.794-.802l.055.048 1.46 2.13a.21.21 0 0 0 .179 0l1.43-2.119.065-.054c.68-.567 1.78-.138 1.78.815v2.536c0 .971.619 1.638 1.46 1.638h.035c.78 0 1.45-.527 1.636-1.277.125-.534.216-1.026.216-1.378-.017-3.835-3.262-6.762-7.188-6.498-3.311.23-5.986 2.905-6.216 6.216A6.705 6.705 0 0 0 8 14.693v1.19a7.895 7.895 0 0 1-7.882-8.44C.39 3.536 3.536.39 7.44.118 12.017-.19 15.88 3.242 15.9 7.8z"/>
</svg>

Before

Width:  |  Height:  |  Size: 776 B

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16px" height="16px">
<path fill="white" d="M15.9 7.801c0 .507-.123 1.12-.248 1.656v.004l-.001.003a2.87 2.87 0 0 1-2.793 2.186h-.036c-1.625 0-2.649-1.334-2.649-2.828v-2.14l-1.21 1.794-.067.055a1.404 1.404 0 0 1-1.793 0l-.065-.053-1.248-1.82v4.414H4.6V6.268c0-.91 1.078-1.439 1.794-.802l.055.048 1.46 2.13a.21.21 0 0 0 .179 0l1.43-2.119.065-.054c.68-.567 1.78-.138 1.78.815v2.536c0 .971.619 1.638 1.46 1.638h.035c.78 0 1.45-.527 1.636-1.277.125-.534.216-1.026.216-1.378-.017-3.835-3.262-6.762-7.188-6.498-3.311.23-5.986 2.905-6.216 6.216A6.705 6.705 0 0 0 8 14.693v1.19a7.895 7.895 0 0 1-7.882-8.44C.39 3.536 3.536.39 7.44.118 12.017-.19 15.88 3.242 15.9 7.8z"/>
</svg>

Before

Width:  |  Height:  |  Size: 776 B

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16px" height="16px">
<path fill="white" d="M15.9 7.801c0 .507-.123 1.12-.248 1.656v.004l-.001.003a2.87 2.87 0 0 1-2.793 2.186h-.036c-1.625 0-2.649-1.334-2.649-2.828v-2.14l-1.21 1.794-.067.055a1.404 1.404 0 0 1-1.793 0l-.065-.053-1.248-1.82v4.414H4.6V6.268c0-.91 1.078-1.439 1.794-.802l.055.048 1.46 2.13a.21.21 0 0 0 .179 0l1.43-2.119.065-.054c.68-.567 1.78-.138 1.78.815v2.536c0 .971.619 1.638 1.46 1.638h.035c.78 0 1.45-.527 1.636-1.277.125-.534.216-1.026.216-1.378-.017-3.835-3.262-6.762-7.188-6.498-3.311.23-5.986 2.905-6.216 6.216A6.705 6.705 0 0 0 8 14.693v1.19a7.895 7.895 0 0 1-7.882-8.44C.39 3.536 3.536.39 7.44.118 12.017-.19 15.88 3.242 15.9 7.8z"/>
</svg>

Before

Width:  |  Height:  |  Size: 776 B

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16px" height="16px">
<path fill="white" d="M15.9 7.801c0 .507-.123 1.12-.248 1.656v.004l-.001.003a2.87 2.87 0 0 1-2.793 2.186h-.036c-1.625 0-2.649-1.334-2.649-2.828v-2.14l-1.21 1.794-.067.055a1.404 1.404 0 0 1-1.793 0l-.065-.053-1.248-1.82v4.414H4.6V6.268c0-.91 1.078-1.439 1.794-.802l.055.048 1.46 2.13a.21.21 0 0 0 .179 0l1.43-2.119.065-.054c.68-.567 1.78-.138 1.78.815v2.536c0 .971.619 1.638 1.46 1.638h.035c.78 0 1.45-.527 1.636-1.277.125-.534.216-1.026.216-1.378-.017-3.835-3.262-6.762-7.188-6.498-3.311.23-5.986 2.905-6.216 6.216A6.705 6.705 0 0 0 8 14.693v1.19a7.895 7.895 0 0 1-7.882-8.44C.39 3.536 3.536.39 7.44.118 12.017-.19 15.88 3.242 15.9 7.8z"/>
</svg>

Before

Width:  |  Height:  |  Size: 776 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 989 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 523 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "Omnivore",
"short_name": "Omnivore",
"version": "2.6.2",
"version": "2.8.2",
"description": "Save PDFs and Articles to your Omnivore library",
"author": "Omnivore Media, Inc",
"default_locale": "en",

File diff suppressed because one or more lines are too long

View File

@ -1,101 +0,0 @@
/**
* Fonts
*/
@font-face {
font-style: normal;
font-weight: 400;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-400.woff2") format("woff2");
}
@font-face {
font-style: normal;
font-weight: 600;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-600.woff2") format("woff2");
}
@font-face {
font-style: normal;
font-weight: 700;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-700.woff2") format("woff2");
}
/**
* Other
*/
html,
body {
width: 100%;
height: 100%;
}
body {
margin: 0;
}
.cta-container {
position: relative;
overflow: hidden;
box-sizing: border-box;
width: 100%;
height: 100%;
padding: 24px 12px;
background: linear-gradient(150deg, #fff 55%, #ffde8c 55%);
background-color: #fff;
color: #3d3d3d;
font-family: Inter, sans-serif;
text-align: center;
}
.cta-container__wrapper {
position: relative;
z-index: 1;
}
.cta-container__title {
padding: 0 24px 24px;
font-weight: 600;
font-size: 16px;
}
.cta-container__icon {
vertical-align: unset;
margin-bottom: -4px;
fill: none;
}
.cta-container__link {
display: flex;
align-items: center;
justify-content: center;
width: 184px;
height: 34px;
margin: 36px auto 14px;
border-radius: 40px;
background-color: #fff;
color: inherit;
font-weight: 700;
font-size: 12px;
text-decoration: none;
cursor: pointer;
}
.cta-container__text {
margin: 0;
font-size: 12px;
}
.cta-container__textlink {
color: inherit;
font-weight: 700;
}

View File

@ -7,33 +7,6 @@
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
@font-face {
font-style: normal;
font-weight: 400;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-400.woff2") format("woff2");
}
@font-face {
font-style: normal;
font-weight: 600;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-600.woff2") format("woff2");
}
@font-face {
font-style: normal;
font-weight: 700;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-700.woff2") format("woff2");
}
html,
body {
@ -55,7 +28,7 @@ body {
background: linear-gradient(150deg, #fff 55%, #ffde8c 55%);
background-color: #fff;
color: #3d3d3d;
font-family: Inter, sans-serif;
font-family: sans-serif;
text-align: center;
}

View File

@ -62,16 +62,54 @@ import Views
import Cocoa
class ShareViewController: NSViewController {
let labelsViewModel = LabelsViewModel()
let viewModel = ShareExtensionViewModel()
override func loadView() {
view = NSView(frame: NSRect(x: 0, y: 0, width: 400, height: 600))
view = NSView(frame: NSRect(x: 0, y: 0, width: 400, height: 300))
}
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
forName: Notification.Name("ShowAddNoteSheet"),
object: nil,
queue: OperationQueue.main
) { _ in
self.openSheet(AnyView(AddNoteSheet(viewModel: self.viewModel)))
}
NotificationCenter.default.addObserver(
forName: Notification.Name("ShowEditLabelsSheet"),
object: nil,
queue: OperationQueue.main
) { _ in
self.openSheet(AnyView(EditLabelsSheet(viewModel: self.viewModel, labelsViewModel: self.labelsViewModel)))
}
NotificationCenter.default.addObserver(
forName: Notification.Name("ShowEditInfoSheet"),
object: nil,
queue: OperationQueue.main
) { _ in
self.openSheet(AnyView(EditInfoSheet(viewModel: self.viewModel)))
}
embed(
childViewController: NSViewController.makeShareExtensionController(extensionContext: extensionContext)
childViewController: NSViewController.makeShareExtensionController(
viewModel: viewModel,
labelsViewModel: labelsViewModel,
extensionContext: extensionContext
)
)
}
func openSheet(_ rootView: AnyView) {
let hostingController = PlatformHostingController(rootView: rootView)
presentAsSheet(hostingController)
}
}
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -1,101 +0,0 @@
/**
* Fonts
*/
@font-face {
font-style: normal;
font-weight: 400;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-400.woff2") format("woff2");
}
@font-face {
font-style: normal;
font-weight: 600;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-600.woff2") format("woff2");
}
@font-face {
font-style: normal;
font-weight: 700;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-700.woff2") format("woff2");
}
/**
* Other
*/
html,
body {
width: 100%;
height: 100%;
}
body {
margin: 0;
}
.cta-container {
position: relative;
overflow: hidden;
box-sizing: border-box;
width: 100%;
height: 100%;
padding: 24px 12px;
background: linear-gradient(150deg, #fff 55%, #ffde8c 55%);
background-color: #fff;
color: #3d3d3d;
font-family: Inter, sans-serif;
text-align: center;
}
.cta-container__wrapper {
position: relative;
z-index: 1;
}
.cta-container__title {
padding: 0 24px 24px;
font-weight: 600;
font-size: 16px;
}
.cta-container__icon {
vertical-align: unset;
margin-bottom: -4px;
fill: none;
}
.cta-container__link {
display: flex;
align-items: center;
justify-content: center;
width: 184px;
height: 34px;
margin: 36px auto 14px;
border-radius: 40px;
background-color: #fff;
color: inherit;
font-weight: 700;
font-size: 12px;
text-decoration: none;
cursor: pointer;
}
.cta-container__text {
margin: 0;
font-size: 12px;
}
.cta-container__textlink {
color: inherit;
font-weight: 700;
}

View File

@ -7,33 +7,6 @@
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
@font-face {
font-style: normal;
font-weight: 400;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-400.woff2") format("woff2");
}
@font-face {
font-style: normal;
font-weight: 600;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-600.woff2") format("woff2");
}
@font-face {
font-style: normal;
font-weight: 700;
font-family: Inter;
src:
local(""),
url("/fonts/inter-v3-latin-700.woff2") format("woff2");
}
html,
body {
@ -55,7 +28,7 @@ body {
background: linear-gradient(150deg, #fff 55%, #ffde8c 55%);
background-color: #fff;
color: #3d3d3d;
font-family: Inter, sans-serif;
font-family: sans-serif;
text-align: center;
}

View File

@ -14,7 +14,7 @@
border-radius: 4px;
color: #3D3D3D;
background: #fff;
font: 400 12px Inter, sans-serif;
font: 400 12px sans-serif;
line-height: 20px;
box-shadow: 0px 5px 20px rgba(32, 31, 29, 0.12);
transition: all 300ms ease;
@ -304,6 +304,7 @@
fill: #898989;
}
.omnivore-save-button button {
margin-top: 10px;
color: #333333;
}
#omnivore-toast-container #omnivore-edit-labels-list button {

Some files were not shown because too many files have changed in this diff Show More