Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/create-vsix-from-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
run: echo "TOKEN=${{ steps.generate-token.outputs.token }}" >> $GITHUB_ENV
#trigger the build on vscode-brightscript-language
- name: Build vsix for branch "${{ github.head_ref}}"
uses: aurelien-baudet/workflow-dispatch@v2.1.1
uses: the-actions-org/workflow-dispatch@v4
id: create-vsix
with:
workflow: create-vsix
Expand Down
410 changes: 210 additions & 200 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"resolve": "^1.22.8",
"roku-debug": "^0.22.0",
"roku-deploy": "^3.12.6",
"roku-test-automation": "^2.0.10",
"roku-test-automation": "^2.2.1",
"semver": "^7.1.3",
"source-map": "^0.7.3",
"strip-ansi": "^5.2.0",
Expand Down Expand Up @@ -321,17 +321,17 @@
},
{
"command": "extension.brightscript.rokuDeviceView.refreshScreenshot",
"when": "view == rokuDeviceView && !brightscript.rokuDeviceView.enableScreenshotCapture",
"when": "view == rokuDeviceView && !brightscript.rokuDeviceView.enableScreenshotCaptureAutoRefresh",
"group": "navigation@1"
},
{
"command": "extension.brightscript.rokuDeviceView.resumeScreenshotCapture",
"when": "view == rokuDeviceView && !brightscript.rokuDeviceView.enableScreenshotCapture && !brightscript.rokuDeviceView.isInspectingNodes",
"when": "view == rokuDeviceView && !brightscript.rokuDeviceView.enableScreenshotCaptureAutoRefresh && !brightscript.rokuDeviceView.isInspectingNodes",
"group": "navigation@2"
},
{
"command": "extension.brightscript.rokuDeviceView.pauseScreenshotCapture",
"when": "view == rokuDeviceView && brightscript.rokuDeviceView.enableScreenshotCapture && !brightscript.rokuDeviceView.isInspectingNodes",
"when": "view == rokuDeviceView && brightscript.rokuDeviceView.enableScreenshotCaptureAutoRefresh",
"group": "navigation@2"
},
{
Expand All @@ -351,7 +351,7 @@
},
{
"command": "extension.brightscript.disconnectFromDevice",
"when": "view == rokuDeviceView && brightscript.rokuDeviceView.isOnDeviceComponentAvailable",
"when": "view == rokuDeviceView && brightscript.isOnDeviceComponentAvailable",
"group": "navigation@5"
},
{
Expand Down
46 changes: 26 additions & 20 deletions src/managers/RtaManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class RtaManager {
public device?: rta.RokuDevice;

private webviewViewProviderManager?: WebviewViewProviderManager;
private lastStoreNodesResponse: Awaited<ReturnType<typeof rta.odc.storeNodeReferences>>;
private lastAppUIResponse: rta.AppUIResponse | undefined;

public setupRtaWithConfig(config: { host: string; password: string; logLevel?: string; disableScreenSaver?: boolean; injectRdbOnDeviceComponent?: boolean }) {
const enableDebugging = ['info', 'debug', 'trace'].includes(config.logLevel);
Expand Down Expand Up @@ -67,20 +67,7 @@ export class RtaManager {
public async sendOdcRequest(requestorId: string, command: string, context: { args: any; options: any }) {
const { args, options } = context;

if (command === rta.RequestType.storeNodeReferences) {
this.lastStoreNodesResponse = await rta.odc.storeNodeReferences(args, options);

const viewIds = [];
if (requestorId === ViewProviderId.rokuDeviceView) {
viewIds.push(ViewProviderId.sceneGraphInspectorView);
} else if (requestorId === ViewProviderId.sceneGraphInspectorView) {
viewIds.push(ViewProviderId.rokuDeviceView);
}
this.webviewViewProviderManager.sendMessageToWebviews(viewIds, {
event: ViewProviderEvent.onStoredNodeReferencesUpdated
});
return this.lastStoreNodesResponse;
} else if (command === rta.RequestType.writeFile) {
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
Expand All @@ -93,16 +80,35 @@ export class RtaManager {
path: args.destinationPath
}, options);
} else {
return this.onDeviceComponent[command](args, options);
const result = await this.onDeviceComponent[command](args, options);
return result;
}
}

public setWebviewViewProviderManager(manager: WebviewViewProviderManager) {
this.webviewViewProviderManager = manager;
public async getAppUI(requestorId: string) {
await this.sendOdcRequest(requestorId, 'assignElementIdOnAllNodes', { args: {}, options: {} });
this.lastAppUIResponse = await rta.ecp.getAppUI();

const viewIds = [];
if (requestorId === ViewProviderId.rokuDeviceView) {
viewIds.push(ViewProviderId.sceneGraphInspectorView);
} else if (requestorId === ViewProviderId.sceneGraphInspectorView) {
viewIds.push(ViewProviderId.rokuDeviceView);
}

// We want to notify the other view providers that the app UI has been updated. Not sending actual payload to avoid overhead if they aren't interested in it
this.webviewViewProviderManager.sendMessageToWebviews(viewIds, {
event: ViewProviderEvent.onStoredAppUIUpdated
});
return this.lastAppUIResponse;
}

public getStoredAppUI() {
return this.lastAppUIResponse;
}

public getStoredNodeReferences() {
return this.lastStoreNodesResponse;
public setWebviewViewProviderManager(manager: WebviewViewProviderManager) {
this.webviewViewProviderManager = manager;
}

private updateDeviceAvailabilityOnWebViewProviders() {
Expand Down
1 change: 1 addition & 0 deletions src/managers/WebviewViewProviderManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export class WebviewViewProviderManager {

// Mainly for communicating between webviews
public sendMessageToWebviews(viewIds: string | string[], message) {
// console.log(`WebviewViewProviderManager: sendMessageToWebviews: ${viewIds} ${JSON.stringify(message)}`);
if (typeof viewIds === 'string') {
viewIds = [viewIds];
}
Expand Down
20 changes: 18 additions & 2 deletions src/viewProviders/BaseRdbViewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,27 @@ export abstract class BaseRdbViewProvider extends BaseWebviewViewProvider {
return Promise.resolve(true);
});

this.addMessageCommandCallback(ViewProviderCommand.getStoredNodeReferences, (message) => {
const response = this.dependencies.rtaManager.getStoredNodeReferences();
this.addMessageCommandCallback(ViewProviderCommand.getStoredAppUI, (message) => {
const response = this.dependencies.rtaManager.getStoredAppUI();
this.postOrQueueMessage(this.createResponseMessage(message, response));
return Promise.resolve(true);
});

this.addMessageCommandCallback(ViewProviderCommand.getAppUI, async (message) => {
try {
const appUIResponse = await this.dependencies.rtaManager.getAppUI(this.id);

this.postOrQueueMessage(this.createResponseMessage(message, {
success: true,
response: appUIResponse
}));
} catch (e) {
this.postOrQueueMessage(this.createResponseMessage(message, {
success: false
}));
}
return true;
});
}

protected onViewReady() {
Expand Down
6 changes: 6 additions & 0 deletions src/viewProviders/BaseWebviewViewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ export abstract class BaseWebviewViewProvider implements vscode.WebviewViewProvi
} else if (command === ViewProviderCommand.setVscodeContext) {
const context = message.context;
await vscodeContextManager.set(context.key, context.value);
} else if (command === ViewProviderCommand.getVscodeContext) {
const context = message.context;
const value = vscodeContextManager.get(context.key);
this.postOrQueueMessage(this.createResponseMessage(message, {
value: value
}));
} else if (command === ViewProviderCommand.sendMessageToWebviews) {
const context = message.context;
this.webviewViewProviderManager.sendMessageToWebviews(context.viewIds, context.message);
Expand Down
6 changes: 4 additions & 2 deletions src/viewProviders/ViewProviderCommand.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
export enum ViewProviderCommand {
deleteRokuFile = 'deleteRokuFile',
getAppUI = 'getAppUI',
getStoredAppUI = 'getStoredAppUI',
getScreenshot = 'getScreenshot',
getStoredNodeReferences = 'getStoredNodeReferences',
getStoredRokuAppOverlays = 'getStoredRokuAppOverlays',
getVscodeContext = 'getVscodeContext',
getWorkspaceState = 'getWorkspaceState',
openRokuFile = 'openRokuFile',
loadRokuAppOverlaysThumbnails = 'loadRokuAppOverlaysThumbnails',
openRokuFile = 'openRokuFile',
runRokuAutomationConfig = 'runRokuAutomationConfig',
sendMessageToWebviews = 'sendMessageToWebviews',
sendReplRequest = 'sendReplRequest',
Expand Down
7 changes: 4 additions & 3 deletions src/viewProviders/ViewProviderEvent.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
export enum ViewProviderEvent {
onTreeNodeFocused = 'onTreeNodeFocused',
onNodeFocused = 'onNodeFocused',
onDeviceAvailabilityChange = 'onDeviceAvailabilityChange',
onVscodeCommandReceived = 'onVscodeCommandReceived',
onRegistryUpdated = 'onRegistryUpdated',
onStoredNodeReferencesUpdated = 'onStoredNodeReferencesUpdated',
onStoredAppUIUpdated = 'onStoredAppUIUpdated',
onRokuAutomationConfigsLoaded = 'onRokuAutomationConfigsLoaded',
onRokuAutomationImportAllAutomations = 'onRokuAutomationImportAllAutomations',
onRokuAutomationExportAllAutomations = 'onRokuAutomationExportAllAutomations',
onRokuAutomationConfigStepChange = 'onRokuAutomationConfigStepChange',
onRokuAutomationKeyPressed = 'onRokuAutomationKeyPressed',
onRokuAppOverlayAdded = 'onRokuAppOverlayAdded',
onRokuAppOverlayThumbnailsLoaded = 'onRokuAppOverlayThumbnailsLoaded'
onRokuAppOverlayThumbnailsLoaded = 'onRokuAppOverlayThumbnailsLoaded',
onVscodeContextSet = 'onVscodeContextSet'
}
43 changes: 30 additions & 13 deletions webviews/src/ExtensionIntermediary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import type * as rta from 'roku-test-automation';
import { RequestType } from 'roku-test-automation/client/dist/types/OnDeviceComponent';
import type { VscodeCommand } from '../../src/commands/VscodeCommand';
import type { ViewProviderEvent } from '../../src/viewProviders/ViewProviderEvent';
import { ViewProviderEvent } from '../../src/viewProviders/ViewProviderEvent';
import { ViewProviderCommand } from '../../src/viewProviders/ViewProviderCommand';
import type { DeleteEntireRegistrySectionsArgs, DeleteNodeReferencesArgs, DeleteRegistrySectionsArgs, FindNodesAtLocationArgs, GetFocusedNodeArgs, GetNodesInfoArgs, GetNodesWithPropertiesArgs, GetValueArgs, GetValuesArgs, HasFocusArgs, IsInFocusChainArgs, OnFieldChangeOnceArgs, ReadRegistryArgs, RequestOptions, SetValueArgs, StoreNodeReferencesArgs, WriteRegistryArgs, GetVolumeListArgs, GetDirectoryListingArgs, StatPathArgs, RenameFileArgs, DeleteFileArgs, CreateDirectoryArgs, RemoveNodeArgs, RemoveNodeChildrenArgs, FocusNodeArgs } from 'roku-test-automation';
import type { DeleteEntireRegistrySectionsArgs, DeleteRegistrySectionsArgs, FindNodesAtLocationArgs, GetFocusedNodeArgs, GetNodesInfoArgs, GetNodesWithPropertiesArgs, GetValueArgs, GetValuesArgs, HasFocusArgs, IsInFocusChainArgs, OnFieldChangeOnceArgs, ReadRegistryArgs, RequestOptions, SetValueArgs, WriteRegistryArgs, GetVolumeListArgs, GetDirectoryListingArgs, StatPathArgs, RenameFileArgs, DeleteFileArgs, CreateDirectoryArgs, RemoveNodeArgs, RemoveNodeChildrenArgs, FocusNodeArgs, AppUIResponse, ConvertKeyPathToSceneKeyPathArgs } from 'roku-test-automation';

class ExtensionIntermediary {
private inflightRequests = {};
Expand Down Expand Up @@ -90,11 +90,23 @@ class ExtensionIntermediary {
});
}

public setVscodeContext(key: string, value: boolean | number | string) {
public setVscodeContext(key: string, value: boolean | number | string, notifyViewIds: string | string[] = []) {
this.postMessage(this.createCommandMessage(ViewProviderCommand.setVscodeContext, {
key: key,
value: value
}));

const message = intermediary.createEventMessage(ViewProviderEvent.onVscodeContextSet, {
key: key,
value: value
});
intermediary.sendMessageToWebviews(notifyViewIds, message);
}

public getVscodeContext(key: string) {
return this.sendCommand(ViewProviderCommand.getVscodeContext, {
key: key
});
}

public updateWorkspaceState(key: string, value: any) {
Expand All @@ -111,8 +123,13 @@ class ExtensionIntermediary {
});
}

public async getStoredNodeReferences() {
return this.sendCommand<ReturnType<typeof rta.odc.storeNodeReferences>>(ViewProviderCommand.getStoredNodeReferences);
public async getStoredAppUI() {
return this.sendCommand<AppUIResponse | undefined>(ViewProviderCommand.getStoredAppUI);
}

public async getAppUI() {
const { response } = await this.sendCommand(ViewProviderCommand.getAppUI);
return response as AppUIResponse;
}

public observeEvent(eventName: string, callback: ObserverCallback) {
Expand All @@ -126,6 +143,10 @@ class ExtensionIntermediary {
}

public sendMessageToWebviews(viewIds: string | string[], message) {
if (!viewIds || (Array.isArray(viewIds) && viewIds.length === 0)) {
return;
}

this.postMessage(this.createCommandMessage(ViewProviderCommand.sendMessageToWebviews, {
viewIds: viewIds,
message: message
Expand Down Expand Up @@ -201,14 +222,6 @@ class ODCIntermediary {
return this.sendOdcMessage<ReturnType<typeof rta.odc.deleteEntireRegistry>>(RequestType.deleteEntireRegistry, args, options);
}

public async storeNodeReferences(args?: StoreNodeReferencesArgs, options?: RequestOptions) {
return this.sendOdcMessage<ReturnType<typeof rta.odc.storeNodeReferences>>(RequestType.storeNodeReferences, args, options);
}

public async deleteNodeReferences(args: DeleteNodeReferencesArgs, options?: RequestOptions) {
return this.sendOdcMessage<ReturnType<typeof rta.odc.deleteNodeReferences>>(RequestType.deleteNodeReferences, args, options);
}

public async getNodesWithProperties(args: GetNodesWithPropertiesArgs, options?: RequestOptions) {
return this.sendOdcMessage<ReturnType<typeof rta.odc.getNodesWithProperties>>(RequestType.getNodesWithProperties, args, options);
}
Expand Down Expand Up @@ -256,6 +269,10 @@ class ODCIntermediary {
public async focusNode(args: FocusNodeArgs, options?: RequestOptions) {
return this.sendOdcMessage<ReturnType<typeof rta.odc.focusNode>>(RequestType.focusNode, args, options);
}

public async convertKeyPathToSceneKeyPath(args: ConvertKeyPathToSceneKeyPathArgs, options?: RequestOptions) {
return this.sendOdcMessage<ReturnType<typeof rta.odc.convertKeyPathToSceneKeyPath>>(RequestType.convertKeyPathToSceneKeyPath, args, options);
}
}

type ObserverCallback = (message) => void;
Expand Down
6 changes: 3 additions & 3 deletions webviews/src/shared/types.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { odc } from '../ExtensionIntermediary';
import type { TreeNode, BaseType } from 'roku-test-automation';
import type { AppUIResponseChild } from 'roku-test-automation';
export type PathContentsInfo = Omit<Partial<Awaited<ReturnType<typeof odc.statPath>>>, 'type'> & {
name: string;
path: string;
type?: 'file' | 'directory' | 'fileSystem';
};

export type TreeNodeWithBase = Partial<TreeNode> & {
base?: keyof typeof BaseType;
export type AppUIResponseChildWithAppUIKeyPath = AppUIResponseChild & {
appUIKeyPath?: string;
};
24 changes: 24 additions & 0 deletions webviews/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { odc } from './ExtensionIntermediary';
import type { AppUIResponseChildWithAppUIKeyPath } from './shared/types';

type AllowedStorageTypes = string | number | boolean | Record<string, string | number | boolean>;

class Utils {
Expand Down Expand Up @@ -62,6 +65,27 @@ class Utils {
delete this.storage[key];
this.getVscodeApi().setState(JSON.stringify(this.storage));
}

/**
* Helps improve performance by removing the children from the AppUIResponseChild object to make the object being passed around much smaller
*/
public getShallowCloneOfAppUIResponseChild(appUIResponseChild: AppUIResponseChildWithAppUIKeyPath) {
return { ...appUIResponseChild, children: [] };
}

/** Provides a central spot to convert key path to be scene based to avoid extra appUI calls */
public async convertAppUIKeyPathToSceneKeyPath(child: AppUIResponseChildWithAppUIKeyPath) {
const { keyPath } = await odc.convertKeyPathToSceneKeyPath({
base: child.base,
keyPath: child.keyPath
});

// Keeping existing appUI key path to allow more fallback options if needed
child.appUIKeyPath = child.keyPath;

child.base = 'scene';
child.keyPath = keyPath;
}
}

const utils = new Utils();
Expand Down
Loading
Loading