feat: 新增包文件
This commit is contained in:
51
packages/chrome-ui/menu.js
Normal file
51
packages/chrome-ui/menu.js
Normal file
@@ -0,0 +1,51 @@
|
||||
const { Menu } = require('electron')
|
||||
|
||||
const setupMenu = (browser) => {
|
||||
const isMac = process.platform === 'darwin'
|
||||
|
||||
const tab = () => browser.getFocusedWindow().getFocusedTab()
|
||||
const tabWc = () => tab().webContents
|
||||
|
||||
const template = [
|
||||
...(isMac ? [{ role: 'appMenu' }] : []),
|
||||
{ role: 'fileMenu' },
|
||||
{ role: 'editMenu' },
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
nonNativeMacOSRole: true,
|
||||
click: () => tabWc().reload(),
|
||||
},
|
||||
{
|
||||
label: 'Force Reload',
|
||||
accelerator: 'Shift+CmdOrCtrl+R',
|
||||
nonNativeMacOSRole: true,
|
||||
click: () => tabWc().reloadIgnoringCache(),
|
||||
},
|
||||
{
|
||||
label: 'Toggle Developer Tool asdf',
|
||||
accelerator: isMac ? 'Alt+Command+I' : 'Ctrl+Shift+I',
|
||||
nonNativeMacOSRole: true,
|
||||
click: () => tabWc().toggleDevTools(),
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ role: 'resetZoom' },
|
||||
{ role: 'zoomIn' },
|
||||
{ role: 'zoomOut' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'togglefullscreen' },
|
||||
],
|
||||
},
|
||||
{ role: 'windowMenu' },
|
||||
]
|
||||
|
||||
const menu = Menu.buildFromTemplate(template)
|
||||
Menu.setApplicationMenu(menu)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setupMenu,
|
||||
}
|
||||
153
packages/chrome-ui/tabs.js
Normal file
153
packages/chrome-ui/tabs.js
Normal file
@@ -0,0 +1,153 @@
|
||||
const { EventEmitter } = require('events')
|
||||
const { WebContentsView } = require('electron')
|
||||
|
||||
const toolbarHeight = 64
|
||||
|
||||
class Tab {
|
||||
constructor(parentWindow, wcvOpts = {}) {
|
||||
this.invalidateLayout = this.invalidateLayout.bind(this)
|
||||
|
||||
// Delete undefined properties which cause WebContentsView constructor to
|
||||
// throw. This should probably be fixed in Electron upstream.
|
||||
if (wcvOpts.hasOwnProperty('webContents') && !wcvOpts.webContents) delete wcvOpts.webContents
|
||||
if (wcvOpts.hasOwnProperty('webPreferences') && !wcvOpts.webPreferences)
|
||||
delete wcvOpts.webPreferences
|
||||
|
||||
this.view = new WebContentsView(wcvOpts)
|
||||
this.id = this.view.webContents.id
|
||||
this.window = parentWindow
|
||||
this.webContents = this.view.webContents
|
||||
this.window.contentView.addChildView(this.view)
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.destroyed) return
|
||||
|
||||
this.destroyed = true
|
||||
|
||||
this.hide()
|
||||
|
||||
this.window.contentView.removeChildView(this.view)
|
||||
this.window = undefined
|
||||
|
||||
if (!this.webContents.isDestroyed()) {
|
||||
if (this.webContents.isDevToolsOpened()) {
|
||||
this.webContents.closeDevTools()
|
||||
}
|
||||
|
||||
// TODO: why is this no longer called?
|
||||
this.webContents.emit('destroyed')
|
||||
|
||||
this.webContents.destroy()
|
||||
}
|
||||
|
||||
this.webContents = undefined
|
||||
this.view = undefined
|
||||
}
|
||||
|
||||
loadURL(url) {
|
||||
return this.view.webContents.loadURL(url)
|
||||
}
|
||||
|
||||
show() {
|
||||
this.invalidateLayout()
|
||||
this.startResizeListener()
|
||||
this.view.setVisible(true)
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.stopResizeListener()
|
||||
this.view.setVisible(false)
|
||||
}
|
||||
|
||||
reload() {
|
||||
this.view.webContents.reload()
|
||||
}
|
||||
|
||||
invalidateLayout() {
|
||||
const [width, height] = this.window.getSize()
|
||||
const padding = 4
|
||||
this.view.setBounds({
|
||||
x: padding,
|
||||
y: toolbarHeight,
|
||||
width: width - padding * 2,
|
||||
height: height - toolbarHeight - padding,
|
||||
})
|
||||
this.view.setBorderRadius(8)
|
||||
}
|
||||
|
||||
// Replacement for BrowserView.setAutoResize. This could probably be better...
|
||||
startResizeListener() {
|
||||
this.stopResizeListener()
|
||||
this.window.on('resize', this.invalidateLayout)
|
||||
}
|
||||
stopResizeListener() {
|
||||
this.window.off('resize', this.invalidateLayout)
|
||||
}
|
||||
}
|
||||
|
||||
class Tabs extends EventEmitter {
|
||||
tabList = []
|
||||
selected = null
|
||||
|
||||
constructor(browserWindow) {
|
||||
super()
|
||||
this.window = browserWindow
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.tabList.forEach((tab) => tab.destroy())
|
||||
this.tabList = []
|
||||
|
||||
this.selected = undefined
|
||||
|
||||
if (this.window) {
|
||||
this.window.destroy()
|
||||
this.window = undefined
|
||||
}
|
||||
}
|
||||
|
||||
get(tabId) {
|
||||
return this.tabList.find((tab) => tab.id === tabId)
|
||||
}
|
||||
|
||||
create(webContentsViewOptions) {
|
||||
const tab = new Tab(this.window, webContentsViewOptions)
|
||||
this.tabList.push(tab)
|
||||
if (!this.selected) this.selected = tab
|
||||
tab.show() // must be attached to window
|
||||
this.emit('tab-created', tab)
|
||||
this.select(tab.id)
|
||||
return tab
|
||||
}
|
||||
|
||||
remove(tabId) {
|
||||
const tabIndex = this.tabList.findIndex((tab) => tab.id === tabId)
|
||||
if (tabIndex < 0) {
|
||||
throw new Error(`Tabs.remove: unable to find tab.id = ${tabId}`)
|
||||
}
|
||||
const tab = this.tabList[tabIndex]
|
||||
this.tabList.splice(tabIndex, 1)
|
||||
tab.destroy()
|
||||
if (this.selected === tab) {
|
||||
this.selected = undefined
|
||||
const nextTab = this.tabList[tabIndex] || this.tabList[tabIndex - 1]
|
||||
if (nextTab) this.select(nextTab.id)
|
||||
}
|
||||
this.emit('tab-destroyed', tab)
|
||||
if (this.tabList.length === 0) {
|
||||
this.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
select(tabId) {
|
||||
const tab = this.get(tabId)
|
||||
if (!tab) return
|
||||
if (this.selected) this.selected.hide()
|
||||
tab.show()
|
||||
this.selected = tab
|
||||
this.emit('tab-selected', tab)
|
||||
}
|
||||
}
|
||||
|
||||
exports.Tabs = Tabs
|
||||
9
packages/chrome-ui/ui/manifest.json
Normal file
9
packages/chrome-ui/ui/manifest.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "WebUI",
|
||||
"version": "1.0.0",
|
||||
"manifest_version": 3,
|
||||
"permissions": [],
|
||||
"chrome_url_overrides": {
|
||||
"newtab": "new-tab.html"
|
||||
}
|
||||
}
|
||||
31
packages/chrome-ui/ui/new-tab.html
Normal file
31
packages/chrome-ui/ui/new-tab.html
Normal file
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>New Tab</title>
|
||||
<style>
|
||||
body {
|
||||
font-size: 16px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>New Tab</h1>
|
||||
<ul>
|
||||
<li><a href="https://www.google.com">https://www.google.com</a></li>
|
||||
<li><a href="https://www.youtube.com">https://www.youtube.com</a></li>
|
||||
<li>
|
||||
<a href="https://github.com/electron/electron">https://github.com/electron/electron</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/samuelmaddock/electron-browser-shell"
|
||||
>https://github.com/samuelmaddock/electron-browser-shell</a
|
||||
>
|
||||
</li>
|
||||
<li><a href="https://chromewebstore.google.com">https://chromewebstore.google.com</a></li>
|
||||
<li><a href="https://microsoftedge.microsoft.com/addons/Microsoft-Edge-Extensions-Home">https://microsoftedge.microsoft.com/addons/Microsoft-Edge-Extensions-Home</a></li>
|
||||
<li><a href="https://permission.site">https://permission.site</a></li>
|
||||
<li><a href="https://samuelmaddock.com">https://samuelmaddock.com</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
253
packages/chrome-ui/ui/webui.html
Normal file
253
packages/chrome-ui/ui/webui.html
Normal file
@@ -0,0 +1,253 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Shell Browser</title>
|
||||
<style>
|
||||
:root {
|
||||
/* https://colorhunt.co/palette/161920 */
|
||||
--bg-color: #39375b;
|
||||
--text-color: #ececec;
|
||||
--tab-color: #745c97;
|
||||
--toolbar-control-color: #d597ce;
|
||||
|
||||
/* electron-chrome-extensions colors */
|
||||
--browser-action-badge-outline: var(--tab-color);
|
||||
}
|
||||
|
||||
*, *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
html {
|
||||
background: var(--tab-color);
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "Ubuntu", "Droid Sans", sans-serif;
|
||||
font-size: 16px;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.topbar {
|
||||
background: var(--bg-color);
|
||||
}
|
||||
|
||||
/*----- TABS -----*/
|
||||
|
||||
#tabstrip {
|
||||
width: 100%;
|
||||
height: calc(env(titlebar-area-height, 31px) + 1px);
|
||||
}
|
||||
|
||||
.tab-container {
|
||||
position: fixed;
|
||||
left: env(titlebar-area-x);
|
||||
top: env(titlebar-area-y);
|
||||
width: env(titlebar-area-width);
|
||||
height: calc(env(titlebar-area-height, 31px) + 1px);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.tab-list {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
#createtab {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
}
|
||||
|
||||
#createtab:hover {
|
||||
background: rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
.tab {
|
||||
padding: 0.2rem 0.4rem;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
width: 12rem;
|
||||
box-shadow: inset -1px 0 0 0 rgba(0,0,0,0.33);
|
||||
}
|
||||
|
||||
.tab[data-active] {
|
||||
background: var(--tab-color);
|
||||
}
|
||||
|
||||
.tab .favicon[src] {
|
||||
display: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 0.2rem;
|
||||
}
|
||||
|
||||
.tab .favicon[src].loaded {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tab .title {
|
||||
white-space: nowrap;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
font-size: 0.725rem;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tab .controls {
|
||||
flex: 0 0 auto;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.tab .controls .control {
|
||||
background: rgba(0,0,0,0.2);
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
padding: 0;
|
||||
margin-left: 0.2rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
color: #aaa;
|
||||
font-size: 0.7rem;
|
||||
vertical-align: middle;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.tab .controls .control:disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.app-drag {
|
||||
flex: 1 0 auto;
|
||||
-webkit-app-region: drag;
|
||||
height: calc(100% - 5px);
|
||||
min-width: 2rem;
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.window-controls {
|
||||
display: none;
|
||||
flex-direction: row;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.platform-linux .window-controls {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.window-controls .control {
|
||||
width: 2.5rem;
|
||||
background: none;
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.window-controls .control:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
/*----- TOOLBAR -----*/
|
||||
|
||||
.toolbar {
|
||||
height: 1.875rem;
|
||||
background-color: var(--tab-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.2rem 0.5rem;
|
||||
}
|
||||
|
||||
.toolbar .page-controls {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.address-bar {
|
||||
flex: 1 0 auto;
|
||||
line-height: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.address-bar input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--bg-color);
|
||||
color: var(--text-color);
|
||||
border: none;
|
||||
border-radius: 2rem;
|
||||
padding: 0 0.5rem;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.toolbar .control {
|
||||
background: none;
|
||||
border: none;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
padding: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="topbar">
|
||||
<div id="tabstrip">
|
||||
<div class="tab-container">
|
||||
<ul class="tab-list">
|
||||
<template id="tabtemplate">
|
||||
<li class="tab">
|
||||
<img class="favicon" />
|
||||
<span class="title"></span>
|
||||
<div class="controls">
|
||||
<button class="control audio" disabled>🔊</button>
|
||||
<button class="control close">✕</button>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
<button id="createtab">+</button>
|
||||
<div class="app-drag"></div>
|
||||
<div class="window-controls">
|
||||
<button id="minimize" class="control">🗕</button>
|
||||
<button id="maximize" class="control">🗖</button>
|
||||
<button id="close" class="control">🗙</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<div class="page-controls">
|
||||
<button id="goback" class="control">⬅️</button>
|
||||
<button id="goforward" class="control">➡️</button>
|
||||
<button id="reload" class="control">🔄</button>
|
||||
</div>
|
||||
<div class="address-bar">
|
||||
<input id="addressurl" spellcheck="false" />
|
||||
</div>
|
||||
<browser-action-list id="actions" alignment="bottom left"></browser-action-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="./webui.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
193
packages/chrome-ui/ui/webui.js
Normal file
193
packages/chrome-ui/ui/webui.js
Normal file
@@ -0,0 +1,193 @@
|
||||
class WebUI {
|
||||
windowId = -1
|
||||
activeTabId = -1
|
||||
/** @type {chrome.tabs.Tab[]} */
|
||||
tabList = []
|
||||
|
||||
constructor() {
|
||||
const $ = document.querySelector.bind(document)
|
||||
|
||||
this.$ = {
|
||||
tabList: $('#tabstrip .tab-list'),
|
||||
tabTemplate: $('#tabtemplate'),
|
||||
createTabButton: $('#createtab'),
|
||||
goBackButton: $('#goback'),
|
||||
goForwardButton: $('#goforward'),
|
||||
reloadButton: $('#reload'),
|
||||
addressUrl: $('#addressurl'),
|
||||
|
||||
browserActions: $('#actions'),
|
||||
|
||||
minimizeButton: $('#minimize'),
|
||||
maximizeButton: $('#maximize'),
|
||||
closeButton: $('#close'),
|
||||
}
|
||||
|
||||
this.$.createTabButton.addEventListener('click', () => chrome.tabs.create())
|
||||
this.$.goBackButton.addEventListener('click', () => chrome.tabs.goBack())
|
||||
this.$.goForwardButton.addEventListener('click', () => chrome.tabs.goForward())
|
||||
this.$.reloadButton.addEventListener('click', () => chrome.tabs.reload())
|
||||
this.$.addressUrl.addEventListener('keypress', this.onAddressUrlKeyPress.bind(this))
|
||||
|
||||
this.$.minimizeButton.addEventListener('click', () =>
|
||||
chrome.windows.get(chrome.windows.WINDOW_ID_CURRENT, (win) => {
|
||||
chrome.windows.update(win.id, { state: win.state === 'minimized' ? 'normal' : 'minimized' })
|
||||
}),
|
||||
)
|
||||
this.$.maximizeButton.addEventListener('click', () =>
|
||||
chrome.windows.get(chrome.windows.WINDOW_ID_CURRENT, (win) => {
|
||||
chrome.windows.update(win.id, { state: win.state === 'maximized' ? 'normal' : 'maximized' })
|
||||
}),
|
||||
)
|
||||
this.$.closeButton.addEventListener('click', () => chrome.windows.remove())
|
||||
|
||||
const platformClass = `platform-${navigator.userAgentData.platform.toLowerCase()}`
|
||||
document.body.classList.add(platformClass)
|
||||
|
||||
this.initTabs()
|
||||
}
|
||||
|
||||
async initTabs() {
|
||||
const tabs = await new Promise((resolve) => chrome.tabs.query({ windowId: -2 }, resolve))
|
||||
this.tabList = [...tabs]
|
||||
this.renderTabs()
|
||||
|
||||
const activeTab = this.tabList.find((tab) => tab.active)
|
||||
if (activeTab) {
|
||||
this.setActiveTab(activeTab)
|
||||
}
|
||||
|
||||
// Wait to setup tabs and windowId prior to listening for updates.
|
||||
this.setupBrowserListeners()
|
||||
}
|
||||
|
||||
setupBrowserListeners() {
|
||||
if (!chrome.tabs.onCreated) {
|
||||
throw new Error(`chrome global not setup. Did the extension preload not get run?`)
|
||||
}
|
||||
|
||||
const findTab = (tabId) => {
|
||||
const existingTab = this.tabList.find((tab) => tab.id === tabId)
|
||||
return existingTab
|
||||
}
|
||||
|
||||
const findOrCreateTab = (tabId) => {
|
||||
const existingTab = findTab(tabId)
|
||||
if (existingTab) return existingTab
|
||||
|
||||
const newTab = { id: tabId }
|
||||
this.tabList.push(newTab)
|
||||
return newTab
|
||||
}
|
||||
|
||||
chrome.tabs.onCreated.addListener((tab) => {
|
||||
if (tab.windowId !== this.windowId) return
|
||||
const newTab = findOrCreateTab(tab.id)
|
||||
Object.assign(newTab, tab)
|
||||
this.renderTabs()
|
||||
})
|
||||
|
||||
chrome.tabs.onActivated.addListener((activeInfo) => {
|
||||
if (activeInfo.windowId !== this.windowId) return
|
||||
|
||||
this.setActiveTab(activeInfo)
|
||||
})
|
||||
|
||||
chrome.tabs.onUpdated.addListener((tabId, changeInfo, details) => {
|
||||
const tab = findTab(tabId)
|
||||
if (!tab) return
|
||||
Object.assign(tab, details)
|
||||
this.renderTabs()
|
||||
if (tabId === this.activeTabId) this.renderToolbar(tab)
|
||||
})
|
||||
|
||||
chrome.tabs.onRemoved.addListener((tabId) => {
|
||||
const tabIndex = this.tabList.findIndex((tab) => tab.id === tabId)
|
||||
if (tabIndex > -1) {
|
||||
this.tabList.splice(tabIndex, 1)
|
||||
this.$.tabList.querySelector(`[data-tab-id="${tabId}"]`).remove()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setActiveTab(activeTab) {
|
||||
this.activeTabId = activeTab.id || activeTab.tabId
|
||||
this.windowId = activeTab.windowId
|
||||
|
||||
for (const tab of this.tabList) {
|
||||
if (tab.id === this.activeTabId) {
|
||||
tab.active = true
|
||||
this.renderTab(tab)
|
||||
this.renderToolbar(tab)
|
||||
} else {
|
||||
if (tab.active) {
|
||||
tab.active = false
|
||||
this.renderTab(tab)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onAddressUrlKeyPress(event) {
|
||||
if (event.code === 'Enter') {
|
||||
const url = this.$.addressUrl.value
|
||||
chrome.tabs.update({ url })
|
||||
}
|
||||
}
|
||||
|
||||
createTabNode(tab) {
|
||||
const tabElem = this.$.tabTemplate.content.cloneNode(true).firstElementChild
|
||||
tabElem.dataset.tabId = tab.id
|
||||
|
||||
tabElem.addEventListener('click', () => {
|
||||
chrome.tabs.update(tab.id, { active: true })
|
||||
})
|
||||
tabElem.querySelector('.close').addEventListener('click', () => {
|
||||
chrome.tabs.remove(tab.id)
|
||||
})
|
||||
const faviconElem = tabElem.querySelector('.favicon')
|
||||
faviconElem?.addEventListener('load', () => {
|
||||
faviconElem.classList.toggle('loaded', true)
|
||||
})
|
||||
faviconElem?.addEventListener('error', () => {
|
||||
faviconElem.classList.toggle('loaded', false)
|
||||
})
|
||||
|
||||
this.$.tabList.appendChild(tabElem)
|
||||
return tabElem
|
||||
}
|
||||
|
||||
renderTab(tab) {
|
||||
let tabElem = this.$.tabList.querySelector(`[data-tab-id="${tab.id}"]`)
|
||||
if (!tabElem) tabElem = this.createTabNode(tab)
|
||||
|
||||
if (tab.active) {
|
||||
tabElem.dataset.active = ''
|
||||
} else {
|
||||
delete tabElem.dataset.active
|
||||
}
|
||||
|
||||
const favicon = tabElem.querySelector('.favicon')
|
||||
if (tab.favIconUrl) {
|
||||
favicon.src = tab.favIconUrl
|
||||
} else {
|
||||
delete favicon.src
|
||||
}
|
||||
|
||||
tabElem.querySelector('.title').textContent = tab.title
|
||||
tabElem.querySelector('.audio').disabled = !tab.audible
|
||||
}
|
||||
|
||||
renderTabs() {
|
||||
this.tabList.forEach((tab) => {
|
||||
this.renderTab(tab)
|
||||
})
|
||||
}
|
||||
|
||||
renderToolbar(tab) {
|
||||
this.$.addressUrl.value = tab.url
|
||||
// this.$.browserActions.tab = tab.id
|
||||
}
|
||||
}
|
||||
|
||||
window.webui = new WebUI()
|
||||
Reference in New Issue
Block a user