import AppKit import SwiftUI import MacToolsPluginKit struct MenuBarHiddenSettingsView: View { @ObservedObject var controller: MenuBarHiddenController private var localization: PluginLocalization { controller.localization } var body: some View { VStack(alignment: .leading, spacing: PluginSettingsTheme.Spacing.section) { behaviorSection layoutSection } .frame(maxWidth: .infinity, alignment: .leading) .onAppear { controller.setSettingsVisible(true) } .onDisappear { controller.setSettingsVisible(false) } } // MARK: - Behavior private var behaviorSection: some View { VStack(alignment: .leading, spacing: PluginSettingsTheme.Spacing.sectionHeaderContent) { sectionHeader( title: localization.string("settings.behavior.title", defaultValue: "行为"), icon: "switch.2" ) VStack(spacing: 0) { toggleRow( title: localization.string("settings.hideIcons.title", defaultValue: "隐藏菜单栏图标"), description: localization.string( "settings.hideIcons.description", defaultValue: "开启后状态栏图标右侧的扩展条会隐藏其左侧的所有图标" ), isOn: Binding( get: { controller.isEnabled }, set: { controller.isEnabled = $0 } ) ) Divider() .padding(.leading, PluginSettingsTheme.Spacing.rowHorizontal) toggleRow( title: localization.string("settings.showInPanel.title", defaultValue: "面板中显示隐藏图标"), description: localization.string( "settings.showInPanel.description", defaultValue: "开启后左键菜单面板显示隐藏图标卡片" ), isOn: Binding( get: { controller.showsHiddenIconsInPanel }, set: { controller.showsHiddenIconsInPanel = $0 } ), isEnabled: controller.permissions.canManageItems ) Divider() .padding(.leading, PluginSettingsTheme.Spacing.rowHorizontal) toggleRow( title: localization.string("settings.alwaysHidden.title", defaultValue: "永久隐藏"), description: localization.string( "settings.alwaysHidden.description", defaultValue: "开启后可将图标放入永久隐藏栏,隐藏开关关闭时也不会显示" ), isOn: Binding( get: { controller.isAlwaysHiddenEnabled }, set: { controller.isAlwaysHiddenEnabled = $0 } ), isEnabled: controller.permissions.canManageItems ) } .pluginSettingsCardBackground(.host) } } // MARK: - Layout strip private var layoutSection: some View { let authorized = controller.permissions.canManageItems return VStack(alignment: .leading, spacing: PluginSettingsTheme.Spacing.sectionHeaderContent) { HStack(spacing: 8) { sectionHeader( title: localization.string("settings.layout.title", defaultValue: "菜单栏布局"), icon: "rectangle.split.2x1" ) if !authorized { Label( localization.string("settings.layout.authorizationRequired", defaultValue: "需要授权"), systemImage: "lock.fill" ) .font(PluginSettingsTheme.Typography.statusBadge) .foregroundStyle(.secondary) .padding(.horizontal, 6) .padding(.vertical, 2) .background(Capsule().fill(Color.primary.opacity(0.07))) } } VStack(alignment: .leading, spacing: 12) { stripRow( title: MenuBarHiddenSection.visible.title(localization: localization), section: .visible, items: authorized ? controller.snapshot.visibleItems : [] ) stripRow( title: MenuBarHiddenSection.hidden.title(localization: localization), section: .hidden, items: authorized ? controller.snapshot.hiddenItems : [] ) if controller.isAlwaysHiddenEnabled { stripRow( title: MenuBarHiddenSection.alwaysHidden.title(localization: localization), section: .alwaysHidden, items: authorized ? controller.snapshot.alwaysHiddenItems : [] ) } } .padding(PluginSettingsTheme.Spacing.cardContent) .pluginSettingsCardBackground(.host) .opacity(authorized ? 1 : 0.4) .allowsHitTesting(authorized) } } // MARK: - Rows private func stripRow(title: String, section: MenuBarHiddenSection, items: [MenuBarItem]) -> some View { VStack(alignment: .leading, spacing: 8) { HStack { Text(title) .font(PluginSettingsTheme.Typography.emphasizedRowTitle) Text("\(items.count)") .font(PluginSettingsTheme.Typography.statusBadge) .foregroundStyle(.secondary) .padding(.horizontal, 6) .padding(.vertical, 2) .background(Capsule().fill(Color.primary.opacity(0.08))) } Group { ZStack { MenuBarHiddenLayoutStripRow( section: section, items: items, iconCache: controller.manager.iconCache, controller: controller ) if items.isEmpty { Text( controller.permissions.canManageItems ? localization.string( "settings.layout.emptyDropTarget", defaultValue: "拖入菜单栏图标到此区域" ) : "-" ) .font(PluginSettingsTheme.Typography.rowDescription) .foregroundStyle(.secondary) .allowsHitTesting(false) } } } .frame(maxWidth: .infinity, minHeight: 48) .background( RoundedRectangle(cornerRadius: 12, style: .continuous) .fill(Color(nsColor: .menuBarHiddenDefaultLayoutBar)) ) .contentShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) } } private func toggleRow( title: String, description: String, isOn: Binding, isEnabled: Bool = true ) -> some View { HStack(spacing: PluginSettingsTheme.Spacing.rowContentControl) { VStack(alignment: .leading, spacing: PluginSettingsTheme.Spacing.rowTitleDescription) { Text(title) .font(PluginSettingsTheme.Typography.emphasizedRowTitle) Text(description) .font(PluginSettingsTheme.Typography.rowDescription) .foregroundStyle(.secondary) } Spacer() Toggle("", isOn: isOn).toggleStyle(.switch).labelsHidden() .disabled(!isEnabled) } .pluginSettingsListRowPadding(interactive: true) .opacity(isEnabled ? 1 : 0.45) } private func sectionHeader(title: String, icon: String) -> some View { Label(title, systemImage: icon) .font(PluginSettingsTheme.Typography.sectionTitle) .foregroundStyle(.secondary) } } private struct MenuBarHiddenLayoutStripRow: View { let section: MenuBarHiddenSection let items: [MenuBarItem] let iconCache: MenuBarHiddenIconCache let controller: MenuBarHiddenController @State private var height: CGFloat = 48 var body: some View { MenuBarHiddenLayoutStrip( section: section, items: items, iconCache: iconCache, controller: controller, measuredHeight: $height ) .frame(maxWidth: .infinity, minHeight: height, idealHeight: height) .fixedSize(horizontal: false, vertical: true) } } private extension NSColor { static var menuBarHiddenDefaultLayoutBar: NSColor { NSColor(name: nil) { appearance in if appearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua { return NSColor.white.withAlphaComponent(0.10) } return NSColor(srgbRed: 0.38, green: 0.39, blue: 0.35, alpha: 1) } } }