Spaces:
Running
Running
File size: 4,818 Bytes
22feb09 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | // Tab management
class TabManager {
constructor() {
this.tabs = [];
this.activeTabId = null;
this.tabCounter = 0;
this.init();
}
init() {
this.tabBar = document.getElementById('tab-bar');
this.browserContainer = document.getElementById('browser-container');
this.newTabBtn = document.getElementById('new-tab-btn');
this.newTabBtn.addEventListener('click', () => this.addTab());
// Add initial tab
this.addTab();
}
addTab(url = '') {
const tabId = ++this.tabCounter;
const tab = {
id: tabId,
url: url || '',
title: 'New Tab',
favicon: '',
iframe: document.createElement('iframe')
};
tab.iframe.className = 'w-full h-full rounded-lg hidden';
tab.iframe.sandbox = 'allow-same-origin allow-scripts allow-popups allow-forms';
this.browserContainer.appendChild(tab.iframe);
const tabElement = document.createElement('button');
tabElement.className = 'px-4 py-1 rounded-t-lg tab-inactive flex items-center space-x-2 smooth-transition';
tabElement.dataset.tabId = tabId;
const favicon = document.createElement('img');
favicon.className = 'w-4 h-4';
favicon.src = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTEyIDJDNi40ODcgMiAyIDYuNDg3IDIgMTJzNC40ODcgMTAgMTAgMTAgMTAtNC40ODcgMTAtMTBTMTcuNTEzIDIgMTIgMnptMCAxOGMtNC40MSAwLTgtMy41OS04LThzMy41OS04IDgtOCA4IDMuNTkgOCA4LTMuNTkgOC04IDh6IiBmaWxsPSJ3aGl0ZSIvPjwvc3ZnPg==';
favicon.alt = '';
const title = document.createElement('span');
title.className = 'truncate max-w-xs';
title.textContent = 'New Tab';
const closeBtn = document.createElement('button');
closeBtn.className = 'ml-2 hover:text-red-400';
closeBtn.innerHTML = '<i data-feather="x" class="w-3 h-3"></i>';
closeBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.closeTab(tabId);
});
tabElement.appendChild(favicon);
tabElement.appendChild(title);
tabElement.appendChild(closeBtn);
tabElement.addEventListener('click', () => this.switchTab(tabId));
this.tabBar.insertBefore(tabElement, this.newTabBtn);
this.tabs.push({
...tab,
element: tabElement,
faviconElement: favicon,
titleElement: title
});
this.switchTab(tabId);
feather.replace();
}
switchTab(tabId) {
this.tabs.forEach(tab => {
const isActive = tab.id === tabId;
tab.element.classList.toggle('tab-active', isActive);
tab.element.classList.toggle('tab-inactive', !isActive);
tab.iframe.classList.toggle('hidden', !isActive);
});
this.activeTabId = tabId;
const activeTab = this.getActiveTab();
// Focus the iframe
if (activeTab.iframe.contentWindow) {
activeTab.iframe.contentWindow.focus();
}
}
closeTab(tabId) {
if (this.tabs.length <= 1) {
return; // Don't close the last tab
}
const tabIndex = this.tabs.findIndex(tab => tab.id === tabId);
if (tabIndex === -1) return;
const tab = this.tabs[tabIndex];
this.browserContainer.removeChild(tab.iframe);
this.tabBar.removeChild(tab.element);
this.tabs.splice(tabIndex, 1);
if (this.activeTabId === tabId) {
this.switchTab(this.tabs[Math.max(0, tabIndex - 1)].id);
}
}
getActiveTab() {
return this.tabs.find(tab => tab.id === this.activeTabId);
}
navigateActiveTab(url) {
const tab = this.getActiveTab();
if (!tab) return;
try {
// Simple proxy handling - in a real proxy, you'd need server-side handling
tab.iframe.src = url;
tab.url = url;
tab.titleElement.textContent = 'Loading...';
} catch (error) {
console.error('Navigation error:', error);
}
}
}
// Initialize the proxy when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
const tabManager = new TabManager();
window.tabManager = tabManager; // Make it accessible for debugging
// Example of how you might handle URL navigation
// In a real implementation, you'd have a proper proxy backend
document.getElementById('navigate-btn')?.addEventListener('click', () => {
const urlInput = document.getElementById('url-input');
if (urlInput && urlInput.value) {
tabManager.navigateActiveTab(urlInput.value);
}
});
}); |