Skip to content

Commit

Permalink
Device disconnect support and other improvements (#548)
Browse files Browse the repository at this point in the history
* Add Roku File System Panel and Roku App Overlays

* small PR cleanup

* Add support for bmp and gif overlays

* Prevent text selection on file system entry selection

* Open file in read only mode

* Switch to using uuid for id generation

* Switch to cursor: pointer

* Switch to progress ring from question mark for better clarity of what is happening

* Rename force to forceReload

* Add documentation

* Fix path issue on windows

* Add UI for empty folder and use odcAvailable instead of deviceAvailable for new panels

* add support for disconnecting from device in webview panels, avoid issues with deploying due to screenshot capture happening at same time, add support for copying node info response in scenegraph inspector detail view

* resume screenshot capture after onDidTerminateDebugSession

* Delete resumeScreenshotCapture after calling (since it's a promise.resolve())

---------

Co-authored-by: Brian Leighty <[email protected]>
Co-authored-by: Bronley Plumb <[email protected]>
  • Loading branch information
3 people committed Mar 1, 2024
1 parent 3a42aa4 commit 5232b07
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 19 deletions.
51 changes: 47 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -264,31 +264,39 @@
"when": "debugType == 'brightscript' && view == rendezvousView",
"group": "navigation"
},

{
"command": "extension.brightscript.refreshDeviceList",
"when": "view == onlineDevicesView",
"group": "navigation"
},

{
"command": "extension.brightscript.rokuRegistry.refreshRegistry",
"when": "view == rokuRegistryView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation"
"group": "navigation@1"
},
{
"command": "extension.brightscript.rokuRegistry.importRegistry",
"when": "view == rokuRegistryView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation"
"group": "navigation@2"
},
{
"command": "extension.brightscript.rokuRegistry.exportRegistry",
"when": "view == rokuRegistryView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation"
"group": "navigation@3"
},
{
"command": "extension.brightscript.rokuRegistry.clearRegistry",
"when": "view == rokuRegistryView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation"
"group": "navigation@4"
},
{
"command": "extension.brightscript.disconnectFromDevice",
"when": "view == rokuRegistryView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation@5"
},

{
"command": "extension.brightscript.rokuDeviceView.refreshScreenshot",
"when": "view == rokuDeviceView && !brightscript.rokuDeviceView.enableScreenshotCapture",
Expand Down Expand Up @@ -319,6 +327,12 @@
"when": "view == rokuDeviceView",
"group": "navigation@4"
},
{
"command": "extension.brightscript.disconnectFromDevice",
"when": "view == rokuDeviceView && brightscript.rokuDeviceView.isOnDeviceComponentAvailable",
"group": "navigation@5"
},

{
"command": "extension.brightscript.rokuAutomationView.startRecording",
"when": "view == rokuAutomationView && !brightscript.rokuAutomationView.isRecording",
Expand All @@ -344,6 +358,12 @@
"when": "view == rokuFileSystemView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation@1"
},
{
"command": "extension.brightscript.disconnectFromDevice",
"when": "view == rokuFileSystemView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation@2"
},

{
"command": "extension.brightscript.rokuAppOverlaysView.addNewOverlay",
"when": "view == rokuAppOverlaysView && brightscript.isOnDeviceComponentAvailable",
Expand All @@ -353,6 +373,23 @@
"command": "extension.brightscript.rokuAppOverlaysView.removeAllOverlays",
"when": "view == rokuAppOverlaysView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation@2"
},
{
"command": "extension.brightscript.disconnectFromDevice",
"when": "view == rokuAppOverlaysView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation@3"
},

{
"command": "extension.brightscript.disconnectFromDevice",
"when": "view == rokuCommandsView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation@1"
},

{
"command": "extension.brightscript.disconnectFromDevice",
"when": "view == sceneGraphInspectorView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation@1"
}
],
"webview/context": [
Expand Down Expand Up @@ -2901,6 +2938,12 @@
"title": "Refresh Nodetree",
"category": "BrighterScript",
"icon": "$(refresh)"
},
{
"command": "extension.brightscript.disconnectFromDevice",
"title": "Disconnect From Roku Device",
"category": "BrighterScript",
"icon": "$(debug-disconnect)"
}
],
"keybindings": [
Expand Down
3 changes: 2 additions & 1 deletion src/commands/VscodeCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ export enum VscodeCommand {
disableRemoteControlMode = 'extension.brightscript.disableRemoteControlMode',
rokuAppOverlaysViewAddNewOverlay = 'extension.brightscript.rokuAppOverlaysView.addNewOverlay',
rokuAppOverlaysViewRemoveAllOverlays = 'extension.brightscript.rokuAppOverlaysView.removeAllOverlays',
rokuFileSystemViewRefresh = 'extension.brightscript.rokuFileSystemView.refresh'
rokuFileSystemViewRefresh = 'extension.brightscript.rokuFileSystemView.refresh',
disconnectFromDevice = 'extension.brightscript.disconnectFromDevice'
}
4 changes: 3 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export class Extension {
userInputManager
);

this.rtaManager = new RtaManager();
this.rtaManager = new RtaManager(context);
this.webviewViewProviderManager = new WebviewViewProviderManager(context, this.rtaManager, this.brightScriptCommands);
this.rtaManager.setWebviewViewProviderManager(this.webviewViewProviderManager);

Expand Down Expand Up @@ -177,6 +177,7 @@ export class Extension {
//if this is a brightscript debug session
if (e.type === 'brightscript') {
logOutputManager.onDidStartDebugSession();
this.webviewViewProviderManager.onDidStartDebugSession(e);
}
this.diagnosticManager.clear();
});
Expand All @@ -189,6 +190,7 @@ export class Extension {
if (config.remoteControlMode?.deactivateOnSessionEnd) {
void this.remoteControlManager.setRemoteControlMode(false, 'launch');
}
this.webviewViewProviderManager.onDidTerminateDebugSession(e);
}
this.diagnosticManager.clear();
});
Expand Down
27 changes: 22 additions & 5 deletions src/managers/RtaManager.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import * as fs from 'fs';
import * as path from 'path';
import * as rta from 'roku-test-automation';
import * as vscode from 'vscode';
import { ViewProviderEvent } from '../viewProviders/ViewProviderEvent';
import { ViewProviderId } from '../viewProviders/ViewProviderId';
import { vscodeContextManager } from './VscodeContextManager';
import type { WebviewViewProviderManager } from './WebviewViewProviderManager';
import { VscodeCommand } from '../commands/VscodeCommand';

