Skip to content

Commit 44dd052

Browse files
committed
macOS: rework window menu
1 parent 084f127 commit 44dd052

File tree

3 files changed

+74
-30
lines changed

3 files changed

+74
-30
lines changed

Amperfy/AppDelegate.swift

+58-24
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,18 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
378378
return nil
379379
}
380380

381+
#if targetEnvironment(macCatalyst)
382+
var isMainOrMiniPlayerPlayerOpen: Bool {
383+
return isMainWindowOpen || isShowingMiniPlayer
384+
}
385+
386+
var isMainWindowOpen: Bool {
387+
return !UIApplication.shared.connectedScenes
388+
.flatMap { ($0 as? UIWindowScene)?.windows ?? [] }
389+
.filter { ($0.rootViewController as? SplitVC) != nil }
390+
.isEmpty
391+
}
392+
381393
func closeMainWindow() {
382394
// Close all main sessions (this might be more than one with multiple tabs open)
383395
UIApplication.shared.connectedScenes
@@ -395,25 +407,60 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
395407
let defaultActivity = NSUserActivity(activityType: defaultWindowActivityType)
396408
UIApplication.shared.requestSceneSessionActivation(nil, userActivity: defaultActivity, options: nil, errorHandler: nil)
397409
}
398-
399-
#if targetEnvironment(macCatalyst)
410+
411+
public func rebuildMainMenu() {
412+
UIMenuSystem.main.setNeedsRebuild()
413+
}
400414

