mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Working a bit
This commit is contained in:
parent
8b9ade25c2
commit
1f0eea3cc6
8 changed files with 881 additions and 91 deletions
182
DynamicIsland/components/OSD/CustomOSDView.swift
Normal file
182
DynamicIsland/components/OSD/CustomOSDView.swift
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
#if os(macOS)
|
||||
import SwiftUI
|
||||
import Defaults
|
||||
|
||||
/// Custom OSD panel that mimics macOS native OSD appearance
|
||||
/// Supports volume, brightness, and keyboard backlight displays
|
||||
struct CustomOSDView: View {
|
||||
@Binding var type: SneakContentType
|
||||
@Binding var value: CGFloat
|
||||
@Binding var icon: String
|
||||
|
||||
@Default(.osdMaterial) var osdMaterial
|
||||
@Default(.osdIconColorStyle) var osdIconColorStyle
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
private let iconSize: CGFloat = 56
|
||||
private let progressBarHeight: CGFloat = 6
|
||||
private let spacing: CGFloat = 20
|
||||
private let segmentCount: Int = 16
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: spacing) {
|
||||
// Icon
|
||||
Image(systemName: symbolName)
|
||||
.font(.system(size: iconSize, weight: .regular))
|
||||
.foregroundStyle(iconColor)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
|
||||
// Progress/Value Indicator
|
||||
progressView
|
||||
.frame(width: 140)
|
||||
}
|
||||
.frame(width: 200, height: 200)
|
||||
.background(
|
||||
backgroundView
|
||||
.clipShape(RoundedRectangle(cornerRadius: 18, style: .continuous))
|
||||
)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 18, style: .continuous))
|
||||
.shadow(color: Color.black.opacity(0.25), radius: 24, x: 0, y: 8)
|
||||
}
|
||||
|
||||
// MARK: - Symbol Logic
|
||||
|
||||
private var symbolName: String {
|
||||
if !icon.isEmpty {
|
||||
return icon
|
||||
}
|
||||
|
||||
switch type {
|
||||
case .volume:
|
||||
if value < 0.01 {
|
||||
return "speaker.slash.fill"
|
||||
} else if value < 0.33 {
|
||||
return "speaker.fill"
|
||||
} else if value < 0.66 {
|
||||
return "speaker.wave.1.fill"
|
||||
} else {
|
||||
return "speaker.wave.3.fill"
|
||||
}
|
||||
|
||||
case .brightness:
|
||||
return "sun.max.fill"
|
||||
|
||||
case .backlight:
|
||||
return value >= 0.5 ? "light.max" : "light.min"
|
||||
|
||||
default:
|
||||
return "questionmark"
|
||||
}
|
||||
}
|
||||
|
||||
private var iconColor: Color {
|
||||
switch osdIconColorStyle {
|
||||
case .white:
|
||||
return .white
|
||||
case .whiteTransparent:
|
||||
return .white.opacity(0.85)
|
||||
case .lightGray:
|
||||
return Color(white: 0.85)
|
||||
case .darkGray:
|
||||
return Color(white: 0.3)
|
||||
case .black:
|
||||
return .black
|
||||
case .blackTransparent:
|
||||
return .black.opacity(0.85)
|
||||
case .auto:
|
||||
return colorScheme == .dark ? .white : .black
|
||||
case .autoTransparent:
|
||||
return colorScheme == .dark ? .white.opacity(0.85) : .black.opacity(0.85)
|
||||
}
|
||||
}
|
||||
|
||||
private var textColor: Color {
|
||||
switch osdIconColorStyle {
|
||||
case .white, .whiteTransparent, .lightGray:
|
||||
return .white
|
||||
case .darkGray, .black, .blackTransparent:
|
||||
return .black
|
||||
case .auto, .autoTransparent:
|
||||
return colorScheme == .dark ? .white : .black
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Progress View
|
||||
|
||||
private var progressView: some View {
|
||||
HStack(spacing: 3) {
|
||||
ForEach(0..<segmentCount, id: \.self) { index in
|
||||
Capsule()
|
||||
.fill(index < Int(value * CGFloat(segmentCount)) ? iconColor : inactiveSegmentColor)
|
||||
.frame(width: 6, height: progressBarHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var inactiveSegmentColor: Color {
|
||||
switch osdIconColorStyle {
|
||||
case .white, .whiteTransparent, .lightGray:
|
||||
return Color.white.opacity(0.25)
|
||||
case .darkGray, .black, .blackTransparent:
|
||||
return Color.black.opacity(0.25)
|
||||
case .auto, .autoTransparent:
|
||||
return colorScheme == .dark ? Color.white.opacity(0.25) : Color.black.opacity(0.25)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Background
|
||||
|
||||
@ViewBuilder
|
||||
private var backgroundView: some View {
|
||||
switch osdMaterial {
|
||||
case .frosted:
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.fill(.ultraThinMaterial)
|
||||
case .liquid:
|
||||
if #available(macOS 26.0, *) {
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.glassEffect(
|
||||
.clear.interactive(),
|
||||
in: .rect(cornerRadius: 18)
|
||||
)
|
||||
} else {
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.fill(.ultraThinMaterial)
|
||||
}
|
||||
case .solidDark:
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.fill(Color.black.opacity(0.85))
|
||||
case .solidLight:
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.fill(Color.white.opacity(0.85))
|
||||
case .solidAuto:
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.fill((colorScheme == .dark ? Color.black : Color.white).opacity(0.85))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - OSD Material Enum
|
||||
|
||||
enum OSDMaterial: String, CaseIterable, Defaults.Serializable {
|
||||
case frosted = "Frosted Glass"
|
||||
case liquid = "Liquid Glass"
|
||||
case solidDark = "Solid Dark"
|
||||
case solidLight = "Solid Light"
|
||||
case solidAuto = "Solid Auto"
|
||||
}
|
||||
|
||||
// MARK: - OSD Icon Color Style Enum
|
||||
|
||||
enum OSDIconColorStyle: String, CaseIterable, Defaults.Serializable {
|
||||
case white = "White"
|
||||
case whiteTransparent = "White (Transparent)"
|
||||
case lightGray = "Light Gray"
|
||||
case darkGray = "Dark Gray"
|
||||
case black = "Black"
|
||||
case blackTransparent = "Black (Transparent)"
|
||||
case auto = "Auto"
|
||||
case autoTransparent = "Auto (Transparent)"
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -24,6 +24,7 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
|||
case timer
|
||||
case calendar
|
||||
case hud
|
||||
case osd
|
||||
case battery
|
||||
case stats
|
||||
case clipboard
|
||||
|
|
@ -46,6 +47,7 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
|||
case .timer: return "Timer"
|
||||
case .calendar: return "Calendar"
|
||||
case .hud: return "HUDs"
|
||||
case .osd: return "Custom OSD"
|
||||
case .battery: return "Battery"
|
||||
case .stats: return "Stats"
|
||||
case .clipboard: return "Clipboard"
|
||||
|
|
@ -68,6 +70,7 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
|||
case .timer: return "timer"
|
||||
case .calendar: return "calendar"
|
||||
case .hud: return "dial.medium.fill"
|
||||
case .osd: return "square.fill.on.square.fill"
|
||||
case .battery: return "battery.100.bolt"
|
||||
case .stats: return "chart.xyaxis.line"
|
||||
case .clipboard: return "clipboard"
|
||||
|
|
@ -90,6 +93,7 @@ private enum SettingsTab: String, CaseIterable, Identifiable {
|
|||
case .timer: return .red
|
||||
case .calendar: return .cyan
|
||||
case .hud: return .indigo
|
||||
case .osd: return .teal
|
||||
case .battery: return .yellow
|
||||
case .stats: return .teal
|
||||
case .clipboard: return .mint
|
||||
|
|
@ -352,6 +356,7 @@ struct SettingsView: View {
|
|||
.timer,
|
||||
.calendar,
|
||||
.hud,
|
||||
.osd,
|
||||
.battery,
|
||||
.stats,
|
||||
.clipboard,
|
||||
|
|
@ -536,7 +541,7 @@ struct SettingsView: View {
|
|||
SettingsSearchEntry(tab: .general, title: "Show on all displays", keywords: ["multi-display", "external monitor"], highlightID: SettingsTab.general.highlightID(for: "Show on all displays")),
|
||||
SettingsSearchEntry(tab: .general, title: "Show on a specific display", keywords: ["preferred screen", "display picker"], highlightID: SettingsTab.general.highlightID(for: "Show on a specific display")),
|
||||
SettingsSearchEntry(tab: .general, title: "Automatically switch displays", keywords: ["auto switch", "displays"], highlightID: SettingsTab.general.highlightID(for: "Automatically switch displays")),
|
||||
SettingsSearchEntry(tab: .general, title: "Hide Atoll during screenshots & recordings", keywords: ["privacy", "screenshot", "recording"], highlightID: SettingsTab.general.highlightID(for: "Hide Atoll during screenshots & recordings")),
|
||||
SettingsSearchEntry(tab: .general, title: "Hide Dynamic Island during screenshots & recordings", keywords: ["privacy", "screenshot", "recording"], highlightID: SettingsTab.general.highlightID(for: "Hide Dynamic Island during screenshots & recordings")),
|
||||
SettingsSearchEntry(tab: .general, title: "Enable Screen Recording Detection", keywords: ["screen recording", "indicator"], highlightID: SettingsTab.general.highlightID(for: "Enable Screen Recording Detection")),
|
||||
SettingsSearchEntry(tab: .general, title: "Show Recording Indicator", keywords: ["recording indicator", "red dot"], highlightID: SettingsTab.general.highlightID(for: "Show Recording Indicator")),
|
||||
SettingsSearchEntry(tab: .general, title: "Enable Focus Detection", keywords: ["focus", "do not disturb", "dnd"], highlightID: SettingsTab.general.highlightID(for: "Enable Focus Detection")),
|
||||
|
|
@ -577,6 +582,14 @@ struct SettingsView: View {
|
|||
SettingsSearchEntry(tab: .hud, title: "Enable glowing effect", keywords: ["glow", "indicator"], highlightID: SettingsTab.hud.highlightID(for: "Enable glowing effect")),
|
||||
SettingsSearchEntry(tab: .hud, title: "Use accent color", keywords: ["accent", "color"], highlightID: SettingsTab.hud.highlightID(for: "Use accent color")),
|
||||
|
||||
// Custom OSD
|
||||
SettingsSearchEntry(tab: .osd, title: "Enable Custom OSD", keywords: ["osd", "on-screen display", "custom osd"], highlightID: SettingsTab.osd.highlightID(for: "Enable Custom OSD")),
|
||||
SettingsSearchEntry(tab: .osd, title: "Volume OSD", keywords: ["volume", "osd"], highlightID: SettingsTab.osd.highlightID(for: "Volume OSD")),
|
||||
SettingsSearchEntry(tab: .osd, title: "Brightness OSD", keywords: ["brightness", "osd"], highlightID: SettingsTab.osd.highlightID(for: "Brightness OSD")),
|
||||
SettingsSearchEntry(tab: .osd, title: "Keyboard Backlight OSD", keywords: ["keyboard", "backlight", "osd"], highlightID: SettingsTab.osd.highlightID(for: "Keyboard Backlight OSD")),
|
||||
SettingsSearchEntry(tab: .osd, title: "Material", keywords: ["material", "frosted", "liquid", "glass", "solid", "osd"], highlightID: SettingsTab.osd.highlightID(for: "Material")),
|
||||
SettingsSearchEntry(tab: .osd, title: "Icon & Progress Color", keywords: ["color", "icon", "white", "black", "gray", "osd"], highlightID: SettingsTab.osd.highlightID(for: "Icon & Progress Color")),
|
||||
|
||||
// Media
|
||||
SettingsSearchEntry(tab: .media, title: "Music Source", keywords: ["media source", "controller"], highlightID: SettingsTab.media.highlightID(for: "Music Source")),
|
||||
SettingsSearchEntry(tab: .media, title: "Skip buttons", keywords: ["skip", "controls", "±10"], highlightID: SettingsTab.media.highlightID(for: "Skip buttons")),
|
||||
|
|
@ -713,6 +726,10 @@ struct SettingsView: View {
|
|||
SettingsForm(tab: .hud) {
|
||||
HUD()
|
||||
}
|
||||
case .osd:
|
||||
SettingsForm(tab: .osd) {
|
||||
CustomOSDSettings()
|
||||
}
|
||||
case .battery:
|
||||
SettingsForm(tab: .battery) {
|
||||
Charge()
|
||||
|
|
@ -839,8 +856,8 @@ struct GeneralSettings: View {
|
|||
}
|
||||
.disabled(showOnAllDisplays)
|
||||
.settingsHighlight(id: highlightID("Automatically switch displays"))
|
||||
Defaults.Toggle("Hide Atoll during screenshots & recordings", key: .hideDynamicIslandFromScreenCapture)
|
||||
.settingsHighlight(id: highlightID("Hide Atoll during screenshots & recordings"))
|
||||
Defaults.Toggle("Hide Dynamic Island during screenshots & recordings", key: .hideDynamicIslandFromScreenCapture)
|
||||
.settingsHighlight(id: highlightID("Hide Dynamic Island during screenshots & recordings"))
|
||||
} header: {
|
||||
Text("System features")
|
||||
}
|
||||
|
|
@ -1239,48 +1256,31 @@ struct HUD: View {
|
|||
var body: some View {
|
||||
Form {
|
||||
Section {
|
||||
Toggle("Enable HUD replacement", isOn: $coordinator.hudReplacement)
|
||||
Toggle("Enable HUDs", isOn: $enableSystemHUD)
|
||||
.disabled(Defaults[.enableCustomOSD])
|
||||
} header: {
|
||||
Text("General")
|
||||
} footer: {
|
||||
Text("Replaces system HUD notifications with Atoll displays.")
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
}
|
||||
|
||||
Section {
|
||||
Toggle("Enable Built-in System HUD", isOn: $enableSystemHUD)
|
||||
|
||||
if enableSystemHUD {
|
||||
Toggle("Volume HUD", isOn: $enableVolumeHUD)
|
||||
Toggle("Brightness HUD", isOn: $enableBrightnessHUD)
|
||||
Toggle("Keyboard Backlight HUD", isOn: $enableKeyboardBacklightHUD)
|
||||
|
||||
HStack {
|
||||
Text("Sensitivity")
|
||||
Spacer()
|
||||
Slider(value: Binding(
|
||||
get: { Double(systemHUDSensitivity) },
|
||||
set: { systemHUDSensitivity = Int($0) }
|
||||
), in: 1...10, step: 1) {
|
||||
Text("Sensitivity")
|
||||
}
|
||||
.frame(width: 120)
|
||||
Text("\(systemHUDSensitivity)")
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
.frame(width: 20)
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
Text("Built-in System Monitoring")
|
||||
} footer: {
|
||||
if enableSystemHUD {
|
||||
Text("Built-in system monitoring detects volume, brightness, and keyboard backlight changes directly without requiring external apps.")
|
||||
if Defaults[.enableCustomOSD] {
|
||||
Text("HUDs are disabled because Custom OSD is enabled. Disable Custom OSD in the Custom OSD tab to use HUDs.")
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
} else {
|
||||
Text("Enable built-in system monitoring to replace macOS HUD notifications with Atoll displays.")
|
||||
Text("Replaces macOS system HUD with Dynamic Island displays for volume, brightness, and keyboard backlight.")
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
|
||||
if enableSystemHUD && !Defaults[.enableCustomOSD] {
|
||||
Section {
|
||||
Toggle("Volume HUD", isOn: $enableVolumeHUD)
|
||||
Toggle("Brightness HUD", isOn: $enableBrightnessHUD)
|
||||
Toggle("Keyboard Backlight HUD", isOn: $enableKeyboardBacklightHUD)
|
||||
} header: {
|
||||
Text("Controls")
|
||||
} footer: {
|
||||
Text("Choose which system controls should display HUD notifications.")
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
}
|
||||
|
|
@ -2414,7 +2414,7 @@ struct LockScreenSettings: View {
|
|||
} header: {
|
||||
Text("Live Activity & Feedback")
|
||||
} footer: {
|
||||
Text("Controls whether Atoll mirrors lock/unlock events with its own live activity and audible chimes.")
|
||||
Text("Controls whether Dynamic Island mirrors lock/unlock events with its own live activity and audible chimes.")
|
||||
}
|
||||
|
||||
Section {
|
||||
|
|
@ -3003,7 +3003,7 @@ struct Shortcuts: View {
|
|||
} header: {
|
||||
Text("Navigation")
|
||||
} footer: {
|
||||
Text("Toggle the Atoll open or closed from anywhere.")
|
||||
Text("Toggle the Dynamic Island open or closed from anywhere.")
|
||||
.multilineTextAlignment(.trailing)
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
|
|
@ -3777,7 +3777,7 @@ struct StatsSettings: View {
|
|||
Text("Graph Visibility")
|
||||
} footer: {
|
||||
if enabledGraphsCount >= 4 {
|
||||
Text("With \(enabledGraphsCount) graphs enabled, the Atoll will expand horizontally to accommodate all graphs in a single row.")
|
||||
Text("With \(enabledGraphsCount) graphs enabled, the Dynamic Island will expand horizontally to accommodate all graphs in a single row.")
|
||||
.multilineTextAlignment(.trailing)
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
|
|
@ -4360,6 +4360,151 @@ struct ColorPickerSettings: View {
|
|||
}
|
||||
}
|
||||
|
||||
struct CustomOSDSettings: View {
|
||||
@Default(.enableCustomOSD) var enableCustomOSD
|
||||
@Default(.enableOSDVolume) var enableOSDVolume
|
||||
@Default(.enableOSDBrightness) var enableOSDBrightness
|
||||
@Default(.enableOSDKeyboardBacklight) var enableOSDKeyboardBacklight
|
||||
@Default(.osdMaterial) var osdMaterial
|
||||
@Default(.osdIconColorStyle) var osdIconColorStyle
|
||||
@Default(.enableSystemHUD) var enableSystemHUD
|
||||
|
||||
@State private var previewValue: CGFloat = 0.65
|
||||
@State private var previewType: SneakContentType = .volume
|
||||
|
||||
private func highlightID(_ title: String) -> String {
|
||||
SettingsTab.osd.highlightID(for: title)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section {
|
||||
Toggle("Enable Custom OSD", isOn: $enableCustomOSD)
|
||||
.settingsHighlight(id: highlightID("Enable Custom OSD"))
|
||||
.disabled(enableSystemHUD)
|
||||
.onChange(of: enableCustomOSD) { _, enabled in
|
||||
if enabled {
|
||||
// Disable System HUD when OSD is enabled
|
||||
enableSystemHUD = false
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
Text("General")
|
||||
} footer: {
|
||||
if enableSystemHUD {
|
||||
Text("Custom OSD is disabled because HUDs are enabled. Disable HUDs in the HUDs tab to use Custom OSD.")
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
} else {
|
||||
Text("Display custom macOS-style OSD windows at the bottom center of the screen when adjusting volume, brightness, or keyboard backlight.")
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
|
||||
if enableCustomOSD {
|
||||
Section {
|
||||
Toggle("Volume OSD", isOn: $enableOSDVolume)
|
||||
.settingsHighlight(id: highlightID("Volume OSD"))
|
||||
Toggle("Brightness OSD", isOn: $enableOSDBrightness)
|
||||
.settingsHighlight(id: highlightID("Brightness OSD"))
|
||||
Toggle("Keyboard Backlight OSD", isOn: $enableOSDKeyboardBacklight)
|
||||
.settingsHighlight(id: highlightID("Keyboard Backlight OSD"))
|
||||
} header: {
|
||||
Text("Controls")
|
||||
} footer: {
|
||||
Text("Choose which system controls should display custom OSD windows.")
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
}
|
||||
|
||||
Section {
|
||||
Picker("Material", selection: $osdMaterial) {
|
||||
ForEach(OSDMaterial.allCases, id: \.self) { material in
|
||||
Text(material.rawValue).tag(material)
|
||||
}
|
||||
}
|
||||
.settingsHighlight(id: highlightID("Material"))
|
||||
.onChange(of: osdMaterial) { _, _ in
|
||||
previewValue = previewValue == 0.65 ? 0.651 : 0.65
|
||||
}
|
||||
|
||||
Picker("Icon & Progress Color", selection: $osdIconColorStyle) {
|
||||
ForEach(OSDIconColorStyle.allCases, id: \.self) { style in
|
||||
Text(style.rawValue).tag(style)
|
||||
}
|
||||
}
|
||||
.settingsHighlight(id: highlightID("Icon & Progress Color"))
|
||||
.onChange(of: osdIconColorStyle) { _, _ in
|
||||
previewValue = previewValue == 0.65 ? 0.651 : 0.65
|
||||
}
|
||||
} header: {
|
||||
Text("Appearance")
|
||||
} footer: {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text("Material Options:")
|
||||
Text("• Frosted Glass: Translucent blur effect")
|
||||
Text("• Liquid Glass: Modern glass effect (macOS 26+)")
|
||||
Text("• Solid Dark/Light/Auto: Opaque backgrounds")
|
||||
Text("")
|
||||
Text("Color options control the icon and progress bar appearance. Auto adapts to system theme.")
|
||||
}
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
}
|
||||
|
||||
Section {
|
||||
HStack {
|
||||
Spacer()
|
||||
VStack(spacing: 16) {
|
||||
Text("Live Preview")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
|
||||
CustomOSDView(
|
||||
type: .constant(previewType),
|
||||
value: .constant(previewValue),
|
||||
icon: .constant("")
|
||||
)
|
||||
.frame(width: 200, height: 200)
|
||||
|
||||
HStack(spacing: 8) {
|
||||
Button("Volume") {
|
||||
previewType = .volume
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
|
||||
Button("Brightness") {
|
||||
previewType = .brightness
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
|
||||
Button("Backlight") {
|
||||
previewType = .backlight
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
}
|
||||
.controlSize(.small)
|
||||
|
||||
Slider(value: $previewValue, in: 0...1)
|
||||
.frame(width: 160)
|
||||
}
|
||||
.padding(.vertical, 12)
|
||||
Spacer()
|
||||
}
|
||||
} header: {
|
||||
Text("Preview")
|
||||
} footer: {
|
||||
Text("Adjust settings above to see changes in real-time. The actual OSD appears at the bottom center of your screen.")
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Custom OSD")
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
HUD()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue