Improve windows handling on macOS

This commit is contained in:
Arkadiusz Fal 2022-01-06 16:35:45 +01:00
parent 3baa7a6893
commit 8a74938b98
7 changed files with 91 additions and 59 deletions

View File

@ -50,7 +50,7 @@ final class NavigationModel: ObservableObject {
) {
let recent = RecentItem(from: channel)
#if os(macOS)
OpenWindow.main.open()
Windows.main.open()
#else
player.hide()
#endif

View File

@ -33,7 +33,7 @@ final class PlayerModel: ObservableObject {
@Published var streamSelection: Stream? { didSet { rebuildTVMenu() } }
@Published var queue = [PlayerQueueItem]() { didSet { Defaults[.queue] = queue } }
@Published var currentItem: PlayerQueueItem!
@Published var currentItem: PlayerQueueItem! { didSet { updateWindowTitle() }}
@Published var historyVideos = [Video]()
@Published var preservedTime: CMTime?
@ -103,13 +103,13 @@ final class PlayerModel: ObservableObject {
func show() {
guard !presentingPlayer else {
#if os(macOS)
OpenWindow.player.focus()
Windows.player.focus()
#endif
return
}
#if os(macOS)
OpenWindow.player.open()
OpenWindow.player.focus()
Windows.player.open()
Windows.player.focus()
#endif
presentingPlayer = true
}
@ -122,9 +122,9 @@ final class PlayerModel: ObservableObject {
func togglePlayer() {
#if os(macOS)
if !presentingPlayer {
OpenWindow.player.open()
Windows.player.open()
}
OpenWindow.player.focus()
Windows.player.focus()
#else
if presentingPlayer {
hide()
@ -804,6 +804,12 @@ final class PlayerModel: ObservableObject {
}
#endif
func updateWindowTitle() {
#if os(macOS)
Windows.player.window?.title = windowTitle
#endif
}
#if os(macOS)
var windowTitle: String {
currentVideo.isNil ? "Not playing" : "\(currentVideo!.title) - \(currentVideo!.author)"

View File

@ -14,7 +14,7 @@ struct OpenURLHandler {
}
#if os(macOS)
guard url.host != OpenWindow.player.location else {
guard url.host != Windows.player.location else {
return
}
#endif
@ -28,7 +28,7 @@ struct OpenURLHandler {
}
#if os(macOS)
OpenWindow.main.open()
Windows.main.open()
#endif
accounts.api.video(id).load().onSuccess { response in

View File

@ -47,12 +47,18 @@ struct YatteeApp: App {
.environmentObject(thumbnails)
.environmentObject(menu)
.environmentObject(search)
#if !os(macOS)
.onReceive(
NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)
) { _ in
player.handleEnterForeground()
}
#if os(macOS)
.background(
HostingWindowFinder { window in
Windows.mainWindow = window
}
)
#else
.onReceive(
NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)
) { _ in
player.handleEnterForeground()
}
#endif
#if os(iOS)
.handlesExternalEvents(preferring: Set(["*"]), allowing: Set(["*"]))
@ -81,6 +87,11 @@ struct YatteeApp: App {
#if os(macOS)
WindowGroup(player.windowTitle) {
VideoPlayerView()
.background(
HostingWindowFinder { window in
Windows.playerWindow = window
}
)
.onAppear { player.presentingPlayer = true }
.onDisappear { player.presentingPlayer = false }
.environment(\.managedObjectContext, persistenceController.container.viewContext)

View File

@ -240,7 +240,7 @@
37732FF22703A26300F04329 /* AccountValidationStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37732FEF2703A26300F04329 /* AccountValidationStatus.swift */; };
37732FF42703D32400F04329 /* Sidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37732FF32703D32400F04329 /* Sidebar.swift */; };
37732FF52703D32400F04329 /* Sidebar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37732FF32703D32400F04329 /* Sidebar.swift */; };
37737786276F9858000521C1 /* OpenWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37737785276F9858000521C1 /* OpenWindow.swift */; };
37737786276F9858000521C1 /* Windows.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37737785276F9858000521C1 /* Windows.swift */; };
3774122A27387B6C00423605 /* InstancesModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3774122927387B6C00423605 /* InstancesModelTests.swift */; };
3774122F27387C7600423605 /* VideosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376A33DF2720CAD6000C1D6B /* VideosApp.swift */; };
3774123327387CB000423605 /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372915E52687E3B900F5A35B /* Defaults.swift */; };
@ -690,7 +690,7 @@
376CD21526FBE18D001E1AC1 /* Instance+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Instance+Fixtures.swift"; sourceTree = "<group>"; };
37732FEF2703A26300F04329 /* AccountValidationStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountValidationStatus.swift; sourceTree = "<group>"; };
37732FF32703D32400F04329 /* Sidebar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sidebar.swift; sourceTree = "<group>"; };
37737785276F9858000521C1 /* OpenWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenWindow.swift; sourceTree = "<group>"; };
37737785276F9858000521C1 /* Windows.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Windows.swift; sourceTree = "<group>"; };
3774122927387B6C00423605 /* InstancesModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesModelTests.swift; sourceTree = "<group>"; };
377A20A82693C9A2002842B8 /* TypedContentAccessors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TypedContentAccessors.swift; sourceTree = "<group>"; };
3782B94E27553A6700990149 /* SearchSuggestions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSuggestions.swift; sourceTree = "<group>"; };
@ -1182,7 +1182,7 @@
37BE7AF227601DBF00DBECED /* Updates */,
374C0542272496E4009BDDBE /* AppDelegate.swift */,
37FD43DB270470B70073EE42 /* InstancesSettings.swift */,
37737785276F9858000521C1 /* OpenWindow.swift */,
37737785276F9858000521C1 /* Windows.swift */,
374108D0272B11B2006C5CC8 /* PictureInPictureDelegate.swift */,
37BE0BDB26A2367F0092E2DB /* Player.swift */,
37BE0BD926A214630092E2DB /* PlayerViewController.swift */,
@ -2060,7 +2060,7 @@
374710062755291C00CE0F87 /* SearchField.swift in Sources */,
378AE93F274EDFB5006A4EE1 /* Tint+Backport.swift in Sources */,
37C194C826F6A9C8005D3B96 /* RecentsModel.swift in Sources */,
37737786276F9858000521C1 /* OpenWindow.swift in Sources */,
37737786276F9858000521C1 /* Windows.swift in Sources */,
37BE0BDC26A2367F0092E2DB /* Player.swift in Sources */,
3743CA53270F284F00E4D32B /* View+Borders.swift in Sources */,
37599F39272B4D740087F250 /* FavoriteButton.swift in Sources */,

View File

@ -1,40 +0,0 @@
import AppKit
import Foundation
enum OpenWindow: String, CaseIterable {
case player, main
var window: NSWindow? {
// this is not solid but works as long as there is only two windows in the app
// needs to be changed in case we ever have more windows to handle
switch self {
case .player:
return NSApplication.shared.windows.last
case .main:
return NSApplication.shared.windows.first
}
}
func focus() {
window?.makeKeyAndOrderFront(self)
}
var location: String {
switch self {
case .player:
return rawValue
case .main:
return ""
}
}
func open() {
switch self {
case .player:
NSWorkspace.shared.open(URL(string: "yattee://\(location)")!)
case .main:
Self.main.focus()
}
}
}

55
macOS/Windows.swift Normal file
View File

@ -0,0 +1,55 @@
import AppKit
import Foundation
import SwiftUI
enum Windows: String, CaseIterable {
case player, main
static var mainWindow: NSWindow?
static var playerWindow: NSWindow?
weak var window: NSWindow? {
switch self {
case .player:
return Self.playerWindow
case .main:
return Self.mainWindow
}
}
func focus() {
window?.makeKeyAndOrderFront(self)
}
var location: String {
switch self {
case .player:
return rawValue
case .main:
return ""
}
}
func open() {
switch self {
case .player:
NSWorkspace.shared.open(URL(string: "yattee://\(location)")!)
case .main:
Self.main.focus()
}
}
}
struct HostingWindowFinder: NSViewRepresentable {
var callback: (NSWindow?) -> Void
func makeNSView(context _: Self.Context) -> NSView {
let view = NSView()
DispatchQueue.main.async { [weak view] in
self.callback(view?.window)
}
return view
}
func updateNSView(_: NSView, context _: Context) {}
}