feat: 优化内置浏览器

This commit is contained in:
Pang 2024-02-26 11:48:49 +08:00 committed by kuaifan
parent b6eb77ae63
commit 779b32e8ad
16 changed files with 843 additions and 45 deletions

View File

@ -72,6 +72,7 @@ contextBridge.exposeInMainWorld(
contextBridge.exposeInMainWorld(
'process', {
type: process.type,
versions: process.versions
versions: process.versions,
platform: process.platform,
}
);

378
electron/electron.js vendored
View File

@ -1,9 +1,11 @@
const fs = require('fs')
const os = require("os");
const path = require('path')
const {app, BrowserWindow, ipcMain, dialog, clipboard, nativeImage, shell, Tray, Menu, globalShortcut, Notification} = require('electron')
const {app, BrowserWindow, ipcMain, dialog, clipboard, nativeImage, shell, Tray, Menu, globalShortcut, Notification, BrowserView, nativeTheme} = require('electron')
const {autoUpdater} = require("electron-updater")
const log = require("electron-log");
const electronConf = require('electron-config')
const userConf = new electronConf()
const fsProm = require('fs/promises');
const PDFDocument = require('pdf-lib').PDFDocument;
const Screenshots = require("electron-screenshots-tool").Screenshots;
@ -33,6 +35,19 @@ let mainWindow = null,
let screenshotObj = null,
screenshotKey = null;
let webWindow = null,
webTabView = [],
webTabHeight = 38;
let showState = {},
onShowWindow = (win) => {
if (typeof showState[win.webContents.id] === 'undefined') {
showState[win.webContents.id] = true
win.setBackgroundColor('rgba(255, 255, 255, 0)')
win.show();
}
}
if (fs.existsSync(devloadCachePath)) {
devloadUrl = fs.readFileSync(devloadCachePath, 'utf8')
}
@ -44,6 +59,8 @@ function createMainWindow() {
mainWindow = new BrowserWindow({
width: 1280,
height: 800,
minWidth: 360,
minHeight: 360,
center: true,
autoHideMenuBar: true,
webPreferences: {
@ -65,13 +82,9 @@ function createMainWindow() {
electronMenu.webContentsMenu(mainWindow.webContents)
if (devloadUrl) {
mainWindow.loadURL(devloadUrl).then(_ => {
})
mainWindow.loadURL(devloadUrl).then(_ => { }).catch(_ => { })
} else {
mainWindow.loadFile('./public/index.html').then(_ => {
})
mainWindow.loadFile('./public/index.html').then(_ => { }).catch(_ => { })
}
mainWindow.on('page-title-updated', (event, title) => {
@ -122,7 +135,10 @@ function createSubWindow(args) {
browser = new BrowserWindow(Object.assign({
width: 1280,
height: 800,
minWidth: 360,
minHeight: 360,
center: true,
show: false,
parent: mainWindow,
autoHideMenuBar: true,
webPreferences: Object.assign({
@ -155,6 +171,14 @@ function createSubWindow(args) {
}
})
browser.once('ready-to-show', () => {
onShowWindow(browser);
})
browser.webContents.once('dom-ready', () => {
onShowWindow(browser);
})
subWindow.push({ name, browser })
}
const originalUA = browser.webContents.session.getUserAgent() || browser.webContents.getUserAgent()
@ -169,15 +193,11 @@ function createSubWindow(args) {
const hash = args.hash || args.path;
if (/^https?:\/\//i.test(hash)) {
browser.loadURL(hash).then(_ => {
})
browser.loadURL(hash).then(_ => { }).catch(_ => { })
return;
}
if (devloadUrl) {
browser.loadURL(devloadUrl + '#' + hash).then(_ => {
})
browser.loadURL(devloadUrl + '#' + hash).then(_ => { }).catch(_ => { })
return;
}
browser.loadFile('./public/index.html', {
@ -204,15 +224,11 @@ function updateSubWindow(browser, args) {
const hash = args.hash || args.path;
if (hash) {
if (devloadUrl) {
browser.loadURL(devloadUrl + '#' + hash).then(_ => {
})
browser.loadURL(devloadUrl + '#' + hash).then(_ => { }).catch(_ => { })
} else {
browser.loadFile('./public/index.html', {
hash
}).then(_ => {
})
}).then(_ => { }).catch(_ => { })
}
}
if (args.name) {
@ -223,6 +239,284 @@ function updateSubWindow(browser, args) {
}
}
/**
* 创建内置浏览器
* @param args {url, ?}
*/
function createWebWindow(args) {
if (!args) {
return;
}
if (!utils.isJson(args)) {
args = {url: args}
}
if (!allowedUrls.test(args.url)) {
return;
}
// 创建父级窗口
if (!webWindow) {
let config = Object.assign(args.config || {}, userConf.get('webWindow', {}));
let webPreferences = args.webPreferences || {};
const titleBarOverlay = {
height: webTabHeight
}
if (nativeTheme.shouldUseDarkColors) {
titleBarOverlay.color = '#3B3B3D'
titleBarOverlay.symbolColor = '#C5C5C5'
}
webWindow = new BrowserWindow(Object.assign({
x: mainWindow.getBounds().x + webTabHeight,
y: mainWindow.getBounds().y + webTabHeight,
width: 1280,
height: 800,
minWidth: 360,
minHeight: 360,
center: true,
show: false,
autoHideMenuBar: true,
titleBarStyle: 'hidden',
titleBarOverlay,
webPreferences: Object.assign({
preload: path.join(__dirname, 'electron-preload.js'),
webSecurity: true,
nodeIntegration: true,
contextIsolation: true,
nativeWindowOpen: true
}, webPreferences),
}, config))
webWindow.on('resize', () => {
resizeWebTab(0)
})
webWindow.on('enter-full-screen', () => {
utils.onDispatchEvent(webWindow.webContents, {
event: 'enter-full-screen',
}).then(_ => { })
})
webWindow.on('leave-full-screen', () => {
utils.onDispatchEvent(webWindow.webContents, {
event: 'leave-full-screen',
}).then(_ => { })
})
webWindow.on('close', event => {
if (!willQuitApp) {
closeWebTab(0)
event.preventDefault()
} else {
userConf.set('webWindow', webWindow.getBounds())
}
})
webWindow.on('closed', () => {
webWindow = null
})
webWindow.once('ready-to-show', () => {
onShowWindow(webWindow);
})
webWindow.webContents.once('dom-ready', () => {
onShowWindow(webWindow);
})
webWindow.webContents.on('before-input-event', (event, input) => {
if (input.meta && input.key.toLowerCase() === 'r') {
reloadWebTab(0)
event.preventDefault()
}
})
webWindow.loadFile('./render/tabs/index.html', {}).then(_ => {
})
}
webWindow.focus();
// 创建子窗口
const browserView = new BrowserView({
useHTMLTitleAndIcon: true,
useLoadingView: true,
useErrorView: true,
webPreferences: {
type: 'browserView',
preload: path.join(__dirname, 'electron-preload.js'),
nodeIntegrationInSubFrames: true,
}
})
if (nativeTheme.shouldUseDarkColors) {
browserView.setBackgroundColor('#575757')
} else {
browserView.setBackgroundColor('#FFFFFF')
}
browserView.setBounds({
x: 0,
y: webTabHeight,
width: webWindow.getContentBounds().width || 1280,
height: (webWindow.getContentBounds().height || 800) - webTabHeight,
})
browserView.webContents.setWindowOpenHandler(({url}) => {
createWebWindow({url})
return {action: 'deny'}
})
browserView.webContents.on('page-title-updated', (event, title) => {
utils.onDispatchEvent(webWindow.webContents, {
event: 'title',
id: browserView.webContents.id,
title: title,
url: browserView.webContents.getURL(),
}).then(_ => { })
})
browserView.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL, isMainFrame) => {
if (!errorDescription) {
return
}
utils.onDispatchEvent(webWindow.webContents, {
event: 'title',
id: browserView.webContents.id,
title: errorDescription,
url: browserView.webContents.getURL(),
}).then(_ => { })
})
browserView.webContents.on('page-favicon-updated', (event, favicons) => {
utils.onDispatchEvent(webWindow.webContents, {
event: 'favicon',
id: browserView.webContents.id,
favicons
}).then(_ => { })
})
browserView.webContents.on('did-start-loading', _ => {
utils.onDispatchEvent(webWindow.webContents, {
event: 'start-loading',
id: browserView.webContents.id,
}).then(_ => { })
})
browserView.webContents.on('did-stop-loading', _ => {
utils.onDispatchEvent(webWindow.webContents, {
event: 'stop-loading',
id: browserView.webContents.id,
}).then(_ => { })
})
browserView.webContents.on('before-input-event', (event, input) => {
if (input.meta && input.key.toLowerCase() === 'r') {
browserView.webContents.reload()
event.preventDefault()
}
})
browserView.webContents.loadURL(args.url).then(_ => { }).catch(_ => { })
webWindow.addBrowserView(browserView)
webTabView.push({
id: browserView.webContents.id,
view: browserView
})
utils.onDispatchEvent(webWindow.webContents, {
event: 'create',
id: browserView.webContents.id,
url: args.url,
}).then(_ => { })
switchWebTab(browserView.webContents.id)
}
/**
* 获取当前内置浏览器标签
* @returns {Electron.BrowserView|undefined}
*/
function currentWebTab() {
const views = webWindow.getBrowserViews()
const view = views.length ? views[views.length - 1] : undefined
if (!view) {
return undefined
}
return webTabView.find(item => item.id == view.webContents.id)
}
/**
* 重新加载内置浏览器标签
* @param id
*/
function reloadWebTab(id) {
const item = id === 0 ? currentWebTab() : webTabView.find(item => item.id == id)
if (!item) {
return
}
item.view.webContents.reload()
}
/**
* 调整内置浏览器标签尺寸
* @param id
*/
function resizeWebTab(id) {
const item = id === 0 ? currentWebTab() : webTabView.find(item => item.id == id)
if (!item) {
return
}
item.view.setBounds({
x: 0,
y: webTabHeight,
width: webWindow.getContentBounds().width || 1280,
height: (webWindow.getContentBounds().height || 800) - webTabHeight,
})
}
/**
* 切换内置浏览器标签
* @param id
*/
function switchWebTab(id) {
const item = id === 0 ? currentWebTab() : webTabView.find(item => item.id == id)
if (!item) {
return
}
resizeWebTab(item.id)
webWindow.setTopBrowserView(item.view)
item.view.webContents.focus()
utils.onDispatchEvent(webWindow.webContents, {
event: 'switch',
id: item.id,
}).then(_ => { })
}
/**
* 关闭内置浏览器标签
* @param id
*/
function closeWebTab(id) {
const item = id === 0 ? currentWebTab() : webTabView.find(item => item.id == id)
if (!item) {
return
}
if (webTabView.length === 1) {
webWindow.hide()
}
webWindow.removeBrowserView(item.view)
item.view.webContents.close()
const index = webTabView.findIndex(({id}) => item.id == id)
if (index > -1) {
webTabView.splice(index, 1)
}
utils.onDispatchEvent(webWindow.webContents, {
event: 'close',
id: item.id,
}).then(_ => { })
if (webTabView.length === 0) {
userConf.set('webWindow', webWindow.getBounds())
webWindow.destroy()
} else {
switchWebTab(0)
}
}
const getTheLock = app.requestSingleInstanceLock()
if (!getTheLock) {
app.quit()
@ -355,6 +649,45 @@ ipcMain.on('updateRouter', (event, args) => {
event.returnValue = "ok"
})
/**
* 内置浏览器 - 打开创建
* @param args {url, ?}
*/
ipcMain.on('openWebWindow', (event, args) => {
createWebWindow(args)
event.returnValue = "ok"
})
/**
* 内置浏览器 - 激活标签
* @param id
*/
ipcMain.on('webTabSwitch', (event, id) => {
switchWebTab(id)
event.returnValue = "ok"
})
/**
* 内置浏览器 - 关闭标签
* @param id
*/
ipcMain.on('webTabClose', (event, id) => {
closeWebTab(id)
event.returnValue = "ok"
})
/**
* 内置浏览器 - 在外部浏览器打开
*/
ipcMain.on('webTabBrowser', (event) => {
const item = currentWebTab()
if (!item) {
return
}
openExternal(item.view.webContents.getURL())
event.returnValue = "ok"
})
/**
* 隐藏窗口macwin隐藏其他关闭
*/
@ -512,9 +845,7 @@ ipcMain.on('storageBrowser', (event, args) => {
},
})
}
storageBrowser.loadURL(args.url).then(_ => {
})
storageBrowser.loadURL(args.url).then(_ => { }).catch(_ => { })
}
event.returnValue = "ok"
})
@ -682,6 +1013,9 @@ ipcMain.on('updateCheckAndDownload', (event, args) => {
autoUpdater.setFeedURL(args)
}
autoUpdater.checkForUpdates().then(info => {
if (!info) {
return
}
if (utils.compareVersion(config.version, info.updateInfo.version) >= 0) {
return
}

View File

@ -26,14 +26,14 @@
"url": "https://github.com/kuaifan/dootask.git"
},
"devDependencies": {
"@electron-forge/cli": "^7.2.0",
"@electron-forge/maker-deb": "^7.2.0",
"@electron-forge/maker-rpm": "^7.2.0",
"@electron-forge/maker-squirrel": "^7.2.0",
"@electron-forge/maker-zip": "^7.2.0",
"@electron-forge/cli": "^7.3.0",
"@electron-forge/maker-deb": "^7.3.0",
"@electron-forge/maker-rpm": "^7.3.0",
"@electron-forge/maker-squirrel": "^7.3.0",
"@electron-forge/maker-zip": "^7.3.0",
"dotenv": "^16.3.1",
"electron": "^28.1.1",
"electron-builder": "^24.9.1",
"electron": "^29.0.1",
"electron-builder": "^24.12.0",
"electron-notarize": "^1.2.2",
"form-data": "^4.0.0",
"ora": "^4.1.1"
@ -41,7 +41,8 @@
"dependencies": {
"axios": "^1.6.2",
"crc": "^3.8.0",
"electron-log": "^5.0.1",
"electron-config": "^2.0.0",
"electron-log": "^5.1.1",
"electron-screenshots-tool": "^1.1.2",
"electron-squirrel-startup": "^1.0.0",
"electron-updater": "^6.1.7",
@ -67,6 +68,7 @@
"output": "dist"
},
"files": [
"render/**/*",
"public/**/*",
"electron-menu.js",
"electron-preload.js",

View File

@ -0,0 +1,269 @@
:root {
--tab-font-family: -apple-system, 'Segoe UI', roboto, oxygen-sans, ubuntu, cantarell, 'Helvetica Neue', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
--tab-font-size: 12px;
--tab-transition: background-color 200ms ease-out, color 200ms ease-out;
--tab-cursor: pointer; /* 设置鼠标指针为手型 */
--tab-color: #7f8792;
--tab-background: #EFF0F4;
--tab-active-color: #222529;
--tab-active-background: #FFFFFF;
--tab-close-color: #9DA3AC;
}
* {
margin: 0;
padding: 0;
}
html, body {
margin: 0;
padding: 0;
font-family: 'Roboto', sans-serif;
font-size: 16px;
color: #333;
}
.nav {
font-family: var(--tab-font-family);
font-feature-settings: 'clig', 'kern';
display: flex;
width: 100%;
cursor: default;
background-color: var(--tab-background);
-webkit-app-region: drag;
}
.nav ul {
display: flex;
height: 30px;
margin: 8px 46px 0 0;
user-select: none;
overflow-x: auto;
overflow-y: hidden;
}
.nav ul::-webkit-scrollbar {
display: none;
}
.nav ul li {
display: inline-flex;
position: relative;
box-sizing: border-box;
align-items: center;
height: 100%;
padding: 7px 8px;
margin: 0 8px 0 0;
min-width: 100px;
max-width: 240px;
scroll-margin: 12px;
font-size: var(--tab-font-size);
color: var(--tab-color);
cursor: var(--tab-cursor);
transition: var(--tab-transition);
-webkit-app-region: none;
}
.nav ul li:first-child {
margin-left: 8px;
border-left: none;
}
.nav ul li.active {
color: var(--tab-active-color);
background: var(--tab-active-background);
border-radius: 6px 6px 0 0;
}
.nav ul li.active::before {
position: absolute;
bottom: 0;
left: -6px;
width: 6px;
height: 6px;
background-image: url(../image/select_left.png);
background-repeat: no-repeat;
background-size: cover;
content: '';
}
.nav ul li.active::after {
position: absolute;
right: -6px;
bottom: 0;
width: 6px;
height: 6px;
background-image: url(../image/select_right.png);
background-repeat: no-repeat;
background-size: cover;
content: '';
}
.nav ul li.active .tab-icon.background {
background-image: url(../image/link_normal_selected_icon.png);
}
.nav ul li:not(.active)::after {
position: absolute;
right: 0;
width: 1px;
height: 16px;
background: rgba(0, 0, 0, 0.08);
content: '';
}
.nav ul li:not(.active):last-child::after {
content: none;
}
/* 浏览器打开 */
.browser {
position: absolute;
top: 0;
right: 0;
display: flex;
align-items: center;
height: 38px;
padding: 0 14px;
cursor: pointer;
-webkit-app-region: none;
}
.browser span {
display: inline-block;
width: 18px;
height: 18px;
background-size: cover;
background-image: url(../image/link_normal_selected_icon.png);
}
/* 图标 */
.tab-icon {
display: inline-block;
flex-shrink: 0;
width: 18px;
height: 18px;
background-size: cover;
}
.tab-icon.background {
background-image: url(../image/link_normal_icon.png);
}
.tab-icon.loading {
background-image: none !important;
}
.tab-icon .tab-icon-loading {
width: 18px;
height: 18px;
border: 2px solid #eeeeee;
border-bottom-color: #84C56A;
border-radius: 50%;
display: inline-block;
box-sizing: border-box;
animation: spin 0.75s linear infinite;
}
.tab-icon:not(.loading) .tab-icon-loading {
display: none;
}
.tab-icon img {
width: 16px;
height: 16px;
border-radius: 4px;
}
@keyframes spin {
0% {
transform: scale(0.8) rotate(0deg);
}
100% {
transform: scale(0.8) rotate(360deg);
}
}
/* 标题 */
.tab-title {
display: inline-block;
flex: 1;
margin-right: 8px;
margin-left: 6px;
overflow: hidden;
line-height: 150%;
text-overflow: ellipsis;
white-space: nowrap;
}
/* 关闭 */
.tab-close {
display: inline-block;
width: 14px;
height: 14px;
margin-right: 2px;
position: relative;
}
.tab-close::after,
.tab-close::before {
position: absolute;
top: 50%;
right: 50%;
transform: translate(50%, -50%) scale(0.9) rotate(45deg);
content: "";
width: 2px;
height: 11px;
border-radius: 3px;
background-color: var(--tab-close-color);
}
.tab-close::before {
transform: translate(50%, -50%) scale(0.9) rotate(-45deg);
}
/* 不同平台样式 */
body.win32 .nav ul {
margin-left: 8px;
margin-right: 186px;
}
body.win32 .browser {
right: 140px;
}
body.darwin .nav ul {
margin-left: 76px;
}
body.darwin.full-screen .nav ul {
margin-left: 8px;
}
/* 暗黑模式 */
@media (prefers-color-scheme: dark) {
:root {
--tab-color: #C5C5C5;
--tab-background: #3B3B3D;
--tab-active-color: #E1E1E1;
--tab-active-background: #575757;
--tab-close-color: #E3E3E3;
}
.nav ul li.active::before {
background-image: url(../image/dark/select_left.png);
}
.nav ul li.active::after {
background-image: url(../image/dark/select_right.png);
}
.nav ul li.active .tab-icon.background {
background-image: url(../image/dark/link_normal_selected_icon.png);
}
.browser span {
background-image: url(../image/dark/link_normal_selected_icon.png);
}
.tab-icon.background {
background-image: url(../image/dark/link_normal_icon.png);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,165 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Untitled</title>
<link rel="stylesheet" href="./assets/css/style.css">
<script src="./assets/js/vue.global.min.js"></script>
</head>
<body>
<div id="app" class="app">
<div class="nav">
<ul>
<li v-for="item in tabs" :data-id="item.id" :class="{active: activeId === item.id}" @click="onSwitch(item)">
<div v-if="item.state === 'loading'" class="tab-icon loading">
<div class="tab-icon-loading"></div>
</div>
<div v-else class="tab-icon background" :style="iconStyle(item)"></div>
<div class="tab-title" :title="item.title">{{tabTitle(item)}}</div>
<div class="tab-close" @click.stop="onClose(item)"></div>
</li>
</ul>
</div>
<div v-if="tabs.length > 0" class="browser" @click="onBrowser">
<span></span>
</div>
</div>
<script>
const App = {
data() {
return {
activeId: 0,
tabs: []
}
},
beforeCreate() {
document.body.classList.add(window.process.platform)
},
mounted() {
window.__onDispatchEvent = (detail) => {
const {id, event} = detail
switch (event) {
case 'create':
this.tabs.push(Object.assign({
id,
title: '',
url: '',
icon: '',
state: 'loading'
}, detail))
break
case 'close':
const closeIndex = this.tabs.findIndex(item => item.id === id)
if (closeIndex > -1) {
this.tabs.splice(closeIndex, 1)
}
break
case 'switch':
this.activeId = id
this.scrollTabActive()
break
case 'title':
const titleItem = this.tabs.find(item => item.id === id)
if (titleItem) {
titleItem.title = detail.title
titleItem.url = detail.url
}
break
case 'favicon':
const faviconItem = this.tabs.find(item => item.id === id)
if (faviconItem) {
faviconItem.icon = detail.favicons[detail.favicons.length - 1]
}
break
case 'start-loading':
const startItem = this.tabs.find(item => item.id === id)
if (startItem) {
startItem.state = 'loading'
}
break
case 'stop-loading':
const stopItem = this.tabs.find(item => item.id === id)
if (stopItem) {
stopItem.state = 'loaded'
}
break
case 'enter-full-screen':
document.body.classList.add('full-screen')
break
case 'leave-full-screen':
document.body.classList.remove('full-screen')
break
}
}
},
computed: {
pageTitle() {
const activeItem = this.tabs.find(item => item.id === this.activeId)
return activeItem ? activeItem.title : 'Untitled'
}
},
watch: {
pageTitle(title) {
document.title = title;
}
},
methods: {
onSwitch(item) {
this.sendMessage('webTabSwitch', item.id)
},
onClose(item) {
this.sendMessage('webTabClose', item.id);
},
onBrowser() {
this.sendMessage('webTabBrowser')
},
iconStyle(item) {
return item.icon ? `background-image: url(${item.icon})` : ''
},
tabTitle(item) {
if (item.title) {
return item.title
}
if (item.state === 'loading') {
return 'Loading...'
}
if (item.url) {
return `${item.url}`.replace(/^https*:\/\//, '')
}
},
scrollTabActive() {
setTimeout(() => {
try {
const child = document.querySelector(`.nav ul li[data-id=${this.activeId}]`)
if (child) {
child.scrollIntoView({behavior: 'smooth', block: 'nearest'})
}
} catch (e) {
//
}
}, 0)
},
sendMessage(event, args) {
electron?.sendMessage(event, args)
}
},
}
Vue.createApp(App).mount('#app')
</script>
</body>
</html>

21
electron/utils.js vendored
View File

@ -321,8 +321,8 @@ module.exports = {
*/
onBeforeOpenWindow(webContents, url) {
return new Promise(resolve => {
const encodeUrl = encodeURIComponent(url)
webContents.executeJavaScript(`if(typeof window.__onBeforeOpenWindow === 'function'){window.__onBeforeOpenWindow({url:decodeURIComponent("${encodeUrl}")})}`, true).then(options => {
const dataStr = JSON.stringify({url: url})
webContents.executeJavaScript(`if(typeof window.__onBeforeOpenWindow === 'function'){window.__onBeforeOpenWindow(${dataStr})}`, true).then(options => {
if (options !== true) {
resolve()
}
@ -332,6 +332,23 @@ module.exports = {
})
},
/**
* 分发事件
* @param webContents
* @param data
* @returns {Promise<unknown>}
*/
onDispatchEvent(webContents, data) {
return new Promise(resolve => {
const dataStr = JSON.stringify(data)
webContents.executeJavaScript(`window.__onDispatchEvent(${dataStr})`, true).then(options => {
resolve(options)
}).catch(_ => {
resolve()
})
})
},
/**
* 版本比较
* @param version1

View File

@ -265,19 +265,15 @@ export default {
}
}
window.__onBeforeOpenWindow = ({url}) => {
if ($A.getDomain(url) != $A.getDomain($A.apiUrl('../'))) {
return false;
if ($A.getDomain(url) == $A.getDomain($A.apiUrl('../'))) {
try {
// 使
if (/^\/uploads\//i.test(new URL(url).pathname)) {
return false;
}
} catch (e) { }
}
this.$Electron.sendMessage('windowRouter', {
name: `window-${encodeURIComponent(url)}`,
path: url,
force: false,
config: {
parent: null,
width: Math.min(window.screen.availWidth, 1440),
height: Math.min(window.screen.availHeight, 900),
},
});
this.$Electron.sendMessage('openWebWindow', {url});
return true;
}
this.$Electron.registerMsgListener('dispatch', args => {