Restored files from old Mac, force pushing

This commit is contained in:
Hariharan Mudaliar 2025-07-13 20:26:03 +05:30
commit 5040381840
126 changed files with 10431 additions and 67 deletions

View file

@ -0,0 +1,107 @@
//
// BoringExtrasMenu.swift
// boringNotch
//
// Created by Harsh Vardhan Goswami on 04/08/24.
//
import SwiftUI
struct BoringLargeButtons: View {
var action: () -> Void
var icon: Image
var title: String
var body: some View {
Button (
action:action,
label: {
ZStack {
RoundedRectangle(cornerRadius: 12.0).fill(.black).frame(width: 70, height: 70)
VStack(spacing: 8) {
icon.resizable()
.aspectRatio(contentMode: .fit).frame(width:20)
Text(title).font(.body)
}
}
}).buttonStyle(PlainButtonStyle()).shadow(color: .black.opacity(0.5), radius: 10)
}
}
struct BoringExtrasMenu : View {
@ObservedObject var vm: DynamicIslandViewModel
var body: some View {
VStack{
HStack(spacing: 20) {
hide
settings
close
}
}
}
var github: some View {
BoringLargeButtons(
action: {
NSWorkspace.shared.open(productPage)
},
icon: Image(.github),
title: "Checkout"
)
}
var donate: some View {
BoringLargeButtons(
action: {
NSWorkspace.shared.open(sponsorPage)
},
icon: Image(systemName: "heart.fill"),
title: "Love Us"
)
}
var settings: some View {
SettingsLink(label: {
ZStack {
RoundedRectangle(cornerRadius: 12.0).fill(.black).frame(width: 70, height: 70)
VStack(spacing: 8) {
Image(systemName: "gear").resizable()
.aspectRatio(contentMode: .fit).frame(width:20)
Text("Settings").font(.body)
}
}
})
.buttonStyle(PlainButtonStyle()).shadow(color: .black.opacity(0.5), radius: 10)
}
var hide: some View {
BoringLargeButtons(
action: {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
//vm.openMusic()
}
},
icon: Image(systemName: "arrow.down.forward.and.arrow.up.backward"),
title: "Hide"
)
}
var close: some View {
BoringLargeButtons(
action: {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
NSApp.terminate(nil)
}
}
},
icon: Image(systemName: "xmark"),
title: "Exit"
)
}
}
#Preview {
BoringExtrasMenu(vm: .init())
}

View file

