mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-24 23:06:51 +00:00
新增询问窗口
This commit is contained in:
@@ -99,6 +99,8 @@ let isAppQuitting = false
|
|||||||
let tray: Tray | null = null
|
let tray: Tray | null = null
|
||||||
let isClosePromptVisible = false
|
let isClosePromptVisible = false
|
||||||
|
|
||||||
|
type WindowCloseBehavior = 'ask' | 'tray' | 'quit'
|
||||||
|
|
||||||
// 更新下载状态管理(Issue #294 修复)
|
// 更新下载状态管理(Issue #294 修复)
|
||||||
let isDownloadInProgress = false
|
let isDownloadInProgress = false
|
||||||
let downloadProgressHandler: ((progress: any) => void) | null = null
|
let downloadProgressHandler: ((progress: any) => void) | null = null
|
||||||
@@ -254,6 +256,19 @@ const setupCustomTitleBarWindow = (win: BrowserWindow): void => {
|
|||||||
win.webContents.on('did-finish-load', emitMaximizeState)
|
win.webContents.on('did-finish-load', emitMaximizeState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getWindowCloseBehavior = (): WindowCloseBehavior => {
|
||||||
|
const behavior = configService?.get('windowCloseBehavior')
|
||||||
|
return behavior === 'tray' || behavior === 'quit' ? behavior : 'ask'
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestMainWindowCloseConfirmation = (win: BrowserWindow): void => {
|
||||||
|
if (isClosePromptVisible) return
|
||||||
|
isClosePromptVisible = true
|
||||||
|
win.webContents.send('window:confirmCloseRequested', {
|
||||||
|
canMinimizeToTray: Boolean(tray)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function createWindow(options: { autoShow?: boolean } = {}) {
|
function createWindow(options: { autoShow?: boolean } = {}) {
|
||||||
// 获取图标路径 - 打包后在 resources 目录
|
// 获取图标路径 - 打包后在 resources 目录
|
||||||
const { autoShow = true } = options
|
const { autoShow = true } = options
|
||||||
@@ -357,12 +372,20 @@ function createWindow(options: { autoShow?: boolean } = {}) {
|
|||||||
win.on('close', (e) => {
|
win.on('close', (e) => {
|
||||||
if (isAppQuitting || win !== mainWindow) return
|
if (isAppQuitting || win !== mainWindow) return
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (isClosePromptVisible) return
|
const closeBehavior = getWindowCloseBehavior()
|
||||||
|
|
||||||
isClosePromptVisible = true
|
if (closeBehavior === 'quit') {
|
||||||
win.webContents.send('window:confirmCloseRequested', {
|
isAppQuitting = true
|
||||||
canMinimizeToTray: Boolean(tray)
|
app.quit()
|
||||||
})
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (closeBehavior === 'tray' && tray) {
|
||||||
|
win.hide()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
requestMainWindowCloseConfirmation(win)
|
||||||
})
|
})
|
||||||
|
|
||||||
win.on('closed', () => {
|
win.on('closed', () => {
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ interface ConfigSchema {
|
|||||||
notificationPosition: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center'
|
notificationPosition: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center'
|
||||||
notificationFilterMode: 'all' | 'whitelist' | 'blacklist'
|
notificationFilterMode: 'all' | 'whitelist' | 'blacklist'
|
||||||
notificationFilterList: string[]
|
notificationFilterList: string[]
|
||||||
|
windowCloseBehavior: 'ask' | 'tray' | 'quit'
|
||||||
wordCloudExcludeWords: string[]
|
wordCloudExcludeWords: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +117,7 @@ export class ConfigService {
|
|||||||
notificationPosition: 'top-right',
|
notificationPosition: 'top-right',
|
||||||
notificationFilterMode: 'all',
|
notificationFilterMode: 'all',
|
||||||
notificationFilterList: [],
|
notificationFilterList: [],
|
||||||
|
windowCloseBehavior: 'ask',
|
||||||
wordCloudExcludeWords: []
|
wordCloudExcludeWords: []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
16
src/App.tsx
16
src/App.tsx
@@ -327,8 +327,19 @@ function App() {
|
|||||||
setUpdateInfo(null)
|
setUpdateInfo(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleWindowCloseAction = async (action: 'tray' | 'quit' | 'cancel') => {
|
const handleWindowCloseAction = async (
|
||||||
|
action: 'tray' | 'quit' | 'cancel',
|
||||||
|
rememberChoice = false
|
||||||
|
) => {
|
||||||
setShowCloseDialog(false)
|
setShowCloseDialog(false)
|
||||||
|
if (rememberChoice && action !== 'cancel') {
|
||||||
|
try {
|
||||||
|
await configService.setWindowCloseBehavior(action)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存关闭偏好失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await window.electronAPI.window.respondCloseConfirm(action)
|
await window.electronAPI.window.respondCloseConfirm(action)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -617,8 +628,7 @@ function App() {
|
|||||||
<WindowCloseDialog
|
<WindowCloseDialog
|
||||||
open={showCloseDialog}
|
open={showCloseDialog}
|
||||||
canMinimizeToTray={canMinimizeToTray}
|
canMinimizeToTray={canMinimizeToTray}
|
||||||
onTray={() => handleWindowCloseAction('tray')}
|
onSelect={(action, rememberChoice) => handleWindowCloseAction(action, rememberChoice)}
|
||||||
onQuit={() => handleWindowCloseAction('quit')}
|
|
||||||
onCancel={() => handleWindowCloseAction('cancel')}
|
onCancel={() => handleWindowCloseAction('cancel')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -140,6 +140,72 @@
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.window-close-dialog-remember {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin: 4px 24px 0;
|
||||||
|
padding: 12px 14px;
|
||||||
|
border: 1px solid color-mix(in srgb, var(--border-color) 72%, transparent);
|
||||||
|
border-radius: 16px;
|
||||||
|
background: color-mix(in srgb, var(--bg-secondary) 76%, transparent);
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
input {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-close-dialog-checkbox {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
flex: 0 0 18px;
|
||||||
|
border: 1.5px solid color-mix(in srgb, var(--border-color) 88%, transparent);
|
||||||
|
border-radius: 6px;
|
||||||
|
background: var(--bg-primary);
|
||||||
|
position: relative;
|
||||||
|
transition:
|
||||||
|
border-color 0.18s ease,
|
||||||
|
background 0.18s ease,
|
||||||
|
box-shadow 0.18s ease;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 5px;
|
||||||
|
top: 1px;
|
||||||
|
width: 5px;
|
||||||
|
height: 10px;
|
||||||
|
border: solid white;
|
||||||
|
border-width: 0 2px 2px 0;
|
||||||
|
transform: rotate(45deg) scale(0.7);
|
||||||
|
opacity: 0;
|
||||||
|
transition:
|
||||||
|
opacity 0.18s ease,
|
||||||
|
transform 0.18s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-close-dialog-remember input:checked + .window-close-dialog-checkbox {
|
||||||
|
background: var(--primary);
|
||||||
|
border-color: var(--primary);
|
||||||
|
box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 16%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-close-dialog-remember input:checked + .window-close-dialog-checkbox::after {
|
||||||
|
opacity: 1;
|
||||||
|
transform: rotate(45deg) scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-close-dialog-remember-text {
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
.window-close-dialog-cancel {
|
.window-close-dialog-cancel {
|
||||||
min-width: 112px;
|
min-width: 112px;
|
||||||
padding: 12px 18px;
|
padding: 12px 18px;
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
import { Minimize2, Power, X } from 'lucide-react'
|
import { Minimize2, Power, X } from 'lucide-react'
|
||||||
import { useEffect } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import './WindowCloseDialog.scss'
|
import './WindowCloseDialog.scss'
|
||||||
|
|
||||||
interface WindowCloseDialogProps {
|
interface WindowCloseDialogProps {
|
||||||
open: boolean
|
open: boolean
|
||||||
canMinimizeToTray: boolean
|
canMinimizeToTray: boolean
|
||||||
onTray: () => void
|
onSelect: (action: 'tray' | 'quit', rememberChoice: boolean) => void
|
||||||
onQuit: () => void
|
|
||||||
onCancel: () => void
|
onCancel: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function WindowCloseDialog({
|
export default function WindowCloseDialog({
|
||||||
open,
|
open,
|
||||||
canMinimizeToTray,
|
canMinimizeToTray,
|
||||||
onTray,
|
onSelect,
|
||||||
onQuit,
|
|
||||||
onCancel
|
onCancel
|
||||||
}: WindowCloseDialogProps) {
|
}: WindowCloseDialogProps) {
|
||||||
|
const [rememberChoice, setRememberChoice] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) return
|
if (!open) return
|
||||||
|
setRememberChoice(false)
|
||||||
|
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
if (event.key === 'Escape') {
|
if (event.key === 'Escape') {
|
||||||
@@ -63,7 +64,11 @@ export default function WindowCloseDialog({
|
|||||||
|
|
||||||
<div className="window-close-dialog-body">
|
<div className="window-close-dialog-body">
|
||||||
{canMinimizeToTray && (
|
{canMinimizeToTray && (
|
||||||
<button type="button" className="window-close-dialog-option" onClick={onTray}>
|
<button
|
||||||
|
type="button"
|
||||||
|
className="window-close-dialog-option"
|
||||||
|
onClick={() => onSelect('tray', rememberChoice)}
|
||||||
|
>
|
||||||
<span className="window-close-dialog-option-icon">
|
<span className="window-close-dialog-option-icon">
|
||||||
<Minimize2 size={18} />
|
<Minimize2 size={18} />
|
||||||
</span>
|
</span>
|
||||||
@@ -77,7 +82,7 @@ export default function WindowCloseDialog({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="window-close-dialog-option is-danger"
|
className="window-close-dialog-option is-danger"
|
||||||
onClick={onQuit}
|
onClick={() => onSelect('quit', rememberChoice)}
|
||||||
>
|
>
|
||||||
<span className="window-close-dialog-option-icon">
|
<span className="window-close-dialog-option-icon">
|
||||||
<Power size={18} />
|
<Power size={18} />
|
||||||
@@ -89,6 +94,16 @@ export default function WindowCloseDialog({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<label className="window-close-dialog-remember">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={rememberChoice}
|
||||||
|
onChange={(event) => setRememberChoice(event.target.checked)}
|
||||||
|
/>
|
||||||
|
<span className="window-close-dialog-checkbox" aria-hidden="true" />
|
||||||
|
<span className="window-close-dialog-remember-text">下次不再提示,直接按本次选择处理</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
<div className="window-close-dialog-actions">
|
<div className="window-close-dialog-actions">
|
||||||
<button type="button" className="window-close-dialog-cancel" onClick={onCancel}>
|
<button type="button" className="window-close-dialog-cancel" onClick={onCancel}>
|
||||||
取消
|
取消
|
||||||
|
|||||||
@@ -107,9 +107,11 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
const [notificationPosition, setNotificationPosition] = useState<'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center'>('top-right')
|
const [notificationPosition, setNotificationPosition] = useState<'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center'>('top-right')
|
||||||
const [notificationFilterMode, setNotificationFilterMode] = useState<'all' | 'whitelist' | 'blacklist'>('all')
|
const [notificationFilterMode, setNotificationFilterMode] = useState<'all' | 'whitelist' | 'blacklist'>('all')
|
||||||
const [notificationFilterList, setNotificationFilterList] = useState<string[]>([])
|
const [notificationFilterList, setNotificationFilterList] = useState<string[]>([])
|
||||||
|
const [windowCloseBehavior, setWindowCloseBehavior] = useState<configService.WindowCloseBehavior>('ask')
|
||||||
const [filterSearchKeyword, setFilterSearchKeyword] = useState('')
|
const [filterSearchKeyword, setFilterSearchKeyword] = useState('')
|
||||||
const [filterModeDropdownOpen, setFilterModeDropdownOpen] = useState(false)
|
const [filterModeDropdownOpen, setFilterModeDropdownOpen] = useState(false)
|
||||||
const [positionDropdownOpen, setPositionDropdownOpen] = useState(false)
|
const [positionDropdownOpen, setPositionDropdownOpen] = useState(false)
|
||||||
|
const [closeBehaviorDropdownOpen, setCloseBehaviorDropdownOpen] = useState(false)
|
||||||
|
|
||||||
const [wordCloudExcludeWords, setWordCloudExcludeWords] = useState<string[]>([])
|
const [wordCloudExcludeWords, setWordCloudExcludeWords] = useState<string[]>([])
|
||||||
const [excludeWordsInput, setExcludeWordsInput] = useState('')
|
const [excludeWordsInput, setExcludeWordsInput] = useState('')
|
||||||
@@ -253,15 +255,16 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
if (!target.closest('.custom-select')) {
|
if (!target.closest('.custom-select')) {
|
||||||
setFilterModeDropdownOpen(false)
|
setFilterModeDropdownOpen(false)
|
||||||
setPositionDropdownOpen(false)
|
setPositionDropdownOpen(false)
|
||||||
|
setCloseBehaviorDropdownOpen(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (filterModeDropdownOpen || positionDropdownOpen) {
|
if (filterModeDropdownOpen || positionDropdownOpen || closeBehaviorDropdownOpen) {
|
||||||
document.addEventListener('click', handleClickOutside)
|
document.addEventListener('click', handleClickOutside)
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('click', handleClickOutside)
|
document.removeEventListener('click', handleClickOutside)
|
||||||
}
|
}
|
||||||
}, [filterModeDropdownOpen, positionDropdownOpen])
|
}, [closeBehaviorDropdownOpen, filterModeDropdownOpen, positionDropdownOpen])
|
||||||
|
|
||||||
|
|
||||||
const loadConfig = async () => {
|
const loadConfig = async () => {
|
||||||
@@ -283,6 +286,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
const savedNotificationPosition = await configService.getNotificationPosition()
|
const savedNotificationPosition = await configService.getNotificationPosition()
|
||||||
const savedNotificationFilterMode = await configService.getNotificationFilterMode()
|
const savedNotificationFilterMode = await configService.getNotificationFilterMode()
|
||||||
const savedNotificationFilterList = await configService.getNotificationFilterList()
|
const savedNotificationFilterList = await configService.getNotificationFilterList()
|
||||||
|
const savedWindowCloseBehavior = await configService.getWindowCloseBehavior()
|
||||||
|
|
||||||
const savedAuthEnabled = await window.electronAPI.auth.verifyEnabled()
|
const savedAuthEnabled = await window.electronAPI.auth.verifyEnabled()
|
||||||
const savedAuthUseHello = await configService.getAuthUseHello()
|
const savedAuthUseHello = await configService.getAuthUseHello()
|
||||||
@@ -318,6 +322,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
setNotificationPosition(savedNotificationPosition)
|
setNotificationPosition(savedNotificationPosition)
|
||||||
setNotificationFilterMode(savedNotificationFilterMode)
|
setNotificationFilterMode(savedNotificationFilterMode)
|
||||||
setNotificationFilterList(savedNotificationFilterList)
|
setNotificationFilterList(savedNotificationFilterList)
|
||||||
|
setWindowCloseBehavior(savedWindowCloseBehavior)
|
||||||
|
|
||||||
const savedExcludeWords = await configService.getWordCloudExcludeWords()
|
const savedExcludeWords = await configService.getWordCloudExcludeWords()
|
||||||
setWordCloudExcludeWords(savedExcludeWords)
|
setWordCloudExcludeWords(savedExcludeWords)
|
||||||
@@ -1024,6 +1029,61 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="divider" />
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label>关闭主窗口时</label>
|
||||||
|
<span className="form-hint">设置点击关闭按钮后的默认行为;选择“每次询问”时会弹出关闭确认。</span>
|
||||||
|
<div className="custom-select">
|
||||||
|
<div
|
||||||
|
className={`custom-select-trigger ${closeBehaviorDropdownOpen ? 'open' : ''}`}
|
||||||
|
onClick={() => setCloseBehaviorDropdownOpen(!closeBehaviorDropdownOpen)}
|
||||||
|
>
|
||||||
|
<span className="custom-select-value">
|
||||||
|
{windowCloseBehavior === 'tray'
|
||||||
|
? '最小化到系统托盘'
|
||||||
|
: windowCloseBehavior === 'quit'
|
||||||
|
? '完全关闭'
|
||||||
|
: '每次询问'}
|
||||||
|
</span>
|
||||||
|
<ChevronDown size={14} className={`custom-select-arrow ${closeBehaviorDropdownOpen ? 'rotate' : ''}`} />
|
||||||
|
</div>
|
||||||
|
<div className={`custom-select-dropdown ${closeBehaviorDropdownOpen ? 'open' : ''}`}>
|
||||||
|
{[
|
||||||
|
{
|
||||||
|
value: 'ask' as const,
|
||||||
|
label: '每次询问',
|
||||||
|
successMessage: '已恢复关闭确认弹窗'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'tray' as const,
|
||||||
|
label: '最小化到系统托盘',
|
||||||
|
successMessage: '关闭按钮已改为最小化到托盘'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'quit' as const,
|
||||||
|
label: '完全关闭',
|
||||||
|
successMessage: '关闭按钮已改为完全关闭'
|
||||||
|
}
|
||||||
|
].map(option => (
|
||||||
|
<div
|
||||||
|
key={option.value}
|
||||||
|
className={`custom-select-option ${windowCloseBehavior === option.value ? 'selected' : ''}`}
|
||||||
|
onClick={async () => {
|
||||||
|
setWindowCloseBehavior(option.value)
|
||||||
|
setCloseBehaviorDropdownOpen(false)
|
||||||
|
await configService.setWindowCloseBehavior(option.value)
|
||||||
|
showMessage(option.successMessage, true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{option.label}
|
||||||
|
{windowCloseBehavior === option.value && <Check size={14} />}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export const CONFIG_KEYS = {
|
|||||||
NOTIFICATION_POSITION: 'notificationPosition',
|
NOTIFICATION_POSITION: 'notificationPosition',
|
||||||
NOTIFICATION_FILTER_MODE: 'notificationFilterMode',
|
NOTIFICATION_FILTER_MODE: 'notificationFilterMode',
|
||||||
NOTIFICATION_FILTER_LIST: 'notificationFilterList',
|
NOTIFICATION_FILTER_LIST: 'notificationFilterList',
|
||||||
|
WINDOW_CLOSE_BEHAVIOR: 'windowCloseBehavior',
|
||||||
|
|
||||||
// 词云
|
// 词云
|
||||||
WORD_CLOUD_EXCLUDE_WORDS: 'wordCloudExcludeWords',
|
WORD_CLOUD_EXCLUDE_WORDS: 'wordCloudExcludeWords',
|
||||||
@@ -85,6 +86,8 @@ export interface ExportDefaultMediaConfig {
|
|||||||
emojis: boolean
|
emojis: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type WindowCloseBehavior = 'ask' | 'tray' | 'quit'
|
||||||
|
|
||||||
const DEFAULT_EXPORT_MEDIA_CONFIG: ExportDefaultMediaConfig = {
|
const DEFAULT_EXPORT_MEDIA_CONFIG: ExportDefaultMediaConfig = {
|
||||||
images: true,
|
images: true,
|
||||||
videos: true,
|
videos: true,
|
||||||
@@ -1188,6 +1191,16 @@ export async function setNotificationFilterList(list: string[]): Promise<void> {
|
|||||||
await config.set(CONFIG_KEYS.NOTIFICATION_FILTER_LIST, list)
|
await config.set(CONFIG_KEYS.NOTIFICATION_FILTER_LIST, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getWindowCloseBehavior(): Promise<WindowCloseBehavior> {
|
||||||
|
const value = await config.get(CONFIG_KEYS.WINDOW_CLOSE_BEHAVIOR)
|
||||||
|
if (value === 'tray' || value === 'quit') return value
|
||||||
|
return 'ask'
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setWindowCloseBehavior(behavior: WindowCloseBehavior): Promise<void> {
|
||||||
|
await config.set(CONFIG_KEYS.WINDOW_CLOSE_BEHAVIOR, behavior)
|
||||||
|
}
|
||||||
|
|
||||||
// 获取词云排除词列表
|
// 获取词云排除词列表
|
||||||
export async function getWordCloudExcludeWords(): Promise<string[]> {
|
export async function getWordCloudExcludeWords(): Promise<string[]> {
|
||||||
const value = await config.get(CONFIG_KEYS.WORD_CLOUD_EXCLUDE_WORDS)
|
const value = await config.get(CONFIG_KEYS.WORD_CLOUD_EXCLUDE_WORDS)
|
||||||
|
|||||||
Reference in New Issue
Block a user