const vscode = require('vscode'); const fs = require('fs'); const path = require('path') const browserTemplate = require('./__browserTemplate') const { getOpenedTabs } = require('./getOpenedTabs') const { restoreByArr } = require('./restoreByArr') let treeView; let context; let panel; global.tabsInfo = {}; const previewKey = 'savedPreviewUrl'; // Key to store last opened URL const previewColumnKey = 'savedPreviewColumn'; // Key to store last panel position const mainEmitter = (type) => { Log(type) console.log(type) } const Log = (args) => { vscode.window.showInformationMessage.call(global, args) } const Storage = { get: (previewKey) => { return context.globalState.get(previewKey) }, set: (key, value) => { context.globalState.update(key, value) } } const frame = { initFrame: () => { }, open: // Function to open a WebView preview function runFrame(url, column = vscode.ViewColumn.Active) { console.log("iframe open", url) if (panel) { // If panel exists, update the content and restore position Storage.set(previewKey, url); panel.webview.html = frame.getWebviewContent(url); panel.reveal(column); } else { // Create a new WebView panel in the last known position panel = vscode.window.createWebviewPanel( 'webPreview', 'Web Preview', column, { enableScripts: true, // Allows JavaScript execution retainContextWhenHidden: true, // Ensures WebView state is preserved } ); panel.webview.html = frame.getWebviewContent(url); // Save URL & position for persistence Storage.set(previewKey, url); Storage.set(previewColumnKey, column); // Track panel movement panel.onDidChangeViewState(e => { if (panel.visible) { Storage.set(previewColumnKey, panel.viewColumn); } }); // Handle WebView disposal (clear references) panel.onDidDispose(() => { panel = null; Storage.set(previewKey, undefined); Storage.set(previewColumnKey, undefined); }); panel.webview.onDidReceiveMessage( message => { if (message.command === 'urlChanged') { console.log('New URL:', message.url); // You can trigger any action in your extension here Storage.set(previewKey, message.url); } if (message.command === 'inspectUrl') { console.log('inspect url') // vscode.commands.executeCommand("workbench.action.webview.openDeveloperTools"); panel.webview.openDevTools(); // Opens DevTools for this WebView iframe only } }, undefined, context.subscriptions ); } tabs.backupTabs && tabs.backupTabs(); }, getWebviewContent: browserTemplate, getCurrentPreviewState: function getCurrentPreviewState() { return { url: Storage.get(previewKey), group: Storage.get(previewColumnKey) || vscode.ViewColumn.One } } } const menu = { updateCount(newMessagesCount) { treeView.badge = { value: newMessagesCount, tooltip: `You have ${newMessagesCount} new documentation` }; }, TabSaver: class TabSaverTreeDataProvider { constructor(tabs) { this.tabs = tabs; } getTreeItem(element) { return new vscode.TreeItem(element); } getChildren(element) { if (!element) { return Promise.resolve(this.tabs); } // If an element is provided, you can handle it accordingly return Promise.resolve([]); } }, treeClickHandler: function treeClickHandler(event, context) { if (event.selection.length > 0) { const selectedItem = event.selection[0]; console.log(`Clicked on: ${selectedItem}`); // Log the clicked item's label frame.open('https://itrum.ru?selectedItem=' + selectedItem, 2) // let cmds = { // Preview: openWelcomeFrame, // HTML: () => openHtml(null, '

asdfasdf