@ -0,0 +1,85 @@
//
// DynamicIslandHeader.swift
// DynamicIsland
//
// Created by Harsh Vardhan Goswami on 04/08/24.
//
import Defaults
import SwiftUI
struct DynamicIslandHeader: View {
@EnvironmentObject var vm: DynamicIslandViewModel
@ObservedObject var batteryModel = BatteryStatusViewModel.shared
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
@StateObject var tvm = TrayDrop.shared
var body: some View {
HStack(spacing: 0) {
HStack {
if (!tvm.isEmpty || coordinator.alwaysShowTabs) && Defaults[.dynamicShelf] {
TabSelectionView()
} else if vm.notchState == .open {
EmptyView()
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.opacity(vm.notchState == .closed ? 0 : 1)
.blur(radius: vm.notchState == .closed ? 20 : 0)
.animation(.smooth.delay(0.1), value: vm.notchState)
.zIndex(2)
if vm.notchState == .open {
Rectangle()
.fill(NSScreen.screens
.first(where: { $0.localizedName == coordinator.selectedScreen })?.safeAreaInsets.top ?? 0 > 0 ? .black : .clear)
.frame(width: vm.closedNotchSize.width)
.mask {
NotchShape()
}
}
HStack(spacing: 4) {
if vm.notchState == .open {
if Defaults[.settingsIconInNotch] {
SettingsLink(label: {
Capsule()
.fill(.black)
.frame(width: 30, height: 30)
.overlay {
Image(systemName: "gear")
.foregroundColor(.white)
.padding()
.imageScale(.medium)
}
})
.buttonStyle(PlainButtonStyle())
}
if Defaults[.showBatteryIndicator] {
DynamicIslandBatteryView(
batteryWidth: 30,
isCharging: batteryModel.isCharging,
isInLowPowerMode: batteryModel.isInLowPowerMode,
isPluggedIn: batteryModel.isPluggedIn,
levelBattery: batteryModel.levelBattery,
maxCapacity: batteryModel.maxCapacity,
timeToFullCharge: batteryModel.timeToFullCharge,
isForNotification: false
)
}
}
}
.font(.system(.headline, design: .rounded))
.frame(maxWidth: .infinity, alignment: .trailing)
.opacity(vm.notchState == .closed ? 0 : 1)
.blur(radius: vm.notchState == .closed ? 20 : 0)
.animation(.smooth.delay(0.1), value: vm.notchState)
.zIndex(2)
}
.foregroundColor(.gray)
.environmentObject(vm)
}
}
#Preview {
DynamicIslandHeader().environmentObject(DynamicIslandViewModel())
}

View file

@ -0,0 +1,50 @@
//
// DynamicIslandWindow.swift
// DynamicIsland
//
// Created by Harsh Vardhan Goswami on 06/08/24.
//
import Cocoa
class DynamicIslandWindow: NSPanel {
override init(
contentRect: NSRect,
styleMask: NSWindow.StyleMask,
backing: NSWindow.BackingStoreType,
defer flag: Bool
) {
super.init(
contentRect: contentRect,
styleMask: styleMask,
backing: backing,
defer: flag
)
isFloatingPanel = true
isOpaque = false
titleVisibility = .hidden
titlebarAppearsTransparent = true
backgroundColor = .clear
isMovable = false
collectionBehavior = [
.fullScreenAuxiliary,
.stationary,
.canJoinAllSpaces,
.ignoresCycle,
]
isReleasedWhenClosed = false
level = .mainMenu + 3
hasShadow = false
}
override var canBecomeKey: Bool {
false
}
override var canBecomeMain: Bool {
false
}
}

View file

@ -0,0 +1,342 @@
//
// NotchHomeView.swift
// boringNotch
//
// Created by Hugo Persson on 2024-08-18.
// Modified by Harsh Vardhan Goswami & Richard Kunkli
//
import Combine
import Defaults
import SwiftUI
// MARK: - Music Player Components
struct MusicPlayerView: View {
@EnvironmentObject var vm: DynamicIslandViewModel
let albumArtNamespace: Namespace.ID
var body: some View {
HStack {
AlbumArtView(vm: vm, albumArtNamespace: albumArtNamespace)
MusicControlsView().drawingGroup().compositingGroup()
}
}
}
struct AlbumArtView: View {
@ObservedObject var musicManager = MusicManager.shared
@ObservedObject var vm: DynamicIslandViewModel
let albumArtNamespace: Namespace.ID
var body: some View {
ZStack(alignment: .bottomTrailing) {
if Defaults[.lightingEffect] {
albumArtBackground
}
albumArtButton
}
}
private var albumArtBackground: some View {
Color.clear
.aspectRatio(1, contentMode: .fit)
.background(
Image(nsImage: musicManager.albumArt)
.resizable()
.aspectRatio(contentMode: .fill)
)
.clipped()
.clipShape(RoundedRectangle(cornerRadius: Defaults[.cornerRadiusScaling] ? MusicPlayerImageSizes.cornerRadiusInset.opened : MusicPlayerImageSizes.cornerRadiusInset.closed))
.scaleEffect(x: 1.3, y: 1.4)
.rotationEffect(.degrees(92))
.blur(radius: 35)
.opacity(min(0.6, 1 - max(musicManager.albumArt.getBrightness(), 0.3)))
}
private var albumArtButton: some View {
Button {
musicManager.openMusicApp()
} label: {
ZStack(alignment: .bottomTrailing) {
albumArtImage
appIconOverlay
}
}
.buttonStyle(PlainButtonStyle())
.opacity(musicManager.isPlaying ? 1 : 0.4)
.scaleEffect(musicManager.isPlaying ? 1 : 0.85)
}
private var albumArtImage: some View {
Color.clear
.aspectRatio(1, contentMode: .fit)
.background(
Image(nsImage: musicManager.albumArt)
.resizable()
.aspectRatio(contentMode: .fill)
.animation(.spring(response: 0.4, dampingFraction: 0.8), value: musicManager.isFlipping)
)
.clipped()
.clipShape(RoundedRectangle(cornerRadius: Defaults[.cornerRadiusScaling] ? MusicPlayerImageSizes.cornerRadiusInset.opened : MusicPlayerImageSizes.cornerRadiusInset.closed))
.matchedGeometryEffect(id: "albumArt", in: albumArtNamespace)
}
@ViewBuilder
private var appIconOverlay: some View {
if vm.notchState == .open && !musicManager.usingAppIconForArtwork {
AppIcon(for: musicManager.bundleIdentifier ?? "com.apple.Music")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 30, height: 30)
.offset(x: 10, y: 10)
.transition(.scale.combined(with: .opacity).animation(.bouncy.delay(0.3)))
}
}
}
struct MusicControlsView: View {
@ObservedObject var musicManager = MusicManager.shared
@State private var sliderValue: Double = 0
@State private var dragging: Bool = false
@State private var lastDragged: Date = .distantPast
var body: some View {
VStack(alignment: .leading) {
songInfoAndSlider
playbackControls
}
.buttonStyle(PlainButtonStyle())
.frame(minWidth: Defaults[.showMirror] && Defaults[.showCalendar] ? 140 : 180)
}
private var songInfoAndSlider: some View {
GeometryReader { geo in
VStack(alignment: .leading, spacing: 4) {
songInfo(width: geo.size.width)
musicSlider
}
}
.padding(.top, 10)
.padding(.leading, 5)
}
private func songInfo(width: CGFloat) -> some View {
VStack(alignment: .leading, spacing: 0) {
MarqueeText($musicManager.songTitle, font: .headline, nsFont: .headline, textColor: .white, frameWidth: width)
MarqueeText(
$musicManager.artistName,
font: .headline,
nsFont: .headline,
textColor: Defaults[.playerColorTinting] ? Color(nsColor: musicManager.avgColor)
.ensureMinimumBrightness(factor: 0.6) : .gray,
frameWidth: width
)
.fontWeight(.medium)
}
}
private var musicSlider: some View {
TimelineView(.animation(minimumInterval: musicManager.playbackRate > 0 ? 0.1 : nil)) { timeline in
MusicSliderView(
sliderValue: $sliderValue,
duration: $musicManager.songDuration,
lastDragged: $lastDragged,
color: musicManager.avgColor,
dragging: $dragging,
currentDate: timeline.date,
lastUpdated: musicManager.lastUpdated,
ignoreLastUpdated: musicManager.ignoreLastUpdated,
timestampDate: musicManager.timestampDate,
elapsedTime: musicManager.elapsedTime,
playbackRate: musicManager.playbackRate,
isPlaying: musicManager.isPlaying
) { newValue in
MusicManager.shared.seek(to: newValue)
}
.padding(.top, 5)
.frame(height: 36)
}
}
private var playbackControls: some View {
HStack(spacing: 8) {
HoverButton(icon: "backward.fill", scale: .medium) {
MusicManager.shared.previousTrack()
}
HoverButton(icon: musicManager.isPlaying ? "pause.fill" : "play.fill", scale: .large) {
MusicManager.shared.togglePlay()
}
HoverButton(icon: "forward.fill", scale: .medium) {
MusicManager.shared.nextTrack()
}
}
.frame(maxWidth: .infinity, alignment: .center)
}
}
// MARK: - Main View
struct NotchHomeView: View {
@EnvironmentObject var vm: DynamicIslandViewModel
@EnvironmentObject var webcamManager: WebcamManager
@ObservedObject var batteryModel = BatteryStatusViewModel.shared
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
let albumArtNamespace: Namespace.ID
var body: some View {
Group {
if !coordinator.firstLaunch {
mainContent
}
}
.transition(.opacity.combined(with: .blurReplace))
}
private var mainContent: some View {
HStack(alignment: .top, spacing: 20) {
MusicPlayerView(albumArtNamespace: albumArtNamespace)
if Defaults[.showCalendar] {
CalendarView()
.onHover { isHovering in
vm.isHoveringCalendar = isHovering
}
.environmentObject(vm)
}
if Defaults[.showMirror] && webcamManager.cameraAvailable {
CameraPreviewView(webcamManager: webcamManager)
.scaledToFit()
.opacity(vm.notchState == .closed ? 0 : 1)
.blur(radius: vm.notchState == .closed ? 20 : 0)
}
}
.transition(.opacity.animation(.smooth.speed(0.9))
.combined(with: .blurReplace.animation(.smooth.speed(0.9)))
.combined(with: .move(edge: .top)))
.blur(radius: vm.notchState == .closed ? 30 : 0)
}
}
struct MusicSliderView: View {
@Binding var sliderValue: Double
@Binding var duration: Double
@Binding var lastDragged: Date
var color: NSColor
@Binding var dragging: Bool
let currentDate: Date
let lastUpdated: Date
let ignoreLastUpdated: Bool
let timestampDate: Date
let elapsedTime: Double
let playbackRate: Double
let isPlaying: Bool
var onValueChange: (Double) -> Void
var currentElapsedTime: Double {
// A small buffer is needed to ensure a meaningful difference between the two dates
guard !dragging, timestampDate.timeIntervalSince(lastDragged) > -0.0001, (timestampDate > lastUpdated || ignoreLastUpdated) else { return sliderValue }
let timeDifference = isPlaying ? currentDate.timeIntervalSince(timestampDate) : 0
let elapsed = elapsedTime + (timeDifference * playbackRate)
return min(elapsed, duration)
}
var body: some View {
VStack {
CustomSlider(
value: $sliderValue,
range: 0 ... duration,
color: Defaults[.sliderColor] == SliderColorEnum.albumArt ? Color(
nsColor: color
).ensureMinimumBrightness(factor: 0.8) : Defaults[.sliderColor] == SliderColorEnum.accent ? Defaults[.accentColor] : .white,
dragging: $dragging,
lastDragged: $lastDragged,
onValueChange: onValueChange
)
.frame(height: 10, alignment: .center)
HStack {
Text(timeString(from: sliderValue))
Spacer()
Text(timeString(from: duration))
}
.fontWeight(.medium)
.foregroundColor(Defaults[.playerColorTinting] ? Color(nsColor: color)
.ensureMinimumBrightness(factor: 0.6) : .gray)
.font(.caption)
}
.onChange(of: currentDate) {
sliderValue = currentElapsedTime
}
}
func timeString(from seconds: Double) -> String {
let totalMinutes = Int(seconds) / 60
let remainingSeconds = Int(seconds) % 60
let hours = totalMinutes / 60
let minutes = totalMinutes % 60
if hours > 0 {
return String(format: "%d:%02d:%02d", hours, minutes, remainingSeconds)
} else {
return String(format: "%d:%02d", minutes, remainingSeconds)
}
}
}
struct CustomSlider: View {
@Binding var value: Double
var range: ClosedRange<Double>
var color: Color = .white
@Binding var dragging: Bool
@Binding var lastDragged: Date
var onValueChange: ((Double) -> Void)?
var thumbSize: CGFloat = 12
var body: some View {
GeometryReader { geometry in
let width = geometry.size.width
let height = CGFloat(dragging ? 9 : 5)
let rangeSpan = range.upperBound - range.lowerBound
let filledTrackWidth = min(rangeSpan == .zero ? 0 : ((value - range.lowerBound) / rangeSpan) * width, width)
ZStack(alignment: .leading) {
// Background track
Rectangle()
.fill(.gray.opacity(0.3))
.frame(height: height)
// Filled track
Rectangle()
.fill(color)
.frame(width: filledTrackWidth, height: height)
}
.cornerRadius(height / 2)
.frame(height: 10)
.contentShape(Rectangle())
.highPriorityGesture(
DragGesture(minimumDistance: 0)
.onChanged { gesture in
withAnimation {
dragging = true
}
let newValue = range.lowerBound + Double(gesture.location.x / width) * rangeSpan
value = min(max(newValue, range.lowerBound), range.upperBound)
}
.onEnded { _ in
onValueChange?(value)
dragging = false
lastDragged = Date()
}
)
.animation(.bouncy.speed(1.4), value: dragging)
}
}
}
#Preview {
NotchHomeView(albumArtNamespace: Namespace().wrappedValue)
.environmentObject(DynamicIslandViewModel())
.environmentObject(WebcamManager())
}

