Created
January 11, 2025 08:26
-
-
Save sadan4/25000f2f39850bd252da379b442f82c6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Manages react webview panels | |
| */ | |
| import { format } from "@modules/format"; | |
| import { mkStringUri, sendToSockets } from "@server"; | |
| import { EvaledPatch, ReporterData, WebviewMessage } from "@type/reporter"; | |
| import { extensionPath, extensionUri } from "./extension"; | |
| import { commands,Disposable, Uri, ViewColumn, WebviewPanel, window } from "vscode"; | |
| type Patch = { patch: EvaledPatch; }; | |
| type PluginName = { pluginName: string; }; | |
| type Diff = { oldModule: string, newModule: string; }; | |
| // TODO: add persistant state | |
| export class ReporterPanel { | |
| /** | |
| * Track the currently panel. Only allow a single panel to exist at a time. | |
| */ | |
| public static currentPanel: ReporterPanel | undefined; | |
| private static readonly viewType = "vencordReporter"; | |
| private readonly _panel: WebviewPanel; | |
| private readonly _extensionUri: Uri; | |
| private readonly _extensionPath: string; | |
| private _disposables: Disposable[] = []; | |
| public static createOrShow(data: ReporterData) { | |
| const column = window.activeTextEditor ? window.activeTextEditor.viewColumn : undefined; | |
| // If we already have a panel, show it. | |
| // Otherwise, create a new panel. | |
| // dont create another panel with the same data | |
| if (ReporterPanel.currentPanel && !data) { | |
| ReporterPanel.currentPanel._panel.reveal(column); | |
| } else { | |
| ReporterPanel.currentPanel = new ReporterPanel(extensionUri, column || ViewColumn.One, data); | |
| } | |
| } | |
| private constructor(extensionUri: Uri, column: ViewColumn, data: ReporterData) { | |
| this._extensionUri = extensionUri; | |
| this._extensionPath = extensionPath; | |
| // Create and show a new webview panel | |
| this._panel = window.createWebviewPanel(ReporterPanel.viewType, "Vencord Reporter", column, { | |
| // Enable javascript in the webview | |
| enableScripts: true, | |
| // And restric the webview to only loading content from our extension's `media` directory. | |
| localResourceRoots: [ | |
| Uri.joinPath(extensionUri, "dist/webview") | |
| ] | |
| }); | |
| // Set the webview's initial html content | |
| this._panel.webview.html = this._getHtmlForWebview(data); | |
| // Listen for when the panel is disposed | |
| // This happens when the user closes the panel or when the panel is closed programatically | |
| this._panel.onDidDispose(() => this.dispose(), null, this._disposables); | |
| // Handle messages from the webview | |
| this._panel.webview.onDidReceiveMessage(async (message: WebviewMessage) => { | |
| try { | |
| switch (message.type) { | |
| case "disable": { | |
| const { pluginName, enabled }: PluginName & { enabled: boolean; } = message.data; | |
| // DISABLE PLUGIN | |
| await sendToSockets({ | |
| type: "disable", | |
| data: { | |
| pluginName, | |
| enabled | |
| } | |
| }); | |
| break; | |
| } | |
| case "jumpToPatch": { | |
| const { pluginName, patch }: Patch & PluginName = message.data; | |
| // any attempt to get this to open without user interaction is a complete shitshow | |
| // just use the builtin fuzzy finder and the patch find | |
| // while there might be more than one find, the user can deal with that | |
| commands.executeCommand("workbench.action.quickOpen", "%" + patch.find); | |
| break; | |
| } | |
| case "extract": { | |
| const { patch }: Patch = message.data; | |
| commands.executeCommand("vencord-companion.extract", +patch.id); | |
| break; | |
| } | |
| case "diff": { | |
| const { oldModule, newModule, id }: Diff & EvaledPatch = message.data; | |
| // we cant format code with syntax errors | |
| let sourceUri, patchedUri; | |
| try { | |
| sourceUri = mkStringUri(await format(oldModule)); | |
| patchedUri = mkStringUri(await format(newModule)); | |
| } catch (error) { | |
| sourceUri = mkStringUri(oldModule); | |
| patchedUri = mkStringUri(newModule); | |
| } | |
| commands.executeCommand("vscode.diff", sourceUri, patchedUri, "Patch Diff: " + id); | |
| break; | |
| } | |
| default: { | |
| window.showErrorMessage("Unknown message type from webview, got : " + message.type); | |
| break; | |
| } | |
| } | |
| } catch (error) { | |
| window.showErrorMessage(String(error)); | |
| } | |
| }, null, this._disposables); | |
| } | |
| public dispose() { | |
| ReporterPanel.currentPanel = undefined; | |
| // Clean up our resources | |
| this._panel.dispose(); | |
| while (this._disposables.length) { | |
| const x = this._disposables.pop(); | |
| if (x) { | |
| x.dispose(); | |
| } | |
| } | |
| } | |
| private _getHtmlForWebview(data: ReporterData) { | |
| const scriptPathOnDisk = Uri.joinPath(this._extensionUri, "dist/webview/index.js"); | |
| const scriptUri = this._panel.webview.asWebviewUri(scriptPathOnDisk); | |
| const stylePathOnDisk = Uri.joinPath(this._extensionUri, "dist/webview/index.css"); | |
| const styleUri = this._panel.webview.asWebviewUri(stylePathOnDisk); | |
| // Use a nonce to whitelist which scripts can be run | |
| const nonce = getNonce(); | |
| return `<!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"> | |
| <meta name="theme-color" content="#000000"> | |
| <title>React App</title> | |
| <script nonce="${nonce}">window.reporterData = ${JSON.stringify(data)}</script> | |
| <link rel="stylesheet" type="text/css" href="${styleUri}"> | |
| <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${this._panel.webview.cspSource} https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src ${this._panel.webview.cspSource} https:; script-src 'nonce-${nonce}';"> | |
| <base href="${this._panel.webview.asWebviewUri(Uri.joinPath(this._extensionUri, "dist/webview"))}/"> | |
| </head> | |
| <body> | |
| <noscript>You need to enable JavaScript to run this app.</noscript> | |
| <div id="root"></div> | |
| <script defer nonce="${nonce}" src="${scriptUri}"></script> | |
| </body> | |
| </html>`; | |
| } | |
| } | |
| function getNonce() { | |
| let text = ""; | |
| const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | |
| for (let i = 0; i < 32; i++) { | |
| text += possible.charAt(Math.floor(Math.random() * possible.length)); | |
| } | |
| return text; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment