mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +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" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"ar" : {
|
||||
"stringUnit" : {
|
||||
|
|
@ -6674,6 +6675,7 @@
|
|||
}
|
||||
},
|
||||
"Description" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"ar" : {
|
||||
"stringUnit" : {
|
||||
|
|
@ -6790,6 +6792,7 @@
|
|||
"isCommentAutoGenerated" : true
|
||||
},
|
||||
"Disable" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"ar" : {
|
||||
"stringUnit" : {
|
||||
|
|
@ -8581,6 +8584,7 @@
|
|||
"isCommentAutoGenerated" : true
|
||||
},
|
||||
"Extensions" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"ar" : {
|
||||
"stringUnit" : {
|
||||
|
|
@ -10537,6 +10541,7 @@
|
|||
}
|
||||
},
|
||||
"Installed extensions" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"ar" : {
|
||||
"stringUnit" : {
|
||||
|
|
@ -13893,6 +13898,7 @@
|
|||
}
|
||||
},
|
||||
"No extension installed" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"ar" : {
|
||||
"stringUnit" : {
|
||||
|
|
@ -15721,6 +15727,7 @@
|
|||
"isCommentAutoGenerated" : true
|
||||
},
|
||||
"Restart" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"ar" : {
|
||||
"stringUnit" : {
|
||||
|
|
@ -15863,6 +15870,7 @@
|
|||
}
|
||||
},
|
||||
"Running" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"ar" : {
|
||||
"stringUnit" : {
|
||||
|
|
@ -19150,6 +19158,7 @@
|
|||
}
|
||||
},
|
||||
"Uninstall" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"ar" : {
|
||||
"stringUnit" : {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
|||
case downloads
|
||||
case shelf
|
||||
case shortcuts
|
||||
case extensions
|
||||
case about
|
||||
|
||||
var id: String { rawValue }
|
||||
|
|
@ -58,7 +57,6 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
|||
case .downloads: return "Downloads"
|
||||
case .shelf: return "Shelf"
|
||||
case .shortcuts: return "Shortcuts"
|
||||
case .extensions: return "Extensions"
|
||||
case .about: return "About"
|
||||
}
|
||||
}
|
||||
|
|
@ -82,7 +80,6 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
|||
case .downloads: return "square.and.arrow.down"
|
||||
case .shelf: return "books.vertical"
|
||||
case .shortcuts: return "keyboard"
|
||||
case .extensions: return "puzzlepiece.extension"
|
||||
case .about: return "info.circle"
|
||||
}
|
||||
}
|
||||
|
|
@ -106,7 +103,6 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
|||
case .downloads: return .gray
|
||||
case .shelf: return .brown
|
||||
case .shortcuts: return .orange
|
||||
case .extensions: return .blue
|
||||
case .about: return .secondary
|
||||
}
|
||||
}
|
||||
|
|
@ -233,7 +229,6 @@ private struct SettingsForm<Content: View>: View {
|
|||
}
|
||||
|
||||
struct SettingsView: View {
|
||||
@StateObject var extensionManager = DynamicIslandExtensionManager()
|
||||
@State private var selectedTab: SettingsTab = .general
|
||||
@State private var searchText: String = ""
|
||||
@StateObject private var highlightCoordinator = SettingsHighlightCoordinator()
|
||||
|
|
@ -260,11 +255,13 @@ struct SettingsView: View {
|
|||
.padding(.horizontal, 12)
|
||||
|
||||
List(filteredTabs, selection: selectionBinding) { tab in
|
||||
let isComingSoon = tab == .downloads
|
||||
NavigationLink(value: tab) {
|
||||
HStack(spacing: 10) {
|
||||
sidebarIcon(for: tab)
|
||||
.opacity(isComingSoon ? 0.45 : 1)
|
||||
Text(tab.title)
|
||||
.foregroundStyle(Color.primary)
|
||||
.foregroundStyle(isComingSoon ? Color.secondary : Color.primary)
|
||||
if tab == .osd {
|
||||
Spacer()
|
||||
Text("ALPHA")
|
||||
|
|
@ -276,11 +273,15 @@ struct SettingsView: View {
|
|||
Capsule()
|
||||
.fill(Color.orange)
|
||||
)
|
||||
} else if isComingSoon {
|
||||
Spacer()
|
||||
comingSoonTag()
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
}
|
||||
.tag(tab)
|
||||
.disabled(isComingSoon)
|
||||
.listRowInsets(EdgeInsets(top: 4, leading: 12, bottom: 4, trailing: 10))
|
||||
}
|
||||
.listStyle(SidebarListStyle())
|
||||
|
|
@ -303,13 +304,12 @@ struct SettingsView: View {
|
|||
.opacity(0) // Invisible, but reserves space for a consistent look between tabs
|
||||
.disabled(true)
|
||||
}
|
||||
.environmentObject(extensionManager)
|
||||
.environmentObject(highlightCoordinator)
|
||||
.formStyle(.grouped)
|
||||
.frame(width: 700)
|
||||
.onChange(of: searchText) { _, newValue in
|
||||
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) {
|
||||
selectedTab = firstMatch
|
||||
}
|
||||
|
|
@ -347,7 +347,10 @@ struct SettingsView: View {
|
|||
private var selectionBinding: Binding<SettingsTab> {
|
||||
Binding(
|
||||
get: { resolvedSelection },
|
||||
set: { selectedTab = $0 }
|
||||
set: { newValue in
|
||||
guard newValue != .downloads else { return }
|
||||
selectedTab = newValue
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -382,7 +385,6 @@ struct SettingsView: View {
|
|||
.downloads,
|
||||
.shelf,
|
||||
.shortcuts,
|
||||
.extensions,
|
||||
.about
|
||||
]
|
||||
|
||||
|
|
@ -402,10 +404,11 @@ struct SettingsView: View {
|
|||
}
|
||||
|
||||
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) {
|
||||
guard suggestion.tab != .downloads else { return }
|
||||
highlightCoordinator.focus(on: suggestion)
|
||||
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 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
|
||||
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")),
|
||||
|
|
@ -714,8 +711,6 @@ struct SettingsView: View {
|
|||
switch tab {
|
||||
case .timer, .stats, .clipboard, .screenAssistant, .colorPicker, .shelf:
|
||||
return !enableMinimalisticUI
|
||||
case .downloads:
|
||||
return extensionManager.installedExtensions.contains { $0.bundleIdentifier == downloadManagerExtension }
|
||||
default:
|
||||
return true
|
||||
}
|
||||
|
|
@ -810,10 +805,6 @@ struct SettingsView: View {
|
|||
SettingsForm(tab: .shortcuts) {
|
||||
Shortcuts()
|
||||
}
|
||||
case .extensions:
|
||||
SettingsForm(tab: .extensions) {
|
||||
Extensions()
|
||||
}
|
||||
case .about:
|
||||
if let controller = updaterController {
|
||||
SettingsForm(tab: .about) {
|
||||
|
|
@ -1150,6 +1141,8 @@ struct Downloads: View {
|
|||
}
|
||||
}
|
||||
.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 {
|
||||
@ObservedObject var coordinator = DynamicIslandViewCoordinator.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