View file

@ -0,0 +1,126 @@
//
// NotchShape.swift
// boringNotch
//
// Created by Kai Azim on 2023-08-24.
// Original source: https://github.com/MrKai77/DynamicNotchKit
// Modified by Alexander Greco on 2025-05-18.
import SwiftUI
struct NotchShape: Shape {
private var topCornerRadius: CGFloat
private var bottomCornerRadius: CGFloat
init(
topCornerRadius: CGFloat? = nil,
bottomCornerRadius: CGFloat? = nil
) {
self.topCornerRadius = topCornerRadius ?? 6
self.bottomCornerRadius = bottomCornerRadius ?? 14
}
var animatableData: AnimatablePair<CGFloat, CGFloat> {
get {
.init(
topCornerRadius,
bottomCornerRadius
)
}
set {
topCornerRadius = newValue.first
bottomCornerRadius = newValue.second
}
}
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(
to: CGPoint(
x: rect.minX,
y: rect.minY
)
)
path.addQuadCurve(
to: CGPoint(
x: rect.minX + topCornerRadius,
y: rect.minY + topCornerRadius
),
control: CGPoint(
x: rect.minX + topCornerRadius,
y: rect.minY
)
)
path.addLine(
to: CGPoint(
x: rect.minX + topCornerRadius,
y: rect.maxY - bottomCornerRadius
)
)
path.addQuadCurve(
to: CGPoint(
x: rect.minX + topCornerRadius + bottomCornerRadius,
y: rect.maxY
),
control: CGPoint(
x: rect.minX + topCornerRadius,
y: rect.maxY
)
)
path.addLine(
to: CGPoint(
x: rect.maxX - topCornerRadius - bottomCornerRadius,
y: rect.maxY
)
)
path.addQuadCurve(
to: CGPoint(
x: rect.maxX - topCornerRadius,
y: rect.maxY - bottomCornerRadius
),
control: CGPoint(
x: rect.maxX - topCornerRadius,
y: rect.maxY
)
)
path.addLine(
to: CGPoint(
x: rect.maxX - topCornerRadius,
y: rect.minY + topCornerRadius
)
)
path.addQuadCurve(
to: CGPoint(
x: rect.maxX,
y: rect.minY
),
control: CGPoint(
x: rect.maxX - topCornerRadius,
y: rect.minY
)
)
path.addLine(
to: CGPoint(
x: rect.minX,
y: rect.minY
)
)
return path
}
}
#Preview {
NotchShape(topCornerRadius: 6, bottomCornerRadius: 14)
.frame(width: 200, height: 32)
.padding(10)
}

