MiniPlayer/Sources/MiniPlayerIcon.swift
yumoqing 3e3a990f5e fix: replace Combine KVO with NSKeyValueObservation to prevent autorelease crash
- Remove Combine import and cancellables
- Use NSKeyValueObservation for timeControlStatus (controlled teardown)
- Invalidate itemStatusObserver before replacing playerItem
- Store endObserver token for proper removal
- Add cleanup() method called on view disappear
- Proper deinit with direct property cleanup (nonisolated-safe)
2026-06-22 00:36:18 +08:00

106 lines
3.6 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import SwiftUI
// MARK: - MiniPlayer +
struct MiniPlayerIcon: View {
var body: some View {
GeometryReader { geo in
let size = min(geo.size.width, geo.size.height)
ZStack {
//
RingArc(startAngle: -30, endAngle: 90)
.stroke(Color(red: 1.0, green: 0.23, blue: 0.19), lineWidth: size * 0.07)
.frame(width: size * 0.82, height: size * 0.82)
RingArc(startAngle: 90, endAngle: 210)
.stroke(Color(red: 0.20, green: 0.78, blue: 0.35), lineWidth: size * 0.07)
.frame(width: size * 0.82, height: size * 0.82)
RingArc(startAngle: 210, endAngle: 330)
.stroke(Color(red: 0.0, green: 0.48, blue: 1.0), lineWidth: size * 0.07)
.frame(width: size * 0.82, height: size * 0.82)
//
TriColorPlay(size: size * 0.38)
.offset(x: size * 0.03) //
}
.frame(width: size, height: size)
}
}
}
// MARK: -
struct RingArc: Shape {
let startAngle: Double
let endAngle: Double
func path(in rect: CGRect) -> Path {
var p = Path()
let center = CGPoint(x: rect.midX, y: rect.midY)
let radius = min(rect.width, rect.height) / 2
p.addArc(
center: center,
radius: radius,
startAngle: .degrees(startAngle),
endAngle: .degrees(endAngle),
clockwise: false
)
return p
}
}
// MARK: -
struct TriColorPlay: View {
let size: CGFloat
var body: some View {
Canvas { ctx, canvasSize in
let w = canvasSize.width
let h = canvasSize.height
//
let top = CGPoint(x: w * 0.15, y: 0)
let bottom = CGPoint(x: w * 0.15, y: h)
let right = CGPoint(x: w, y: h * 0.5)
//
let cx = (top.x + bottom.x + right.x) / 3
let cy = (top.y + bottom.y + right.y) / 3
let center = CGPoint(x: cx, y: cy)
//
let red = Path { p in
p.move(to: center)
p.addLine(to: top)
p.addLine(to: right)
p.closeSubpath()
}
let green = Path { p in
p.move(to: center)
p.addLine(to: right)
p.addLine(to: bottom)
p.closeSubpath()
}
let blue = Path { p in
p.move(to: center)
p.addLine(to: bottom)
p.addLine(to: top)
p.closeSubpath()
}
ctx.fill(red, with: .color(Color(red: 1.0, green: 0.23, blue: 0.19)))
ctx.fill(green, with: .color(Color(red: 0.20, green: 0.78, blue: 0.35)))
ctx.fill(blue, with: .color(Color(red: 0.0, green: 0.48, blue: 1.0)))
// 线
let lineW = max(0.5, w * 0.015)
for vertex in [top, bottom, right] {
var lp = Path()
lp.move(to: center)
lp.addLine(to: vertex)
ctx.stroke(lp, with: .color(.white.opacity(0.6)), lineWidth: lineW)
}
}
.frame(width: size, height: size)
}
}