401415
override func buildMenu(with builder: any UIMenuBuilder) {
402416
super.buildMenu(with: builder)
403417

404418
guard builder.system == .main else { return }
405419

406-
// Add a settings menu
407-
let settingsMenu = UIMenu(options: .displayInline, children: [
408-
UIKeyCommand(title: "Settings…", action: #selector(showSettings), input: ",", modifierFlags: .command)
420+
// Add File menu
421+
let fileMenu = UIMenu(title: "File", children: [
422+
UIMenu(options: .displayInline, children: [
423+
UIAction(title: "Open Player Window", attributes: self.isMainOrMiniPlayerPlayerOpen ? .disabled : []) { _ in
424+
self.openMainWindow()
425+
},
426+
UIAction(title: "Close Player Window", attributes: !self.isMainOrMiniPlayerPlayerOpen ? .disabled : []) { _ in
427+
if self.isMainWindowOpen {
428+
self.closeMainWindow()
429+
} else if self.isShowingMiniPlayer {
430+
self.closeMiniPlayer()
431+
}
432+
}
433+
]),
434+
UIMenu(options: .displayInline, children: [
435+
UIAction(title: "Switch Library/Mini Player") { _ in
436+
if self.isShowingMiniPlayer {
437+
self.closeMiniPlayer()
438+
self.openMainWindow()
439+
} else {
440+
self.closeMainWindow()
441+
self.showMiniPlayer()
442+
}
443+
}
444+
]),
445+
// Add a settings menu
446+
UIMenu(options: .displayInline, children: [
447+
UIKeyCommand(title: "Open Settings", action: #selector(showSettings), input: ",", modifierFlags: .command)
448+
])
409449
])
410-
builder.insertSibling(settingsMenu, afterMenu: .about)
450+
builder.insertSibling(fileMenu, beforeMenu: .view)
451+
411452
// Add media controls
412453
builder.insertSibling(buildControlsMenu(), afterMenu: .view)
413454

414-
// Remove "new window" and toolbar options
455+
// Remove not needed default menu items
415456
builder.remove(menu: .toolbar)
416-
builder.remove(menu: .newScene)
457+
builder.remove(menu: .file)
458+
builder.remove(menu: .edit)
459+
builder.remove(menu: .format)
460+
builder.remove(menu: .font)
461+
builder.remove(menu: .text)
462+
builder.remove(menu: .services)
463+
builder.remove(menu: .help)
417464

418465
if (self.focusedWindowTitle == windowSettingsTitle) || (self.focusedWindowTitle == windowMiniPlayerTitle) {
419466
// Do any settings specific menu setup here
@@ -499,25 +546,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
499546
}
500547

501548
let section3 = [
502-
UIAction(title: self.player.playerMode.nextMode.description) { _ in
549+
UIAction(title: "Switch Music/Podcast mode") { _ in
503550
self.player.setPlayerMode(self.player.playerMode.nextMode)
504551
}
505552
]
506553

507-
let section4 = [
508-
UIAction(title: self.isShowingMiniPlayer ? "Main Window" : "Mini Player") { _ in
509-
if self.isShowingMiniPlayer {
510-
self.closeMiniPlayer()
511-
// Is automatically opened
512-
//self.openMainWindow()
513-
} else {
514-
self.closeMainWindow()
515-
self.showMiniPlayer()
516-
}
517-
}
518-
]
519-
520-
let sections: [[UIMenuElement]] = [section1, section2, section3, section4]
554+
let sections: [[UIMenuElement]] = [section1, section2, section3]
521555

522556
return UIMenu(title: "Controls", children: sections.reduce([], { (result, section) in
523557
result + [UIMenu(options: .displayInline)] + section
@@ -547,7 +581,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
547581
UIApplication.shared.requestSceneSessionDestruction($0.session, options: options, errorHandler: nil)
548582
}
549583
}
550-
#endif
584+
#endif
551585
}
552586

553587
#if targetEnvironment(macCatalyst)

Amperfy/MiniPlayerSceneDelegate.swift

+10-6
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ class MiniPlayerSceneDelegate: UIResponder, UIWindowSceneDelegate {
4646
self.window = UIWindow(windowScene: windowScene)
4747
self.window?.backgroundColor = .secondarySystemBackground
4848

49-
#if targetEnvironment(macCatalyst)
50-
49+
#if targetEnvironment(macCatalyst)
5150
windowScene.title = windowMiniPlayerTitle
5251

5352
if let titleBar = windowScene.titlebar {
@@ -73,13 +72,14 @@ class MiniPlayerSceneDelegate: UIResponder, UIWindowSceneDelegate {
7372
windowScene.sizeRestrictions?.allowsFullScreen = false
7473
}
7574
windowScene.sizeRestrictions?.minimumSize = minSize
76-
77-
#endif
75+
#endif
7876

7977
self.window?.rootViewController = PopupPlayerVC()
8078
self.window?.makeKeyAndVisible()
8179

80+
#if targetEnvironment(macCatalyst)
8281
self.appDelegate.closeMainWindow()
82+
#endif
8383
}
8484

8585
/** Called when the user activates your application by selecting a shortcut on the Home Screen,
@@ -98,14 +98,18 @@ class MiniPlayerSceneDelegate: UIResponder, UIWindowSceneDelegate {
9898
// Release any resources associated with this scene that can be re-created the next time the scene connects.
9999
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
100100
os_log("MiniPlayer: sceneDidDisconnect", log: self.log, type: .info)
101-
102-
self.appDelegate.openMainWindow()
101+
#if targetEnvironment(macCatalyst)
102+
appDelegate.rebuildMainMenu()
103+
#endif
103104
}
104105

105106
func sceneDidBecomeActive(_ scene: UIScene) {
106107
// Called when the scene has moved from an inactive state to an active state.
107108
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
108109
os_log("MiniPlayer: sceneDidBecomeActive", log: self.log, type: .info)
110+
#if targetEnvironment(macCatalyst)
111+
appDelegate.rebuildMainMenu()
112+
#endif
109113
}
110114

111115
func sceneWillResignActive(_ scene: UIScene) {

Amperfy/SceneDelegate.swift

+6
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,19 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
120120
// Release any resources associated with this scene that can be re-created the next time the scene connects.
121121
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
122122
os_log("sceneDidDisconnect", log: self.log, type: .info)
123+
#if targetEnvironment(macCatalyst)
124+
appDelegate.rebuildMainMenu()
125+
#endif
123126
}
124127

125128
func sceneDidBecomeActive(_ scene: UIScene) {
126129
// Called when the scene has moved from an inactive state to an active state.
127130
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
128131
os_log("sceneDidBecomeActive", log: self.log, type: .info)
129132
appDelegate.quickActionsManager.handleSavedShortCutItemIfSaved()
133+
#if targetEnvironment(macCatalyst)
134+
appDelegate.rebuildMainMenu()
135+
#endif
130136
}
131137

132138
func sceneWillResignActive(_ scene: UIScene) {

0 commit comments

Comments
 (0)