View file

@ -0,0 +1,64 @@
import SwiftUI
struct NotchShelfView: View {
@EnvironmentObject var vm: DynamicIslandViewModel
@StateObject var tvm = TrayDrop.shared
var body: some View {
HStack {
AirDropView()
panel
.onDrop(of: [.data], isTargeted: $vm.dropZoneTargeting) { providers in
vm.dropEvent = true
DispatchQueue.global().async {
tvm.load(providers)
}
return true
}
}
}
var panel: some View {
RoundedRectangle(cornerRadius: 16)
.strokeBorder(style: StrokeStyle(lineWidth: 4, dash: [10]))
.foregroundStyle(.white.opacity(0.1))
.overlay {
content
.padding()
}
.animation(vm.animation, value: tvm.items)
.animation(vm.animation, value: tvm.isLoading)
}
var content: some View {
Group {
if tvm.isEmpty {
VStack(spacing: 10) {
Image(systemName: "tray.and.arrow.down")
.symbolVariant(.fill)
.symbolRenderingMode(.hierarchical)
.foregroundStyle(.white, .gray)
.imageScale(.large)
Text("Drop files here")
.foregroundStyle(.gray)
.font(.system(.title3, design: .rounded))
.fontWeight(.medium)
}
} else {
ScrollView(.horizontal) {
HStack(spacing: spacing) {
ForEach(tvm.items) { item in
DropItemView(item: item)
}
}
.padding(spacing)
}
.padding(-spacing)
.scrollIndicators(.never)
}
}
}
}