import * as vscode from "vscode"; import { getWebviewContent } from "./webviewContent"; import { isTokenExpired } from "../utils/jwtUtils"; import { handleUserMessage, insertCodeToEditor, handleReadFile, handleCreateFile, handleUpdateFile, handleRenameFile, handleReplaceInFile, handleUserAnswer, abortCurrentDialog, handleOptimizePrompt, } from "../utils/messageHandler"; /** * 创建并显示IC 侧边栏视图 */ export function showICHelperPanel(context: vscode.ExtensionContext) { // 创建WebView面板 const panel = vscode.window.createWebviewPanel( "icCoder", // 面板ID "IC Coder", // 面板标题 vscode.ViewColumn.Beside, // 显示在旁边 { enableScripts: true, retainContextWhenHidden: true, localResourceRoots: [ vscode.Uri.joinPath(context.extensionUri, "media"), vscode.Uri.joinPath(context.extensionUri, "src", "assets") ], } ); // 设置标签页图标 panel.iconPath = vscode.Uri.joinPath( context.extensionUri, "media", "icon.png" ); // 获取页面内图标URI const iconUri = panel.webview.asWebviewUri( vscode.Uri.joinPath(context.extensionUri, "media", "icon.png") ); // 获取模型图标URI const autoIconUri = panel.webview.asWebviewUri( vscode.Uri.joinPath(context.extensionUri, "src", "assets", "model", "Auto.png") ); const liteIconUri = panel.webview.asWebviewUri( vscode.Uri.joinPath(context.extensionUri, "src", "assets", "model", "lite.png") ); const syIconUri = panel.webview.asWebviewUri( vscode.Uri.joinPath(context.extensionUri, "src", "assets", "model", "Sy.png") ); const maxIconUri = panel.webview.asWebviewUri( vscode.Uri.joinPath(context.extensionUri, "src", "assets", "model", "Max.png") ); // 获取二维码图片URI const qrCodeUri = panel.webview.asWebviewUri( vscode.Uri.joinPath(context.extensionUri, "src", "assets", "QRCode", "wx.png") ); // 获取Logo URI const logoUri = panel.webview.asWebviewUri( vscode.Uri.joinPath(context.extensionUri, "media", "homepage-logo.png") ); // 设置HTML内容 panel.webview.html = getWebviewContent( iconUri.toString(), autoIconUri.toString(), liteIconUri.toString(), syIconUri.toString(), maxIconUri.toString(), qrCodeUri.toString(), logoUri.toString() ); // 处理消息 panel.webview.onDidReceiveMessage( (message) => { console.log("[ICViewProvider] ====== 收到 WebView 消息 ======"); console.log("[ICViewProvider] command:", message.command); console.log("[ICViewProvider] 完整消息:", JSON.stringify(message)); switch (message.command) { case "sendMessage": handleUserMessage(panel, message.text, context.extensionPath, message.mode); break; case "readFile": handleReadFile(panel, message.filePath); break; case "updateFile": handleUpdateFile(panel, message.filePath, message.content); break; case "renameFile": handleRenameFile(panel, message.oldPath, message.newPath); break; case "replaceInFile": handleReplaceInFile( panel, message.filePath, message.searchText, message.replaceText ); break; case "insertCode": insertCodeToEditor(message.code); break; case "createFile": handleCreateFile( panel, message.filePath, message.content, message.overwrite ); break; case "showInfo": vscode.window.showInformationMessage(message.text); break; case "showWarning": vscode.window.showWarningMessage(message.message); break; // 新增:处理用户回答 case "submitAnswer": handleUserAnswer( message.askId, message.selected, message.customInput ); break; // 新增:中止对话 case "abortDialog": void abortCurrentDialog(); break; // 新增:优化提示词 case "optimizePrompt": handleOptimizePrompt(panel, message.prompt); break; } }, undefined, context.subscriptions ); } /** * 侧边栏视图提供者 */ export class ICViewProvider implements vscode.WebviewViewProvider { private _view?: vscode.WebviewView; constructor( private readonly extensionUri: vscode.Uri, private readonly context: vscode.ExtensionContext ) { // 监听认证状态变化 this.context.subscriptions.push( vscode.authentication.onDidChangeSessions((e) => { if (e.provider.id === "iccoder") { this.refreshLoginStatus(); } }) ); } /** * 刷新登录状态并更新视图 */ private async refreshLoginStatus(): Promise { if (this._view) { const isLoggedIn = await this.checkLoginStatus(); this._view.webview.html = this.getWebviewContent( this._view.webview, isLoggedIn ); } } /** * 检查登录状态(使用 Authentication API) */ private async checkLoginStatus(): Promise { try { const session = await vscode.authentication.getSession("iccoder", [], { createIfNone: false }); console.log("[ICViewProvider] 检查登录状态, session:", session ? "存在" : "不存在"); if (!session) { return false; } // 检查 token 是否过期 const expired = isTokenExpired(session.accessToken); console.log("[ICViewProvider] token 过期检查结果:", expired); // 只有明确过期才认为未登录,无法判断时认为已登录 if (expired === true) { console.log("[ICViewProvider] Token 已过期"); return false; } return true; } catch (error) { console.log("[ICViewProvider] 检查登录状态失败:", error); return false; } } resolveWebviewView(webviewView: vscode.WebviewView) { console.log('[ICViewProvider] ========== resolveWebviewView 被调用 =========='); // 保存引用以便后续刷新 this._view = webviewView; webviewView.webview.options = { enableScripts: true, localResourceRoots: [ vscode.Uri.joinPath(this.extensionUri, "media"), vscode.Uri.joinPath(this.extensionUri, "src", "assets") ], }; console.log('[ICViewProvider] Webview options 已设置'); console.log('[ICViewProvider] extensionUri:', this.extensionUri.toString()); // 【关键修复】先设置默认 HTML,避免一直加载 try { const html = this.getWebviewContent(webviewView.webview, false); console.log('[ICViewProvider] HTML 内容已生成,长度:', html.length); webviewView.webview.html = html; console.log('[ICViewProvider] HTML 已设置到 webview'); } catch (error) { console.error('[ICViewProvider] 设置 HTML 失败:', error); } // 异步检查登录状态并更新 UI this.checkLoginStatus() .then((isLoggedIn) => { console.log('[ICViewProvider] 登录状态检查完成:', isLoggedIn); webviewView.webview.html = this.getWebviewContent( webviewView.webview, isLoggedIn ); }) .catch((error) => { console.error('[ICViewProvider] 检查登录状态失败:', error); // 即使失败也显示未登录状态 webviewView.webview.html = this.getWebviewContent(webviewView.webview, false); }); // 处理侧边栏的消息 webviewView.webview.onDidReceiveMessage( (message) => { if (message.command === "openChat") { vscode.commands.executeCommand("ic-coder.openChat"); } else if (message.command === "login") { vscode.commands.executeCommand("ic-coder.login"); } else if (message.command === "logout") { // 退出登录(前端已有确认对话框) vscode.commands.executeCommand("ic-coder.logout"); } else if (message.command === "openICCoder") { // 打开 IC Coder 官网 vscode.env.openExternal(vscode.Uri.parse('https://www.iccoder.com')); } else if (message.command === "openExternalUrl") { // 打开外部链接 if (message.url) { vscode.env.openExternal(vscode.Uri.parse(message.url)); } } }, undefined, this.context.subscriptions ); } private getWebviewContent( webview: vscode.Webview, isLoggedIn: boolean ): string { console.log('[ICViewProvider] 开始生成 HTML 内容, isLoggedIn:', isLoggedIn); const logoUri = webview.asWebviewUri( vscode.Uri.joinPath(this.extensionUri, "media", "icon.png") ); return `
IC Coder

欢迎使用 IC Coder

${isLoggedIn ? '' : '' }
`; } }