perf(apps): launch never waits on the credentials RPC — 1.2s budget + memo #119
@ -646,37 +646,51 @@ function launchAppNow(id: string) {
|
||||
useAppLauncherStore().openSession(id)
|
||||
}
|
||||
|
||||
async function maybeShowCredentialsBeforeLaunch(id: string): Promise<boolean> {
|
||||
try {
|
||||
const result = await rpcClient.call<AppCredentialsResponse>({
|
||||
// Per-app credentials memo: the pre-launch RPC could hold an Apps-tab launch
|
||||
// hostage for its full 5s timeout over the mesh (home-card launches skip this
|
||||
// gate entirely, which is why they always felt instant). First launch waits at
|
||||
// most LAUNCH_CRED_BUDGET_MS; the RPC keeps running in the background and its
|
||||
// answer is memoized, so every later launch of that app resolves instantly.
|
||||
const LAUNCH_CRED_BUDGET_MS = 1200
|
||||
const credentialsCache = new Map<string, AppCredentialsResponse | null>()
|
||||
|
||||
function fetchCredentials(id: string): Promise<AppCredentialsResponse | null> {
|
||||
return rpcClient
|
||||
.call<AppCredentialsResponse>({
|
||||
method: 'package.credentials',
|
||||
params: { app_id: id },
|
||||
timeout: 5000,
|
||||
})
|
||||
const credentials = resolveAppCredentials(id, result)
|
||||
if (!credentials) return false
|
||||
credentialModal.value = {
|
||||
show: true,
|
||||
appId: id,
|
||||
title: credentials.title || `${packages.value[id]?.manifest.title || id} credentials`,
|
||||
description: credentials.description || 'Use these credentials when the app asks you to sign in.',
|
||||
credentials: credentials.credentials,
|
||||
copied: '',
|
||||
}
|
||||
return true
|
||||
} catch {
|
||||
const credentials = resolveAppCredentials(id, null)
|
||||
if (!credentials) return false
|
||||
credentialModal.value = {
|
||||
show: true,
|
||||
appId: id,
|
||||
title: credentials.title || `${packages.value[id]?.manifest.title || id} credentials`,
|
||||
description: credentials.description || 'Use these credentials when the app asks you to sign in.',
|
||||
credentials: credentials.credentials,
|
||||
copied: '',
|
||||
}
|
||||
return true
|
||||
.then((r) => {
|
||||
credentialsCache.set(id, r)
|
||||
return r
|
||||
})
|
||||
.catch(() => {
|
||||
credentialsCache.set(id, null)
|
||||
return null
|
||||
})
|
||||
}
|
||||
|
||||
async function maybeShowCredentialsBeforeLaunch(id: string): Promise<boolean> {
|
||||
const result = credentialsCache.has(id)
|
||||
? credentialsCache.get(id) ?? null
|
||||
: await Promise.race([
|
||||
fetchCredentials(id),
|
||||
// Budget exceeded → launch with the static fallback config; the
|
||||
// in-flight RPC still lands in the cache for next time.
|
||||
new Promise<null>((resolve) => setTimeout(() => resolve(null), LAUNCH_CRED_BUDGET_MS)),
|
||||
])
|
||||
const credentials = resolveAppCredentials(id, result)
|
||||
if (!credentials) return false
|
||||
credentialModal.value = {
|
||||
show: true,
|
||||
appId: id,
|
||||
title: credentials.title || `${packages.value[id]?.manifest.title || id} credentials`,
|
||||
description: credentials.description || 'Use these credentials when the app asks you to sign in.',
|
||||
credentials: credentials.credentials,
|
||||
copied: '',
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
function closeCredentialModal() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user