diff --git a/src/ActiveDeviceManager.ts b/src/ActiveDeviceManager.ts index 8d292c72..d5cd76d2 100644 --- a/src/ActiveDeviceManager.ts +++ b/src/ActiveDeviceManager.ts @@ -45,7 +45,7 @@ export class ActiveDeviceManager extends EventEmitter { public firstRequestForDevices: boolean; public lastUsedDevice: string; - private enabled: boolean; + public enabled: boolean; private showInfoMessages: boolean; private deviceCache: NodeCache; private exponentialBackoff: any; @@ -54,7 +54,7 @@ export class ActiveDeviceManager extends EventEmitter { // Returns an object will all the active devices by device id public getActiveDevices() { this.firstRequestForDevices = false; - return this.deviceCache.mget(this.deviceCache.keys()); + return this.deviceCache.mget>(this.deviceCache.keys()); } // Returns the device cache statistics. diff --git a/src/BrightScriptCommands.ts b/src/BrightScriptCommands.ts index a27c7adc..48d628ec 100644 --- a/src/BrightScriptCommands.ts +++ b/src/BrightScriptCommands.ts @@ -257,6 +257,14 @@ export class BrightScriptCommands { this.registerCommand('showReleaseNotes', () => { this.whatsNewManager.showReleaseNotes(); }); + + this.registerCommand('setPrimaryDevice', async (host?: string) => { + if (host) { + + } else { + host = await util.showDeviceQuickPicker(this.activeDeviceManager); + } + }); } public async openFile(filename: string, range: vscode.Range = null, preview = false): Promise { diff --git a/src/DebugConfigurationProvider.ts b/src/DebugConfigurationProvider.ts index 9ec60752..907a937d 100644 --- a/src/DebugConfigurationProvider.ts +++ b/src/DebugConfigurationProvider.ts @@ -364,62 +364,9 @@ export class BrightScriptDebugConfigurationProvider implements DebugConfiguratio let showInputBox = false; if (config.host.trim() === '${promptForHost}' || (config?.deepLinkUrl?.includes('${promptForHost}'))) { - if (this.activeDeviceManager.enabled) { - if (this.activeDeviceManager.firstRequestForDevices && !this.activeDeviceManager.getCacheStats().keys) { - let deviceWaitTime = 5000; - if (this.showDeviceInfoMessages) { - await vscode.window.showInformationMessage(`Device Info: Allowing time for device discovery (${deviceWaitTime} ms)`); - } - - await util.delay(deviceWaitTime); - } - - let activeDevices = this.activeDeviceManager.getActiveDevices(); - - if (activeDevices && Object.keys(activeDevices).length) { - let items = []; - - // Create the Quick Picker option items - for (const key of Object.keys(activeDevices)) { - let device = activeDevices[key]; - let itemText = `${device.ip} | ${device.deviceInfo['default-device-name']} - ${device.deviceInfo['model-number']}`; - - if (this.activeDeviceManager.lastUsedDevice && device.deviceInfo['default-device-name'] === this.activeDeviceManager.lastUsedDevice) { - items.unshift(itemText); - } else { - items.push(itemText); - } - } - - // Give the user the option to type their own IP incase the device they want has not yet been detected on the network - let manualIpOption = 'Other'; - items.push(manualIpOption); - - let host = await vscode.window.showQuickPick(items, { placeHolder: `Please Select a Roku or use the "${manualIpOption}" option to enter a IP` }); - - if (host === manualIpOption) { - showInputBox = true; - } else if (host) { - let defaultDeviceName = host.substring(host.toLowerCase().indexOf(' | ') + 3, host.toLowerCase().lastIndexOf(' - ')); - let deviceIP = host.substring(0, host.toLowerCase().indexOf(' | ')); - if (defaultDeviceName) { - this.activeDeviceManager.lastUsedDevice = defaultDeviceName; - } - config.host = deviceIP; - } else { - // User canceled. Give them one more change to enter an ip - showInputBox = true; - } - } else { - showInputBox = true; - } - } else { - showInputBox = true; - } - } - - if (showInputBox) { - config.host = await this.openInputBox('The IP address of your Roku device'); + config.host = await util.showDeviceQuickPicker(this.activeDeviceManager, true); + } else if (showInputBox) { + config.host = await util.openInputBox('The IP address of your Roku device'); } // #endregion @@ -440,7 +387,7 @@ export class BrightScriptDebugConfigurationProvider implements DebugConfiguratio private async processPasswordParameter(config: BrightScriptLaunchConfiguration) { //prompt for password if not hardcoded if (config.password.trim() === '${promptForPassword}') { - config.password = await this.openInputBox('The developer account password for your Roku device.'); + config.password = await util.openInputBox('The developer account password for your Roku device.'); if (!config.password) { throw new Error('Debug session terminated: password is required.'); } @@ -458,30 +405,18 @@ export class BrightScriptDebugConfigurationProvider implements DebugConfiguratio config.deepLinkUrl = config.deepLinkUrl.replace('${host}', config.host); config.deepLinkUrl = config.deepLinkUrl.replace('${promptForHost}', config.host); if (config.deepLinkUrl.includes('${promptForQueryParams}')) { - let queryParams = await this.openInputBox('Querystring params for deep link'); + let queryParams = await util.openInputBox('Querystring params for deep link'); config.deepLinkUrl = config.deepLinkUrl.replace('${promptForQueryParams}', queryParams); } if (config.deepLinkUrl === '${promptForDeepLinkUrl}') { - config.deepLinkUrl = await this.openInputBox('Full deep link url'); + config.deepLinkUrl = await util.openInputBox('Full deep link url'); } } return config; } /** - * Helper to open a vscode input box ui - * @param placeHolder placeHolder text - * @param value default value - */ - private async openInputBox(placeHolder: string, value = '') { - return vscode.window.showInputBox({ - placeHolder: placeHolder, - value: value - }); - } - - /** - * Get the bsconfig file, if available + * Get the brsConfig file, if available */ public getBsConfig(workspaceFolder: vscode.Uri) { //try to load bsconfig settings diff --git a/src/extension.ts b/src/extension.ts index c6efe2e6..7211489f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -43,6 +43,7 @@ export class Extension { private telemetryManager: TelemetryManager; private remoteControlManager: RemoteControlManager; private brightScriptCommands: BrightScriptCommands; + private activeDeviceManager: ActiveDeviceManager; public odc?: rta.OnDeviceComponent; @@ -63,6 +64,7 @@ export class Extension { this.globalStateManager = new GlobalStateManager(context); this.whatsNewManager = new WhatsNewManager(this.globalStateManager, currentExtensionVersion); this.chanperfStatusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); + this.activeDeviceManager = new ActiveDeviceManager(); //initialize the analytics manager context.subscriptions.push( @@ -86,7 +88,6 @@ export class Extension { //update the tracked version of the extension this.globalStateManager.lastRunExtensionVersion = currentExtensionVersion; - const declarationProvider = new DeclarationProvider(); context.subscriptions.push(declarationProvider); @@ -138,7 +139,7 @@ export class Extension { ); //register the debug configuration provider - let configProvider = new BrightScriptDebugConfigurationProvider(context, activeDeviceManager, this.telemetryManager); + let configProvider = new BrightScriptDebugConfigurationProvider(context, this.activeDeviceManager, this.telemetryManager); context.subscriptions.push( vscode.debug.registerDebugConfigurationProvider('brightscript', configProvider) ); diff --git a/src/util.ts b/src/util.ts index a9954749..108ddae4 100644 --- a/src/util.ts +++ b/src/util.ts @@ -4,6 +4,7 @@ import * as net from 'net'; import * as url from 'url'; import { debounce } from 'debounce'; import * as vscode from 'vscode'; +import type { ActiveDeviceManager } from './ActiveDeviceManager'; import { Cache } from 'brighterscript/dist/Cache'; class Util { @@ -239,6 +240,74 @@ class Util { return channel; } + public async showDeviceQuickPicker(activeDeviceManager: ActiveDeviceManager, updateLastUsedDevice = false) { + let host: string; + + const config: any = vscode.workspace.getConfiguration('brightscript') || {}; + const showDeviceInfoMessages = (config.deviceDiscovery || {}).showInfoMessages; + if (activeDeviceManager.enabled) { + if (activeDeviceManager.firstRequestForDevices && !activeDeviceManager.getCacheStats().keys) { + let deviceWaitTime = 5000; + if (showDeviceInfoMessages) { + await vscode.window.showInformationMessage(`Device Info: Allowing time for device discovery (${deviceWaitTime} ms)`); + } + + await util.delay(deviceWaitTime); + } + + let activeDevices = activeDeviceManager.getActiveDevices(); + + if (activeDevices && Object.keys(activeDevices).length) { + let items = []; + + // Create the Quick Picker option items + for (const key of Object.keys(activeDevices)) { + let device = activeDevices[key]; + let itemText = `${device.ip} | ${device.deviceInfo['default-device-name']} - ${device.deviceInfo['model-number']}`; + + if (activeDeviceManager.lastUsedDevice && device.deviceInfo['default-device-name'] === activeDeviceManager.lastUsedDevice) { + items.unshift(itemText); + } else { + items.push(itemText); + } + } + + // Give the user the option to type their own IP incase the device they want has not yet been detected on the network + let manualIpOption = 'Other'; + items.push(manualIpOption); + + let host = await vscode.window.showQuickPick(items, { placeHolder: `Please Select a Roku or use the "${manualIpOption}" option to enter a IP` }); + + if (host !== manualIpOption) { + let defaultDeviceName = host.substring(host.toLowerCase().indexOf(' | ') + 3, host.toLowerCase().lastIndexOf(' - ')); + let deviceIP = host.substring(0, host.toLowerCase().indexOf(' | ')); + if (defaultDeviceName && updateLastUsedDevice) { + activeDeviceManager.lastUsedDevice = defaultDeviceName; + } + host = deviceIP; + } + } + } + + if (!host) { + host = await this.openInputBox('The IP address of your Roku device'); + } + + return host; + } + + /** + * Helper to open a vscode input box ui + * @param placeHolder placeHolder text + * @param value default value + */ + public async openInputBox(placeHolder: string, value = '') { + return vscode.window.showInputBox({ + placeHolder: placeHolder, + value: value + }); + } + /** * Shows ether a QuickPick or InputBox to the user and allows them to enter * items not in the QuickPick list of items