Skip to content

Commit

Permalink
0.17.8: fix keyboard shortcuts on monterey
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiayang committed May 21, 2022
1 parent 399fcba commit c1883a7
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 43 deletions.
12 changes: 10 additions & 2 deletions MoeStreamer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
2B4077EB256D8B8C0054F4DC /* Socket in Frameworks */ = {isa = PBXBuildFile; productRef = 2B4077EA256D8B8C0054F4DC /* Socket */; };
2B520CA12537F2A400FECA0E /* DFRFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B520CA02537F2A400FECA0E /* DFRFoundation.framework */; };
2B743D9D25EE737D00CC7D1D /* AudioEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B743D9C25EE737D00CC7D1D /* AudioEngine.swift */; };
2B9B8BD22838DE78003C38F5 /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B9B8BD12838DE78003C38F5 /* Backport.swift */; };
2B9B8BD42838DEF9003C38F5 /* KeyboardShortcut.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B9B8BD32838DEF9003C38F5 /* KeyboardShortcut.swift */; };
2B9DB59E23F0074500950421 /* ListenMoeSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B9DB59D23F0074500950421 /* ListenMoeSession.swift */; };
2B9DB5A023F0085E00950421 /* ServiceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B9DB59F23F0085E00950421 /* ServiceController.swift */; };
2BA155DB254125B300BB33FF /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 2BA155DA254125B300BB33FF /* Introspect */; };
Expand Down Expand Up @@ -102,6 +104,8 @@
2B520CA02537F2A400FECA0E /* DFRFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DFRFoundation.framework; path = ../../../../System/Library/PrivateFrameworks/DFRFoundation.framework; sourceTree = "<group>"; };
2B743D9C25EE737D00CC7D1D /* AudioEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioEngine.swift; sourceTree = "<group>"; };
2B84385923F0208D00291BDA /* SwiftyJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyJSON.framework; path = Carthage/Build/Mac/SwiftyJSON.framework; sourceTree = "<group>"; };
2B9B8BD12838DE78003C38F5 /* Backport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Backport.swift; sourceTree = "<group>"; };
2B9B8BD32838DEF9003C38F5 /* KeyboardShortcut.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardShortcut.swift; sourceTree = "<group>"; };
2B9DB59D23F0074500950421 /* ListenMoeSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListenMoeSession.swift; sourceTree = "<group>"; };
2B9DB59F23F0085E00950421 /* ServiceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceController.swift; sourceTree = "<group>"; };
2BA283F523F08201008E0DEB /* KeychainSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = KeychainSwift.framework; path = Carthage/Build/Mac/KeychainSwift.framework; sourceTree = "<group>"; };
Expand Down Expand Up @@ -356,6 +360,8 @@
2BE995E523FB9BB10092023C /* VolumeSlider.swift */,
2BE995E723FB9BD40092023C /* ScrollView.swift */,
2BE995F123FBAB340092023C /* PopupButton.swift */,
2B9B8BD12838DE78003C38F5 /* Backport.swift */,
2B9B8BD32838DEF9003C38F5 /* KeyboardShortcut.swift */,
);
path = wrappers;
sourceTree = "<group>";
Expand Down Expand Up @@ -473,6 +479,7 @@
buildActionMask = 2147483647;
files = (
2B22659F25412DB600F970B9 /* ListenMoeController.swift in Sources */,
2B9B8BD22838DE78003C38F5 /* Backport.swift in Sources */,
2BD486C423EFE3030066F1C4 /* MainView.swift in Sources */,
2BCFF60223F1DF9700A58EFE /* Logger.swift in Sources */,
2B4077E6256D74810054F4DC /* Client.swift in Sources */,
Expand All @@ -497,6 +504,7 @@
2BE995F023FBA0CE0092023C /* AudioController.swift in Sources */,
2BD486D523EFE6C20066F1C4 /* ViewController.swift in Sources */,
2B125D7D253753D1000C45C5 /* MediaKeyHandler.swift in Sources */,
2B9B8BD42838DEF9003C38F5 /* KeyboardShortcut.swift in Sources */,
2B9DB5A023F0085E00950421 /* ServiceController.swift in Sources */,
2BA9071923F0731300782C94 /* Settings.swift in Sources */,
2BECD3EB2577852F00FF2544 /* InsomniaInducer.swift in Sources */,
Expand Down Expand Up @@ -665,7 +673,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 0.17.7;
MARKETING_VERSION = 0.17.8;
PRODUCT_BUNDLE_IDENTIFIER = com.zhiayang.MoeStreamer;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "";
Expand Down Expand Up @@ -700,7 +708,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 0.17.7;
MARKETING_VERSION = 0.17.8;
PRODUCT_BUNDLE_IDENTIFIER = com.zhiayang.MoeStreamer;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "";
Expand Down
2 changes: 1 addition & 1 deletion MoeStreamer/src/backends/itunes/LocalMusic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ class LocalMusicController : ServiceController

func getCapabilities() -> ServiceCapabilities
{
return [ .nextTrack, .searchTracks, .timeInfo ]
return [ .nextTrack, .previousTrack, .searchTracks, .timeInfo ]
}

func setViewModel(viewModel: ViewModel)
Expand Down
32 changes: 31 additions & 1 deletion MoeStreamer/src/ui/MainView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ struct MainView : View
// .border(Color.yellow)

HStack(spacing: 2) {
ShortcutMaker(shortcuts: [" ", "k"]) {
self.model.isPlaying.toggle()
self.model.poke()
}

// play/pause button
Button(action: {
self.model.isPlaying.toggle()
Expand All @@ -105,6 +110,10 @@ struct MainView : View
// skip button
if self.model.controller().getCapabilities().contains(.nextTrack)
{
ShortcutMaker(shortcuts: ["l"]) {
self.model.controller().nextSong()
}

Button(action: {
self.model.controller().nextSong()
}) {
Expand All @@ -117,9 +126,22 @@ struct MainView : View
.buttonStyle(PlainButtonStyle())
}

// previous (but we don't have a button for this)
if self.model.controller().getCapabilities().contains(.previousTrack)
{
ShortcutMaker(shortcuts: ["j"], action: {
self.model.controller().previousSong()
})
}


// favourite/unfavourite button
if self.model.controller().getCapabilities().contains(.favourite)
{
ShortcutMaker(shortcuts: ["f"]) {
self.model.controller().toggleFavourite()
}

Button(action: {
self.model.controller().toggleFavourite()
}) {
Expand Down Expand Up @@ -147,6 +169,11 @@ struct MainView : View


// mute/unmute button
ShortcutMaker(shortcuts: ["m"]) {
self.model.isMuted.toggle()
self.model.poke()
}

Button(action: {
self.model.isMuted.toggle()
self.model.poke()
Expand All @@ -155,7 +182,6 @@ struct MainView : View
.resizable()
.frame(width: 24, height: 24)
.foregroundColor(self.iconColour)
// .border(Color.green)
}
.buttonStyle(PlainButtonStyle())

Expand Down Expand Up @@ -197,6 +223,10 @@ struct MainView : View
// if the backend doesn't support search (eg. listen.moe) then don't show the button, duh
if self.model.controller().getCapabilities().contains(.searchTracks)
{
ShortcutMaker(shortcuts: ["/"]) {
self.currentSubView.toggle(into: .Search)
}

Button(action: {
self.currentSubView.toggle(into: .Search)
}) {
Expand Down
80 changes: 41 additions & 39 deletions MoeStreamer/src/ui/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,47 +128,49 @@ class ViewController : NSObject, NSPopoverDelegate
popover.behavior = .transient
popover.delegate = self

popover.keydownHandler = { (event) in
switch event.characters?.first?.asciiValue
{
case UInt8(ascii: "m"):
self.viewModel.isMuted.toggle()
self.viewModel.poke()

case UInt8(ascii: " "): fallthrough
case UInt8(ascii: "k"):
self.viewModel.isPlaying.toggle()
self.viewModel.poke()

case UInt8(ascii: "j"):
self.viewModel.controller().previousSong()

case UInt8(ascii: "l"):
self.viewModel.controller().nextSong()

case UInt8(ascii: "f"):
self.viewModel.controller().toggleFavourite()

case UInt8(ascii: "\u{1b}"):
if self.rootView.currentSubView == .None
{
self.popover.performClose(nil)
}
else
{
self.rootView.currentSubView.toggle(into: .None)
}

case UInt8(ascii: "/"):
if self.viewModel.controller().getCapabilities().contains(.searchTracks)
{
self.rootView.currentSubView.toggle(into: .Search)
if #available(macOS 11.0, *)
{
popover.keydownHandler = { (event) in
switch event.characters?.first?.asciiValue
{
case UInt8(ascii: "m"):
self.viewModel.isMuted.toggle()
self.viewModel.poke()
}

case UInt8(ascii: " "): fallthrough
case UInt8(ascii: "k"):
self.viewModel.isPlaying.toggle()
self.viewModel.poke()

default:
break
case UInt8(ascii: "j"):
self.viewModel.controller().previousSong()

case UInt8(ascii: "l"):
self.viewModel.controller().nextSong()

case UInt8(ascii: "f"):
self.viewModel.controller().toggleFavourite()

case UInt8(ascii: "\u{1b}"):
if self.rootView.currentSubView == .None
{
self.popover.performClose(nil)
}
else
{
self.rootView.currentSubView.toggle(into: .None)
}

case UInt8(ascii: "/"):
if self.viewModel.controller().getCapabilities().contains(.searchTracks)
{
self.rootView.currentSubView.toggle(into: .Search)
self.viewModel.poke()
}

default:
break
}
}
}
}
Expand All @@ -192,7 +194,7 @@ class ViewController : NSObject, NSPopoverDelegate
func showPopover()
{
self.popover.show(relativeTo: statusBarButton.bounds, of: statusBarButton,
preferredEdge: NSRectEdge.maxY)
preferredEdge: NSRectEdge.minY)
self.popover.contentViewController?.view.window?.makeKey()
}

Expand Down
20 changes: 20 additions & 0 deletions MoeStreamer/src/ui/wrappers/Backport.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Backport.swift
// Copyright (c) 2022, zhiayang
// SPDX-License-Identifier: Apache-2.0

// https://developer.apple.com/forums/thread/689189

import SwiftUI
import Foundation

struct Backport<Content: View>
{
let content: Content
}

extension View
{
var montereyCompat: Backport<Self> {
Backport(content: self)
}
}
50 changes: 50 additions & 0 deletions MoeStreamer/src/ui/wrappers/KeyboardShortcut.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// KeyboardShortcut.swift
// Copyright (c) 2022, zhiayang
// SPDX-License-Identifier: Apache-2.0

import SwiftUI
import Foundation

extension Backport
{
@ViewBuilder func keyboardShortcut(key: Character) -> some View
{
if #available(macOS 11.0, *)
{
content.keyboardShortcut(KeyEquivalent(key), modifiers: [])
}
else
{
self.content
}
}
}

struct ShortcutMaker: View
{
let shortcuts: [Character]
let action: () -> Void

var body: some View {
ZStack {
ForEach(self.shortcuts, id: \.self) { key in
Button(action: self.action) {
EmptyView()
}
.montereyCompat
.keyboardShortcut(key: key)
.buttonStyle(.borderless)
.fixedSize()
.frame(width: 0.0, height: 0.0)
.padding(0)
.clipped()
.hidden()
}
}
.fixedSize()
.frame(width: 0.0, height: 0.0)
.padding(0)
.clipped()
.hidden()
}
}

0 comments on commit c1883a7

Please sign in to comment.