mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Restored files from old Mac, force pushing
This commit is contained in:
parent
5dd95228b8
commit
5040381840
126 changed files with 10431 additions and 67 deletions
151
DynamicIsland/models/DynamicIslandViewModel.swift
Normal file
151
DynamicIsland/models/DynamicIslandViewModel.swift
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
//
|
||||
// DynamicIslandViewModel.swift
|
||||
// DynamicIsland
|
||||
//
|
||||
// Created by Harsh Vardhan Goswami on 04/08/24.
|
||||
//
|
||||
|
||||
import Combine
|
||||
import Defaults
|
||||
import SwiftUI
|
||||
import TheBoringWorkerNotifier
|
||||
|
||||
class DynamicIslandViewModel: NSObject, ObservableObject {
|
||||
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
|
||||
@ObservedObject var detector = FullscreenMediaDetector.shared
|
||||
|
||||
let animationLibrary: DynamicIslandAnimations = .init()
|
||||
let animation: Animation?
|
||||
|
||||
@Published var contentType: ContentType = .normal
|
||||
@Published private(set) var notchState: NotchState = .closed
|
||||
|
||||
@Published var dragDetectorTargeting: Bool = false
|
||||
@Published var dropZoneTargeting: Bool = false
|
||||
@Published var dropEvent: Bool = false
|
||||
@Published var anyDropZoneTargeting: Bool = false
|
||||
var cancellables: Set<AnyCancellable> = []
|
||||
|
||||
@Published var hideOnClosed: Bool = true
|
||||
@Published var isHoveringCalendar: Bool = false
|
||||
@Published var isBatteryPopoverActive: Bool = false
|
||||
|
||||
@Published var screen: String?
|
||||
|
||||
@Published var notchSize: CGSize = getClosedNotchSize()
|
||||
@Published var closedNotchSize: CGSize = getClosedNotchSize()
|
||||
|
||||
deinit {
|
||||
destroy()
|
||||
}
|
||||
|
||||
func destroy() {
|
||||
cancellables.forEach { $0.cancel() }
|
||||
cancellables.removeAll()
|
||||
}
|
||||
|
||||
init(screen: String? = nil) {
|
||||
animation = animationLibrary.animation
|
||||
|
||||
super.init()
|
||||
|
||||
self.screen = screen
|
||||
notchSize = getClosedNotchSize(screen: screen)
|
||||
closedNotchSize = notchSize
|
||||
|
||||
Publishers.CombineLatest($dropZoneTargeting, $dragDetectorTargeting)
|
||||
.map { value1, value2 in
|
||||
value1 || value2
|
||||
}
|
||||
.assign(to: \.anyDropZoneTargeting, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
setupDetectorObserver()
|
||||
}
|
||||
|
||||
private func setupDetectorObserver() {
|
||||
// 1) Publisher for the user’s fullscreen detection setting
|
||||
let enabledPublisher = Defaults
|
||||
.publisher(.enableFullscreenMediaDetection)
|
||||
.map(\.newValue)
|
||||
|
||||
// 2) For each non‑nil screen name, map to a Bool publisher for that screen's status
|
||||
let statusPublisher = $screen
|
||||
.compactMap { $0 }
|
||||
.removeDuplicates()
|
||||
.map { screenName in
|
||||
self.detector.$fullscreenStatus
|
||||
.map { $0[screenName] ?? false }
|
||||
.removeDuplicates()
|
||||
}
|
||||
.switchToLatest()
|
||||
|
||||
// 3) Combine enabled & status, animate only on changes
|
||||
Publishers.CombineLatest(statusPublisher, enabledPublisher)
|
||||
.map { status, enabled in enabled && status }
|
||||
.removeDuplicates()
|
||||
.receive(on: RunLoop.main)
|
||||
.sink { [weak self] shouldHide in
|
||||
withAnimation(.smooth) {
|
||||
self?.hideOnClosed = shouldHide
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
// Computed property for effective notch height
|
||||
var effectiveClosedNotchHeight: CGFloat {
|
||||
let currentScreen = NSScreen.screens.first { $0.localizedName == screen }
|
||||
let noNotchAndFullscreen = hideOnClosed && (currentScreen?.safeAreaInsets.top ?? 0 <= 0 || currentScreen == nil)
|
||||
return noNotchAndFullscreen ? 0 : closedNotchSize.height
|
||||
}
|
||||
|
||||
func isMouseHovering(position: NSPoint = NSEvent.mouseLocation) -> Bool {
|
||||
let screenFrame = getScreenFrame(screen)
|
||||
if let frame = screenFrame {
|
||||
|
||||
let baseY = frame.maxY - notchSize.height
|
||||
let baseX = frame.midX - notchSize.width / 2
|
||||
|
||||
return position.y >= baseY && position.x >= baseX && position.x <= baseX + notchSize.width
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func open() {
|
||||
withAnimation(.bouncy) {
|
||||
self.notchSize = openNotchSize
|
||||
self.notchState = .open
|
||||
}
|
||||
|
||||
// Force music information update when notch is opened
|
||||
MusicManager.shared.forceUpdate()
|
||||
}
|
||||
|
||||
func close() {
|
||||
withAnimation(.smooth) { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.notchSize = getClosedNotchSize(screen: self.screen)
|
||||
self.closedNotchSize = self.notchSize
|
||||
self.notchState = .closed
|
||||
}
|
||||
|
||||
// Set the current view to shelf if it contains files and the user enables openShelfByDefault
|
||||
// Otherwise, if the user has not enabled openLastShelfByDefault, set the view to home
|
||||
if !TrayDrop.shared.isEmpty && Defaults[.openShelfByDefault] {
|
||||
coordinator.currentView = .shelf
|
||||
} else if !coordinator.openLastTabByDefault {
|
||||
coordinator.currentView = .home
|
||||
}
|
||||
}
|
||||
|
||||
func closeHello() {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 3.5) { [weak self] in
|
||||
self?.coordinator.firstLaunch = false
|
||||
withAnimation(self?.animationLibrary.animation) {
|
||||
self?.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue