mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Update Settings View
This commit is contained in:
parent
0d68bfff94
commit
105b0466a4
2 changed files with 163 additions and 2 deletions
|
|
@ -12419,6 +12419,10 @@
|
|||
},
|
||||
"shouldTranslate" : false
|
||||
},
|
||||
"HUD icon style" : {
|
||||
"comment" : "A label describing the style of the 3D or symbol-based Bluetooth HUD icon.",
|
||||
"isCommentAutoGenerated" : true
|
||||
},
|
||||
"HUD Position" : {
|
||||
"localizations" : {
|
||||
"pt-BR" : {
|
||||
|
|
|
|||
|
|
@ -1776,6 +1776,7 @@ private struct HUDSelectionCard<Preview: View>: View {
|
|||
|
||||
private struct DevicesSettingsView: View {
|
||||
@Default(.progressBarStyle) var progressBarStyle
|
||||
@Default(.useBluetoothHUD3DIcon) private var useBluetoothHUD3DIcon
|
||||
|
||||
private func highlightID(_ title: String) -> String {
|
||||
SettingsTab.devices.highlightID(for: title)
|
||||
|
|
@ -1796,8 +1797,29 @@ private struct DevicesSettingsView: View {
|
|||
.settingsHighlight(id: highlightID("Show battery percentage text in HUD"))
|
||||
Defaults.Toggle("Scroll device name in HUD", key: .showBluetoothDeviceNameMarquee)
|
||||
.settingsHighlight(id: highlightID("Scroll device name in HUD"))
|
||||
Defaults.Toggle("Use 3D Bluetooth HUD icon", key: .useBluetoothHUD3DIcon)
|
||||
.settingsHighlight(id: highlightID("Use 3D Bluetooth HUD icon"))
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
Text("HUD icon style")
|
||||
.font(.system(size: 13, weight: .semibold))
|
||||
.foregroundStyle(.primary)
|
||||
|
||||
HStack(spacing: 16) {
|
||||
Spacer(minLength: 0)
|
||||
BluetoothHUDIconStyleCard(
|
||||
style: .symbol,
|
||||
isSelected: !useBluetoothHUD3DIcon
|
||||
) {
|
||||
useBluetoothHUD3DIcon = false
|
||||
}
|
||||
BluetoothHUDIconStyleCard(
|
||||
style: .threeD,
|
||||
isSelected: useBluetoothHUD3DIcon
|
||||
) {
|
||||
useBluetoothHUD3DIcon = true
|
||||
}
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
}
|
||||
.settingsHighlight(id: highlightID("Use 3D Bluetooth HUD icon"))
|
||||
} header: {
|
||||
Text("Bluetooth Audio Devices")
|
||||
} footer: {
|
||||
|
|
@ -2669,6 +2691,141 @@ struct About: View {
|
|||
}
|
||||
}
|
||||
|
||||
private extension DevicesSettingsView {
|
||||
enum BluetoothHUDIconStyle: String {
|
||||
case symbol
|
||||
case threeD
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .symbol:
|
||||
return "Symbol"
|
||||
case .threeD:
|
||||
return "3D"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct BluetoothHUDIconStyleCard: View {
|
||||
let style: BluetoothHUDIconStyle
|
||||
let isSelected: Bool
|
||||
let action: () -> Void
|
||||
|
||||
@State private var isHovering = false
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 8) {
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.fill(backgroundColor)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.strokeBorder(borderColor, lineWidth: isSelected ? 2 : 1)
|
||||
)
|
||||
|
||||
preview
|
||||
}
|
||||
.frame(width: 90, height: 64)
|
||||
.onHover { hovering in
|
||||
withAnimation(.easeInOut(duration: 0.2)) {
|
||||
isHovering = hovering
|
||||
}
|
||||
}
|
||||
|
||||
Text(style.title)
|
||||
.font(.caption)
|
||||
.fontWeight(.medium)
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture { action() }
|
||||
}
|
||||
|
||||
private var preview: some View {
|
||||
Group {
|
||||
switch style {
|
||||
case .symbol:
|
||||
Image(systemName: BluetoothAudioDeviceType.airpods.sfSymbol)
|
||||
.font(.system(size: 24, weight: .semibold))
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
case .threeD:
|
||||
if let url = Bundle.main.url(
|
||||
forResource: BluetoothAudioDeviceType.airpods.inlineHUDAnimationBaseName,
|
||||
withExtension: "mov"
|
||||
) {
|
||||
SettingsLoopingVideoIcon(url: url, size: CGSize(width: 28, height: 28))
|
||||
.frame(width: 28, height: 28)
|
||||
} else {
|
||||
Image(systemName: BluetoothAudioDeviceType.airpods.sfSymbol)
|
||||
.font(.system(size: 24, weight: .semibold))
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var backgroundColor: Color {
|
||||
if isSelected { return Color.accentColor.opacity(0.12) }
|
||||
if isHovering { return Color.primary.opacity(0.05) }
|
||||
return Color(nsColor: .controlBackgroundColor)
|
||||
}
|
||||
|
||||
private var borderColor: Color {
|
||||
if isSelected { return Color.accentColor }
|
||||
if isHovering { return Color.primary.opacity(0.1) }
|
||||
return Color.clear
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct SettingsLoopingVideoIcon: NSViewRepresentable {
|
||||
let url: URL
|
||||
let size: CGSize
|
||||
|
||||
func makeNSView(context: Context) -> NSView {
|
||||
let view = NSView(frame: NSRect(origin: .zero, size: size))
|
||||
view.wantsLayer = true
|
||||
|
||||
let layer = AVPlayerLayer()
|
||||
layer.videoGravity = .resizeAspect
|
||||
layer.frame = view.bounds
|
||||
view.layer?.addSublayer(layer)
|
||||
context.coordinator.attach(layer: layer, url: url)
|
||||
return view
|
||||
}
|
||||
|
||||
func updateNSView(_ nsView: NSView, context: Context) {}
|
||||
|
||||
func makeCoordinator() -> Coordinator { Coordinator() }
|
||||
|
||||
final class Coordinator {
|
||||
private var controller: SettingsLoopingPlayerController?
|
||||
|
||||
func attach(layer: AVPlayerLayer, url: URL) {
|
||||
controller = SettingsLoopingPlayerController(url: url)
|
||||
layer.player = controller?.player
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class SettingsLoopingPlayerController {
|
||||
let player: AVQueuePlayer
|
||||
private var looper: AVPlayerLooper?
|
||||
|
||||
init(url: URL) {
|
||||
let item = AVPlayerItem(url: url)
|
||||
player = AVQueuePlayer()
|
||||
player.isMuted = true
|
||||
player.actionAtItemEnd = .none
|
||||
looper = AVPlayerLooper(player: player, templateItem: item)
|
||||
player.play()
|
||||
}
|
||||
|
||||
deinit {
|
||||
player.pause()
|
||||
looper = nil
|
||||
}
|
||||
}
|
||||
|
||||
struct Shelf: View {
|
||||
@Default(.quickShareProvider) var quickShareProvider
|
||||
@Default(.expandedDragDetection) var expandedDragDetection
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue