Working Lock Screen HUD

This commit is contained in:
Hariharan Mudaliar 2025-10-17 18:13:36 +05:30
commit ce8cce0252
4 changed files with 265 additions and 10 deletions

View file

@ -0,0 +1,95 @@
//
// LockScreenLiveActivityOverlay.swift
// DynamicIsland
//
// Mirrors the closed-notch live activity layout on the macOS lock screen.
//
import SwiftUI
enum LockLiveActivityState: Equatable {
case locked
case unlocking
}
struct LockScreenLiveActivityOverlay: View {
let state: LockLiveActivityState
let notchSize: CGSize
private var indicatorSize: CGFloat {
max(0, notchSize.height - 12)
}
private var horizontalPadding: CGFloat {
cornerRadiusInsets.closed.bottom
}
private var baseWidth: CGFloat {
notchSize.width + (indicatorSize * 2)
}
private var totalWidth: CGFloat {
baseWidth + (horizontalPadding * 2)
}
private var iconName: String {
state == .locked ? "lock.fill" : "lock.open.fill"
}
private var iconColor: Color {
state == .locked ? .blue : .green
}
private var glowColor: Color {
state == .locked ? Color.blue.opacity(0.15) : Color.green.opacity(0.2)
}
var body: some View {
HStack(spacing: 0) {
Color.clear
.background {
HStack {
ZStack {
RoundedRectangle(cornerRadius: 6)
.fill(glowColor)
Image(systemName: iconName)
.font(.system(size: 12, weight: .semibold))
.foregroundColor(iconColor)
.modifier(LockPulsingModifier(isUnlocking: state == .unlocking))
}
.frame(width: indicatorSize, height: indicatorSize)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
}
.frame(width: indicatorSize, height: notchSize.height)
Color.clear
.frame(width: notchSize.width, height: notchSize.height)
Color.clear
.frame(width: indicatorSize, height: notchSize.height)
}
.frame(width: baseWidth, height: notchSize.height)
.padding(.horizontal, horizontalPadding)
.background(Color.black)
.clipShape(
NotchShape(
topCornerRadius: cornerRadiusInsets.closed.top,
bottomCornerRadius: cornerRadiusInsets.closed.bottom
)
)
.frame(width: totalWidth, height: notchSize.height)
.animation(.spring(response: 0.45, dampingFraction: 0.85), value: state)
.drawingGroup()
}
}
#Preview {
VStack(spacing: 24) {
LockScreenLiveActivityOverlay(state: .locked, notchSize: CGSize(width: 220, height: 32))
LockScreenLiveActivityOverlay(state: .unlocking, notchSize: CGSize(width: 220, height: 32))
}
.padding()
.background(Color.gray.opacity(0.2))
}