From 98d8324ff95aa75e0d79c88e169414b66d024e86 Mon Sep 17 00:00:00 2001 From: Tom Zu <138054255+tomcat323@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:19:32 -0500 Subject: [PATCH] feat(notification): Use virtual txt file and telemetry url wrapper (#5939) Created a `ReadonlyDocument` class in `textDocumentUtilities` to show a virtual read-only txt file. Converted existing txt notifications. Use telemetry url wrapper instead of `openExternal` Also updated some local notification JSON for future testing --- packages/core/src/notifications/panelNode.ts | 52 ++++------------ .../shared/utilities/textDocumentUtilities.ts | 44 +++++++++++++ .../resources/emergency/1.x.json | 62 ++++--------------- .../notifications/resources/startup/1.x.json | 40 ++++++++++-- 4 files changed, 100 insertions(+), 98 deletions(-) diff --git a/packages/core/src/notifications/panelNode.ts b/packages/core/src/notifications/panelNode.ts index 70d2a6d3634..118f7da1706 100644 --- a/packages/core/src/notifications/panelNode.ts +++ b/packages/core/src/notifications/panelNode.ts @@ -12,10 +12,9 @@ import { NotificationType, ToolkitNotification } from './types' import { ToolkitError } from '../shared/errors' import { isAmazonQ } from '../shared/extensionUtilities' import { getLogger } from '../shared/logger/logger' -import { tempDirPath } from '../shared/filesystemUtilities' -import path from 'path' -import fs from '../shared/fs/fs' import { registerToolView } from '../awsexplorer/activationShared' +import { readonlyDocument } from '../shared/utilities/textDocumentUtilities' +import { openUrl } from '../shared/utilities/vsCodeUtils' /** * Controls the "Notifications" side panel/tree in each extension. It takes purely UX actions @@ -143,49 +142,19 @@ export class NotificationsNode implements TreeNode { } // Show open url option getLogger('notifications').verbose(`opening url for notification: ${notification.id} ...`) - await vscode.env.openExternal(vscode.Uri.parse(notification.uiRenderInstructions.onClick.url)) + await openUrl(vscode.Uri.parse(notification.uiRenderInstructions.onClick.url)) break case 'openTextDocument': // Display read-only txt document getLogger('notifications').verbose(`showing txt document for notification: ${notification.id} ...`) - await this.showReadonlyTextDocument(notification.uiRenderInstructions.content['en-US'].description) + await readonlyDocument.show( + notification.uiRenderInstructions.content['en-US'].description, + `Notification: ${notification.id}` + ) break } } - /** - * Shows a read only txt file for the contect of notification on a side column - * It's read-only so that the "save" option doesn't appear when user closes the notification - */ - private async showReadonlyTextDocument(content: string): Promise { - try { - const tempFilePath = path.join(tempDirPath, 'AWSToolkitNotifications.txt') - - if (await fs.existsFile(tempFilePath)) { - // If file exist, make sure it has write permission (0o644) - await fs.chmod(tempFilePath, 0o644) - } - - await fs.writeFile(tempFilePath, content) - - // Set the file permissions to read-only (0o444) - await fs.chmod(tempFilePath, 0o444) - - // Now, open the document - const document = await vscode.workspace.openTextDocument(tempFilePath) - - const options: vscode.TextDocumentShowOptions = { - viewColumn: vscode.ViewColumn.Beside, - preserveFocus: true, - preview: true, - } - - await vscode.window.showTextDocument(document, options) - } catch (error) { - throw new ToolkitError(`Error showing text document: ${error}`) - } - } - /** * Renders information window with the notification's content and buttons. * Can be either a blocking modal or a bottom-right corner toast @@ -217,8 +186,9 @@ export class NotificationsNode implements TreeNode { if (selectedButton) { switch (selectedButton.type) { case 'openTxt': - await this.showReadonlyTextDocument( - notification.uiRenderInstructions.content['en-US'].description + await readonlyDocument.show( + notification.uiRenderInstructions.content['en-US'].description, + `Notification: ${notification.id}` ) break case 'updateAndReload': @@ -226,7 +196,7 @@ export class NotificationsNode implements TreeNode { break case 'openUrl': if (selectedButton.url) { - await vscode.env.openExternal(vscode.Uri.parse(selectedButton.url)) + await openUrl(vscode.Uri.parse(selectedButton.url)) } else { throw new ToolkitError('url not provided') } diff --git a/packages/core/src/shared/utilities/textDocumentUtilities.ts b/packages/core/src/shared/utilities/textDocumentUtilities.ts index e164523f9bc..20222a84f7d 100644 --- a/packages/core/src/shared/utilities/textDocumentUtilities.ts +++ b/packages/core/src/shared/utilities/textDocumentUtilities.ts @@ -223,3 +223,47 @@ export async function addEofNewline(editor: vscode.TextEditor) { }) } } + +class ReadonlyTextDocumentProvider implements vscode.TextDocumentContentProvider { + private content = '' + + setContent(content: string) { + this.content = content + } + + provideTextDocumentContent(uri: vscode.Uri): string { + return this.content + } +} + +/** + * Shows a read only virtual txt file on a side column + * It's read-only so that the "save" option doesn't appear when user closes the pop up window + * Usage: ReadonlyDocument.show(content, filename) + * @param content The content to be displayed in the virtual document + * @param filename The title on top of the pop up window + */ +class ReadonlyDocument { + private readonly scheme = 'AWStoolkit-readonly' + private readonly provider = new ReadonlyTextDocumentProvider() + + constructor() { + vscode.workspace.registerTextDocumentContentProvider(this.scheme, this.provider) + } + + public async show(content: string, filename: string) { + this.provider.setContent(content) + const uri = vscode.Uri.parse(`${this.scheme}:/${filename}.txt`) + const options: vscode.TextDocumentShowOptions = { + viewColumn: vscode.ViewColumn.Beside, + preserveFocus: true, + preview: true, + } + + // Open the document with the updated content + const document = await vscode.workspace.openTextDocument(uri) + await vscode.window.showTextDocument(document, options) + } +} + +export const readonlyDocument = new ReadonlyDocument() diff --git a/packages/core/src/test/notifications/resources/emergency/1.x.json b/packages/core/src/test/notifications/resources/emergency/1.x.json index bfd22830170..ced10965ab5 100644 --- a/packages/core/src/test/notifications/resources/emergency/1.x.json +++ b/packages/core/src/test/notifications/resources/emergency/1.x.json @@ -2,74 +2,41 @@ "schemaVersion": "1.x", "notifications": [ { - "id": "amazonq_emergency_local_1", + "id": "emergency1", "displayIf": { "extensionId": "amazonwebservices.amazon-q-vscode" }, "uiRenderInstructions": { "content": { "en-US": { - "title": "[local] Emergency: url", - "description": "Something crazy is happening! Please update your extension.", - "toastPreview": "omg" - } - }, - "onRecieve": "toast", - "onClick": { - "type": "modal" - }, - "actions": [ - { - "type": "updateAndReload", - "displayText": { - "en-US": "Update and Reload" - } - }, - { - "type": "openUrl", - "url": "https://aws.amazon.com/visualstudiocode/", - "displayText": { - "en-US": "Proceed to wiki" - } - } - ] - } - }, - { - "id": "amazonq_emergency_local_2", - "displayIf": { - "extensionId": "amazonwebservices.amazon-q-vscode" - }, - "uiRenderInstructions": { - "content": { - "en-US": { - "title": "[local] Emergency: txt", - "description": "Something crazy is happening! Please update your extension.", - "toastPreview": "omg" + "title": "Can't sign in to Amazon Q", + "description": "There is currently a bug that is preventing users from signing into Amazon Q. If this impacts you, please try this workaround:\n\n 1. Reload your IDE\n 2. Run the command in the command palette:: `Amazon Q: Reset State`.\n 3. Set your default region to `us-east-3`.\n 4. Try to sign into Amazon Q with your desired region in the dropdown.\n\nWe are currently working on releasing a fix so that this workaround is not required.\nPlease reach out on our github issues with any questions.", + "toastPreview": "Signing into Amazon Q is broken, please try this workaround while we work on releasing a fix." } }, "onRecieve": "toast", "onClick": { "type": "openTextDocument" - } + }, + "actions": [] } }, { - "id": "amazonq_emergency_local_3", + "id": "emergency2", "displayIf": { "extensionId": "amazonwebservices.amazon-q-vscode" }, "uiRenderInstructions": { "content": { "en-US": { - "title": "[local] Emergency: modal", - "description": "Something crazy is happening! Please update your extension.", - "toastPreview": "new notification: something crazy is happening! Please update your entension and look on our wiki." + "title": "Update Amazon Q to avoid breaking bugs", + "description": "There is currently a bug that prevents Amazon Q from responding to chat requests. It is fixed in the latest version. Please update your Amazon Q now.", + "toastPreview": "This version of Amazon Q is currently broken, please update to avoid issues." } }, "onRecieve": "toast", "onClick": { - "type": "openTextDocument" + "type": "modal" }, "actions": [ { @@ -77,13 +44,6 @@ "displayText": { "en-US": "Update and Reload" } - }, - { - "type": "openUrl", - "url": "https://aws.amazon.com/visualstudiocode/", - "displayText": { - "en-US": "Proceed to wiki" - } } ] } diff --git a/packages/core/src/test/notifications/resources/startup/1.x.json b/packages/core/src/test/notifications/resources/startup/1.x.json index 7dbf7ad0a2f..29a7e7e89cd 100644 --- a/packages/core/src/test/notifications/resources/startup/1.x.json +++ b/packages/core/src/test/notifications/resources/startup/1.x.json @@ -2,23 +2,51 @@ "schemaVersion": "1.x", "notifications": [ { - "id": "amazonq_startUp_local_1", + "id": "startup1", "displayIf": { "extensionId": "amazonwebservices.amazon-q-vscode" }, "uiRenderInstructions": { "content": { "en-US": { - "title": "[local] What's New, url", - "description": "Check out this new stuff!", - "toastPreview": "omg" + "title": "New Amazon Q Chat features", + "description": "You can now use Amazon Q inline in your IDE, without ever touching the mouse or using copy and paste. \nPress ⌘+I (Ctrl+I on Windows) to trigger inline chat. \nDescribe a function or feature you'd like to develop and Amazon Q will generate and display a code diff that inserts new code at the cursor position. \nPress Enter to accept and apply the diff, or Escape to reject it. \nAlternatively you select a block of code (maybe even the entire file) then press ⌘+I (Ctrl+I on Windows) to provide instructions on how to refactor the selected code. \nYou will see a diff against the selected code and can press Enter to accept and apply the diff.", + "toastPreview": "New Amazon Q features available: inline chat" + } + }, + "onRecieve": "toast", + "onClick": { + "type": "openTextDocument" + }, + "actions": [ + { + "type": "openUrl", + "url": "https://aws.amazon.com/developer/generative-ai/amazon-q/change-log/", + "displayText": { + "en-US": "Learn more" + } + } + ] + } + }, + { + "id": "startup2", + "displayIf": { + "extensionId": "amazonwebservices.amazon-q-vscode" + }, + "uiRenderInstructions": { + "content": { + "en-US": { + "title": "What's New", + "toastPreview": "New Amazon Q features are available!" } }, "onRecieve": "toast", "onClick": { "type": "openUrl", - "url": "https://aws.amazon.com/visualstudiocode/" - } + "url": "https://aws.amazon.com/developer/generative-ai/amazon-q/change-log/" + }, + "actions": [] } } ]