diff --git a/src/bridges/settings.ts b/src/bridges/settings.ts index c20c4597..92ab09d3 100644 --- a/src/bridges/settings.ts +++ b/src/bridges/settings.ts @@ -23,6 +23,13 @@ const settingsBridge = { ipcRenderer.invoke("set-menu", state) }, + getWebViewOpenUrlStatus: (): boolean => { + return ipcRenderer.sendSync("get-webview-open-url-status") + }, + toggleWebViewOpenUrlStatus: () => { + ipcRenderer.send("toggle-webview-open-url-status") + }, + getProxyStatus: (): boolean => { return ipcRenderer.sendSync("get-proxy-status") }, diff --git a/src/components/article.tsx b/src/components/article.tsx index 18a640ab..b2351b2f 100644 --- a/src/components/article.tsx +++ b/src/components/article.tsx @@ -212,6 +212,10 @@ class Article extends React.Component { } keyDownHandler = (input: Electron.Input) => { + if (this.state.loadWebpage) { + // 内置网页中禁止快捷键以防影响网页登录之类功能, + return; + } if (input.type === "keyDown") { switch (input.key) { case "Escape": diff --git a/src/components/settings/app.tsx b/src/components/settings/app.tsx index 5a018e3d..6acfc931 100644 --- a/src/components/settings/app.tsx +++ b/src/components/settings/app.tsx @@ -34,6 +34,7 @@ type AppTabProps = { } type AppTabState = { + webViewOpenUrlStatus: boolean pacStatus: boolean pacUrl: string themeSettings: ThemeSettings @@ -46,6 +47,7 @@ class AppTab extends React.Component { constructor(props) { super(props) this.state = { + webViewOpenUrlStatus: window.settings.getWebViewOpenUrlStatus(), pacStatus: window.settings.getProxyStatus(), pacUrl: window.settings.getProxy(), themeSettings: getThemeSettings(), @@ -148,6 +150,13 @@ class AppTab extends React.Component { { key: "zh-TW", text: "中文(繁體)" }, ] + toggleWebViewOpenUrlStatus = () => { + window.settings.toggleWebViewOpenUrlStatus() + this.setState({ + webViewOpenUrlStatus: window.settings.getWebViewOpenUrlStatus(), + }) + } + toggleStatus = () => { window.settings.toggleProxyStatus() this.setState({ @@ -220,6 +229,21 @@ class AppTab extends React.Component { + + + + + + + + + + {intl.get("app.webViewOpenUrlHint")} + + diff --git a/src/electron.ts b/src/electron.ts index af353bb4..eb94fdb2 100644 --- a/src/electron.ts +++ b/src/electron.ts @@ -1,8 +1,9 @@ import { app, ipcMain, Menu, nativeTheme } from "electron" import { ThemeSettings, SchemaTypes } from "./schema-types" -import { store } from "./main/settings" +import { getWebViewOpenUrlStatus, store } from "./main/settings" import performUpdate from "./main/update-scripts" import { WindowManager } from "./main/window" +import { saveCookies } from "./main/cookies" if (!process.mas) { const locked = app.requestSingleInstanceLock() @@ -106,10 +107,12 @@ if (process.platform === "darwin") { const winManager = new WindowManager() app.on("window-all-closed", () => { - if (winManager.hasWindow()) { - winManager.mainWindow.webContents.session.clearStorageData({ - storages: ["cookies", "localstorage"], - }) + if (!getWebViewOpenUrlStatus()) { + if (winManager.hasWindow()) { + winManager.mainWindow.webContents.session.clearStorageData({ + storages: ["cookies", "localstorage"], + }) + } } winManager.mainWindow = null if (restarting) { diff --git a/src/main/cookies.ts b/src/main/cookies.ts new file mode 100644 index 00000000..70d0f0e0 --- /dev/null +++ b/src/main/cookies.ts @@ -0,0 +1,26 @@ +import Store = require("electron-store") +import { getWebViewOpenUrlStatus } from "./settings" +import { BrowserWindow, WebContents } from "electron" + +const cookieStore = new Store() +const COOKIES_KEY = "cookiesKey" +export async function saveCookies(webContents: WebContents) { + const currentSession = webContents.session + await currentSession.cookies.flushStore() + let cookies = await currentSession.cookies.get({}) + let customCookies = cookies.map(cookie => ({ + ...cookie, + url:(cookie.secure ? 'https://' : 'http://') + cookie.domain.replace(/^\./, '') + cookie.path + })) + cookieStore.set(COOKIES_KEY, customCookies) +} +export async function loadCookies(webContents: WebContents) { + const savedCookies = cookieStore.get(COOKIES_KEY) + cookieStore.get + if (savedCookies && savedCookies.length > 0) { + const currentSession = webContents.session + savedCookies.forEach(cookie => { + currentSession.cookies.set(cookie) + }) + } +} \ No newline at end of file diff --git a/src/main/settings.ts b/src/main/settings.ts index e6e6a029..ba42fb15 100644 --- a/src/main/settings.ts +++ b/src/main/settings.ts @@ -30,6 +30,20 @@ ipcMain.handle("set-menu", (_, state: boolean) => { store.set(MENU_STORE_KEY, state) }) +const WEBVIEW_OPEN_URL_STATUS_KEY = "webViewOpenUrlStatus" +export function getWebViewOpenUrlStatus() { + return store.get(WEBVIEW_OPEN_URL_STATUS_KEY, false) +} +function toggleWebViewOpenUrlStatus() { + store.set(WEBVIEW_OPEN_URL_STATUS_KEY, !getWebViewOpenUrlStatus()) +} +ipcMain.on("get-webview-open-url-status", event => { + event.returnValue = getWebViewOpenUrlStatus() +}) +ipcMain.on("toggle-webview-open-url-status", () => { + toggleWebViewOpenUrlStatus() +}) + const PAC_STORE_KEY = "pac" const PAC_STATUS_KEY = "pacOn" function getProxyStatus() { diff --git a/src/main/utils.ts b/src/main/utils.ts index 1f18ca76..230fb808 100644 --- a/src/main/utils.ts +++ b/src/main/utils.ts @@ -4,6 +4,9 @@ import fs = require("fs") import { ImageCallbackTypes, TouchBarTexts } from "../schema-types" import { initMainTouchBar } from "./touchbar" import fontList = require("font-list") +import settingsBridge from "../bridges/settings" +import { getWebViewOpenUrlStatus } from "./settings" +import { loadCookies, saveCookies } from "./cookies" export function setUtilsListeners(manager: WindowManager) { async function openExternal(url: string, background = false) { @@ -22,16 +25,24 @@ export function setUtilsListeners(manager: WindowManager) { app.on("web-contents-created", (_, contents) => { contents.setWindowOpenHandler(details => { - if (contents.getType() === "webview") - openExternal( - details.url, - details.disposition === "background-tab" - ) + if (contents.getType() === "webview") { + if (getWebViewOpenUrlStatus()) { + contents.loadURL(details.url) + } else { + openExternal( + details.url, + details.disposition === "background-tab" + ) + } + } return { action: manager.hasWindow() ? "deny" : "allow", } }) contents.on("will-navigate", (event, url) => { + if (getWebViewOpenUrlStatus()) { + return; + } event.preventDefault() if (contents.getType() === "webview") openExternal(url) }) @@ -237,6 +248,12 @@ export function setUtilsListeners(manager: WindowManager) { contents.send("webview-keydown", input) } }) + if (getWebViewOpenUrlStatus()) { + loadCookies(contents) + contents.on('did-finish-load', () => { + saveCookies(contents) + }) + } } }) diff --git a/src/schema-types.ts b/src/schema-types.ts index d295f9a0..cc2e6c57 100644 --- a/src/schema-types.ts +++ b/src/schema-types.ts @@ -86,6 +86,7 @@ export type SchemaTypes = { theme: ThemeSettings pac: string pacOn: boolean + webViewOpenUrlStatus: boolean view: ViewType locale: string sourceGroups: SourceGroup[] diff --git a/src/scripts/i18n/en-US.json b/src/scripts/i18n/en-US.json index fad7eacd..da378dfd 100644 --- a/src/scripts/i18n/en-US.json +++ b/src/scripts/i18n/en-US.json @@ -231,6 +231,8 @@ "theme": "Theme", "lightTheme": "Light mode", "darkTheme": "Dark mode", + "enableWebViewOpenUrl": "Enable WebView open url", + "webViewOpenUrlHint": "Enabling this switch will save cookies data for the built-in browser.", "enableProxy": "Enable Proxy", "badUrl": "Invalid URL", "pac": "PAC Address", diff --git a/src/scripts/i18n/zh-CN.json b/src/scripts/i18n/zh-CN.json index bbe9a25c..a51cd7ed 100644 --- a/src/scripts/i18n/zh-CN.json +++ b/src/scripts/i18n/zh-CN.json @@ -229,6 +229,8 @@ "theme": "应用主题", "lightTheme": "浅色模式", "darkTheme": "深色模式", + "enableWebViewOpenUrl": "允许内置浏览器打开网页", + "webViewOpenUrlHint": "开启后会保存内置浏览器的cookie数据。", "enableProxy": "启用代理", "badUrl": "请正确输入URL", "pac": "PAC地址",