export class RtaManager {
constructor(
context: vscode.ExtensionContext
) {
context.subscriptions.push(vscode.commands.registerCommand(VscodeCommand.disconnectFromDevice, () => {
void this.onDeviceComponent?.shutdown();
this.onDeviceComponent = undefined;
void vscodeContextManager.set('brightscript.isOnDeviceComponentAvailable', false);
this.updateDeviceAvailabilityOnWebViewProviders();
}));
}

public onDeviceComponent?: rta.OnDeviceComponent;
public device?: rta.RokuDevice;

Expand Down Expand Up @@ -44,11 +57,7 @@ export class RtaManager {
}
void vscodeContextManager.set('brightscript.isOnDeviceComponentAvailable', !!this.onDeviceComponent);

for (const webviewProvider of this.webviewViewProviderManager.getWebviewViewProviders()) {
if (typeof webviewProvider.updateDeviceAvailability === 'function') {
webviewProvider.updateDeviceAvailability();
}
}
this.updateDeviceAvailabilityOnWebViewProviders();

if (config.disableScreenSaver) {
void this.onDeviceComponent?.disableScreenSaver({ disableScreensaver: true });
Expand Down Expand Up @@ -95,4 +104,12 @@ export class RtaManager {
public getStoredNodeReferences() {
return this.lastStoreNodesResponse;
}

private updateDeviceAvailabilityOnWebViewProviders() {
for (const webviewProvider of this.webviewViewProviderManager.getWebviewViewProviders()) {
if (typeof webviewProvider.updateDeviceAvailability === 'function') {
webviewProvider.updateDeviceAvailability();
}
}
}
}
4 changes: 2 additions & 2 deletions src/managers/WebviewViewProviderManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe('WebviewViewProviderManager', () => {
let spy;
before(() => {
spy = sinon.spy(vscode.window, 'registerWebviewViewProvider');
rtaManager = new RtaManager();
rtaManager = new RtaManager(context);
webviewViewProviderManager = new WebviewViewProviderManager(context, rtaManager, brightScriptCommands);
});

Expand Down Expand Up @@ -76,7 +76,7 @@ describe('WebviewViewProviderManager', () => {
}
};

rtaManager = new RtaManager();
rtaManager = new RtaManager(context);
webviewViewProviderManager = new WebviewViewProviderManager(context, rtaManager, brightScriptCommands);
rtaManager.setWebviewViewProviderManager(webviewViewProviderManager);
});
Expand Down
12 changes: 12 additions & 0 deletions src/managers/WebviewViewProviderManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@ export class WebviewViewProviderManager {
return providers;
}

public onDidStartDebugSession(e: vscode.DebugSession) {
for (const webview of this.webviewViews) {
webview.provider.onDidStartDebugSession(e);
}
}

public onDidTerminateDebugSession(e: vscode.DebugSession) {
for (const webview of this.webviewViews) {
webview.provider.onDidTerminateDebugSession(e);
}
}

// Notification from extension
public onChannelPublishedEvent(e: ChannelPublishedEvent) {
const config = e.body.launchConfiguration as BrightScriptLaunchConfiguration;
Expand Down
8 changes: 8 additions & 0 deletions src/viewProviders/BaseWebviewViewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ export abstract class BaseWebviewViewProvider implements vscode.WebviewViewProvi
this.webviewViewProviderManager = manager;
}

public onDidStartDebugSession(e: vscode.DebugSession) {
// Can be overwritten in a child to notify on debug session start
}

public onDidTerminateDebugSession(e: vscode.DebugSession) {
// Can be overwritten in a child to notify on debug session end
}

public onChannelPublishedEvent(e: ChannelPublishedEvent) {
// Can be overwritten in a child to notify on channel publish
}
Expand Down
29 changes: 28 additions & 1 deletion src/viewProviders/RokuDeviceViewViewProvider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type * as vscode from 'vscode';
import type { ChannelPublishedEvent } from 'roku-debug';
import { VscodeCommand } from '../commands/VscodeCommand';
import { BaseRdbViewProvider } from './BaseRdbViewProvider';
import { ViewProviderId } from './ViewProviderId';
Expand All @@ -7,6 +8,9 @@ import { ViewProviderCommand } from './ViewProviderCommand';
export class RokuDeviceViewViewProvider extends BaseRdbViewProvider {
public readonly id = ViewProviderId.rokuDeviceView;

private temporarilyDisableScreenshotCapture = false;
private resumeScreenshotCapture?: () => void;

constructor(context: vscode.ExtensionContext, dependencies) {
super(context, dependencies);

Expand All @@ -20,9 +24,15 @@ export class RokuDeviceViewViewProvider extends BaseRdbViewProvider {
this.view.show(false);
});


this.addMessageCommandCallback(ViewProviderCommand.getScreenshot, async (message) => {
try {
if (this.temporarilyDisableScreenshotCapture) {
// Sometimes we need to temporarily stop screenshot capture as it can prevent successful package deployment to the device
// Originally was just returning true here but now we just pause until we resume capturing
await new Promise<void>((resolve) => {
this.resumeScreenshotCapture = resolve;
});
}
const result = await this.dependencies.rtaManager.device.getScreenshot();
this.postOrQueueMessage({
...message,
Expand All @@ -42,4 +52,21 @@ export class RokuDeviceViewViewProvider extends BaseRdbViewProvider {
return true;
});
}

public onDidStartDebugSession(e: vscode.DebugSession) {
this.temporarilyDisableScreenshotCapture = true;
}

public onDidTerminateDebugSession(e: vscode.DebugSession) {
// In case we failed to start debugging we want to allow screenshots again
this.temporarilyDisableScreenshotCapture = false;
this.resumeScreenshotCapture?.();
delete this.resumeScreenshotCapture;
}

public onChannelPublishedEvent(e: ChannelPublishedEvent) {
this.temporarilyDisableScreenshotCapture = false;
this.resumeScreenshotCapture?.();
delete this.resumeScreenshotCapture;
}
}
2 changes: 1 addition & 1 deletion src/viewProviders/RokuRegistryViewProvider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ afterEach(() => {
});

describe('RokuRegistryViewProvider', () => {
const rtaManager = new RtaManager();
const rtaManager = new RtaManager(vscode.context);
const provider = new RokuRegistryViewProvider(vscode.context, {
rtaManager: rtaManager
});
Expand Down
22 changes: 18 additions & 4 deletions webviews/src/views/SceneGraphInspectorView/NodeDetailPage.svelte
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

<script lang="ts">
import throttle from 'just-throttle';
import type { TreeNode, BaseKeyPath } from 'roku-test-automation';
Expand All @@ -6,7 +7,7 @@
import ColorField from './ColorField.svelte';
import NumberField from '../../shared/NumberField.svelte';
import Chevron from '../../shared/Chevron.svelte';
import { Refresh, Discard, ArrowLeft, Move, Key } from 'svelte-codicons';
import { Refresh, Discard, ArrowLeft, Move, Key, Clippy } from 'svelte-codicons';
export let inspectNodeSubtype: string;
// Key path for pulling info
Expand Down Expand Up @@ -43,6 +44,8 @@
let numberInputsStep = '1';
let nodeInfoResponse;
let fields = {} as {
[key: string]: {
fieldType: string;
Expand Down Expand Up @@ -79,9 +82,9 @@
request: inspectNodeBaseKeyPath
}
});
const node = results.request;
fields = node.fields;
children = node.children;
nodeInfoResponse = results.request;
fields = nodeInfoResponse.fields;
children = nodeInfoResponse.children;
}
refresh();
Expand Down Expand Up @@ -291,6 +294,10 @@
return output;
}
function copyNodeInfoJson() {
navigator.clipboard.writeText(JSON.stringify(nodeInfoResponse, undefined, 4))
}
</script>

<style>
Expand Down Expand Up @@ -413,6 +420,13 @@
<Key />
</vscode-button>
{/if}

<vscode-button
appearance="icon"
title="Copy Node Info Response JSON"
on:click={copyNodeInfoJson}>
<Clippy />
</vscode-button>
</section>
</div>
{#if showKeyPathInfo && persistentBaseKeyPath}
Expand Down

0 comments on commit 5232b07

Please sign in to comment.