mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-08 08:39:59 +00:00
Improve optional checking in native selector
This commit is contained in:
@@ -2,47 +2,30 @@ import Cocoa
|
||||
|
||||
|
||||
class AppDelegate : NSObject, NSApplicationDelegate {
|
||||
var initData: InitData!
|
||||
|
||||
var mainWindow: NSWindow?
|
||||
var mainWindowController: NSWindowController?
|
||||
var mainWindowViewController: ViewController?
|
||||
|
||||
|
||||
func applicationDidFinishLaunching (_ aNotification: Notification) {
|
||||
if CommandLine.argc < 2 {
|
||||
fputs("Error: Not enough args\n", stderr)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
guard let data = CommandLine.arguments[1].data(using: .utf8) else {
|
||||
fputs("Error: Failed to convert input to data\n", stderr)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
do {
|
||||
// Decode and store initialization JSON data
|
||||
self.initData = try JSONDecoder().decode(InitData.self, from: data)
|
||||
} catch {
|
||||
fputs("Error: Failed to parse input data\n (\(error))", stderr)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
|
||||
let window = NSWindow(
|
||||
contentRect: NSZeroRect
|
||||
, styleMask: [ .titled, .closable ]
|
||||
, backing: .buffered
|
||||
, defer: false)
|
||||
|
||||
let screenHeight = NSScreen.main!.frame.height
|
||||
|
||||
window.titleVisibility = .hidden
|
||||
window.isMovableByWindowBackground = true
|
||||
window.orderFrontRegardless()
|
||||
window.setFrameTopLeftPoint(NSPoint(
|
||||
x: self.initData.windowPositionX
|
||||
, y: Int(screenHeight - CGFloat(self.initData.windowPositionY))))
|
||||
|
||||
if let screen = NSScreen.main {
|
||||
let windowX = InitDataProvider.shared.data.windowPositionX
|
||||
let windowY = Int(screen.frame.height - CGFloat(
|
||||
InitDataProvider.shared.data.windowPositionY))
|
||||
|
||||
window.setFrameTopLeftPoint(NSPoint(x: windowX, y: windowY))
|
||||
}
|
||||
|
||||
|
||||
let windowController = NSWindowController(window: window)
|
||||
windowController.showWindow(window)
|
||||
@@ -59,7 +42,7 @@ class AppDelegate : NSObject, NSApplicationDelegate {
|
||||
}
|
||||
|
||||
func applicationDidResignActive (_ aNotification: Notification) {
|
||||
if self.initData.closeIfFocusLost {
|
||||
if InitDataProvider.shared.data.closeIfFocusLost {
|
||||
self.mainWindow?.performClose(aNotification)
|
||||
}
|
||||
}
|
||||
|
||||
20
app/NativeMacReceiverSelector/InitDataProvider.swift
Normal file
20
app/NativeMacReceiverSelector/InitDataProvider.swift
Normal file
@@ -0,0 +1,20 @@
|
||||
import Cocoa
|
||||
|
||||
class InitDataProvider {
|
||||
static let shared = InitDataProvider()
|
||||
|
||||
let data: InitData
|
||||
|
||||
private init() {
|
||||
if CommandLine.argc < 2 {
|
||||
fatalError("Missing init data")
|
||||
}
|
||||
|
||||
if let input = CommandLine.arguments[1].data(using: .utf8)
|
||||
, let parsed = try? JSONDecoder().decode(InitData.self, from: input) {
|
||||
self.data = parsed
|
||||
} else {
|
||||
fatalError("Failed to convert and parse init data")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ class ReceiverView : NSStackView {
|
||||
super.init(coder: coder)
|
||||
}
|
||||
|
||||
init (receiver: Receiver, initData: InitData) {
|
||||
init (receiver: Receiver) {
|
||||
super.init(frame: NSZeroRect)
|
||||
|
||||
self.receiver = receiver
|
||||
@@ -63,7 +63,7 @@ class ReceiverView : NSStackView {
|
||||
|
||||
|
||||
self.castButton = NSButton(
|
||||
title: initData.i18n_castButtonTitle
|
||||
title: InitDataProvider.shared.data.i18n_castButtonTitle
|
||||
, target: self
|
||||
, action: #selector(ReceiverView.onCast))
|
||||
|
||||
@@ -89,12 +89,14 @@ class ReceiverView : NSStackView {
|
||||
if !constraintsSet {
|
||||
self.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
self.leadingAnchor.constraint(
|
||||
equalTo: superview!.leadingAnchor
|
||||
, constant: 8).isActive = true
|
||||
self.trailingAnchor.constraint(
|
||||
equalTo: superview!.trailingAnchor
|
||||
, constant: -8).isActive = true
|
||||
if let superview = self.superview {
|
||||
self.leadingAnchor.constraint(
|
||||
equalTo: superview.leadingAnchor
|
||||
, constant: 8).isActive = true
|
||||
self.trailingAnchor.constraint(
|
||||
equalTo: superview.trailingAnchor
|
||||
, constant: -8).isActive = true
|
||||
}
|
||||
|
||||
constraintsSet = true
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ import Cocoa
|
||||
|
||||
|
||||
class ViewController : NSViewController {
|
||||
var initData: InitData!
|
||||
|
||||
var mediaTypePopUpButton: NSPopUpButton!
|
||||
var receiverViews = [ReceiverView]()
|
||||
|
||||
@@ -21,7 +19,7 @@ class ViewController : NSViewController {
|
||||
override func viewDidLoad () {
|
||||
super.viewDidLoad()
|
||||
|
||||
self.initData = (NSApplication.shared.delegate as! AppDelegate).initData
|
||||
let initData = InitDataProvider.shared.data
|
||||
|
||||
/**
|
||||
* View Hierarchy
|
||||
@@ -59,27 +57,27 @@ class ViewController : NSViewController {
|
||||
, initData.i18n_mediaTypeFile
|
||||
])
|
||||
|
||||
let mediaTypePopUpButtonMenu = self.mediaTypePopUpButton.menu!
|
||||
mediaTypePopUpButtonMenu.delegate = self
|
||||
if let appItem = self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeApp)
|
||||
, let tabItem = self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeTab)
|
||||
, let screenItem = self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeScreen)
|
||||
, let fileItem = self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeFile) {
|
||||
|
||||
let appItem = self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeApp)!
|
||||
let tabItem = self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeTab)!
|
||||
let screenItem = self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeScreen)!
|
||||
let fileItem = self.mediaTypePopUpButton
|
||||
.item(withTitle: initData.i18n_mediaTypeFile)!
|
||||
if let mediaTypePopUpButtonMenu = self.mediaTypePopUpButton.menu {
|
||||
mediaTypePopUpButtonMenu.delegate = self
|
||||
mediaTypePopUpButtonMenu.insertItem(NSMenuItem.separator()
|
||||
, at: mediaTypePopUpButtonMenu.index(of: fileItem))
|
||||
}
|
||||
|
||||
mediaTypePopUpButtonMenu
|
||||
.insertItem(NSMenuItem.separator()
|
||||
, at: mediaTypePopUpButtonMenu.index(of: fileItem))
|
||||
|
||||
// Set tags to enum value
|
||||
appItem.tag = MediaType.app.rawValue
|
||||
tabItem.tag = MediaType.tab.rawValue
|
||||
screenItem.tag = MediaType.screen.rawValue
|
||||
fileItem.tag = MediaType.file.rawValue
|
||||
// Set tags to enum value
|
||||
appItem.tag = MediaType.app.rawValue
|
||||
tabItem.tag = MediaType.tab.rawValue
|
||||
screenItem.tag = MediaType.screen.rawValue
|
||||
fileItem.tag = MediaType.file.rawValue
|
||||
}
|
||||
|
||||
for item in self.mediaTypePopUpButton.itemArray {
|
||||
if (initData.availableMediaTypes & item.tag) == 0 {
|
||||
@@ -121,15 +119,12 @@ class ViewController : NSViewController {
|
||||
let receiverSeparator = NSBox()
|
||||
receiverSeparator.boxType = .separator
|
||||
|
||||
let receiverView = ReceiverView(
|
||||
receiver: receiver
|
||||
, initData: self.initData)
|
||||
|
||||
let receiverView = ReceiverView(receiver: receiver)
|
||||
receiverView.receiverViewDelegate = self
|
||||
|
||||
if UInt(initData!.availableMediaTypes) == 0
|
||||
|| (initData!.availableMediaTypes
|
||||
& initData!.defaultMediaType.rawValue) == 0 {
|
||||
if UInt(initData.availableMediaTypes) == 0
|
||||
|| (initData.availableMediaTypes
|
||||
& initData.defaultMediaType.rawValue) == 0 {
|
||||
receiverView.isEnabled = false
|
||||
}
|
||||
|
||||
@@ -149,26 +144,33 @@ class ViewController : NSViewController {
|
||||
|
||||
override func viewDidAppear () {
|
||||
// Set window title and update visibility
|
||||
let window = self.view.window!
|
||||
window.title = initData.i18n_extensionName
|
||||
window.titleVisibility = .visible
|
||||
if let window = self.view.window {
|
||||
window.title = InitDataProvider.shared.data.i18n_extensionName
|
||||
window.titleVisibility = .visible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ViewController : NSMenuDelegate {
|
||||
func menuDidClose (_ menu: NSMenu) {
|
||||
let mediaType = MediaType(
|
||||
rawValue: self.mediaTypePopUpButton.selectedItem!.tag)!
|
||||
let initData = InitDataProvider.shared.data
|
||||
|
||||
if self.initData.availableMediaTypes & mediaType.rawValue != 0 {
|
||||
guard let selectedItem = self.mediaTypePopUpButton.selectedItem
|
||||
, let mediaType = MediaType(rawValue: selectedItem.tag) else {
|
||||
return
|
||||
}
|
||||
|
||||
if initData.availableMediaTypes & mediaType.rawValue != 0 {
|
||||
for receiverView in self.receiverViews {
|
||||
receiverView.isEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
let fileItem = self.mediaTypePopUpButton
|
||||
guard let fileItem = self.mediaTypePopUpButton
|
||||
.item(at: self.mediaTypePopUpButton.indexOfItem(
|
||||
withTag: MediaType.file.rawValue))!
|
||||
withTag: MediaType.file.rawValue)) else {
|
||||
return
|
||||
}
|
||||
|
||||
if (mediaType == .file) {
|
||||
let panel = NSOpenPanel()
|
||||
@@ -178,7 +180,9 @@ extension ViewController : NSMenuDelegate {
|
||||
panel.canCreateDirectories = false
|
||||
panel.canChooseFiles = true
|
||||
|
||||
panel.beginSheetModal(for: self.view.window!) { (result) in
|
||||
guard let window = self.view.window else { return }
|
||||
|
||||
panel.beginSheetModal(for: window) { (result) in
|
||||
if (result == .OK) {
|
||||
let url = panel.urls[0]
|
||||
let fileName = url.lastPathComponent
|
||||
@@ -194,14 +198,21 @@ extension ViewController : NSMenuDelegate {
|
||||
} else {
|
||||
// Re-select the default media type item
|
||||
self.mediaTypePopUpButton.selectItem(
|
||||
withTag: self.initData.defaultMediaType.rawValue)
|
||||
withTag: initData.defaultMediaType.rawValue)
|
||||
|
||||
let defaultMediaTypeAvailable = initData.availableMediaTypes
|
||||
& initData.defaultMediaType.rawValue != 0
|
||||
|
||||
for receiverView in self.receiverViews {
|
||||
receiverView.isEnabled = defaultMediaTypeAvailable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Reset file item
|
||||
fileItem.title = self.initData.i18n_mediaTypeFile
|
||||
fileItem.title = initData.i18n_mediaTypeFile
|
||||
self.filePath = nil
|
||||
}
|
||||
}
|
||||
@@ -217,23 +228,23 @@ extension ViewController : ReceiverViewDelegate {
|
||||
receiverView.isEnabled = false
|
||||
}
|
||||
|
||||
do {
|
||||
let mediaType = MediaType(
|
||||
rawValue: self.mediaTypePopUpButton.selectedItem!.tag)!
|
||||
|
||||
let selection = ReceiverSelection(
|
||||
receiver: receiver
|
||||
, mediaType: mediaType
|
||||
, filePath: self.filePath ?? nil)
|
||||
guard let selectedItem = self.mediaTypePopUpButton.selectedItem
|
||||
, let mediaType = MediaType(rawValue: selectedItem.tag) else {
|
||||
return
|
||||
}
|
||||
|
||||
let jsonData = try JSONEncoder().encode(selection)
|
||||
let jsonString = String(data: jsonData, encoding: .utf8)
|
||||
let selection = ReceiverSelection(
|
||||
receiver: receiver
|
||||
, mediaType: mediaType
|
||||
, filePath: self.filePath ?? nil)
|
||||
|
||||
print(jsonString!)
|
||||
if let jsonData = try? JSONEncoder().encode(selection)
|
||||
, let jsonString = String(data: jsonData, encoding: .utf8) {
|
||||
print(jsonString)
|
||||
fflush(stdout)
|
||||
} catch {
|
||||
fputs("Error: Failed to encode output data", stderr)
|
||||
exit(1)
|
||||
} else {
|
||||
fatalError("Error: Failed to encode output data")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user