Skip to content

Commit

Permalink
Add Roku File System Panel and Roku App Overlays Panel (#545)
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

---------

Co-authored-by: Brian Leighty <bleighty@tubi.tv>
Co-authored-by: Bronley Plumb <bronley@gmail.com>
  • Loading branch information
3 people committed Feb 29, 2024
1 parent e5a62e0 commit 3a42aa4
Show file tree
Hide file tree
Showing 23 changed files with 1,031 additions and 62 deletions.
81 changes: 75 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 52 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"source-map": "^0.7.3",
"thenby": "^1.3.4",
"undent": "^0.1.0",
"uuid": "^9.0.1",
"vscode-languageclient": "^7.0.0",
"vscode-uri": "^1.0.6"
},
Expand Down Expand Up @@ -206,8 +207,20 @@
},
{
"id": "rokuDeviceView",
"contextualTitle": "Roku",
"name": "Device View",
"contextualTitle": "Roku Device View",
"name": "Roku Device View",
"type": "webview"
},
{
"id": "rokuFileSystemView",
"contextualTitle": "Roku File System",
"name": "Roku File System",
"type": "webview"
},
{
"id": "rokuAppOverlaysView",
"contextualTitle": "Roku App Overlays",
"name": "Roku App Overlays",
"type": "webview"
},
{
Expand Down Expand Up @@ -258,22 +271,22 @@
},
{
"command": "extension.brightscript.rokuRegistry.refreshRegistry",
"when": "view == rokuRegistryView",
"when": "view == rokuRegistryView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation"
},
{
"command": "extension.brightscript.rokuRegistry.importRegistry",
"when": "view == rokuRegistryView",
"when": "view == rokuRegistryView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation"
},
{
"command": "extension.brightscript.rokuRegistry.exportRegistry",
"when": "view == rokuRegistryView",
"when": "view == rokuRegistryView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation"
},
{
"command": "extension.brightscript.rokuRegistry.clearRegistry",
"when": "view == rokuRegistryView",
"when": "view == rokuRegistryView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation"
},
{
Expand Down Expand Up @@ -325,6 +338,21 @@
"command": "extension.brightscript.rokuAutomationView.disableAutorunOnDeploy",
"when": "view == rokuAutomationView && brightscript.rokuAutomationView.autorunOnDeploy",
"group": "navigation@2"
},
{
"command": "extension.brightscript.rokuFileSystemView.refresh",
"when": "view == rokuFileSystemView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation@1"
},
{
"command": "extension.brightscript.rokuAppOverlaysView.addNewOverlay",
"when": "view == rokuAppOverlaysView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation@1"
},
{
"command": "extension.brightscript.rokuAppOverlaysView.removeAllOverlays",
"when": "view == rokuAppOverlaysView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation@2"
}
],
"webview/context": [
Expand Down Expand Up @@ -2798,6 +2826,24 @@
"category": "BrighterScript",
"icon": "$(pass-filled)"
},
{
"command": "extension.brightscript.rokuFileSystemView.refresh",
"title": "Refresh",
"category": "BrightScript",
"icon": "$(refresh)"
},
{
"command": "extension.brightscript.rokuAppOverlaysView.addNewOverlay",
"title": "Add New Overlay",
"category": "BrighterScript",
"icon": "$(new-file)"
},
{
"command": "extension.brightscript.rokuAppOverlaysView.removeAllOverlays",
"title": "Remove All Overlays",
"category": "BrighterScript",
"icon": "$(trash)"
},
{
"command": "extension.brightscript.languageServer.restart",
"title": "Restart Language Server",
Expand Down
5 changes: 4 additions & 1 deletion src/commands/VscodeCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@ export enum VscodeCommand {
rokuAutomationViewStartRecording = 'extension.brightscript.rokuAutomationView.startRecording',
rokuAutomationViewStopRecording = 'extension.brightscript.rokuAutomationView.stopRecording',
enableRemoteControlMode = 'extension.brightscript.enableRemoteControlMode',
disableRemoteControlMode = 'extension.brightscript.disableRemoteControlMode'
disableRemoteControlMode = 'extension.brightscript.disableRemoteControlMode',
rokuAppOverlaysViewAddNewOverlay = 'extension.brightscript.rokuAppOverlaysView.addNewOverlay',
rokuAppOverlaysViewRemoveAllOverlays = 'extension.brightscript.rokuAppOverlaysView.removeAllOverlays',
rokuFileSystemViewRefresh = 'extension.brightscript.rokuFileSystemView.refresh'
}
34 changes: 15 additions & 19 deletions src/managers/RtaManager.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as fs from 'fs';
import * as path from 'path';
import * as rta from 'roku-test-automation';
import { ViewProviderEvent } from '../viewProviders/ViewProviderEvent';
import { ViewProviderId } from '../viewProviders/ViewProviderId';
Expand Down Expand Up @@ -56,25 +58,7 @@ export class RtaManager {
public async sendOdcRequest(requestorId: string, command: string, context: { args: any; options: any }) {
const { args, options } = context;

if (command === rta.RequestType.findNodesAtLocation) {
if (!this.lastStoreNodesResponse) {
args.includeBoundingRectInfo = true;
await this.sendOdcRequest(requestorId, rta.RequestType.storeNodeReferences, args);
}
context.args.nodeTreeResponse = this.lastStoreNodesResponse;
let { matches } = await rta.odc.findNodesAtLocation(args, options);
if (requestorId === ViewProviderId.rokuDeviceView) {
if (matches.length) {
const match = { ...matches[0] };
// Remove children as this is where most of the payload is and we don't need this info
match.children = [];
matches = [match];
}
}
return {
matches: matches
};
} else if (command === rta.RequestType.storeNodeReferences) {
if (command === rta.RequestType.storeNodeReferences) {
this.lastStoreNodesResponse = await rta.odc.storeNodeReferences(args, options);

const viewIds = [];
Expand All @@ -87,6 +71,18 @@ export class RtaManager {
event: ViewProviderEvent.onStoredNodeReferencesUpdated
});
return this.lastStoreNodesResponse;
} else if (command === rta.RequestType.writeFile) {
// We can't access files from the webview so we just store the path and access it in node instead
const directoryPath = path.dirname(args.destinationPath);
// We always try to make the directory. Doesn't fail if it already exists
await rta.odc.createDirectory({
path: directoryPath
});

return rta.odc.writeFile({
binaryPayload: fs.readFileSync(args.sourcePath),
path: args.destinationPath
}, options);
} else {
return this.onDeviceComponent[command](args, options);
}
Expand Down
23 changes: 15 additions & 8 deletions src/managers/WebviewViewProviderManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import type { BrightScriptCommands } from '../BrightScriptCommands';
import * as vscode from 'vscode';
import { RokuCommandsViewProvider } from '../viewProviders/RokuCommandsViewProvider';
import { RokuDeviceViewViewProvider } from '../viewProviders/RokuDeviceViewViewProvider';
import { RokuFileSystemViewViewProvider } from '../viewProviders/RokuFileSystemViewViewProvider';
import { RokuAppOverlaysViewViewProvider } from '../viewProviders/RokuAppOverlaysViewViewProvider';
import { RokuRegistryViewProvider } from '../viewProviders/RokuRegistryViewProvider';
import { SceneGraphInspectorViewProvider } from '../viewProviders/SceneGraphInspectorViewProvider';
import { RokuAutomationViewViewProvider } from '../viewProviders/RokuAutomationViewViewProvider';
Expand All @@ -15,7 +17,6 @@ export class WebviewViewProviderManager {
private rtaManager: RtaManager,
brightScriptCommands: BrightScriptCommands
) {

for (const webview of this.webviewViews) {
if (!webview.provider) {
webview.provider = new webview.constructor(context, {
Expand All @@ -30,20 +31,26 @@ export class WebviewViewProviderManager {
}

private webviewViews = [{
constructor: SceneGraphInspectorViewProvider,
provider: undefined as SceneGraphInspectorViewProvider
}, {
constructor: RokuRegistryViewProvider,
provider: undefined as RokuRegistryViewProvider
constructor: RokuAutomationViewViewProvider,
provider: undefined as RokuAutomationViewViewProvider
}, {
constructor: RokuCommandsViewProvider,
provider: undefined as RokuCommandsViewProvider
}, {
constructor: RokuDeviceViewViewProvider,
provider: undefined as RokuDeviceViewViewProvider
}, {
constructor: RokuAutomationViewViewProvider,
provider: undefined as RokuAutomationViewViewProvider
constructor: RokuFileSystemViewViewProvider,
provider: undefined as RokuFileSystemViewViewProvider
}, {
constructor: RokuRegistryViewProvider,
provider: undefined as RokuRegistryViewProvider
}, {
constructor: RokuAppOverlaysViewViewProvider,
provider: undefined as RokuAppOverlaysViewViewProvider
}, {
constructor: SceneGraphInspectorViewProvider,
provider: undefined as SceneGraphInspectorViewProvider
}];

public getWebviewViewProviders() {
Expand Down
13 changes: 13 additions & 0 deletions src/viewProviders/BaseWebviewViewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,19 @@ export abstract class BaseWebviewViewProvider implements vscode.WebviewViewProvi
} else if (command === ViewProviderCommand.sendMessageToWebviews) {
const context = message.context;
this.webviewViewProviderManager.sendMessageToWebviews(context.viewIds, context.message);
} else if (command === ViewProviderCommand.updateWorkspaceState) {
const context = message.context;
await this.extensionContext.workspaceState.update(context.key, context.value);
this.postOrQueueMessage({
...message
});
} else if (command === ViewProviderCommand.getWorkspaceState) {
const context = message.context;
const response = await this.extensionContext.workspaceState.get(context.key, context.defaultValue);
this.postOrQueueMessage({
...message,
response: response
});
} else {
const callback = this.messageCommandCallbacks[command];
if (!callback || !await callback(message)) {
Expand Down
Loading

0 comments on commit 3a42aa4

Please sign in to comment.