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
|
||||
Loading…
Add table
Add a link
Reference in a new issue