fix: ensure media cache is populated before checking exists

On iOS (and web), the media cache wasn't populated before the drafts
query ran, causing drafts with local media to incorrectly show as
"missing media" on app restart. The issue would resolve itself after
closing and reopening the composer because by then the cache was ready.

This fix adds ensureMediaCachePopulated() and awaits it in useDrafts
before checking which media exists locally.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-01-16 11:30:28 +02:00
parent a0ed43d903
commit 28da42fd61
2 changed files with 18 additions and 3 deletions
+2
View File
@@ -25,6 +25,8 @@ export function useDrafts() {
return useQuery<DraftSummary[]>({
queryKey: DRAFTS_QUERY_KEY,
queryFn: async () => {
// Ensure media cache is populated before checking which media exists
await storage.ensureMediaCachePopulated()
const res = await agent.app.bsky.draft.getDrafts({})
return res.data.drafts.map(view =>
draftViewToSummary(view, path => storage.mediaExists(path)),
+16 -3
View File
@@ -137,19 +137,20 @@ export async function deleteMediaFromLocal(
*/
const mediaExistsCache = new Map<string, boolean>()
let cachePopulated = false
let populateCachePromise: Promise<void> | null = null
export function mediaExists(localRefPath: string): boolean {
if (mediaExistsCache.has(localRefPath)) {
return mediaExistsCache.get(localRefPath)!
}
// If cache not populated yet, trigger async population
if (!cachePopulated) {
populateCache()
if (!cachePopulated && !populateCachePromise) {
populateCachePromise = populateCacheInternal()
}
return false // Conservative: assume doesn't exist if not in cache
}
async function populateCache(): Promise<void> {
async function populateCacheInternal(): Promise<void> {
try {
const db = await getDB()
const keys = await db.getAllKeys('media')
@@ -162,12 +163,24 @@ async function populateCache(): Promise<void> {
}
}
/**
* Ensure the media cache is populated. Call this before checking mediaExists.
*/
export async function ensureMediaCachePopulated(): Promise<void> {
if (cachePopulated) return
if (!populateCachePromise) {
populateCachePromise = populateCacheInternal()
}
await populateCachePromise
}
/**
* Clear the media exists cache (call when media is added/deleted)
*/
export function clearMediaCache(): void {
mediaExistsCache.clear()
cachePopulated = false
populateCachePromise = null
}
/**