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
}