UNPKG

pag-player

Version:

pag预览插件

217 lines (197 loc) 8.35 kB
import * as vscode from "vscode"; const path = require("path"); const fs = require("fs"); class PagCustomDocument implements vscode.CustomDocument { uri: vscode.Uri; constructor(uri: vscode.Uri) { this.uri = uri; } dispose(): void { // 如果需要清理资源,可以在这里实现 } } export class PagCustomEditorProvider implements vscode.CustomReadonlyEditorProvider<PagCustomDocument> { public static readonly viewType = "pag-preview.editor"; private statusBarItem: vscode.StatusBarItem; // private pagInfo: any = {}; private pagInfoMap: WeakMap<vscode.WebviewPanel, { width: number; height: number; size: number, duration: number }>; constructor(private readonly context: vscode.ExtensionContext) { // 创建状态栏项 this.statusBarItem = vscode.window.createStatusBarItem( vscode.StatusBarAlignment.Right, // 对齐到右下角 100 // 优先级 ); this.pagInfoMap = new WeakMap(); // 使用 WeakMap 存储每个 Webview 的 pagInfo } /** * openCustomDocument 方法,用于打开自定义文档 */ public openCustomDocument( uri: vscode.Uri, _openContext: vscode.CustomDocumentOpenContext, _token: vscode.CancellationToken ): vscode.CustomDocument | Thenable<vscode.CustomDocument> { // 创建并返回自定义文档实例 return new PagCustomDocument(uri); } /** * resolveCustomEditor 方法,在文件被打开时触发 */ public async resolveCustomEditor( document: PagCustomDocument, webviewPanel: vscode.WebviewPanel, _token: vscode.CancellationToken ): Promise<void> { console.log(`Opening file: ${document.uri.fsPath}`); // vscode指令通信 // vscode.commands.executeCommand("pag-preview.fileDetail", document.uri); // 设置 Webview 选项 webviewPanel.webview.options = { enableScripts: true, // localResourceRoots作用:防止 WebView 意外访问到插件不该访问的本地文件系统区域。只有处在 localResourceRoots 所列出的目录中的资源,才可以被 WebView 加载,这有助于保障用户系统的安全,避免恶意代码利用 WebView 越界访问敏感文件 localResourceRoots: [ vscode.Uri.file(path.join(this.context.extensionPath, "dist")), vscode.Uri.file(path.dirname(document.uri.fsPath)), ], }; // 获取当前主题模式 const currentTheme = vscode.window.activeColorTheme.kind; const themeMap: { [key in vscode.ColorThemeKind]: string } = { [vscode.ColorThemeKind.Dark]: "dark", [vscode.ColorThemeKind.Light]: "light", [vscode.ColorThemeKind.HighContrast]: "highContrast", [vscode.ColorThemeKind.HighContrastLight]: "highContrastLight", } webviewPanel.webview.postMessage({ type: "themeChange", theme: themeMap[currentTheme] || "dark", }); vscode.window.onDidChangeActiveColorTheme((e) => { // console.log("VSCode 主题已切换为:", e.kind); webviewPanel.webview.postMessage({ type: "themeChange", theme: themeMap[e.kind] || "dark", }); }); // 关键:将文件 URI 转为 Webview 可访问的路径 const fileUri = webviewPanel.webview.asWebviewUri(document.uri); // console.log("uri--", fileUri.toString()); https://file%2B.vscode-resource.vscode-cdn.net/Users/xxx/vscode/pag-preview/dist/webview/pag.min.js // const htmlPath = path.join( // this.context.extensionPath, // "dist/index.html" // ); // // console.log("htmlPath", htmlPath); // // 解析html内容 // const htmlContent = fs.readFileSync(htmlPath, "utf-8"); // console.log('path: 777777', path.join(this.context.extensionPath, "dist/pag.min.js")); // const fastDiffUri = webviewPanel.webview.asWebviewUri( // vscode.Uri.file( // path.join(this.context.extensionPath, "dist/pag.min.js") // ) // ); // const updatedHtmlContent = htmlContent.replace("./pag.min.js", fastDiffUri); // // 设置 Webview 内容 // webviewPanel.webview.html = updatedHtmlContent; webviewPanel.webview.html = this.getWebviewContent(document, webviewPanel.webview); // 将文件内容发送到 Webview webviewPanel.webview.postMessage({ type: "loadFile", fileUri: fileUri.toString(), }); // 加载 PAG 文件并获取宽高和文件大小 const fileSize = await this.getFileSize(document.uri.fsPath); // const { width, height } = await this.getPagDimensions(webviewPanel.webview); // 更新状态栏 // this.updateStatusBar(width, height, fileSize); // 监听来自 Webview 的消息 webviewPanel.webview.onDidReceiveMessage((message) => { if (message.command === "alert") { vscode.window.showInformationMessage(message.text); } else if (message.type === "pagDimensions") { console.log("PAG Dimensions:", message.width, message.height); this.pagInfoMap.set(webviewPanel, { width: message.width, height: message.height, size: fileSize, duration: message.duration }); this.updateStatusBar(message.width, message.height, fileSize, message.duration); } }); // 监听 Webview 可见状态变化 webviewPanel.onDidChangeViewState((e) => { if (e.webviewPanel.visible) { console.log('回来了呀', e); webviewPanel.webview.postMessage({ type: "play" }); const pagInfo = this.pagInfoMap.get(webviewPanel); if (pagInfo) { // this.statusBarItem.show(); // 显示状态栏 this.updateStatusBar(pagInfo.width, pagInfo.height, pagInfo.size, pagInfo.duration); } } else { webviewPanel.webview.postMessage({ type: "pause" }); this.statusBarItem.hide(); } }); // 处理自定义编辑器生命周期 webviewPanel.onDidDispose(() => { console.log('pag文件关闭'); // vscode.commands.executeCommand("pag-preview.fileDetail"); console.log('PAG file closed'); this.statusBarItem.hide(); // 隐藏状态栏 document.dispose(); // 不需要手动清理 WeakMap,垃圾回收会自动处理 }); } private getWebviewContent(document: PagCustomDocument, webview: vscode.Webview): string { const htmlPath = path.join(this.context.extensionPath, "dist/index.html"); let htmlContent; try { htmlContent = fs.readFileSync(htmlPath, "utf-8"); } catch (error: any) { vscode.window.showErrorMessage(`Failed to load HTML file: ${error.message}`); return ""; } const pagJsUri = webview.asWebviewUri( vscode.Uri.file(path.join(this.context.extensionPath, "dist/pag.min.js")) ); return htmlContent.replace("./pag.min.js", pagJsUri.toString()); } private async getFileSize(filePath: string): Promise<number> { try { const stats = fs.statSync(filePath); return stats.size; // 返回文件大小(字节) } catch (error) { console.error("Failed to get file size:", error); return 0; } } private async getPagDimensions(webview: vscode.Webview): Promise<{ width: number; height: number }> { return new Promise((resolve) => { const listener = webview.onDidReceiveMessage((message) => { if (message.type === "pagDimensions") { resolve({ width: message.width, height: message.height }); listener.dispose(); // 移除监听器 } }); // 请求 Webview 发送 PAG 文件的宽高 webview.postMessage({ type: "getPagDimensions" }); }); } private updateStatusBar(width: number, height: number, fileSize: number, duration: number): void { const sizeInKB = (fileSize / 1024).toFixed(2); // 将文件大小转换为 KB this.statusBarItem.text = `PAG: ${width}x${height} | ${sizeInKB} KB | ${duration} s`; this.statusBarItem.show(); // 显示状态栏 console.log('statusBarItem Info:', width, height, sizeInKB); } } export default (context: vscode.ExtensionContext) => { console.log("PAG Custom Editor Activated!"); let disposable = vscode.window.registerCustomEditorProvider( PagCustomEditorProvider.viewType, new PagCustomEditorProvider(context), { webviewOptions: { retainContextWhenHidden: true, // 切换标签时保留上下文 }, } ); return disposable; };