fix: load draft preview images and get dimensions
Fix draft preview images not showing on web and add proper aspect ratio support: 1. Try to load all images regardless of the exists cache flag, which may be stale due to async cache population timing 2. Use Image.loadAsync() from expo-image to get image dimensions 3. Pass dimensions to viewImages for proper aspect ratio in previews Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,12 +5,12 @@ import {type AppBskyEmbedImages} from '@atproto/api'
|
|||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
|
|
||||||
import {isNative} from '#/platform/detection'
|
|
||||||
import {
|
import {
|
||||||
type DraftPostDisplay,
|
type DraftPostDisplay,
|
||||||
type DraftSummary,
|
type DraftSummary,
|
||||||
type LocalMediaDisplay,
|
type LocalMediaDisplay,
|
||||||
} from '#/state/drafts'
|
} from '#/state/drafts'
|
||||||
|
import * as storage from '#/state/drafts/storage'
|
||||||
import {useCurrentAccountProfile} from '#/state/queries/useCurrentAccountProfile'
|
import {useCurrentAccountProfile} from '#/state/queries/useCurrentAccountProfile'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {TimeElapsed} from '#/view/com/util/TimeElapsed'
|
import {TimeElapsed} from '#/view/com/util/TimeElapsed'
|
||||||
@@ -23,11 +23,6 @@ import {ImageLayoutGrid} from '#/components/images/ImageLayoutGrid'
|
|||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
// Platform-specific storage import
|
|
||||||
const storage = isNative
|
|
||||||
? require('#/state/drafts/storage')
|
|
||||||
: require('#/state/drafts/storage.web')
|
|
||||||
|
|
||||||
export function DraftItem({
|
export function DraftItem({
|
||||||
draft,
|
draft,
|
||||||
onSelect,
|
onSelect,
|
||||||
@@ -215,6 +210,8 @@ function DraftPostRow({
|
|||||||
type LoadedImage = {
|
type LoadedImage = {
|
||||||
url: string
|
url: string
|
||||||
meta: LocalMediaDisplay
|
meta: LocalMediaDisplay
|
||||||
|
width?: number
|
||||||
|
height?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
function DraftMediaPreview({post}: {post: DraftPostDisplay}) {
|
function DraftMediaPreview({post}: {post: DraftPostDisplay}) {
|
||||||
@@ -223,17 +220,25 @@ function DraftMediaPreview({post}: {post: DraftPostDisplay}) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function loadMedia() {
|
async function loadMedia() {
|
||||||
// Load images that exist locally
|
// Try to load all images - the exists flag may be stale due to async cache
|
||||||
if (post.images && post.images.length > 0) {
|
if (post.images && post.images.length > 0) {
|
||||||
const loaded: LoadedImage[] = []
|
const loaded: LoadedImage[] = []
|
||||||
for (const image of post.images) {
|
for (const image of post.images) {
|
||||||
if (image.exists) {
|
try {
|
||||||
|
const url = await storage.loadMediaFromLocal(image.localPath)
|
||||||
|
// Get dimensions using expo-image's loadAsync
|
||||||
|
let width: number | undefined
|
||||||
|
let height: number | undefined
|
||||||
try {
|
try {
|
||||||
const url = await storage.loadMediaFromLocal(image.localPath)
|
const imageRef = await Image.loadAsync(url)
|
||||||
loaded.push({url, meta: image})
|
width = imageRef.width
|
||||||
} catch (e) {
|
height = imageRef.height
|
||||||
console.warn('Failed to load draft image', e)
|
} catch {
|
||||||
|
// Dimensions unavailable, will use default aspect ratio
|
||||||
}
|
}
|
||||||
|
loaded.push({url, meta: {...image, exists: true}, width, height})
|
||||||
|
} catch (e) {
|
||||||
|
// Image doesn't exist locally, skip it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setLoadedImages(loaded)
|
setLoadedImages(loaded)
|
||||||
@@ -245,16 +250,16 @@ function DraftMediaPreview({post}: {post: DraftPostDisplay}) {
|
|||||||
|
|
||||||
// Convert loaded images to ViewImage format for the embed components
|
// Convert loaded images to ViewImage format for the embed components
|
||||||
const viewImages = useMemo<AppBskyEmbedImages.ViewImage[]>(() => {
|
const viewImages = useMemo<AppBskyEmbedImages.ViewImage[]>(() => {
|
||||||
return loadedImages.map(({url}) => ({
|
return loadedImages.map(({url, width, height, meta}) => ({
|
||||||
thumb: url,
|
thumb: url,
|
||||||
fullsize: url,
|
fullsize: url,
|
||||||
alt: '',
|
alt: meta.altText || '',
|
||||||
aspectRatio: undefined, // No dimensions stored in new schema
|
aspectRatio: width && height ? {width, height} : {width: 1, height: 1},
|
||||||
}))
|
}))
|
||||||
}, [loadedImages])
|
}, [loadedImages])
|
||||||
|
|
||||||
// Count missing images
|
// Count missing images (images we tried to load but couldn't)
|
||||||
const missingImageCount = post.images?.filter(img => !img.exists).length ?? 0
|
const missingImageCount = (post.images?.length ?? 0) - loadedImages.length
|
||||||
|
|
||||||
// Nothing to show
|
// Nothing to show
|
||||||
if (viewImages.length === 0 && !post.gif && !post.video) {
|
if (viewImages.length === 0 && !post.gif && !post.video) {
|
||||||
|
|||||||
Reference in New Issue
Block a user