Add file media type to receiver selectors

This commit is contained in:
hensm
2019-07-09 16:04:11 +01:00
parent 70e05566fa
commit 615f158832
10 changed files with 141 additions and 29 deletions

View File

@@ -8,15 +8,9 @@ class AppDelegate : NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching (_ aNotification: Notification) {
let window = NSPanel(
let window = NSWindow(
contentRect: NSZeroRect
, styleMask: [
.titled
, .closable
, .hudWindow
, .utilityWindow
, .nonactivatingPanel
]
, styleMask: [ .titled, .closable ]
, backing: .buffered
, defer: false)

View File

@@ -7,13 +7,15 @@ class ViewController : NSViewController {
var mediaTypePopUpButton: NSPopUpButton!
var receiverViews = [ReceiverView]()
var filePath: String?
override func loadView () {
let visualEffectView = NSVisualEffectView()
/*let visualEffectView = NSVisualEffectView()
visualEffectView.blendingMode = .behindWindow
visualEffectView.state = .active
visualEffectView.state = .active*/
self.view = visualEffectView
self.view = NSView()
}
override func viewDidLoad () {
@@ -71,34 +73,35 @@ class ViewController : NSViewController {
initData.i18n_mediaTypeApp
, initData.i18n_mediaTypeTab
, initData.i18n_mediaTypeScreen
, initData.i18n_mediaTypeFile
])
let mediaTypePopUpButtonMenu = self.mediaTypePopUpButton.menu!
mediaTypePopUpButtonMenu.delegate = self
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)!
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
if (initData.availableMediaTypes & appItem.tag) == 0 {
self.mediaTypePopUpButton
.item(withTitle: initData.i18n_mediaTypeApp)?
.isEnabled = false
}
if (initData.availableMediaTypes & tabItem.tag) == 0 {
self.mediaTypePopUpButton
.item(withTitle: initData.i18n_mediaTypeTab)?
.isEnabled = false
}
if (initData.availableMediaTypes & screenItem.tag) == 0 {
self.mediaTypePopUpButton
.item(withTitle: initData.i18n_mediaTypeScreen)?
.isEnabled = false
for item in self.mediaTypePopUpButton.itemArray {
if (initData.availableMediaTypes & item.tag) == 0 {
item.isEnabled = false
}
}
self.mediaTypePopUpButton.selectItem(
@@ -155,6 +158,50 @@ class ViewController : NSViewController {
}
}
extension ViewController : NSMenuDelegate {
func menuDidClose (_ menu: NSMenu) {
let mediaType = MediaType(
rawValue: self.mediaTypePopUpButton.selectedItem!.tag)!
let fileItem = self.mediaTypePopUpButton
.item(at: self.mediaTypePopUpButton.indexOfItem(
withTag: MediaType.file.rawValue))!
if (mediaType == .file) {
let panel = NSOpenPanel()
panel.allowsMultipleSelection = false
panel.allowedFileTypes = [ "aac", "mp3", "mp4", "wav", "webm" ]
panel.canChooseDirectories = false
panel.canCreateDirectories = false
panel.canChooseFiles = true
panel.beginSheetModal(for: self.view.window!) { (result) in
if (result == .OK) {
let url = panel.urls[0]
let fileName = url.lastPathComponent
// Truncate file name and set as title
fileItem.title = fileName.count > 12
? "\(fileName.prefix(12))..."
: fileName
self.filePath = url.path
return
} else {
// Re-select the default media type item
self.mediaTypePopUpButton.selectItem(
withTag: self.initData.defaultMediaType.rawValue)
}
}
}
// Reset file item
fileItem.title = self.initData.i18n_mediaTypeFile
self.filePath = nil
}
}
extension ViewController : ReceiverViewDelegate {
func didCast (_ receiver: Receiver) {
@@ -173,7 +220,8 @@ extension ViewController : ReceiverViewDelegate {
let selection = ReceiverSelection(
receiver: receiver
, mediaType: mediaType)
, mediaType: mediaType
, filePath: self.filePath ?? nil)
let jsonData = try JSONEncoder().encode(selection)
let jsonString = String(data: jsonData, encoding: .utf8)

View File

@@ -8,6 +8,7 @@ struct InitData : Codable {
let i18n_mediaTypeApp: String
let i18n_mediaTypeTab: String
let i18n_mediaTypeScreen: String
let i18n_mediaTypeFile: String
let i18n_mediaSelectCastLabel: String
let i18n_mediaSelectToLabel: String
}

View File

@@ -5,4 +5,5 @@ enum MediaType: Int, Codable {
case app = 1
case tab = 2
case screen = 4
case file = 8
}

View File

@@ -1,4 +1,5 @@
struct ReceiverSelection : Codable {
let receiver: Receiver
let mediaType: MediaType
let filePath: String?
}

View File

@@ -21,6 +21,10 @@
"message": "Screen"
, "description": "Receiver selector media type <option> text for screen."
}
, "popupMediaTypeFile": {
"message": "Browse..."
, "description": "Receiver selector media type <option> text for opening a file selector dialog."
}
, "popupMediaSelectCastLabel": {
"message": "Cast"

View File

@@ -70,6 +70,7 @@ export default class NativeMacReceiverSelector
, i18n_mediaTypeApp: _("popupMediaTypeApp")
, i18n_mediaTypeTab: _("popupMediaTypeTab")
, i18n_mediaTypeScreen: _("popupMediaTypeScreen")
, i18n_mediaTypeFile: _("popupMediaTypeFile")
, i18n_mediaSelectCastLabel: _("popupMediaSelectCastLabel")
, i18n_mediaSelectToLabel: _("popupMediaSelectToLabel")
})

View File

@@ -7,11 +7,13 @@ export enum ReceiverSelectorMediaType {
App = 1
, Tab = 2
, Screen = 4
, File = 8
}
export interface ReceiverSelection {
receiver: Receiver;
mediaType: ReceiverSelectorMediaType;
filePath?: string;
}
export type ReceiverSelectorSelectedEvent = CustomEvent<ReceiverSelection>;

View File

@@ -31,6 +31,7 @@ export default class ApiConfig {
, public _availableMediaTypes: ReceiverSelectorMediaType
= ReceiverSelectorMediaType.App
| ReceiverSelectorMediaType.Tab
| ReceiverSelectorMediaType.Screen) {
| ReceiverSelectorMediaType.Screen
| ReceiverSelectorMediaType.File) {
}
}

View File

@@ -30,11 +30,13 @@ interface PopupAppState {
mediaType: ReceiverSelectorMediaType;
availableMediaTypes: ReceiverSelectorMediaType;
isLoading: boolean;
filePath: string;
}
class PopupApp extends Component<{}, PopupAppState> {
private port: browser.runtime.Port;
private win: browser.windows.Window;
private defaultMediaType: ReceiverSelectorMediaType;
constructor (props: {}) {
super(props);
@@ -44,6 +46,7 @@ class PopupApp extends Component<{}, PopupAppState> {
, mediaType: ReceiverSelectorMediaType.App
, availableMediaTypes: ReceiverSelectorMediaType.App
, isLoading: false
, filePath: null
};
// Store window ref
@@ -63,9 +66,11 @@ class PopupApp extends Component<{}, PopupAppState> {
this.port.onMessage.addListener((message: Message) => {
switch (message.subject) {
case "popup:/populateReceiverList": {
this.defaultMediaType = message.data.defaultMediaType;
this.setState({
receivers: message.data.receivers
, mediaType: message.data.defaultMediaType
, mediaType: this.defaultMediaType
, availableMediaTypes: message.data.availableMediaTypes
});
@@ -93,6 +98,18 @@ class PopupApp extends Component<{}, PopupAppState> {
}
public render () {
let truncatedFileName: string;
if (this.state.filePath) {
const filePath = this.state.filePath;
const fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
truncatedFileName = fileName.length > 12
? `${fileName.substring(0, 12)}...`
: fileName;
}
return (
<div>
<div className="media-select">
@@ -115,6 +132,16 @@ class PopupApp extends Component<{}, PopupAppState> {
& ReceiverSelectorMediaType.Screen) }>
{ _("popupMediaTypeScreen") }
</option>
<option disabled>
</option>
<option value={ ReceiverSelectorMediaType.File }
disabled={ !(this.state.availableMediaTypes
& ReceiverSelectorMediaType.File) }>
{ this.state.filePath
? truncatedFileName
: _("popupMediaTypeFile") }
</option>
</select>
{ _("popupMediaSelectToLabel") }
</div>
@@ -140,13 +167,45 @@ class PopupApp extends Component<{}, PopupAppState> {
, data: {
receiver
, mediaType: this.state.mediaType
, filePath: this.state.filePath
}
});
}
private onSelectChange (ev: React.ChangeEvent<HTMLSelectElement>) {
const mediaType = parseInt(ev.target.value);
if (mediaType === ReceiverSelectorMediaType.File) {
try {
const filePath = window.prompt();
// Validate URL
const fileUrl = new URL(filePath.startsWith("file://")
? filePath
: `file://${filePath}`);
this.setState({
mediaType
, filePath
});
return;
} catch (err) {
// Don't need to handle any errors
}
// Set media type to default if failed to set filePath
this.setState({
mediaType: this.defaultMediaType
});
} else {
this.setState({
mediaType
});
}
this.setState({
mediaType: parseInt(ev.target.value)
filePath: null
});
}
}