mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-04-26 07:26:46 +00:00
Merge pull request #842 from Jasonzhu1207/main
feat: add silent startup
This commit is contained in:
@@ -748,6 +748,10 @@ const getWindowCloseBehavior = (): WindowCloseBehavior => {
|
|||||||
return behavior === 'tray' || behavior === 'quit' ? behavior : 'ask'
|
return behavior === 'tray' || behavior === 'quit' ? behavior : 'ask'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isSilentStartupEnabled = (): boolean => {
|
||||||
|
return configService?.get('silentStartup') === true
|
||||||
|
}
|
||||||
|
|
||||||
const requestMainWindowCloseConfirmation = (win: BrowserWindow): void => {
|
const requestMainWindowCloseConfirmation = (win: BrowserWindow): void => {
|
||||||
if (isClosePromptVisible) return
|
if (isClosePromptVisible) return
|
||||||
isClosePromptVisible = true
|
isClosePromptVisible = true
|
||||||
@@ -3740,21 +3744,31 @@ function checkForUpdatesOnStartup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.whenReady().then(async () => {
|
app.whenReady().then(async () => {
|
||||||
// 立即创建 Splash 窗口,确保用户尽快看到反馈
|
// 先初始化配置,以便在启动早期判定是否需要静默启动
|
||||||
createSplashWindow()
|
configService = new ConfigService()
|
||||||
|
applyAutoUpdateChannel('startup')
|
||||||
|
syncLaunchAtStartupPreference()
|
||||||
|
const onboardingDone = configService.get('onboardingDone') === true
|
||||||
|
const startInBackground = onboardingDone && isSilentStartupEnabled()
|
||||||
|
shouldShowMain = onboardingDone
|
||||||
|
|
||||||
// 等待 Splash 页面加载完成后再推送进度
|
if (!startInBackground) {
|
||||||
if (splashWindow) {
|
// 非静默模式下显示 Splash,提供启动反馈
|
||||||
await new Promise<void>((resolve) => {
|
createSplashWindow()
|
||||||
if (splashWindow!.webContents.isLoading()) {
|
|
||||||
splashWindow!.webContents.once('did-finish-load', () => resolve())
|
// 等待 Splash 页面加载完成后再推送进度
|
||||||
} else {
|
if (splashWindow) {
|
||||||
resolve()
|
await new Promise<void>((resolve) => {
|
||||||
}
|
if (splashWindow!.webContents.isLoading()) {
|
||||||
})
|
splashWindow!.webContents.once('did-finish-load', () => resolve())
|
||||||
splashWindow.webContents
|
} else {
|
||||||
.executeJavaScript(`setVersion(${JSON.stringify(app.getVersion())})`)
|
resolve()
|
||||||
.catch(() => {})
|
}
|
||||||
|
})
|
||||||
|
splashWindow.webContents
|
||||||
|
.executeJavaScript(`setVersion(${JSON.stringify(app.getVersion())})`)
|
||||||
|
.catch(() => {})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
|
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
|
||||||
@@ -3783,13 +3797,7 @@ app.whenReady().then(async () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化配置服务
|
|
||||||
updateSplashProgress(5, '正在加载配置...')
|
updateSplashProgress(5, '正在加载配置...')
|
||||||
configService = new ConfigService()
|
|
||||||
applyAutoUpdateChannel('startup')
|
|
||||||
syncLaunchAtStartupPreference()
|
|
||||||
const onboardingDone = configService.get('onboardingDone') === true
|
|
||||||
shouldShowMain = onboardingDone
|
|
||||||
|
|
||||||
// 将用户主题配置推送给 Splash 窗口
|
// 将用户主题配置推送给 Splash 窗口
|
||||||
if (splashWindow && !splashWindow.isDestroyed()) {
|
if (splashWindow && !splashWindow.isDestroyed()) {
|
||||||
@@ -3956,6 +3964,8 @@ app.whenReady().then(async () => {
|
|||||||
|
|
||||||
if (!onboardingDone) {
|
if (!onboardingDone) {
|
||||||
createOnboardingWindow()
|
createOnboardingWindow()
|
||||||
|
} else if (startInBackground && tray) {
|
||||||
|
mainWindow?.hide()
|
||||||
} else {
|
} else {
|
||||||
mainWindow?.show()
|
mainWindow?.show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ interface ConfigSchema {
|
|||||||
language: string
|
language: string
|
||||||
logEnabled: boolean
|
logEnabled: boolean
|
||||||
launchAtStartup?: boolean
|
launchAtStartup?: boolean
|
||||||
|
silentStartup?: boolean
|
||||||
llmModelPath: string
|
llmModelPath: string
|
||||||
whisperModelName: string
|
whisperModelName: string
|
||||||
whisperModelDir: string
|
whisperModelDir: string
|
||||||
@@ -163,6 +164,7 @@ export class ConfigService {
|
|||||||
themeId: 'cloud-dancer',
|
themeId: 'cloud-dancer',
|
||||||
language: 'zh-CN',
|
language: 'zh-CN',
|
||||||
logEnabled: false,
|
logEnabled: false,
|
||||||
|
silentStartup: false,
|
||||||
llmModelPath: '',
|
llmModelPath: '',
|
||||||
whisperModelName: 'base',
|
whisperModelName: 'base',
|
||||||
whisperModelDir: '',
|
whisperModelDir: '',
|
||||||
|
|||||||
@@ -195,6 +195,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
const [launchAtStartup, setLaunchAtStartup] = useState(false)
|
const [launchAtStartup, setLaunchAtStartup] = useState(false)
|
||||||
const [launchAtStartupSupported, setLaunchAtStartupSupported] = useState(isWindows || isMac)
|
const [launchAtStartupSupported, setLaunchAtStartupSupported] = useState(isWindows || isMac)
|
||||||
const [launchAtStartupReason, setLaunchAtStartupReason] = useState('')
|
const [launchAtStartupReason, setLaunchAtStartupReason] = useState('')
|
||||||
|
const [silentStartup, setSilentStartup] = useState(false)
|
||||||
const [windowCloseBehavior, setWindowCloseBehavior] = useState<configService.WindowCloseBehavior>('ask')
|
const [windowCloseBehavior, setWindowCloseBehavior] = useState<configService.WindowCloseBehavior>('ask')
|
||||||
const [quoteLayout, setQuoteLayout] = useState<configService.QuoteLayout>('quote-top')
|
const [quoteLayout, setQuoteLayout] = useState<configService.QuoteLayout>('quote-top')
|
||||||
const [updateChannel, setUpdateChannel] = useState<configService.UpdateChannel>('stable')
|
const [updateChannel, setUpdateChannel] = useState<configService.UpdateChannel>('stable')
|
||||||
@@ -222,6 +223,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
const [isFetchingImageKey, setIsFetchingImageKey] = useState(false)
|
const [isFetchingImageKey, setIsFetchingImageKey] = useState(false)
|
||||||
const [isCheckingUpdate, setIsCheckingUpdate] = useState(false)
|
const [isCheckingUpdate, setIsCheckingUpdate] = useState(false)
|
||||||
const [isUpdatingLaunchAtStartup, setIsUpdatingLaunchAtStartup] = useState(false)
|
const [isUpdatingLaunchAtStartup, setIsUpdatingLaunchAtStartup] = useState(false)
|
||||||
|
const [isUpdatingSilentStartup, setIsUpdatingSilentStartup] = useState(false)
|
||||||
const [appVersion, setAppVersion] = useState('')
|
const [appVersion, setAppVersion] = useState('')
|
||||||
const [message, setMessage] = useState<{ text: string; success: boolean } | null>(null)
|
const [message, setMessage] = useState<{ text: string; success: boolean } | null>(null)
|
||||||
const [showDecryptKey, setShowDecryptKey] = useState(false)
|
const [showDecryptKey, setShowDecryptKey] = useState(false)
|
||||||
@@ -445,6 +447,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
const savedMessagePushFilterList = await configService.getMessagePushFilterList()
|
const savedMessagePushFilterList = await configService.getMessagePushFilterList()
|
||||||
const contactsResult = await window.electronAPI.chat.getContacts({ lite: true })
|
const contactsResult = await window.electronAPI.chat.getContacts({ lite: true })
|
||||||
const savedLaunchAtStartupStatus = await window.electronAPI.app.getLaunchAtStartupStatus()
|
const savedLaunchAtStartupStatus = await window.electronAPI.app.getLaunchAtStartupStatus()
|
||||||
|
const savedSilentStartup = await configService.getSilentStartup()
|
||||||
const savedWindowCloseBehavior = await configService.getWindowCloseBehavior()
|
const savedWindowCloseBehavior = await configService.getWindowCloseBehavior()
|
||||||
const savedQuoteLayout = await configService.getQuoteLayout()
|
const savedQuoteLayout = await configService.getQuoteLayout()
|
||||||
const savedUpdateChannel = await configService.getUpdateChannel()
|
const savedUpdateChannel = await configService.getUpdateChannel()
|
||||||
@@ -502,6 +505,7 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
setLaunchAtStartup(savedLaunchAtStartupStatus.enabled)
|
setLaunchAtStartup(savedLaunchAtStartupStatus.enabled)
|
||||||
setLaunchAtStartupSupported(savedLaunchAtStartupStatus.supported)
|
setLaunchAtStartupSupported(savedLaunchAtStartupStatus.supported)
|
||||||
setLaunchAtStartupReason(savedLaunchAtStartupStatus.reason || '')
|
setLaunchAtStartupReason(savedLaunchAtStartupStatus.reason || '')
|
||||||
|
setSilentStartup(savedSilentStartup)
|
||||||
setWindowCloseBehavior(savedWindowCloseBehavior)
|
setWindowCloseBehavior(savedWindowCloseBehavior)
|
||||||
setQuoteLayout(savedQuoteLayout)
|
setQuoteLayout(savedQuoteLayout)
|
||||||
if (savedUpdateChannel) {
|
if (savedUpdateChannel) {
|
||||||
@@ -615,6 +619,21 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleSilentStartupChange = async (enabled: boolean) => {
|
||||||
|
if (isUpdatingSilentStartup) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsUpdatingSilentStartup(true)
|
||||||
|
await configService.setSilentStartup(enabled)
|
||||||
|
setSilentStartup(enabled)
|
||||||
|
showMessage(enabled ? '已开启静默启动' : '已关闭静默启动', true)
|
||||||
|
} catch (e: any) {
|
||||||
|
showMessage(`设置静默启动失败: ${e?.message || String(e)}`, false)
|
||||||
|
} finally {
|
||||||
|
setIsUpdatingSilentStartup(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const refreshWhisperStatus = async (modelDirValue = whisperModelDir) => {
|
const refreshWhisperStatus = async (modelDirValue = whisperModelDir) => {
|
||||||
try {
|
try {
|
||||||
const result = await window.electronAPI.whisper?.getModelStatus()
|
const result = await window.electronAPI.whisper?.getModelStatus()
|
||||||
@@ -1684,6 +1703,35 @@ function SettingsPage({ onClose }: SettingsPageProps = {}) {
|
|||||||
|
|
||||||
<div className="divider" />
|
<div className="divider" />
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label>静默启动</label>
|
||||||
|
<span className="form-hint">
|
||||||
|
开启后,无论手动启动还是开机自启动,都会先驻留到系统托盘,不主动显示主窗口。
|
||||||
|
</span>
|
||||||
|
<div className="log-toggle-line">
|
||||||
|
<span className="log-status">
|
||||||
|
{isUpdatingSilentStartup
|
||||||
|
? '保存中...'
|
||||||
|
: (silentStartup ? '已开启' : '已关闭')}
|
||||||
|
</span>
|
||||||
|
<label className="switch" htmlFor="silent-startup-toggle">
|
||||||
|
<input
|
||||||
|
id="silent-startup-toggle"
|
||||||
|
className="switch-input"
|
||||||
|
type="checkbox"
|
||||||
|
checked={silentStartup}
|
||||||
|
disabled={isUpdatingSilentStartup}
|
||||||
|
onChange={(e) => {
|
||||||
|
void handleSilentStartupChange(e.target.checked)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span className="switch-slider" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="divider" />
|
||||||
|
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label>关闭主窗口时</label>
|
<label>关闭主窗口时</label>
|
||||||
<span className="form-hint">设置点击关闭按钮后的默认行为;选择“每次询问”时会弹出关闭确认。</span>
|
<span className="form-hint">设置点击关闭按钮后的默认行为;选择“每次询问”时会弹出关闭确认。</span>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export const CONFIG_KEYS = {
|
|||||||
WINDOW_BOUNDS: 'windowBounds',
|
WINDOW_BOUNDS: 'windowBounds',
|
||||||
CACHE_PATH: 'cachePath',
|
CACHE_PATH: 'cachePath',
|
||||||
LAUNCH_AT_STARTUP: 'launchAtStartup',
|
LAUNCH_AT_STARTUP: 'launchAtStartup',
|
||||||
|
SILENT_STARTUP: 'silentStartup',
|
||||||
|
|
||||||
EXPORT_PATH: 'exportPath',
|
EXPORT_PATH: 'exportPath',
|
||||||
AGREEMENT_ACCEPTED: 'agreementAccepted',
|
AGREEMENT_ACCEPTED: 'agreementAccepted',
|
||||||
@@ -321,6 +322,17 @@ export async function setLaunchAtStartup(enabled: boolean): Promise<void> {
|
|||||||
await config.set(CONFIG_KEYS.LAUNCH_AT_STARTUP, enabled)
|
await config.set(CONFIG_KEYS.LAUNCH_AT_STARTUP, enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取静默启动偏好
|
||||||
|
export async function getSilentStartup(): Promise<boolean> {
|
||||||
|
const value = await config.get(CONFIG_KEYS.SILENT_STARTUP)
|
||||||
|
return value === true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置静默启动偏好
|
||||||
|
export async function setSilentStartup(enabled: boolean): Promise<void> {
|
||||||
|
await config.set(CONFIG_KEYS.SILENT_STARTUP, enabled)
|
||||||
|
}
|
||||||
|
|
||||||
// 获取 LLM 模型路径
|
// 获取 LLM 模型路径
|
||||||
export async function getLlmModelPath(): Promise<string | null> {
|
export async function getLlmModelPath(): Promise<string | null> {
|
||||||
const value = await config.get(CONFIG_KEYS.LLM_MODEL_PATH)
|
const value = await config.get(CONFIG_KEYS.LLM_MODEL_PATH)
|
||||||
|
|||||||
Reference in New Issue
Block a user