mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 08:29:07 +00:00
v3.2.0
This commit is contained in:
@@ -152,7 +152,7 @@ struct AboutSettingsTab: View {
|
||||
Text("Made with ❤️ by Alin Lupascu (dev@itsalin.com)").font(.footnote).padding(.bottom)
|
||||
}
|
||||
.padding(20)
|
||||
.frame(width: 500, height: 650)
|
||||
.frame(width: 500, height: 600)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,32 +35,11 @@ struct GeneralSettingsTab: View {
|
||||
VStack {
|
||||
|
||||
HStack() {
|
||||
Text("Appearance").font(.title2)
|
||||
Text("Functionality").font(.title2)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: glass ? "cube.transparent" : "cube.transparent.fill")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(glass ? "Transparent material enabled" : "Transparent material disabled")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
// InfoButton(text: "When transparent material is enabled, sticky section headers (User/System) in app list are disabled to keep from showing app name text overlayed under the section header text with no background to separate the two.", color: nil)
|
||||
Spacer()
|
||||
Toggle(isOn: $glass, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: instantSearch ? "bolt" : "bolt.slash")
|
||||
@@ -110,146 +89,6 @@ struct GeneralSettingsTab: View {
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: displayMode.colorScheme == .dark ? "moon.fill" : "sun.max.fill")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("Set application color mode")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
Spacer()
|
||||
Picker("", selection: $selectedTheme) {
|
||||
ForEach(themes, id: \.self) { theme in
|
||||
Text(theme)
|
||||
}
|
||||
}
|
||||
.pickerStyle(SegmentedPickerStyle())
|
||||
.frame(width: 200)
|
||||
.onChange(of: selectedTheme) { newTheme in
|
||||
switch newTheme {
|
||||
case "Auto":
|
||||
displayMode.colorScheme = nil
|
||||
if isDarkModeEnabled() {
|
||||
displayMode.colorScheme = .dark
|
||||
} else {
|
||||
displayMode.colorScheme = .light
|
||||
}
|
||||
case "Dark":
|
||||
displayMode.colorScheme = .dark
|
||||
case "Light":
|
||||
displayMode.colorScheme = .light
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
// === Mini =================================================================================================
|
||||
|
||||
Divider()
|
||||
.padding()
|
||||
|
||||
|
||||
|
||||
HStack() {
|
||||
Text("Mini Configuration").font(.title2)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: mini ? "square.resize.up" : "square.resize.down")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(mini ? "Mini window mode selected" : "Full size window mode selected")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
Spacer()
|
||||
Toggle(isOn: $mini, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
.onChange(of: mini) { newVal in
|
||||
if mini {
|
||||
appState.currentView = miniView ? .apps : .empty
|
||||
showPopover = false
|
||||
resizeWindowAuto(windowSettings: windowSettings)
|
||||
} else {
|
||||
resizeWindowAuto(windowSettings: windowSettings)
|
||||
if appState.appInfo.appName.isEmpty {
|
||||
appState.currentView = .empty
|
||||
} else {
|
||||
appState.currentView = .files
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: miniView ? "square.grid.3x3.square" : "plus.square.dashed")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(miniView ? "Show apps list on startup" : "Show drop target on startup")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
|
||||
InfoButton(text: "In mini window mode, you can have Pearcleaner startup to the Apps List view or the Drop Target view.", color: nil, label: "")
|
||||
|
||||
Spacer()
|
||||
Toggle(isOn: $miniView, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
.onChange(of: miniView) { newVal in
|
||||
appState.currentView = newVal ? .apps : .empty
|
||||
}
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: popoverStay ? "pin" : "pin.slash")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(popoverStay ? "Popover window will stay on top" : "Popover window will not stay on top")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
|
||||
InfoButton(text: "In mini window mode, if you pin the Files popover on top, clicking away from the window will not dismiss it. Otherwise, it will dismiss by clicking anywhere outside the popover.", color: nil, label: "")
|
||||
|
||||
Spacer()
|
||||
Toggle(isOn: $popoverStay, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
// === Perms ================================================================================================
|
||||
|
||||
|
||||
@@ -369,7 +208,7 @@ struct GeneralSettingsTab: View {
|
||||
|
||||
}
|
||||
.padding(20)
|
||||
.frame(width: 500, height: 690)
|
||||
.frame(width: 500, height: 420)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,396 @@
|
||||
//
|
||||
// Interface.swift
|
||||
// Pearcleaner
|
||||
//
|
||||
// Created by Alin Lupascu on 3/18/24.
|
||||
//
|
||||
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import ServiceManagement
|
||||
|
||||
struct InterfaceSettingsTab: View {
|
||||
@EnvironmentObject var appState: AppState
|
||||
@EnvironmentObject var locations: Locations
|
||||
@State private var windowSettings = WindowSettings()
|
||||
@AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false
|
||||
// @AppStorage("settings.dock.enabled") private var dockEnabled: Bool = false
|
||||
@AppStorage("settings.general.mini") private var mini: Bool = false
|
||||
@AppStorage("displayMode") var displayMode: DisplayMode = .system
|
||||
@AppStorage("settings.general.glass") private var glass: Bool = true
|
||||
@AppStorage("settings.general.dark") var isDark: Bool = true
|
||||
@AppStorage("settings.general.popover") private var popoverStay: Bool = true
|
||||
@AppStorage("settings.general.miniview") private var miniView: Bool = true
|
||||
@AppStorage("settings.general.selectedTheme") var selectedTheme: String = "Auto"
|
||||
@AppStorage("settings.interface.selectedMenubarIcon") var selectedMenubarIcon: String = "pear-4"
|
||||
private let themes = ["Auto", "Dark", "Light"]
|
||||
@State private var isLaunchAtLoginEnabled: Bool = false
|
||||
let icons = ["externaldrive", "trash", "folder", "pear-1", "pear-1.5", "pear-2", "pear-3", "pear-4"]
|
||||
|
||||
@Binding var showPopover: Bool
|
||||
@Binding var search: String
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
VStack {
|
||||
|
||||
HStack() {
|
||||
Text("Appearance").font(.title2)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: glass ? "cube.transparent" : "cube.transparent.fill")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(glass ? "Transparent material enabled" : "Transparent material disabled")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
Spacer()
|
||||
Toggle(isOn: $glass, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: displayMode.colorScheme == .dark ? "moon.fill" : "sun.max.fill")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("Application color mode")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
Spacer()
|
||||
Picker("", selection: $selectedTheme) {
|
||||
ForEach(themes, id: \.self) { theme in
|
||||
Text(theme)
|
||||
}
|
||||
}
|
||||
.pickerStyle(SegmentedPickerStyle())
|
||||
.frame(width: 200)
|
||||
.onChange(of: selectedTheme) { newTheme in
|
||||
switch newTheme {
|
||||
case "Auto":
|
||||
displayMode.colorScheme = nil
|
||||
if isDarkModeEnabled() {
|
||||
displayMode.colorScheme = .dark
|
||||
} else {
|
||||
displayMode.colorScheme = .light
|
||||
}
|
||||
case "Dark":
|
||||
displayMode.colorScheme = .dark
|
||||
case "Light":
|
||||
displayMode.colorScheme = .light
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
|
||||
// === Mini =================================================================================================
|
||||
|
||||
Divider()
|
||||
.padding()
|
||||
|
||||
|
||||
|
||||
HStack() {
|
||||
Text("Mini Configuration").font(.title2)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: mini ? "square.resize.up" : "square.resize.down")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(mini ? "Mini window mode" : "Full size window mode")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
Spacer()
|
||||
Toggle(isOn: $mini, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
.onChange(of: mini) { newVal in
|
||||
if mini {
|
||||
appState.currentView = miniView ? .apps : .empty
|
||||
showPopover = false
|
||||
resizeWindowAuto(windowSettings: windowSettings)
|
||||
} else {
|
||||
resizeWindowAuto(windowSettings: windowSettings)
|
||||
if appState.appInfo.appName.isEmpty {
|
||||
appState.currentView = .empty
|
||||
} else {
|
||||
appState.currentView = .files
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: miniView ? "square.grid.3x3.square" : "plus.square.dashed")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(miniView ? "Show apps list on startup" : "Show drop target on startup")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
|
||||
InfoButton(text: "In mini window mode, you can have Pearcleaner startup to the Apps List view or the Drop Target view.", color: nil, label: "")
|
||||
|
||||
Spacer()
|
||||
Toggle(isOn: $miniView, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
.onChange(of: miniView) { newVal in
|
||||
appState.currentView = newVal ? .apps : .empty
|
||||
}
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: popoverStay ? "pin" : "pin.slash")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(popoverStay ? "Popover window will stay on top" : "Popover window will not stay on top")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
|
||||
InfoButton(text: "In mini window mode, if you pin the Files popover on top, clicking away from the window will not dismiss it. Otherwise, it will dismiss by clicking anywhere outside the popover.", color: nil, label: "")
|
||||
|
||||
Spacer()
|
||||
Toggle(isOn: $popoverStay, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
// === MenuBar===============================================================================================
|
||||
|
||||
Divider()
|
||||
.padding()
|
||||
|
||||
HStack() {
|
||||
Text("Menubar").font(.title2)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: "menubar.rectangle")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(menubarEnabled ? "Menubar icon enabled" : "Menubar icon disabled")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
InfoButton(text: "When menubar icon is enabled, the main app window and dock icon will be hidden. You can still pop-out the main app window from the menubar icon temporarily if you'd like.", color: nil, label: "")
|
||||
Spacer()
|
||||
Toggle(isOn: $menubarEnabled, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
.onChange(of: menubarEnabled) { newVal in
|
||||
if newVal {
|
||||
MenuBarExtraManager.shared.addMenuBarExtra(withView: {
|
||||
MenuBarMiniAppView(search: $search, showPopover: $showPopover)
|
||||
.environmentObject(locations)
|
||||
.environmentObject(appState)
|
||||
}, icon: selectedMenubarIcon)
|
||||
NSApplication.shared.setActivationPolicy(.accessory)
|
||||
findAndShowWindows(named: ["Pearcleaner", "Interface"])
|
||||
} else {
|
||||
MenuBarExtraManager.shared.removeMenuBarExtra()
|
||||
// dockEnabled = true
|
||||
NSApplication.shared.setActivationPolicy(.regular)
|
||||
if !hasWindowOpen() {
|
||||
if mini {
|
||||
windowSettings.newWindow {
|
||||
MiniMode(search: $search, showPopover: $showPopover)
|
||||
.environmentObject(locations)
|
||||
.environmentObject(appState)
|
||||
}
|
||||
} else {
|
||||
windowSettings.newWindow {
|
||||
RegularMode(search: $search, showPopover: $showPopover)
|
||||
.environmentObject(locations)
|
||||
.environmentObject(appState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: isLaunchAtLoginEnabled ? "person" : "person.slash")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(isLaunchAtLoginEnabled ? "Launch at login enabled" : "Launch at login disabled")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
InfoButton(text: "This setting will affect Pearcleaner whether you're running in menubar mode or regular mode. If you disable menubar icon, you might want to disable this as well so Pearcleaner doesn't start on login.", color: nil, label: "")
|
||||
Spacer()
|
||||
Toggle(isOn: $isLaunchAtLoginEnabled, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
.onAppear {
|
||||
isLaunchAtLoginEnabled = SMAppService.mainApp.status == .enabled
|
||||
}
|
||||
.onChange(of: isLaunchAtLoginEnabled) { newValue in
|
||||
do {
|
||||
if newValue {
|
||||
if SMAppService.mainApp.status == .enabled {
|
||||
try? SMAppService.mainApp.unregister()
|
||||
}
|
||||
|
||||
try SMAppService.mainApp.register()
|
||||
} else {
|
||||
try SMAppService.mainApp.unregister()
|
||||
}
|
||||
} catch {
|
||||
printOS("Failed to \(newValue ? "enable" : "disable") launch at login: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: "paintbrush")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("Menubar icon")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
Spacer()
|
||||
Picker("", selection: $selectedMenubarIcon) {
|
||||
ForEach(icons, id: \.self) { icon in
|
||||
HStack {
|
||||
if icon.contains("pear") {
|
||||
Image(icon)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
} else {
|
||||
Image(systemName: icon)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
}
|
||||
}
|
||||
.tag(icon)
|
||||
|
||||
}
|
||||
}
|
||||
.frame(width: 60)
|
||||
.onChange(of: selectedMenubarIcon) { newValue in
|
||||
MenuBarExtraManager.shared.swapMenuBarIcon(icon: newValue)
|
||||
}
|
||||
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
// HStack(spacing: 0) {
|
||||
// Image(systemName: "dock.rectangle")
|
||||
// .resizable()
|
||||
// .scaledToFit()
|
||||
// .frame(width: 20, height: 20)
|
||||
// .padding(.trailing)
|
||||
// .foregroundStyle(.gray)
|
||||
// VStack(alignment: .leading, spacing: 5) {
|
||||
// Text("\(dockEnabled ? "Show dock icon" : "Hide dock icon")")
|
||||
// .font(.callout)
|
||||
// .foregroundStyle(.gray)
|
||||
// }
|
||||
// InfoButton(text: "This setting only affects Pearcleaner when the menubar icon is enabled, otherwise the dock icon will always show", color: nil, label: "")
|
||||
// Spacer()
|
||||
// Toggle(isOn: $dockEnabled, label: {
|
||||
// })
|
||||
// .toggleStyle(.switch)
|
||||
// .onChange(of: dockEnabled) { newValue in
|
||||
// if newValue {
|
||||
// NSApplication.shared.setActivationPolicy(.regular)
|
||||
// } else {
|
||||
// if menubarEnabled {
|
||||
// NSApplication.shared.setActivationPolicy(.accessory)
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// .padding(5)
|
||||
// .padding(.leading)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
||||
}
|
||||
.padding(20)
|
||||
.frame(width: 500, height: 520)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
//
|
||||
// MenuBar.swift
|
||||
// Pearcleaner
|
||||
//
|
||||
// Created by Alin Lupascu on 3/16/24.
|
||||
//
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import ServiceManagement
|
||||
|
||||
struct MenuBarSettingsTab: View {
|
||||
@EnvironmentObject var appState: AppState
|
||||
@EnvironmentObject var locations: Locations
|
||||
@AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false
|
||||
@State private var isLaunchAtLoginEnabled: Bool = false
|
||||
|
||||
@Binding var showPopover: Bool
|
||||
@Binding var search: String
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
VStack {
|
||||
|
||||
HStack() {
|
||||
Text("Configuration").font(.title2)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: "menubar.rectangle")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(menubarEnabled ? "Menubar icon enabled" : "Menubar icon disabled")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
Spacer()
|
||||
Toggle(isOn: $menubarEnabled, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
.onChange(of: menubarEnabled) { newVal in
|
||||
if newVal {
|
||||
MenuBarExtraManager.shared.addMenuBarExtra {
|
||||
MenuBarMiniAppView(search: $search, showPopover: $showPopover)
|
||||
.environmentObject(locations)
|
||||
.environmentObject(appState)
|
||||
}
|
||||
} else {
|
||||
MenuBarExtraManager.shared.removeMenuBarExtra()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: isLaunchAtLoginEnabled ? "person.crop.circle.badge.checkmark" : "person.crop.circle")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(isLaunchAtLoginEnabled ? "Launch at login enabled" : "Launch at login disabled")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
Spacer()
|
||||
Toggle(isOn: $isLaunchAtLoginEnabled, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
.onAppear {
|
||||
isLaunchAtLoginEnabled = SMAppService.mainApp.status == .enabled
|
||||
}
|
||||
.onChange(of: isLaunchAtLoginEnabled) { newValue in
|
||||
do {
|
||||
if newValue {
|
||||
if SMAppService.mainApp.status == .enabled {
|
||||
try? SMAppService.mainApp.unregister()
|
||||
}
|
||||
|
||||
try SMAppService.mainApp.register()
|
||||
} else {
|
||||
try SMAppService.mainApp.unregister()
|
||||
}
|
||||
} catch {
|
||||
printOS("Failed to \(newValue ? "enable" : "disable") launch at login: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
||||
}
|
||||
.padding(20)
|
||||
.frame(width: 500, height: 690)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,11 +23,11 @@ struct SettingsView: View {
|
||||
}
|
||||
.tag(CurrentTabView.general)
|
||||
|
||||
MenuBarSettingsTab(showPopover: $showPopover, search: $search)
|
||||
InterfaceSettingsTab(showPopover: $showPopover, search: $search)
|
||||
.tabItem {
|
||||
Label(CurrentTabView.menubar.title, systemImage: "menubar.rectangle")
|
||||
Label(CurrentTabView.interface.title, systemImage: "macwindow")
|
||||
}
|
||||
.tag(CurrentTabView.menubar)
|
||||
.tag(CurrentTabView.interface)
|
||||
|
||||
UpdateSettingsTab(showFeature: $showFeature)
|
||||
.tabItem {
|
||||
|
||||
@@ -107,7 +107,7 @@ struct UpdateSettingsTab: View {
|
||||
|
||||
}
|
||||
.padding(20)
|
||||
.frame(width: 500, height: 650)
|
||||
.frame(width: 500, height: 520)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user