feat(desktop): enhance error handling and logging for session synchronization and window mode transitions
This commit is contained in:
@@ -62,6 +62,7 @@ const SOHU_ORIGIN = 'https://mp.sohu.com'
|
|||||||
const SOHU_MANAGE_URL = `${SOHU_ORIGIN}/mpfe/v4/contentManagement/first/page?newsType=1`
|
const SOHU_MANAGE_URL = `${SOHU_ORIGIN}/mpfe/v4/contentManagement/first/page?newsType=1`
|
||||||
const SOHU_PUBLISH_URL = `${SOHU_ORIGIN}/mpbp/bp/news/v4/news/publish/v2`
|
const SOHU_PUBLISH_URL = `${SOHU_ORIGIN}/mpbp/bp/news/v4/news/publish/v2`
|
||||||
const SOHU_DRAFT_URL = `${SOHU_ORIGIN}/mpbp/bp/news/v4/news/draft/v2`
|
const SOHU_DRAFT_URL = `${SOHU_ORIGIN}/mpbp/bp/news/v4/news/draft/v2`
|
||||||
|
const SOHU_NOT_LOGGED_IN_MESSAGE = '搜狐号账号登录态已失效,请重新登录搜狐号后再重试。'
|
||||||
|
|
||||||
function stringId(value: unknown): string {
|
function stringId(value: unknown): string {
|
||||||
if (typeof value === 'number') {
|
if (typeof value === 'number') {
|
||||||
@@ -296,7 +297,7 @@ function failureResult(
|
|||||||
summary: '搜狐号登录态失效,无法执行发布。',
|
summary: '搜狐号登录态失效,无法执行发布。',
|
||||||
error: {
|
error: {
|
||||||
code: 'sohuhao_not_logged_in',
|
code: 'sohuhao_not_logged_in',
|
||||||
message,
|
message: SOHU_NOT_LOGGED_IN_MESSAGE,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -757,13 +757,39 @@ async function createSettingsWindow(): Promise<ElectronBrowserWindow> {
|
|||||||
return window
|
return window
|
||||||
}
|
}
|
||||||
|
|
||||||
function flattenError(error: unknown): Error {
|
function ipcErrorMessage(error: unknown): string {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
const copy = new Error(error.message || 'ipc_handler_failed')
|
return error.message || 'ipc_handler_failed'
|
||||||
|
}
|
||||||
|
if (typeof error === 'string') {
|
||||||
|
return error || 'ipc_handler_failed'
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
error &&
|
||||||
|
typeof error === 'object' &&
|
||||||
|
'message' in error &&
|
||||||
|
typeof (error as { message?: unknown }).message === 'string'
|
||||||
|
) {
|
||||||
|
return (error as { message: string }).message || 'ipc_handler_failed'
|
||||||
|
}
|
||||||
|
return 'ipc_handler_failed'
|
||||||
|
}
|
||||||
|
|
||||||
|
function flattenError(channel: string, error: unknown): Error {
|
||||||
|
const message = ipcErrorMessage(error)
|
||||||
|
console.error('[desktop-main] ipc handler failed', {
|
||||||
|
channel,
|
||||||
|
name: error instanceof Error ? error.name : typeof error,
|
||||||
|
message,
|
||||||
|
stack: error instanceof Error ? error.stack : undefined,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (error instanceof Error) {
|
||||||
|
const copy = new Error(message)
|
||||||
copy.name = error.name
|
copy.name = error.name
|
||||||
return copy
|
return copy
|
||||||
}
|
}
|
||||||
return new Error(typeof error === 'string' ? error : 'ipc_handler_failed')
|
return new Error(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
function safeHandle<Args extends unknown[], Result>(
|
function safeHandle<Args extends unknown[], Result>(
|
||||||
@@ -774,7 +800,7 @@ function safeHandle<Args extends unknown[], Result>(
|
|||||||
try {
|
try {
|
||||||
return await handler(...(args as unknown as Args))
|
return await handler(...(args as unknown as Args))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw flattenError(error)
|
throw flattenError(channel, error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1065,7 +1091,7 @@ function registerBridgeHandlers(): void {
|
|||||||
return setDesktopAppSetting(key, value)
|
return setDesktopAppSetting(key, value)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
ipcMain.handle(
|
safeHandle(
|
||||||
'desktop:runtime-session-sync',
|
'desktop:runtime-session-sync',
|
||||||
(_event, session: DesktopRuntimeSessionSyncRequest | null) => {
|
(_event, session: DesktopRuntimeSessionSyncRequest | null) => {
|
||||||
syncRuntimeSession(session)
|
syncRuntimeSession(session)
|
||||||
@@ -1105,16 +1131,19 @@ function registerBridgeHandlers(): void {
|
|||||||
await releaseRuntimeSession({ revoke: Boolean(revoke) })
|
await releaseRuntimeSession({ revoke: Boolean(revoke) })
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
ipcMain.handle('desktop:set-window-mode', async (event, mode: WindowMode, request?: unknown) => {
|
safeHandle(
|
||||||
if (mode === 'login' || mode === 'main') {
|
'desktop:set-window-mode',
|
||||||
await queueWindowModeSwitch(
|
async (event: IpcMainInvokeEvent, mode: WindowMode, request?: unknown) => {
|
||||||
mode,
|
if (mode === 'login' || mode === 'main') {
|
||||||
normalizeWindowModeRequest(request),
|
await queueWindowModeSwitch(
|
||||||
windowFromIpcEvent(event),
|
mode,
|
||||||
)
|
normalizeWindowModeRequest(request),
|
||||||
}
|
windowFromIpcEvent(event),
|
||||||
return null
|
)
|
||||||
})
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasSingleInstanceLock = initSingleInstance((argv) => {
|
const hasSingleInstanceLock = initSingleInstance((argv) => {
|
||||||
|
|||||||
@@ -30,7 +30,14 @@ function getModeBridge(): WindowModeBridge | undefined {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function syncWindowMode(authenticated: boolean): void {
|
function syncWindowMode(authenticated: boolean): void {
|
||||||
void getModeBridge()?.setWindowMode?.(authenticated ? 'main' : 'login', { source: 'auth-state' })
|
void getModeBridge()
|
||||||
|
?.setWindowMode?.(authenticated ? 'main' : 'login', { source: 'auth-state' })
|
||||||
|
.catch((err) => {
|
||||||
|
console.warn('[desktop-app] window mode sync failed', {
|
||||||
|
authenticated,
|
||||||
|
message: err instanceof Error ? err.message : String(err),
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const rendererWindowMode = resolveRendererWindowMode()
|
const rendererWindowMode = resolveRendererWindowMode()
|
||||||
@@ -62,7 +69,11 @@ if (rendererWindowMode === 'main') {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (rendererWindowMode !== 'login') {
|
if (rendererWindowMode !== 'login') {
|
||||||
void syncRuntimeSession()
|
void syncRuntimeSession().catch((err) => {
|
||||||
|
console.warn('[desktop-app] runtime session sync failed', {
|
||||||
|
message: err instanceof Error ? err.message : String(err),
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if (usesAutomaticWindowMode) {
|
if (usesAutomaticWindowMode) {
|
||||||
syncWindowMode(isAuthenticated.value)
|
syncWindowMode(isAuthenticated.value)
|
||||||
|
|||||||
@@ -55,6 +55,13 @@ let logoutPromise: Promise<void> | null = null
|
|||||||
let renewPromise: Promise<void> | null = null
|
let renewPromise: Promise<void> | null = null
|
||||||
let tokenRenewTimer: ReturnType<typeof setInterval> | null = null
|
let tokenRenewTimer: ReturnType<typeof setInterval> | null = null
|
||||||
|
|
||||||
|
function logRuntimeSessionSyncFailure(reason: string, err: unknown): void {
|
||||||
|
console.warn('[desktop-session] runtime session sync failed', {
|
||||||
|
reason,
|
||||||
|
message: err instanceof Error ? err.message : String(err),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function readStoredSession(): DesktopSession | null {
|
function readStoredSession(): DesktopSession | null {
|
||||||
if (typeof window === 'undefined') {
|
if (typeof window === 'undefined') {
|
||||||
return null
|
return null
|
||||||
@@ -117,7 +124,9 @@ function persistSession(next: DesktopSession | null): void {
|
|||||||
window.localStorage.setItem(sessionStorageKey, JSON.stringify(next))
|
window.localStorage.setItem(sessionStorageKey, JSON.stringify(next))
|
||||||
}
|
}
|
||||||
|
|
||||||
void syncRuntimeSessionToMain(next)
|
void syncRuntimeSessionToMain(next).catch((err) => {
|
||||||
|
logRuntimeSessionSyncFailure('persist-session', err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function readStoredApiBaseURL(): string {
|
function readStoredApiBaseURL(): string {
|
||||||
@@ -141,7 +150,9 @@ function persistApiBaseURL(value: string): void {
|
|||||||
window.localStorage.setItem(apiBaseURLStorageKey, normalized)
|
window.localStorage.setItem(apiBaseURLStorageKey, normalized)
|
||||||
}
|
}
|
||||||
|
|
||||||
void syncRuntimeSessionToMain()
|
void syncRuntimeSessionToMain().catch((err) => {
|
||||||
|
logRuntimeSessionSyncFailure('api-base-url-change', err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function createPublicClient() {
|
function createPublicClient() {
|
||||||
@@ -753,7 +764,9 @@ if (typeof window !== 'undefined') {
|
|||||||
window.addEventListener('storage', (event) => {
|
window.addEventListener('storage', (event) => {
|
||||||
if (event.key === apiBaseURLStorageKey) {
|
if (event.key === apiBaseURLStorageKey) {
|
||||||
apiBaseURL.value = normalizeDesktopApiBaseURL(event.newValue, normalizedDefaultApiBaseURL)
|
apiBaseURL.value = normalizeDesktopApiBaseURL(event.newValue, normalizedDefaultApiBaseURL)
|
||||||
void syncRuntimeSessionToMain()
|
void syncRuntimeSessionToMain().catch((err) => {
|
||||||
|
logRuntimeSessionSyncFailure('storage-api-base-url-change', err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
void syncStoredDesktopClientDeviceInfo()
|
void syncStoredDesktopClientDeviceInfo()
|
||||||
|
|||||||
@@ -62,7 +62,13 @@ async function submitLogin() {
|
|||||||
password: form.password,
|
password: form.password,
|
||||||
})
|
})
|
||||||
await persistCredentialsPreference()
|
await persistCredentialsPreference()
|
||||||
await window.desktopBridge?.app?.setWindowMode?.('main', { source: 'login' })
|
try {
|
||||||
|
await window.desktopBridge?.app?.setWindowMode?.('main', { source: 'login' })
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('[login-view] switch to main window failed', {
|
||||||
|
message: err instanceof Error ? err.message : String(err),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function hydrateSavedCredentials() {
|
async function hydrateSavedCredentials() {
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ describe('publisher error normalization', () => {
|
|||||||
expect(normalizePublisherErrorMessage('qiehao_cookie_missing')).toBe(
|
expect(normalizePublisherErrorMessage('qiehao_cookie_missing')).toBe(
|
||||||
'企鹅号账号登录态已失效,请重新登录该平台后再重试。',
|
'企鹅号账号登录态已失效,请重新登录该平台后再重试。',
|
||||||
)
|
)
|
||||||
|
expect(normalizePublisherErrorMessage('sohuhao_not_logged_in')).toBe(
|
||||||
|
'搜狐号账号登录态已失效,请重新登录该平台后再重试。',
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('uses a generic Chinese message for unknown publisher login-state failures', () => {
|
it('uses a generic Chinese message for unknown publisher login-state failures', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user