217 lines
5.3 KiB
JavaScript
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()
|
|
}
|
|
}
|