'), // 'Run Tests': openTestsFrame, // 'Close Tabs': closeAllTabs // } // let fn = cmds[selectedItem]; // fn && fn(); } }, initTreeView: function initTreeView() { const view = vscode.window.createTreeView('itk.mainView', { treeDataProvider: new menu.TabSaver(['HTML', 'Preview', 'Close Tabs']) }); context.subscriptions.push(view); treeView = view; const view2 = vscode.window.createTreeView('itk.runView', { treeDataProvider: new menu.TabSaver(['Run Tests', 'Close Tabs']) }); context.subscriptions.push(view); context.subscriptions.push(view2); console.log('view', view) view.onDidChangeSelection((event) => menu.treeClickHandler(event, context)); view2.onDidChangeSelection((event) => menu.treeClickHandler(event, context)); }, } const tabs = { init: () => { let disposable = vscode.commands.registerCommand('itk.getTabs', () => tabs.getTabs()); context.subscriptions.push(disposable); context.subscriptions.push(vscode.commands.registerCommand('itk.closeAllTabs', () => tabs.closeTabs())); context.subscriptions.push(vscode.commands.registerCommand('itk.openTabs', () => tabs.restoreOrKeepCurrent(true))); context.subscriptions.push(vscode.commands.registerCommand('itk.terminal', () => terminal.startAndCmd(`sshpass -p "root" ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@t24`))); context.subscriptions.push(vscode.commands.registerCommand('itk.scrollTo', () => tabs.scrollTo(29))); }, scrollTo: function scrollToLine(lineNumber) { const editor = vscode.window.activeTextEditor; mainEmitter(lineNumber) if (!editor) { vscode.window.showErrorMessage('No active editor found.'); return; } const line = Math.max(0, lineNumber - 1); // Convert to zero-based index const range = new vscode.Range(line, 0, line, 0); editor.revealRange(range, vscode.TextEditorRevealType.InCenter); }, async restoreOrKeepCurrent(isRestore) { try { let idKey = 'vsSessionId' let data = require('./files/openTabs') let curOpenTabsId = data[idKey]; let curVsCodeId = Storage.get(idKey) console.log("{data!!!", curOpenTabsId, curVsCodeId) let isFromScratch = isRestore || (curVsCodeId != curOpenTabsId); isFromScratch = true; mainEmitter(curVsCodeId + '___' + curOpenTabsId + 'OPEN TABS. length =' + data?.tabs?.length + ' isfrom scratch ? ' + (isFromScratch ? 'YES' : 'no')) if (isFromScratch) { // await tabs.closeTabs() mainEmitter('All tabs closed') await tabs.restoreByArr(data.tabs) Storage.set(idKey, curOpenTabsId) } mainEmitter('openTabs Complete step 1') // Log('FRAME OPEN START') console.log('data', data.preview) // if (isFromScratch) { // data.preview.url && await frame.open(data.preview.url, data.preview.group) // } // if (!isFromScratch) { // await frame.open(Storage.get(previewKey), Storage.get(previewColumnKey)) // } mainEmitter('openFrame Final Skip') } catch (e) { console.log('eee', e) } }, restoreByArr: restoreByArr, // async restoreByArr(groups) { // const openPromises = []; // let groupTabs = {}; // const workspaceFolder = vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders[0]; // if (!workspaceFolder) { // vscode.window.showErrorMessage('No workspace folder is open. Please open a folder or workspace.'); // return; // } // mainEmitter('workspaceFolder = ' + workspaceFolder) // groups.forEach((group, groupIndex) => { // const groupId = groupIndex + 1; // Group ID corresponds to column // // Open files first, in order // group.filter(item => item.relPath).forEach((item, index) => { // const filePath = vscode.Uri.joinPath(workspaceFolder.uri, item.relPath); // openPromises.push(vscode.workspace.openTextDocument(filePath) // .then(doc => { // // Use groupId as the column index // const columnToUse = groupId; // // Manage the tab order per group // let lastTab = groupTabs[groupId] || 1; // Start at tab 1 by default // vscode.window.showTextDocument(doc, { viewColumn: columnToUse, preview: false }).then(() => { // groupTabs[groupId] = lastTab + 1; // Increment tab order for next file // }); // })); // }); // // After files, open Webview (iframe) last for this group // // group.filter(item => item.url).forEach(item => { // // openPromises.push(openWebview(item.url, groupId)); // // }); // }); // // Wait for all files/URLs to be opened // return Promise.all(openPromises).then(() => { // console.log('All files and URLs have been opened.'); // }).catch(err => { // console.error('Error opening files or URLs:', err); // }); // }, initFileChanges() { // let disposable2 = vscode.commands.registerCommand('itk.openGit', async () => { // // Get the Git extension // // Get the Git extension // return; // const gitExtension = vscode.extensions.getExtension('vscode.git')?.exports; // if (!gitExtension) { // vscode.window.showErrorMessage('Git extension not found.'); // return; // } // // Get the API from the Git extension // const git = gitExtension.getAPI(1); // if (git.repositories.length === 0) { // vscode.window.showErrorMessage('No Git repositories found.'); // return; // } // // Get the first repository (you can loop through all repositories if needed) // const repo = git.repositories[0]; // // Get the changes in the working tree // const changes = repo.state.workingTreeChanges; // if (changes.length === 0) { // vscode.window.showInformationMessage('No changes in the working tree.'); // return; // } // // Loop through all changed files and open their diff views // for (const change of changes) { // const fileUri = change.uri; // const fileName = fileUri.fsPath.split('/').pop(); // Get the file name for the tab title // // Open the diff view for each file // await vscode.commands.executeCommand('vscode.diff', change.originalUri, fileUri, `Changes: ${fileName}`); // } // }); // context.subscriptions.push(disposable2); let disposable = vscode.window.onDidChangeVisibleTextEditors(tabs.backupTabs); context.subscriptions.push(disposable); // Add to subscriptions to prevent memory leaks //on close tab, a more specific way to detect closes. disposable = vscode.workspace.onDidCloseTextDocument((document) => { // console.log(`Tab closed: ${document.fileName}`); //perform your logic here. tabs.backupTabs() }); context.subscriptions.push(disposable); //on open tab. disposable = vscode.workspace.onDidOpenTextDocument((document) => { // console.log(`Tab opened: ${document.fileName}`); //perform your logic here. tabs.backupTabs() }); context.subscriptions.push(disposable); // Add event on scroll disposable = vscode.window.onDidChangeTextEditorVisibleRanges((event) => { // Logic for scroll event // console.log(`Scroll event in ${event.textEditor.document.fileName}`); tabs.backupTabs() // You can access the visible ranges using event.visibleRanges // event.visibleRanges.forEach(range => { // console.log(`Visible range: ${range.start.line} - ${range.end.line}`); // }); }); context.subscriptions.push(disposable); // Add event on selection disposable = vscode.window.onDidChangeTextEditorSelection((event) => { // Logic for selection event // console.log(`Selection changed in ${event.textEditor.document.fileName}`); tabs.backupTabs() // You can access the selection using event.selections // event.selections.forEach(selection => { // console.log(`Selection: ${selection.start.line}:${selection.start.character} - ${selection.end.line}:${selection.end.character}`); // }); }); context.subscriptions.push(disposable); }, getCurrentPreviewState: frame.getCurrentPreviewState, async closeTabs() { try { await vscode.commands.executeCommand('workbench.action.closeAllEditors'); console.log("all tabs are closed") } catch (e) { vscode.window.showInformationMessage("Tabs Closing Error"); } }, writeFile(relPath, content) { const filePath = path.join(__dirname, relPath); fs.writeFileSync(filePath, content); }, async backupTabs() { vscode.window.showInformationMessage('Tabs Chagnges!'); let v = await tabs.getTabs() tabs.writeFile('./files/backupTabs.js', `module.exports = ${JSON.stringify(v, null, 4)}`) }, getTabs: getOpenedTabs, // () { // const tabGroups = vscode.window.tabGroups.all; // if (tabGroups.length === 0) { // vscode.window.showInformationMessage('No open tabs found.'); // return; // } // let tabInfo = []; // const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; // Get workspace folder // tabGroups.forEach((group, index) => { // let curTabsInGroup = [] // group.tabs.forEach(tab => { // let filePath = ""; // if (tab.input instanceof vscode.TabInputText) { // filePath = tab.input.uri.fsPath; // } // let relativePath = ""; // if (filePath) { // relativePath = path.relative(workspaceFolder, filePath); // Use path.relative // } // curTabsInGroup.push({ // group: tab.group.viewColumn, // label: tab.label, // isActive: tab.isActive, // isPinned: tab.isPinned, // absPath: filePath, // relPath: relativePath, // }); // }); // tabInfo.push(curTabsInGroup) // }); // vscode.window.showInformationMessage(`Opened Tabs:\n${JSON.stringify(tabInfo, null, 4)}`); // return { tabs: tabInfo, preview: tabs.getCurrentPreviewState() }; // } } let terminal = { startAndCmd(cmd, name) { // Open a terminal const terminal = vscode.window.createTerminal(name || "Auto Terminal"); // Run a command terminal.show(); terminal.sendText(cmd || "echo Hello, VS Code!"); console.log("Auto Terminal Extension is active!"); } } function activate(_context) { console.log('Congratulations, your extension "itk" is now active!'); context = _context; // terminal.startAndCmd(); menu.initTreeView(); menu.updateCount(117) tabs.restoreOrKeepCurrent(false); tabs.init() tabs.initFileChanges(); } function deactivate() { console.log("ITK DEACTIVE") } module.exports = { activate, deactivate }