mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
216 lines
6.9 KiB
Swift
216 lines
6.9 KiB
Swift
//
|
|
// DynamicIslandViewCoordinator.swift
|
|
// DynamicIsland
|
|
//
|
|
// Created by Alexander on 2024-11-20.
|
|
//
|
|
|
|
import Combine
|
|
import Defaults
|
|
import SwiftUI
|
|
import TheBoringWorkerNotifier
|
|
|
|
enum SneakContentType {
|
|
case brightness
|
|
case volume
|
|
case backlight
|
|
case music
|
|
case mic
|
|
case battery
|
|
case download
|
|
case timer
|
|
}
|
|
|
|
struct sneakPeek {
|
|
var show: Bool = false
|
|
var type: SneakContentType = .music
|
|
var value: CGFloat = 0
|
|
var icon: String = ""
|
|
}
|
|
|
|
struct SharedSneakPeek: Codable {
|
|
var show: Bool
|
|
var type: String
|
|
var value: String
|
|
var icon: String
|
|
}
|
|
|
|
enum BrowserType {
|
|
case chromium
|
|
case safari
|
|
}
|
|
|
|
struct ExpandedItem {
|
|
var show: Bool = false
|
|
var type: SneakContentType = .battery
|
|
var value: CGFloat = 0
|
|
var browser: BrowserType = .chromium
|
|
}
|
|
|
|
class DynamicIslandViewCoordinator: ObservableObject {
|
|
static let shared = DynamicIslandViewCoordinator()
|
|
var notifier: TheBoringWorkerNotifier = .init()
|
|
|
|
@Published var currentView: NotchViews = .home
|
|
private var sneakPeekDispatch: DispatchWorkItem?
|
|
private var expandingViewDispatch: DispatchWorkItem?
|
|
|
|
|
|
@AppStorage("firstLaunch") var firstLaunch: Bool = true
|
|
@AppStorage("showWhatsNew") var showWhatsNew: Bool = true
|
|
@AppStorage("musicLiveActivityEnabled") var musicLiveActivityEnabled: Bool = true
|
|
@AppStorage("timerLiveActivityEnabled") var timerLiveActivityEnabled: Bool = true
|
|
@AppStorage("currentMicStatus") var currentMicStatus: Bool = true
|
|
|
|
@AppStorage("alwaysShowTabs") var alwaysShowTabs: Bool = true {
|
|
didSet {
|
|
if !alwaysShowTabs {
|
|
openLastTabByDefault = false
|
|
if TrayDrop.shared.isEmpty || !Defaults[.openShelfByDefault] {
|
|
currentView = .home
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@AppStorage("openLastTabByDefault") var openLastTabByDefault: Bool = false {
|
|
didSet {
|
|
if openLastTabByDefault {
|
|
alwaysShowTabs = true
|
|
}
|
|
}
|
|
}
|
|
|
|
@AppStorage("hudReplacement") var hudReplacement: Bool = true {
|
|
didSet {
|
|
notifier.postNotification(name: notifier.toggleHudReplacementNotification.name, userInfo: nil)
|
|
}
|
|
}
|
|
|
|
@AppStorage("preferred_screen_name") var preferredScreen = NSScreen.main?.localizedName ?? "Unknown" {
|
|
didSet {
|
|
selectedScreen = preferredScreen
|
|
NotificationCenter.default.post(name: Notification.Name.selectedScreenChanged, object: nil)
|
|
}
|
|
}
|
|
|
|
@Published var selectedScreen: String = NSScreen.main?.localizedName ?? "Unknown"
|
|
|
|
@Published var optionKeyPressed: Bool = true
|
|
|
|
private init() {
|
|
selectedScreen = preferredScreen
|
|
notifier = TheBoringWorkerNotifier()
|
|
}
|
|
|
|
func setupWorkersNotificationObservers() {
|
|
notifier.setupObserver(notification: notifier.micStatusNotification, handler: initialMicStatus)
|
|
notifier.setupObserver(notification: notifier.sneakPeakNotification, handler: sneakPeekEvent)
|
|
}
|
|
|
|
@objc func sneakPeekEvent(_ notification: Notification) {
|
|
let decoder = JSONDecoder()
|
|
if let decodedData = try? decoder.decode(SharedSneakPeek.self, from: notification.userInfo?.first?.value as! Data) {
|
|
let contentType = decodedData.type == "brightness" ? SneakContentType.brightness : decodedData.type == "volume" ? SneakContentType.volume : decodedData.type == "backlight" ? SneakContentType.backlight : decodedData.type == "mic" ? SneakContentType.mic : decodedData.type == "timer" ? SneakContentType.timer : SneakContentType.brightness
|
|
|
|
let value = CGFloat((NumberFormatter().number(from: decodedData.value) ?? 0.0).floatValue)
|
|
let icon = decodedData.icon
|
|
|
|
print(decodedData)
|
|
|
|
toggleSneakPeek(status: decodedData.show, type: contentType, value: value, icon: icon)
|
|
|
|
} else {
|
|
print("Failed to decode JSON data")
|
|
}
|
|
}
|
|
|
|
func toggleSneakPeek(status: Bool, type: SneakContentType, duration: TimeInterval = 1.5, value: CGFloat = 0, icon: String = "") {
|
|
sneakPeekDuration = duration
|
|
if type != .music && type != .timer {
|
|
// close()
|
|
if !hudReplacement {
|
|
return
|
|
}
|
|
}
|
|
DispatchQueue.main.async {
|
|
withAnimation(.smooth) {
|
|
self.sneakPeek.show = status
|
|
self.sneakPeek.type = type
|
|
self.sneakPeek.value = value
|
|
self.sneakPeek.icon = icon
|
|
}
|
|
}
|
|
|
|
if type == .mic {
|
|
currentMicStatus = value == 1
|
|
}
|
|
}
|
|
|
|
private var sneakPeekDuration: TimeInterval = 1.5
|
|
|
|
@Published var sneakPeek: sneakPeek = .init() {
|
|
didSet {
|
|
if sneakPeek.show {
|
|
sneakPeekDispatch?.cancel()
|
|
|
|
sneakPeekDispatch = DispatchWorkItem { [weak self] in
|
|
guard let self = self else { return }
|
|
withAnimation {
|
|
self.toggleSneakPeek(status: false, type: SneakContentType.music)
|
|
self.sneakPeekDuration = 1.5
|
|
}
|
|
}
|
|
DispatchQueue.main
|
|
.asyncAfter(
|
|
deadline: .now() + self.sneakPeekDuration,
|
|
execute: sneakPeekDispatch!
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
func toggleExpandingView(status: Bool, type: SneakContentType, value: CGFloat = 0, browser: BrowserType = .chromium) {
|
|
if expandingView.show {
|
|
withAnimation(.smooth) {
|
|
self.expandingView.show = false
|
|
}
|
|
}
|
|
DispatchQueue.main.async {
|
|
withAnimation(.smooth) {
|
|
self.expandingView.show = status
|
|
self.expandingView.type = type
|
|
self.expandingView.value = value
|
|
self.expandingView.browser = browser
|
|
}
|
|
}
|
|
}
|
|
|
|
@Published var expandingView: ExpandedItem = .init() {
|
|
didSet {
|
|
if expandingView.show {
|
|
expandingViewDispatch?.cancel()
|
|
|
|
expandingViewDispatch = DispatchWorkItem { [weak self] in
|
|
guard let self = self else { return }
|
|
self.toggleExpandingView(status: false, type: SneakContentType.battery)
|
|
}
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + (expandingView.type == .download ? 2 : 3), execute: expandingViewDispatch!)
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@objc func initialMicStatus(_ notification: Notification) {
|
|
currentMicStatus = notification.userInfo?.first?.value as! Bool
|
|
}
|
|
|
|
func toggleMic() {
|
|
notifier.postNotification(name: notifier.toggleMicNotification.name, userInfo: nil)
|
|
}
|
|
|
|
func showEmpty() {
|
|
currentView = .home
|
|
}
|
|
}
|