mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-28 23:54:32 +00:00
Update Settings View and stuff
This commit is contained in:
parent
f4b0231c23
commit
106f431682
3 changed files with 25 additions and 204 deletions
|
|
@ -2033,6 +2033,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Add manually" : {
|
"Add manually" : {
|
||||||
|
"extractionState" : "stale",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ar" : {
|
"ar" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
|
|
@ -6674,6 +6675,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Description" : {
|
"Description" : {
|
||||||
|
"extractionState" : "stale",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ar" : {
|
"ar" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
|
|
@ -6790,6 +6792,7 @@
|
||||||
"isCommentAutoGenerated" : true
|
"isCommentAutoGenerated" : true
|
||||||
},
|
},
|
||||||
"Disable" : {
|
"Disable" : {
|
||||||
|
"extractionState" : "stale",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ar" : {
|
"ar" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
|
|
@ -8581,6 +8584,7 @@
|
||||||
"isCommentAutoGenerated" : true
|
"isCommentAutoGenerated" : true
|
||||||
},
|
},
|
||||||
"Extensions" : {
|
"Extensions" : {
|
||||||
|
"extractionState" : "stale",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ar" : {
|
"ar" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
|
|
@ -10537,6 +10541,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Installed extensions" : {
|
"Installed extensions" : {
|
||||||
|
"extractionState" : "stale",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ar" : {
|
"ar" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
|
|
@ -13893,6 +13898,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"No extension installed" : {
|
"No extension installed" : {
|
||||||
|
"extractionState" : "stale",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ar" : {
|
"ar" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
|
|
@ -15721,6 +15727,7 @@
|
||||||
"isCommentAutoGenerated" : true
|
"isCommentAutoGenerated" : true
|
||||||
},
|
},
|
||||||
"Restart" : {
|
"Restart" : {
|
||||||
|
"extractionState" : "stale",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ar" : {
|
"ar" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
|
|
@ -15863,6 +15870,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Running" : {
|
"Running" : {
|
||||||
|
"extractionState" : "stale",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ar" : {
|
"ar" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
|
|
@ -19150,6 +19158,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Uninstall" : {
|
"Uninstall" : {
|
||||||
|
"extractionState" : "stale",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"ar" : {
|
"ar" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
||||||
case downloads
|
case downloads
|
||||||
case shelf
|
case shelf
|
||||||
case shortcuts
|
case shortcuts
|
||||||
case extensions
|
|
||||||
case about
|
case about
|
||||||
|
|
||||||
var id: String { rawValue }
|
var id: String { rawValue }
|
||||||
|
|
@ -58,7 +57,6 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
||||||
case .downloads: return "Downloads"
|
case .downloads: return "Downloads"
|
||||||
case .shelf: return "Shelf"
|
case .shelf: return "Shelf"
|
||||||
case .shortcuts: return "Shortcuts"
|
case .shortcuts: return "Shortcuts"
|
||||||
case .extensions: return "Extensions"
|
|
||||||
case .about: return "About"
|
case .about: return "About"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +80,6 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
||||||
case .downloads: return "square.and.arrow.down"
|
case .downloads: return "square.and.arrow.down"
|
||||||
case .shelf: return "books.vertical"
|
case .shelf: return "books.vertical"
|
||||||
case .shortcuts: return "keyboard"
|
case .shortcuts: return "keyboard"
|
||||||
case .extensions: return "puzzlepiece.extension"
|
|
||||||
case .about: return "info.circle"
|
case .about: return "info.circle"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +103,6 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
||||||
case .downloads: return .gray
|
case .downloads: return .gray
|
||||||
case .shelf: return .brown
|
case .shelf: return .brown
|
||||||
case .shortcuts: return .orange
|
case .shortcuts: return .orange
|
||||||
case .extensions: return .blue
|
|
||||||
case .about: return .secondary
|
case .about: return .secondary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -233,7 +229,6 @@ private struct SettingsForm<Content: View>: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SettingsView: View {
|
struct SettingsView: View {
|
||||||
@StateObject var extensionManager = DynamicIslandExtensionManager()
|
|
||||||
@State private var selectedTab: SettingsTab = .general
|
@State private var selectedTab: SettingsTab = .general
|
||||||
@State private var searchText: String = ""
|
@State private var searchText: String = ""
|
||||||
@StateObject private var highlightCoordinator = SettingsHighlightCoordinator()
|
@StateObject private var highlightCoordinator = SettingsHighlightCoordinator()
|
||||||
|
|
@ -260,11 +255,13 @@ struct SettingsView: View {
|
||||||
.padding(.horizontal, 12)
|
.padding(.horizontal, 12)
|
||||||
|
|
||||||
List(filteredTabs, selection: selectionBinding) { tab in
|
List(filteredTabs, selection: selectionBinding) { tab in
|
||||||
|
let isComingSoon = tab == .downloads
|
||||||
NavigationLink(value: tab) {
|
NavigationLink(value: tab) {
|
||||||
HStack(spacing: 10) {
|
HStack(spacing: 10) {
|
||||||
sidebarIcon(for: tab)
|
sidebarIcon(for: tab)
|
||||||
|
.opacity(isComingSoon ? 0.45 : 1)
|
||||||
Text(tab.title)
|
Text(tab.title)
|
||||||
.foregroundStyle(Color.primary)
|
.foregroundStyle(isComingSoon ? Color.secondary : Color.primary)
|
||||||
if tab == .osd {
|
if tab == .osd {
|
||||||
Spacer()
|
Spacer()
|
||||||
Text("ALPHA")
|
Text("ALPHA")
|
||||||
|
|
@ -276,11 +273,15 @@ struct SettingsView: View {
|
||||||
Capsule()
|
Capsule()
|
||||||
.fill(Color.orange)
|
.fill(Color.orange)
|
||||||
)
|
)
|
||||||
|
} else if isComingSoon {
|
||||||
|
Spacer()
|
||||||
|
comingSoonTag()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.vertical, 4)
|
.padding(.vertical, 4)
|
||||||
}
|
}
|
||||||
.tag(tab)
|
.tag(tab)
|
||||||
|
.disabled(isComingSoon)
|
||||||
.listRowInsets(EdgeInsets(top: 4, leading: 12, bottom: 4, trailing: 10))
|
.listRowInsets(EdgeInsets(top: 4, leading: 12, bottom: 4, trailing: 10))
|
||||||
}
|
}
|
||||||
.listStyle(SidebarListStyle())
|
.listStyle(SidebarListStyle())
|
||||||
|
|
@ -303,13 +304,12 @@ struct SettingsView: View {
|
||||||
.opacity(0) // Invisible, but reserves space for a consistent look between tabs
|
.opacity(0) // Invisible, but reserves space for a consistent look between tabs
|
||||||
.disabled(true)
|
.disabled(true)
|
||||||
}
|
}
|
||||||
.environmentObject(extensionManager)
|
|
||||||
.environmentObject(highlightCoordinator)
|
.environmentObject(highlightCoordinator)
|
||||||
.formStyle(.grouped)
|
.formStyle(.grouped)
|
||||||
.frame(width: 700)
|
.frame(width: 700)
|
||||||
.onChange(of: searchText) { _, newValue in
|
.onChange(of: searchText) { _, newValue in
|
||||||
let matches = tabsMatchingSearch(newValue)
|
let matches = tabsMatchingSearch(newValue)
|
||||||
guard let firstMatch = matches.first else { return }
|
guard let firstMatch = matches.first(where: { $0 != .downloads }) else { return }
|
||||||
if !matches.contains(resolvedSelection) {
|
if !matches.contains(resolvedSelection) {
|
||||||
selectedTab = firstMatch
|
selectedTab = firstMatch
|
||||||
}
|
}
|
||||||
|
|
@ -347,7 +347,10 @@ struct SettingsView: View {
|
||||||
private var selectionBinding: Binding<SettingsTab> {
|
private var selectionBinding: Binding<SettingsTab> {
|
||||||
Binding(
|
Binding(
|
||||||
get: { resolvedSelection },
|
get: { resolvedSelection },
|
||||||
set: { selectedTab = $0 }
|
set: { newValue in
|
||||||
|
guard newValue != .downloads else { return }
|
||||||
|
selectedTab = newValue
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -382,7 +385,6 @@ struct SettingsView: View {
|
||||||
.downloads,
|
.downloads,
|
||||||
.shelf,
|
.shelf,
|
||||||
.shortcuts,
|
.shortcuts,
|
||||||
.extensions,
|
|
||||||
.about
|
.about
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -402,10 +404,11 @@ struct SettingsView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
private var searchSuggestions: [SettingsSearchEntry] {
|
private var searchSuggestions: [SettingsSearchEntry] {
|
||||||
Array(searchEntries(matching: searchText).prefix(8))
|
Array(searchEntries(matching: searchText).filter { $0.tab != .downloads }.prefix(8))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleSearchSuggestionSelection(_ suggestion: SettingsSearchEntry) {
|
private func handleSearchSuggestionSelection(_ suggestion: SettingsSearchEntry) {
|
||||||
|
guard suggestion.tab != .downloads else { return }
|
||||||
highlightCoordinator.focus(on: suggestion)
|
highlightCoordinator.focus(on: suggestion)
|
||||||
selectedTab = suggestion.tab
|
selectedTab = suggestion.tab
|
||||||
}
|
}
|
||||||
|
|
@ -583,12 +586,6 @@ struct SettingsView: View {
|
||||||
SettingsSearchEntry(tab: .battery, title: "Show power status notifications", keywords: ["notifications", "power"], highlightID: SettingsTab.battery.highlightID(for: "Show power status notifications")),
|
SettingsSearchEntry(tab: .battery, title: "Show power status notifications", keywords: ["notifications", "power"], highlightID: SettingsTab.battery.highlightID(for: "Show power status notifications")),
|
||||||
SettingsSearchEntry(tab: .battery, title: "Show power status icons", keywords: ["power icons", "charging icon"], highlightID: SettingsTab.battery.highlightID(for: "Show power status icons")),
|
SettingsSearchEntry(tab: .battery, title: "Show power status icons", keywords: ["power icons", "charging icon"], highlightID: SettingsTab.battery.highlightID(for: "Show power status icons")),
|
||||||
|
|
||||||
// Downloads
|
|
||||||
SettingsSearchEntry(tab: .downloads, title: "Show download progress", keywords: ["downloads", "progress"], highlightID: SettingsTab.downloads.highlightID(for: "Show download progress")),
|
|
||||||
SettingsSearchEntry(tab: .downloads, title: "Enable Safari Downloads", keywords: ["safari", "browser"], highlightID: SettingsTab.downloads.highlightID(for: "Enable Safari Downloads")),
|
|
||||||
SettingsSearchEntry(tab: .downloads, title: "Download indicator style", keywords: ["indicator", "style"], highlightID: SettingsTab.downloads.highlightID(for: "Download indicator style")),
|
|
||||||
SettingsSearchEntry(tab: .downloads, title: "Download icon style", keywords: ["icon", "style"], highlightID: SettingsTab.downloads.highlightID(for: "Download icon style")),
|
|
||||||
|
|
||||||
// HUDs
|
// HUDs
|
||||||
SettingsSearchEntry(tab: .hud, title: "Show Bluetooth device connections", keywords: ["bluetooth", "hud"], highlightID: SettingsTab.hud.highlightID(for: "Show Bluetooth device connections")),
|
SettingsSearchEntry(tab: .hud, title: "Show Bluetooth device connections", keywords: ["bluetooth", "hud"], highlightID: SettingsTab.hud.highlightID(for: "Show Bluetooth device connections")),
|
||||||
SettingsSearchEntry(tab: .hud, title: "Use circular battery indicator", keywords: ["battery", "circular"], highlightID: SettingsTab.hud.highlightID(for: "Use circular battery indicator")),
|
SettingsSearchEntry(tab: .hud, title: "Use circular battery indicator", keywords: ["battery", "circular"], highlightID: SettingsTab.hud.highlightID(for: "Use circular battery indicator")),
|
||||||
|
|
@ -714,8 +711,6 @@ struct SettingsView: View {
|
||||||
switch tab {
|
switch tab {
|
||||||
case .timer, .stats, .clipboard, .screenAssistant, .colorPicker, .shelf:
|
case .timer, .stats, .clipboard, .screenAssistant, .colorPicker, .shelf:
|
||||||
return !enableMinimalisticUI
|
return !enableMinimalisticUI
|
||||||
case .downloads:
|
|
||||||
return extensionManager.installedExtensions.contains { $0.bundleIdentifier == downloadManagerExtension }
|
|
||||||
default:
|
default:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -810,10 +805,6 @@ struct SettingsView: View {
|
||||||
SettingsForm(tab: .shortcuts) {
|
SettingsForm(tab: .shortcuts) {
|
||||||
Shortcuts()
|
Shortcuts()
|
||||||
}
|
}
|
||||||
case .extensions:
|
|
||||||
SettingsForm(tab: .extensions) {
|
|
||||||
Extensions()
|
|
||||||
}
|
|
||||||
case .about:
|
case .about:
|
||||||
if let controller = updaterController {
|
if let controller = updaterController {
|
||||||
SettingsForm(tab: .about) {
|
SettingsForm(tab: .about) {
|
||||||
|
|
@ -1150,6 +1141,8 @@ struct Downloads: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("Downloads")
|
.navigationTitle("Downloads")
|
||||||
|
.disabled(true)
|
||||||
|
.opacity(0.6)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1928,125 +1921,6 @@ struct Shelf: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Extensions: View {
|
|
||||||
@EnvironmentObject var extensionManager: DynamicIslandExtensionManager
|
|
||||||
@State private var effectTrigger: Bool = false
|
|
||||||
var body: some View {
|
|
||||||
Form {
|
|
||||||
//warningBadge("We don't support extensions yet") // Uhhhh You do? <><><> Oori.S
|
|
||||||
Section {
|
|
||||||
List {
|
|
||||||
ForEach(extensionManager.installedExtensions.indices, id: \.self) { index in
|
|
||||||
let item = extensionManager.installedExtensions[index]
|
|
||||||
HStack {
|
|
||||||
AppIcon(for: item.bundleIdentifier)
|
|
||||||
.resizable()
|
|
||||||
.frame(width: 24, height: 24)
|
|
||||||
Text(item.name)
|
|
||||||
ListItemPopover {
|
|
||||||
Text("Description")
|
|
||||||
}
|
|
||||||
Spacer(minLength: 0)
|
|
||||||
HStack(spacing: 6) {
|
|
||||||
Circle()
|
|
||||||
.frame(width: 6, height: 6)
|
|
||||||
.foregroundColor(isExtensionRunning(item.bundleIdentifier) ? .green : item.status == .disabled ? .gray : .red)
|
|
||||||
.conditionalModifier(isExtensionRunning(item.bundleIdentifier)) { view in
|
|
||||||
view
|
|
||||||
.shadow(color: .green, radius: 3)
|
|
||||||
}
|
|
||||||
Text(isExtensionRunning(item.bundleIdentifier) ? "Running" : item.status == .disabled ? "Disabled" : "Stopped")
|
|
||||||
.contentTransition(.numericText())
|
|
||||||
.foregroundStyle(.secondary)
|
|
||||||
.font(.footnote)
|
|
||||||
}
|
|
||||||
.frame(width: 60, alignment: .leading)
|
|
||||||
|
|
||||||
Menu(content: {
|
|
||||||
Button("Restart") {
|
|
||||||
let ws = NSWorkspace.shared
|
|
||||||
|
|
||||||
if let ext = ws.runningApplications.first(where: { $0.bundleIdentifier == item.bundleIdentifier }) {
|
|
||||||
ext.terminate()
|
|
||||||
}
|
|
||||||
|
|
||||||
if let appURL = ws.urlForApplication(withBundleIdentifier: item.bundleIdentifier) {
|
|
||||||
ws.openApplication(at: appURL, configuration: .init(), completionHandler: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.keyboardShortcut("R", modifiers: .command)
|
|
||||||
Button("Disable") {
|
|
||||||
if let ext = NSWorkspace.shared.runningApplications.first(where: { $0.bundleIdentifier == item.bundleIdentifier }) {
|
|
||||||
ext.terminate()
|
|
||||||
}
|
|
||||||
extensionManager.installedExtensions[index].status = .disabled
|
|
||||||
}
|
|
||||||
.keyboardShortcut("D", modifiers: .command)
|
|
||||||
Divider()
|
|
||||||
Button("Uninstall", role: .destructive) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}, label: {
|
|
||||||
Image(systemName: "ellipsis.circle")
|
|
||||||
.foregroundStyle(.secondary)
|
|
||||||
})
|
|
||||||
.controlSize(.regular)
|
|
||||||
}
|
|
||||||
.buttonStyle(PlainButtonStyle())
|
|
||||||
.padding(.vertical, 5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.frame(minHeight: 120)
|
|
||||||
.actionBar {
|
|
||||||
Button {} label: {
|
|
||||||
HStack(spacing: 3) {
|
|
||||||
Image(systemName: "plus")
|
|
||||||
Text("Add manually")
|
|
||||||
}
|
|
||||||
.foregroundStyle(.secondary)
|
|
||||||
}
|
|
||||||
.disabled(true)
|
|
||||||
Spacer()
|
|
||||||
Button {
|
|
||||||
withAnimation(.linear(duration: 1)) {
|
|
||||||
effectTrigger.toggle()
|
|
||||||
} completion: {
|
|
||||||
effectTrigger.toggle()
|
|
||||||
}
|
|
||||||
extensionManager.checkIfExtensionsAreInstalled()
|
|
||||||
} label: {
|
|
||||||
HStack(spacing: 3) {
|
|
||||||
Image(systemName: "arrow.triangle.2.circlepath")
|
|
||||||
.rotationEffect(effectTrigger ? .degrees(360) : .zero)
|
|
||||||
}
|
|
||||||
.foregroundStyle(.secondary)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.controlSize(.small)
|
|
||||||
.buttonStyle(PlainButtonStyle())
|
|
||||||
.overlay {
|
|
||||||
if extensionManager.installedExtensions.isEmpty {
|
|
||||||
Text("No extension installed")
|
|
||||||
.foregroundStyle(Color(.secondaryLabelColor))
|
|
||||||
.padding(.bottom, 22)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} header: {
|
|
||||||
HStack(spacing: 0) {
|
|
||||||
Text("Installed extensions")
|
|
||||||
if !extensionManager.installedExtensions.isEmpty {
|
|
||||||
Text(" – \(extensionManager.installedExtensions.count)")
|
|
||||||
.foregroundStyle(.secondary)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.navigationTitle("Extensions")
|
|
||||||
// TipsView()
|
|
||||||
// .padding(.horizontal, 19)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LiveActivitiesSettings: View {
|
struct LiveActivitiesSettings: View {
|
||||||
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
|
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
|
||||||
@ObservedObject var recordingManager = ScreenRecordingManager.shared
|
@ObservedObject var recordingManager = ScreenRecordingManager.shared
|
||||||
|
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
//
|
|
||||||
// DynamicIslandExtensionManager.swift
|
|
||||||
// DynamicIsland
|
|
||||||
//
|
|
||||||
// Created by Harsh Vardhan Goswami on 04/08/24.
|
|
||||||
// DynamicIslandExtensionManager.swift
|
|
||||||
// DynamicIsland
|
|
||||||
//
|
|
||||||
// Created by Harsh Vardhan Goswami on 07/09/24.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
var clipboardExtension: String = "dynamicisland.TheDynamicClipboard"
|
|
||||||
var hudExtension: String = "dynamicisland.TheDynamicHUDs"
|
|
||||||
var downloadManagerExtension: String = "dynamicisland.TheDynamicDownloadManager"
|
|
||||||
|
|
||||||
struct Extension: Identifiable, Hashable {
|
|
||||||
var id = UUID()
|
|
||||||
var name: String
|
|
||||||
var bundleIdentifier: String
|
|
||||||
var status: StatusModel = .enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
enum StatusModel {
|
|
||||||
case disabled
|
|
||||||
case enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
class DynamicIslandExtensionManager: ObservableObject {
|
|
||||||
|
|
||||||
@Published var installedExtensions: [Extension] = [] {
|
|
||||||
didSet {
|
|
||||||
// Only log when there's an actual change in content, not just initialization
|
|
||||||
if oldValue != installedExtensions {
|
|
||||||
print("📦 Extensions installed: \(installedExtensions.map { $0.name })")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var extensions = [
|
|
||||||
clipboardExtension,
|
|
||||||
hudExtension
|
|
||||||
]
|
|
||||||
|
|
||||||
init() {
|
|
||||||
checkIfExtensionsAreInstalled()
|
|
||||||
|
|
||||||
DistributedNotificationCenter.default().addObserver(self, selector: #selector(checkIfExtensionsAreInstalled), name: NSNotification.Name("NSWorkspaceDidLaunchApplicationNotification"), object: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func checkIfExtensionsAreInstalled() {
|
|
||||||
installedExtensions = []
|
|
||||||
for extensionName in extensions {
|
|
||||||
if NSWorkspace.shared.urlForApplication(withBundleIdentifier: extensionName) != nil {
|
|
||||||
let ext = Extension(name: extensionName.components(separatedBy: ".").last ?? extensionName, bundleIdentifier: extensionName)
|
|
||||||
installedExtensions.append(ext)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue