Browse Source

bug-fixes

imwald
Silberengel 1 month ago
parent
commit
7748ac86bd
  1. 57
      src/components/Note/ArticleCardCoverImage.tsx
  2. 29
      src/components/Note/LongFormCard.tsx
  3. 28
      src/components/Note/MarkdownArticle/MarkdownArticle.tsx
  4. 31
      src/components/Note/WikiCard.tsx
  5. 3
      src/components/ReplyNoteList/index.tsx
  6. 4
      src/lib/relay-list-builder.ts
  7. 4
      src/services/client-replaceable-events.service.ts

57
src/components/Note/ArticleCardCoverImage.tsx

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
import ContentImage from '@/components/Image'
import UserAvatar from '@/components/UserAvatar'
import { cn } from '@/lib/utils'
import type { Event } from 'nostr-tools'
/**
* Long-form / wikistyle card cover: NIP-23 `image` tag when present, otherwise the author avatar.
*/
export default function ArticleCardCoverImage({
event,
imageUrl,
autoLoadMedia,
layout,
hideImageIfError = false
}: {
event: Event
imageUrl?: string
autoLoadMedia: boolean
layout: 'stacked' | 'row'
/** Passed through to {@link ContentImage} when an `image` tag URL exists. */
hideImageIfError?: boolean
}) {
const trimmed = imageUrl?.trim()
if (trimmed && autoLoadMedia) {
return (
<ContentImage
image={{ url: trimmed, pubkey: event.pubkey }}
className={
layout === 'stacked'
? 'mb-3 aspect-video w-full max-w-[400px]'
: 'h-44 max-w-[400px] shrink rounded-lg bg-foreground object-cover aspect-[4/3] xl:aspect-video'
}
classNames={layout === 'row' ? { wrapper: 'w-auto max-w-[400px] shrink-0' } : undefined}
hideIfError={hideImageIfError}
/>
)
}
if (trimmed) return null
return (
<div
className={cn(
'flex items-center justify-center rounded-lg bg-muted',
layout === 'stacked'
? 'mb-3 h-44 w-full max-w-[400px]'
: 'h-44 w-auto max-w-[400px] shrink-0 aspect-[4/3] xl:aspect-video'
)}
>
<UserAvatar
userId={event.pubkey}
size="large"
deferRemoteAvatar={false}
className="!h-[7.5rem] !w-[7.5rem] rounded-xl"
/>
</div>
)
}

29
src/components/Note/LongFormCard.tsx

@ -8,7 +8,7 @@ import { cn } from '@/lib/utils' @@ -8,7 +8,7 @@ import { cn } from '@/lib/utils'
import { Event, kinds } from 'nostr-tools'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import Image from '../Image'
import ArticleCardCoverImage from './ArticleCardCoverImage'
/**
* Feed / embed / preview surface for NIP-23 long-form (kind 30023): title, summary, image, tags no Show more body.
@ -93,13 +93,12 @@ export default function LongFormCard({ @@ -93,13 +93,12 @@ export default function LongFormCard({
return (
<div className={shellClass}>
<div className={cardClass} onClick={interactive ? handleCardClick : undefined}>
{metadata.image && autoLoadMedia && (
<Image
image={{ url: metadata.image, pubkey: event.pubkey }}
className="mb-3 aspect-video w-full max-w-[400px]"
hideIfError
/>
)}
<ArticleCardCoverImage
event={event}
imageUrl={metadata.image}
autoLoadMedia={autoLoadMedia}
layout="stacked"
/>
<div className="space-y-2">
{titleComponent}
{summaryComponent}
@ -115,14 +114,12 @@ export default function LongFormCard({ @@ -115,14 +114,12 @@ export default function LongFormCard({
<div className={cn('w-full min-w-0', shellClass)}>
<div className={cn(cardClass, 'min-w-0')} onClick={interactive ? handleCardClick : undefined}>
<div className="flex min-w-0 gap-4">
{metadata.image && autoLoadMedia && (
<Image
image={{ url: metadata.image, pubkey: event.pubkey }}
classNames={{ wrapper: 'w-auto max-w-[400px] shrink-0' }}
className="h-44 max-w-[400px] shrink rounded-lg bg-foreground object-cover aspect-[4/3] xl:aspect-video"
hideIfError
/>
)}
<ArticleCardCoverImage
event={event}
imageUrl={metadata.image}
autoLoadMedia={autoLoadMedia}
layout="row"
/>
<div className="min-w-0 flex-1 basis-0 space-y-2 overflow-hidden">
{titleComponent}
{summaryComponent}

28
src/components/Note/MarkdownArticle/MarkdownArticle.tsx

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
import { useSecondaryPageOptional, useSmartHashtagNavigationOptional, useSmartRelayNavigationOptional } from '@/PageManager'
import Image from '@/components/Image'
import UserAvatar from '@/components/UserAvatar'
import MediaPlayer from '@/components/MediaPlayer'
import Wikilink from '@/components/UniversalContent/Wikilink'
import { BookstrContent } from '@/components/Bookstr'
@ -5899,12 +5900,39 @@ export default function MarkdownArticle({ @@ -5899,12 +5900,39 @@ export default function MarkdownArticle({
<p className="break-words">{metadata.summary}</p>
</blockquote>
)}
{!hideMetadata &&
event.kind === kinds.LongFormArticle &&
!metadata.image?.trim() && (
<div className="not-prose my-4 flex max-w-[400px] justify-center rounded-lg bg-muted p-6">
<UserAvatar
userId={event.pubkey}
size="large"
deferRemoteAvatar={false}
className="!h-36 !w-36 rounded-xl"
/>
</div>
)}
{hideMetadata &&
metadata.title &&
event.kind !== ExtendedKind.DISCUSSION &&
!isNip52CalendarCardKind(event.kind) && (
<h2 className="text-2xl font-bold mb-4 leading-tight break-words">{metadata.title}</h2>
)}
{hideMetadata &&
metadata.title &&
event.kind === kinds.LongFormArticle &&
!metadata.image?.trim() &&
event.kind !== ExtendedKind.DISCUSSION &&
!isNip52CalendarCardKind(event.kind) && (
<div className="not-prose mb-4 flex max-w-[400px] justify-center rounded-lg bg-muted p-6">
<UserAvatar
userId={event.pubkey}
size="large"
deferRemoteAvatar={false}
className="!h-36 !w-36 rounded-xl"
/>
</div>
)}
{/* Metadata image */}
{!hideMetadata && metadata.image && (() => {

31
src/components/Note/WikiCard.tsx

@ -6,7 +6,7 @@ import { useContentPolicyOptional } from '@/providers/ContentPolicyProvider' @@ -6,7 +6,7 @@ import { useContentPolicyOptional } from '@/providers/ContentPolicyProvider'
import { useScreenSizeOptional } from '@/providers/ScreenSizeProvider'
import { Event, kinds } from 'nostr-tools'
import { useMemo } from 'react'
import Image from '../Image'
import ArticleCardCoverImage from './ArticleCardCoverImage'
export default function WikiCard({
event,
@ -60,13 +60,13 @@ export default function WikiCard({ @@ -60,13 +60,13 @@ export default function WikiCard({
className="cursor-pointer rounded-lg border p-4 hover:bg-muted/50 transition-colors"
onClick={handleCardClick}
>
{metadata.image && autoLoadMedia && (
<Image
image={{ url: metadata.image, pubkey: event.pubkey }}
className="w-full max-w-[400px] aspect-video mb-3"
hideIfError
/>
)}
<ArticleCardCoverImage
event={event}
imageUrl={metadata.image}
autoLoadMedia={autoLoadMedia}
layout="stacked"
hideImageIfError
/>
<div className="space-y-2">
{titleComponent}
{summaryComponent}
@ -84,14 +84,13 @@ export default function WikiCard({ @@ -84,14 +84,13 @@ export default function WikiCard({
onClick={handleCardClick}
>
<div className="flex gap-4">
{metadata.image && autoLoadMedia && (
<Image
image={{ url: metadata.image, pubkey: event.pubkey }}
classNames={{ wrapper: 'w-auto max-w-[400px] shrink-0' }}
className="rounded-lg aspect-[4/3] xl:aspect-video object-cover bg-foreground h-44 max-w-[400px]"
hideIfError
/>
)}
<ArticleCardCoverImage
event={event}
imageUrl={metadata.image}
autoLoadMedia={autoLoadMedia}
layout="row"
hideImageIfError
/>
<div className="flex-1 w-0 space-y-2">
{titleComponent}
{summaryComponent}

3
src/components/ReplyNoteList/index.tsx

@ -775,7 +775,8 @@ function ReplyNoteList({ @@ -775,7 +775,8 @@ function ReplyNoteList({
next.set(pkNorm, {
pubkey: pkNorm,
npub: pubkeyToNpub(pkNorm) ?? '',
username: formatPubkey(pkNorm)
username: formatPubkey(pkNorm),
batchPlaceholder: true
})
}
}

4
src/lib/relay-list-builder.ts

@ -386,6 +386,10 @@ export async function buildReplyReadRelayList( @@ -386,6 +386,10 @@ export async function buildReplyReadRelayList(
includeFastReadRelays: true,
includeSearchableRelays: true,
includeLocalRelays: true,
/** Same menu list as timelines — threads often opened from favorites. */
includeFavoriteRelays: Boolean(userPubkey),
/** FAST_READ + SEARCHABLE before author/user NIP-65 slices so broken personal relays do not starve thread REQ under the global connection cap. */
preferPublicReadRelaysEarly: true,
blockedRelays
})
}

4
src/services/client-replaceable-events.service.ts

@ -1143,7 +1143,9 @@ export class ReplaceableEventService { @@ -1143,7 +1143,9 @@ export class ReplaceableEventService {
profiles.push({
pubkey,
npub: pubkeyToNpub(pubkey) ?? '',
username: formatPubkey(pubkey)
username: formatPubkey(pubkey),
/** Lets {@link useFetchProfile} retry per-pubkey when batch REQ missed kind 0. */
batchPlaceholder: true
})
}
}

Loading…
Cancel
Save