mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-27 12:51:26 +08:00
feat: open popup url in external browser (#4446)
* feat: open popup url in external browser * fix: allow google auth popup internal * feat: add functionality(including settings) to open links in external browser for webviews * fix: set useragent globally * fix: remove setUserAgent in webview * fix: set Chrome version to newest
This commit is contained in:
parent
e5db6e79b3
commit
8c22c3c9d5
@ -20,6 +20,8 @@ export enum IpcChannel {
|
||||
App_InstallUvBinary = 'app:install-uv-binary',
|
||||
App_InstallBunBinary = 'app:install-bun-binary',
|
||||
|
||||
Webview_SetOpenLinkExternal = 'webview:set-open-link-external',
|
||||
|
||||
// Open
|
||||
Open_Path = 'open:path',
|
||||
Open_Website = 'open:website',
|
||||
|
||||
@ -75,14 +75,6 @@ if (!app.requestSingleInstanceLock()) {
|
||||
handleProtocolUrl(url)
|
||||
})
|
||||
|
||||
registerProtocolClient(app)
|
||||
|
||||
// macOS specific: handle protocol when app is already running
|
||||
app.on('open-url', (event, url) => {
|
||||
event.preventDefault()
|
||||
handleProtocolUrl(url)
|
||||
})
|
||||
|
||||
// Listen for second instance
|
||||
app.on('second-instance', (_event, argv) => {
|
||||
windowService.showMainWindow()
|
||||
|
||||
@ -25,6 +25,7 @@ import { ProxyConfig, proxyManager } from './services/ProxyManager'
|
||||
import { searchService } from './services/SearchService'
|
||||
import { registerShortcuts, unregisterAllShortcuts } from './services/ShortcutService'
|
||||
import { TrayService } from './services/TrayService'
|
||||
import { setOpenLinkExternal } from './services/WebviewService'
|
||||
import { windowService } from './services/WindowService'
|
||||
import { getResourcePath } from './utils'
|
||||
import { decrypt, encrypt } from './utils/aes'
|
||||
@ -342,4 +343,9 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
||||
ipcMain.handle(IpcChannel.SearchWindow_OpenUrl, async (_, uid: string, url: string) => {
|
||||
return await searchService.openUrlInSearchWindow(uid, url)
|
||||
})
|
||||
|
||||
// webview
|
||||
ipcMain.handle(IpcChannel.Webview_SetOpenLinkExternal, (_, webviewId: number, isExternal: boolean) =>
|
||||
setOpenLinkExternal(webviewId, isExternal)
|
||||
)
|
||||
}
|
||||
|
||||
35
src/main/services/WebviewService.ts
Normal file
35
src/main/services/WebviewService.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { session, shell, webContents } from 'electron'
|
||||
|
||||
/**
|
||||
* init the useragent of the webview session
|
||||
* remove the CherryStudio and Electron from the useragent
|
||||
*/
|
||||
export function initSessionUserAgent() {
|
||||
const wvSession = session.fromPartition('persist:webview')
|
||||
const newChromeVersion = '135.0.7049.96'
|
||||
const originUA = wvSession.getUserAgent()
|
||||
const newUA = originUA
|
||||
.replace(/CherryStudio\/\S+\s/, '')
|
||||
.replace(/Electron\/\S+\s/, '')
|
||||
.replace(/Chrome\/\d+\.\d+\.\d+\.\d+/, `Chrome/${newChromeVersion}`)
|
||||
|
||||
wvSession.setUserAgent(newUA)
|
||||
}
|
||||
|
||||
/**
|
||||
* WebviewService handles the behavior of links opened from webview elements
|
||||
* It controls whether links should be opened within the application or in an external browser
|
||||
*/
|
||||
export function setOpenLinkExternal(webviewId: number, isExternal: boolean) {
|
||||
const webview = webContents.fromId(webviewId)
|
||||
if (!webview) return
|
||||
|
||||
webview.setWindowOpenHandler(({ url }) => {
|
||||
if (isExternal) {
|
||||
shell.openExternal(url)
|
||||
return { action: 'deny' }
|
||||
} else {
|
||||
return { action: 'allow' }
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -11,6 +11,7 @@ import icon from '../../../build/icon.png?asset'
|
||||
import { titleBarOverlayDark, titleBarOverlayLight } from '../config'
|
||||
import { locales } from '../utils/locales'
|
||||
import { configManager } from './ConfigManager'
|
||||
import { initSessionUserAgent } from './WebviewService'
|
||||
|
||||
export class WindowService {
|
||||
private static instance: WindowService | null = null
|
||||
@ -81,6 +82,9 @@ export class WindowService {
|
||||
this.miniWindow = this.createMiniWindow(true)
|
||||
}
|
||||
|
||||
//init the MinApp webviews' useragent
|
||||
initSessionUserAgent()
|
||||
|
||||
return this.mainWindow
|
||||
}
|
||||
|
||||
|
||||
3
src/preload/index.d.ts
vendored
3
src/preload/index.d.ts
vendored
@ -204,6 +204,9 @@ declare global {
|
||||
closeSearchWindow: (uid: string) => Promise<string>
|
||||
openUrlInSearchWindow: (uid: string, url: string) => Promise<string>
|
||||
}
|
||||
webview: {
|
||||
setOpenLinkExternal: (webviewId: number, isExternal: boolean) => Promise<void>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,6 +185,10 @@ const api = {
|
||||
openSearchWindow: (uid: string) => ipcRenderer.invoke(IpcChannel.SearchWindow_Open, uid),
|
||||
closeSearchWindow: (uid: string) => ipcRenderer.invoke(IpcChannel.SearchWindow_Close, uid),
|
||||
openUrlInSearchWindow: (uid: string, url: string) => ipcRenderer.invoke(IpcChannel.SearchWindow_OpenUrl, uid, url)
|
||||
},
|
||||
webview: {
|
||||
setOpenLinkExternal: (webviewId: number, isExternal: boolean) =>
|
||||
ipcRenderer.invoke(IpcChannel.Webview_SetOpenLinkExternal, webviewId, isExternal)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ import {
|
||||
CodeOutlined,
|
||||
CopyOutlined,
|
||||
ExportOutlined,
|
||||
LinkOutlined,
|
||||
MinusOutlined,
|
||||
PushpinOutlined,
|
||||
ReloadOutlined
|
||||
@ -14,6 +15,9 @@ import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
|
||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import useNavBackgroundColor from '@renderer/hooks/useNavBackgroundColor'
|
||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { setMinappsOpenLinkExternal } from '@renderer/store/settings'
|
||||
import { MinAppType } from '@renderer/types'
|
||||
import { delay } from '@renderer/utils'
|
||||
import { Avatar, Drawer, Tooltip } from 'antd'
|
||||
@ -40,6 +44,7 @@ const MinappPopupContainer: React.FC = () => {
|
||||
const { pinned, updatePinnedMinapps } = useMinapps()
|
||||
const { t } = useTranslation()
|
||||
const backgroundColor = useNavBackgroundColor()
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
/** control the drawer open or close */
|
||||
const [isPopupShow, setIsPopupShow] = useState(true)
|
||||
@ -57,6 +62,8 @@ const MinappPopupContainer: React.FC = () => {
|
||||
const webviewRefs = useRef<Map<string, WebviewTag | null>>(new Map())
|
||||
/** indicate whether the webview has loaded */
|
||||
const webviewLoadedRefs = useRef<Map<string, boolean>>(new Map())
|
||||
/** whether the minapps open link external is enabled */
|
||||
const { minappsOpenLinkExternal } = useSettings()
|
||||
|
||||
const isInDevelopment = process.env.NODE_ENV === 'development'
|
||||
|
||||
@ -107,9 +114,14 @@ const MinappPopupContainer: React.FC = () => {
|
||||
webviewLoadedRefs.current.forEach((_, appid) => {
|
||||
if (!webviewRefs.current.has(appid)) {
|
||||
webviewLoadedRefs.current.delete(appid)
|
||||
} else if (appid === currentMinappId) {
|
||||
const webviewId = webviewRefs.current.get(appid)?.getWebContentsId()
|
||||
if (webviewId) {
|
||||
window.api.webview.setOpenLinkExternal(webviewId, minappsOpenLinkExternal)
|
||||
}
|
||||
}
|
||||
})
|
||||
}, [currentMinappId])
|
||||
}, [currentMinappId, minappsOpenLinkExternal])
|
||||
|
||||
/** only the keepalive minapp can be minimized */
|
||||
const canMinimize = !(openedOneOffMinapp && openedOneOffMinapp.id == currentMinappId)
|
||||
@ -175,6 +187,10 @@ const MinappPopupContainer: React.FC = () => {
|
||||
/** the callback function to set the webviews loaded indicator */
|
||||
const handleWebviewLoaded = (appid: string) => {
|
||||
webviewLoadedRefs.current.set(appid, true)
|
||||
const webviewId = webviewRefs.current.get(appid)?.getWebContentsId()
|
||||
if (webviewId) {
|
||||
window.api.webview.setOpenLinkExternal(webviewId, minappsOpenLinkExternal)
|
||||
}
|
||||
if (appid == currentMinappId) {
|
||||
setTimeout(() => setIsReady(true), 200)
|
||||
}
|
||||
@ -220,6 +236,11 @@ const MinappPopupContainer: React.FC = () => {
|
||||
updatePinnedMinapps(newPinned)
|
||||
}
|
||||
|
||||
/** set the open external status */
|
||||
const handleToggleOpenExternal = () => {
|
||||
dispatch(setMinappsOpenLinkExternal(!minappsOpenLinkExternal))
|
||||
}
|
||||
|
||||
/** Title bar of the popup */
|
||||
const Title = ({ appInfo, url }: { appInfo: AppInfo | null; url: string | null }) => {
|
||||
if (!appInfo) return null
|
||||
@ -238,7 +259,7 @@ const MinappPopupContainer: React.FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<TitleContainer style={{ backgroundColor: backgroundColor, justifyContent: 'space-between' }}>
|
||||
<TitleContainer style={{ backgroundColor: backgroundColor }}>
|
||||
<Tooltip
|
||||
title={
|
||||
<TitleTextTooltip>
|
||||
@ -256,6 +277,14 @@ const MinappPopupContainer: React.FC = () => {
|
||||
}}>
|
||||
<TitleText onContextMenu={(e) => handleCopyUrl(e, url ?? appInfo.url)}>{appInfo.name}</TitleText>
|
||||
</Tooltip>
|
||||
{appInfo.canOpenExternalLink && (
|
||||
<Tooltip title={t('minapp.popup.openExternal')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Button onClick={() => handleOpenLink(url ?? appInfo.url)}>
|
||||
<ExportOutlined />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Spacer />
|
||||
<ButtonsGroup className={isWindows ? 'windows' : ''}>
|
||||
<Tooltip title={t('minapp.popup.refresh')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Button onClick={() => handleReload(appInfo.id)}>
|
||||
@ -272,13 +301,18 @@ const MinappPopupContainer: React.FC = () => {
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{appInfo.canOpenExternalLink && (
|
||||
<Tooltip title={t('minapp.popup.openExternal')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Button onClick={() => handleOpenLink(url ?? appInfo.url)}>
|
||||
<ExportOutlined />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip
|
||||
title={
|
||||
minappsOpenLinkExternal
|
||||
? t('minapp.popup.open_link_external_on')
|
||||
: t('minapp.popup.open_link_external_off')
|
||||
}
|
||||
mouseEnterDelay={0.8}
|
||||
placement="bottom">
|
||||
<Button onClick={handleToggleOpenExternal} className={minappsOpenLinkExternal ? 'open-external' : ''}>
|
||||
<LinkOutlined />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{isInDevelopment && (
|
||||
<Tooltip title={t('minapp.popup.devtools')} mouseEnterDelay={0.8} placement="bottom">
|
||||
<Button onClick={() => handleOpenDevTools(appInfo.id)}>
|
||||
@ -367,8 +401,8 @@ const TitleText = styled.div`
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
color: var(--color-text-1);
|
||||
margin-right: 10px;
|
||||
-webkit-app-region: no-drag;
|
||||
margin-right: 5px;
|
||||
`
|
||||
|
||||
const TitleTextTooltip = styled.span`
|
||||
@ -407,6 +441,7 @@ const Button = styled.div`
|
||||
color: var(--color-text-2);
|
||||
transition: all 0.2s ease;
|
||||
font-size: 14px;
|
||||
-webkit-app-region: no-drag;
|
||||
&:hover {
|
||||
color: var(--color-text-1);
|
||||
background-color: var(--color-background-mute);
|
||||
@ -415,6 +450,10 @@ const Button = styled.div`
|
||||
color: var(--color-primary);
|
||||
background-color: var(--color-primary-bg);
|
||||
}
|
||||
&.open-external {
|
||||
color: var(--color-primary);
|
||||
background-color: var(--color-primary-bg);
|
||||
}
|
||||
`
|
||||
|
||||
const EmptyView = styled.div`
|
||||
@ -428,4 +467,8 @@ const EmptyView = styled.div`
|
||||
background-color: var(--color-background);
|
||||
`
|
||||
|
||||
const Spacer = styled.div`
|
||||
flex: 1;
|
||||
`
|
||||
|
||||
export default MinappPopupContainer
|
||||
|
||||
@ -60,9 +60,6 @@ const WebviewContainer = memo(
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [appid, url])
|
||||
|
||||
//remove the tag of CherryStudio and Electron
|
||||
const userAgent = navigator.userAgent.replace(/CherryStudio\/\S+\s/, '').replace(/Electron\/\S+\s/, '')
|
||||
|
||||
return (
|
||||
<webview
|
||||
key={appid}
|
||||
@ -70,7 +67,6 @@ const WebviewContainer = memo(
|
||||
style={WebviewStyle}
|
||||
allowpopups={'true' as any}
|
||||
partition="persist:webview"
|
||||
useragent={userAgent}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@ -585,7 +585,9 @@
|
||||
"minimize": "Minimize MinApp",
|
||||
"devtools": "Developer Tools",
|
||||
"openExternal": "Open in Browser",
|
||||
"rightclick_copyurl": "Right-click to copy URL"
|
||||
"rightclick_copyurl": "Right-click to copy URL",
|
||||
"open_link_external_on": "Current: Open links in browser",
|
||||
"open_link_external_off": "Current: Open links in default window"
|
||||
},
|
||||
"sidebar.add.title": "Add to sidebar",
|
||||
"sidebar.remove.title": "Remove from sidebar",
|
||||
@ -1020,6 +1022,9 @@
|
||||
"disabled": "Hidden Mini Apps",
|
||||
"empty": "Drag mini apps from the left to hide them",
|
||||
"visible": "Visible Mini Apps",
|
||||
"open_link_external": {
|
||||
"title": "Open new-window links in browser"
|
||||
},
|
||||
"cache_settings": "Cache Settings",
|
||||
"cache_title": "Mini App Cache Limit",
|
||||
"cache_description": "Set the maximum number of active mini apps to keep in memory",
|
||||
|
||||
@ -585,7 +585,9 @@
|
||||
"minimize": "ミニアプリを最小化",
|
||||
"devtools": "開発者ツール",
|
||||
"openExternal": "ブラウザで開く",
|
||||
"rightclick_copyurl": "右クリックでURLをコピー"
|
||||
"rightclick_copyurl": "右クリックでURLをコピー",
|
||||
"open_link_external_on": "現在:ブラウザで開く",
|
||||
"open_link_external_off": "現在:デフォルトのウィンドウで開く"
|
||||
},
|
||||
"sidebar.add.title": "サイドバーに追加",
|
||||
"sidebar.remove.title": "サイドバーから削除",
|
||||
@ -1020,6 +1022,9 @@
|
||||
"disabled": "非表示のミニアプリ",
|
||||
"empty": "非表示にするミニアプリを左側からここにドラッグしてください",
|
||||
"visible": "表示するミニアプリ",
|
||||
"open_link_external": {
|
||||
"title": "新視窗のリンクをブラウザで開く"
|
||||
},
|
||||
"cache_settings": "キャッシュ設定",
|
||||
"cache_title": "ミニアプリのキャッシュ数",
|
||||
"cache_description": "メモリに保持するアクティブなミニアプリの最大数を設定します",
|
||||
|
||||
@ -585,7 +585,9 @@
|
||||
"minimize": "Свернуть встроенное приложение",
|
||||
"devtools": "Инструменты разработчика",
|
||||
"openExternal": "Открыть в браузере",
|
||||
"rightclick_copyurl": "ПКМ → Копировать URL"
|
||||
"rightclick_copyurl": "ПКМ → Копировать URL",
|
||||
"open_link_external_on": "Текущий: Открыть ссылки в браузере",
|
||||
"open_link_external_off": "Текущий: Открыть ссылки в окне по умолчанию"
|
||||
},
|
||||
"sidebar.add.title": "Добавить в боковую панель",
|
||||
"sidebar.remove.title": "Удалить из боковой панели",
|
||||
@ -1020,6 +1022,9 @@
|
||||
"disabled": "Скрытые мини-приложения",
|
||||
"empty": "Перетащите мини-приложения слева, чтобы скрыть их",
|
||||
"visible": "Отображаемые мини-приложения",
|
||||
"open_link_external": {
|
||||
"title": "Открывать новые окна в браузере"
|
||||
},
|
||||
"cache_settings": "Настройки кэша",
|
||||
"cache_title": "Количество кэшируемых мини-приложений",
|
||||
"cache_description": "Установить максимальное количество активных мини-приложений в памяти",
|
||||
|
||||
@ -585,7 +585,9 @@
|
||||
"minimize": "最小化小程序",
|
||||
"devtools": "开发者工具",
|
||||
"openExternal": "在浏览器中打开",
|
||||
"rightclick_copyurl": "右键复制URL"
|
||||
"rightclick_copyurl": "右键复制URL",
|
||||
"open_link_external_on": "当前:在浏览器中打开链接",
|
||||
"open_link_external_off": "当前:使用默认窗口打开链接"
|
||||
},
|
||||
"sidebar.add.title": "添加到侧边栏",
|
||||
"sidebar.remove.title": "从侧边栏移除",
|
||||
@ -1020,6 +1022,9 @@
|
||||
"disabled": "隐藏的小程序",
|
||||
"empty": "把要隐藏的小程序从左侧拖拽到这里",
|
||||
"visible": "显示的小程序",
|
||||
"open_link_external": {
|
||||
"title": "在浏览器中打开新窗口链接"
|
||||
},
|
||||
"cache_settings": "缓存设置",
|
||||
"cache_title": "小程序缓存数量",
|
||||
"cache_description": "设置同时保持活跃状态的小程序最大数量",
|
||||
|
||||
@ -585,7 +585,9 @@
|
||||
"minimize": "最小化小工具",
|
||||
"devtools": "開發者工具",
|
||||
"openExternal": "在瀏覽器中開啟",
|
||||
"rightclick_copyurl": "右鍵複製URL"
|
||||
"rightclick_copyurl": "右鍵複製URL",
|
||||
"open_link_external_on": "当前:在瀏覽器中開啟連結",
|
||||
"open_link_external_off": "当前:使用預設視窗開啟連結"
|
||||
},
|
||||
"sidebar.add.title": "新增到側邊欄",
|
||||
"sidebar.remove.title": "從側邊欄移除",
|
||||
@ -1020,6 +1022,9 @@
|
||||
"disabled": "隱藏的小程式",
|
||||
"empty": "把要隱藏的小程式從左側拖拽到這裡",
|
||||
"visible": "顯示的小程式",
|
||||
"open_link_external": {
|
||||
"title": "在瀏覽器中打開新視窗連結"
|
||||
},
|
||||
"cache_settings": "緩存設置",
|
||||
"cache_title": "小程式緩存數量",
|
||||
"cache_description": "設置同時保持活躍狀態的小程式最大數量",
|
||||
|
||||
@ -4,7 +4,11 @@ import { useTheme } from '@renderer/context/ThemeProvider'
|
||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import { useSettings } from '@renderer/hooks/useSettings'
|
||||
import { useAppDispatch } from '@renderer/store'
|
||||
import { setMaxKeepAliveMinapps, setShowOpenedMinappsInSidebar } from '@renderer/store/settings'
|
||||
import {
|
||||
setMaxKeepAliveMinapps,
|
||||
setMinappsOpenLinkExternal,
|
||||
setShowOpenedMinappsInSidebar
|
||||
} from '@renderer/store/settings'
|
||||
import { Button, message, Slider, Switch, Tooltip } from 'antd'
|
||||
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -20,7 +24,7 @@ const MiniAppSettings: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
const { theme } = useTheme()
|
||||
const dispatch = useAppDispatch()
|
||||
const { maxKeepAliveMinapps, showOpenedMinappsInSidebar } = useSettings()
|
||||
const { maxKeepAliveMinapps, showOpenedMinappsInSidebar, minappsOpenLinkExternal } = useSettings()
|
||||
const { minapps, disabled, updateMinapps, updateDisabledMinapps } = useMinapps()
|
||||
|
||||
const [visibleMiniApps, setVisibleMiniApps] = useState(minapps)
|
||||
@ -89,9 +93,19 @@ const MiniAppSettings: FC = () => {
|
||||
/>
|
||||
</BorderedContainer>
|
||||
<SettingDivider />
|
||||
<SettingRow>
|
||||
<SettingLabelGroup>
|
||||
<SettingRowTitle>{t('settings.miniapps.open_link_external.title')}</SettingRowTitle>
|
||||
</SettingLabelGroup>
|
||||
<Switch
|
||||
checked={minappsOpenLinkExternal}
|
||||
onChange={(checked) => dispatch(setMinappsOpenLinkExternal(checked))}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
|
||||
{/* 缓存小程序数量设置 */}
|
||||
<CacheSettingRow>
|
||||
<SettingRow>
|
||||
<SettingLabelGroup>
|
||||
<SettingRowTitle>{t('settings.miniapps.cache_title')}</SettingRowTitle>
|
||||
<SettingDescription>{t('settings.miniapps.cache_description')}</SettingDescription>
|
||||
@ -117,9 +131,9 @@ const MiniAppSettings: FC = () => {
|
||||
/>
|
||||
</SliderWithResetContainer>
|
||||
</CacheSettingControls>
|
||||
</CacheSettingRow>
|
||||
</SettingRow>
|
||||
<SettingDivider />
|
||||
<SidebarSettingRow>
|
||||
<SettingRow>
|
||||
<SettingLabelGroup>
|
||||
<SettingRowTitle>{t('settings.miniapps.sidebar_title')}</SettingRowTitle>
|
||||
<SettingDescription>{t('settings.miniapps.sidebar_description')}</SettingDescription>
|
||||
@ -128,14 +142,14 @@ const MiniAppSettings: FC = () => {
|
||||
checked={showOpenedMinappsInSidebar}
|
||||
onChange={(checked) => dispatch(setShowOpenedMinappsInSidebar(checked))}
|
||||
/>
|
||||
</SidebarSettingRow>
|
||||
</SettingRow>
|
||||
</SettingGroup>
|
||||
</SettingContainer>
|
||||
)
|
||||
}
|
||||
|
||||
// 修改和新增样式
|
||||
const CacheSettingRow = styled.div`
|
||||
const SettingRow = styled.div`
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
@ -206,14 +220,6 @@ const ResetButtonWrapper = styled.div`
|
||||
justify-content: center;
|
||||
`
|
||||
|
||||
// 新增侧边栏设置行样式
|
||||
const SidebarSettingRow = styled.div`
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 20px;
|
||||
`
|
||||
|
||||
// 新增: 带边框的容器组件
|
||||
const BorderedContainer = styled.div`
|
||||
border: 1px solid var(--color-border);
|
||||
|
||||
@ -109,8 +109,10 @@ export interface SettingsState {
|
||||
siyuanToken: string | null
|
||||
siyuanBoxId: string | null
|
||||
siyuanRootPath: string | null
|
||||
// MinApps
|
||||
maxKeepAliveMinapps: number
|
||||
showOpenedMinappsInSidebar: boolean
|
||||
minappsOpenLinkExternal: boolean
|
||||
// 隐私设置
|
||||
enableDataCollection: boolean
|
||||
enableQuickPanelTriggers: boolean
|
||||
@ -211,8 +213,10 @@ export const initialState: SettingsState = {
|
||||
siyuanToken: null,
|
||||
siyuanBoxId: null,
|
||||
siyuanRootPath: null,
|
||||
// MinApps
|
||||
maxKeepAliveMinapps: 3,
|
||||
showOpenedMinappsInSidebar: true,
|
||||
minappsOpenLinkExternal: false,
|
||||
enableDataCollection: false,
|
||||
enableQuickPanelTriggers: false,
|
||||
enableBackspaceDeleteModel: true,
|
||||
@ -482,6 +486,9 @@ const settingsSlice = createSlice({
|
||||
setShowOpenedMinappsInSidebar: (state, action: PayloadAction<boolean>) => {
|
||||
state.showOpenedMinappsInSidebar = action.payload
|
||||
},
|
||||
setMinappsOpenLinkExternal: (state, action: PayloadAction<boolean>) => {
|
||||
state.minappsOpenLinkExternal = action.payload
|
||||
},
|
||||
setEnableDataCollection: (state, action: PayloadAction<boolean>) => {
|
||||
state.enableDataCollection = action.payload
|
||||
},
|
||||
@ -579,6 +586,7 @@ export const {
|
||||
setSiyuanRootPath,
|
||||
setMaxKeepAliveMinapps,
|
||||
setShowOpenedMinappsInSidebar,
|
||||
setMinappsOpenLinkExternal,
|
||||
setEnableDataCollection,
|
||||
setEnableQuickPanelTriggers,
|
||||
setExportMenuOptions,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user