Files
WebView2Browser/assets/wvbrowser_ui/controls_ui/tabs.js
2025-07-07 09:39:03 +08:00

217 lines
5.3 KiB
JavaScript

var tabs = new Map();
var tabIdCounter = 0;
var activeTabId = 0;
const INVALID_TAB_ID = 0;
function getNewTabId() {
return ++tabIdCounter;
}
function isValidTabId(tabId) {
return tabId != INVALID_TAB_ID && tabs.has(tabId);
}
function createNewTab(shouldBeActive) {
const tabId = getNewTabId();
var message = {
message: commands.MG_CREATE_TAB,
args: {
tabId: parseInt(tabId),
active: shouldBeActive || false
}
};
window.chrome.webview.postMessage(message);
tabs.set(parseInt(tabId), {
title: 'New Tab',
uri: '',
uriToShow: '',
favicon: 'img/favicon.png',
isFavorite: false,
isLoading: false,
canGoBack: false,
canGoForward: false,
securityState: 'unknown',
historyItemId: INVALID_HISTORY_ID
});
loadTabUI(tabId);
if (shouldBeActive) {
switchToTab(tabId, false);
}
}
function switchToTab(id, updateOnHost) {
if (!id) {
console.log('ID not provided');
return;
}
// Check the tab to switch to is valid
if (!isValidTabId(id)) {
return;
}
// No need to switch if the tab is already active
if (id == activeTabId) {
return;
}
// Get the tab element to switch to
var tab = document.getElementById(`tab-${id}`);
if (!tab) {
console.log(`Can't switch to tab ${id}: element does not exist`);
return;
}
// Change the style for the previously active tab
if (isValidTabId(activeTabId)) {
const activeTabElement = document.getElementById(`tab-${activeTabId}`);
// Check the previously active tab element does actually exist
if (activeTabElement) {
activeTabElement.className = 'tab';
}
}
// Set tab as active
tab.className = 'tab-active';
activeTabId = id;
// Instruct host app to switch tab
if (updateOnHost) {
var message = {
message: commands.MG_SWITCH_TAB,
args: {
tabId: parseInt(activeTabId)
}
};
window.chrome.webview.postMessage(message);
}
updateNavigationUI(commands.MG_SWITCH_TAB);
}
function closeTab(id) {
// If closing tab was active, switch tab or close window
if (id == activeTabId) {
if (tabs.size == 1) {
// Last tab is closing, shut window down
tabs.delete(id);
closeWindow();
return;
}
// Other tabs are open, switch to rightmost tab
var tabsEntries = Array.from(tabs.entries());
var lastEntry = tabsEntries.pop();
if (lastEntry[0] == id) {
lastEntry = tabsEntries.pop();
}
switchToTab(lastEntry[0], true);
}
// Remove tab element
var tabElement = document.getElementById(`tab-${id}`);
if (tabElement) {
tabElement.parentNode.removeChild(tabElement);
}
// Remove tab from map
tabs.delete(id);
var message = {
message: commands.MG_CLOSE_TAB,
args: {
tabId: id
}
};
window.chrome.webview.postMessage(message);
}
function updateFaviconURI(tabId, src) {
let tab = tabs.get(tabId);
if (tab.favicon != src) {
let img = new Image();
// Update favicon element on successful load
img.onload = () => {
console.log('Favicon loaded');
tab.favicon = src;
if (tabId == activeTabId) {
updatedFaviconURIHandler(tabId, tab);
}
};
if (src) {
// Try load from root on failed load
img.onerror = () => {
console.log('Cannot load favicon from link, trying with root');
updateFaviconURI(tabId, '');
};
} else {
// No link for favicon, try loading from root
try {
let tabURI = new URL(tab.uri);
src = `${tabURI.origin}/favicon.ico`;
} catch(e) {
console.log(`Could not parse tab ${tabId} URI`);
}
img.onerror = () => {
console.log('No favicon in site root. Using default favicon.');
tab.favicon = 'img/favicon.png';
updatedFaviconURIHandler(tabId, tab);
};
}
img.src = src;
}
}
function updatedFaviconURIHandler(tabId, tab) {
updateNavigationUI(commands.MG_UPDATE_FAVICON);
// Update favicon in history item
if (tab.historyItemId != INVALID_HISTORY_ID) {
updateHistoryItem(tab.historyItemId, historyItemFromTab(tabId));
}
}
function favoriteFromTab(tabId) {
if (!isValidTabId(tabId)) {
console.log('Invalid tab ID');
return;
}
let tab = tabs.get(tabId);
let favicon = tab.favicon == 'img/favicon.png' ? '../controls_ui/' + tab.favicon : tab.favicon;
return {
uri: tab.uri,
uriToShow: tab.uriToShow,
title: tab.title,
favicon: favicon
};
}
function historyItemFromTab(tabId) {
if (!isValidTabId(tabId)) {
console.log('Invalid tab ID');
return;
}
let tab = tabs.get(tabId);
let favicon = tab.favicon == 'img/favicon.png' ? '../controls_ui/' + tab.favicon : tab.favicon;
return {
uri: tab.uri,
title: tab.title,
favicon: favicon,
timestamp: new Date()
}
}