7 changed files with 85 additions and 8 deletions
@ -1,12 +1,21 @@
@@ -1,12 +1,21 @@
|
||||
import { Event } from 'nostr-tools' |
||||
import Content from '../Content' |
||||
|
||||
export default function VideoNote({ event, className }: { event: Event; className?: string }) { |
||||
export default function VideoNote({ |
||||
event, |
||||
className, |
||||
loadMedia = false |
||||
}: { |
||||
event: Event |
||||
className?: string |
||||
/** When true (note detail / expanded view), long-form video may autoload. */ |
||||
loadMedia?: boolean |
||||
}) { |
||||
// Content component already handles all media rendering (from content and tags)
|
||||
// with proper deduplication, so we don't need to add anything extra
|
||||
return ( |
||||
<div className={className}> |
||||
<Content event={event} /> |
||||
<Content event={event} mustLoadMedia={loadMedia} /> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
import { describe, expect, it } from 'vitest' |
||||
import { ExtendedKind } from '@/constants' |
||||
import type { Event } from 'nostr-tools' |
||||
import { |
||||
isLongFormNip71VideoEventKind, |
||||
shouldDeferLongVideoAutoload |
||||
} from './long-video-load-policy' |
||||
|
||||
function fakeEvent(kind: number): Event { |
||||
return { kind, id: 'ab'.repeat(32), pubkey: 'cd'.repeat(32), created_at: 0, tags: [], content: '' } |
||||
} |
||||
|
||||
describe('long-video-load-policy', () => { |
||||
it('treats kind 21 and 34235 as long-form', () => { |
||||
expect(isLongFormNip71VideoEventKind(ExtendedKind.VIDEO)).toBe(true) |
||||
expect(isLongFormNip71VideoEventKind(ExtendedKind.VIDEO_ADDRESSABLE)).toBe(true) |
||||
expect(isLongFormNip71VideoEventKind(ExtendedKind.SHORT_VIDEO)).toBe(false) |
||||
}) |
||||
|
||||
it('defers autoload for long-form events unless forced', () => { |
||||
expect(shouldDeferLongVideoAutoload(fakeEvent(ExtendedKind.VIDEO))).toBe(true) |
||||
expect( |
||||
shouldDeferLongVideoAutoload(fakeEvent(ExtendedKind.VIDEO), { forceLoadMedia: true }) |
||||
).toBe(false) |
||||
expect(shouldDeferLongVideoAutoload(fakeEvent(ExtendedKind.SHORT_VIDEO))).toBe(false) |
||||
}) |
||||
}) |
||||
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
import { ExtendedKind } from '@/constants' |
||||
import type { Event } from 'nostr-tools' |
||||
|
||||
/** Long-form video threshold (matches publish-time kind 21 vs 22 split). */ |
||||
export const LONG_VIDEO_MIN_DURATION_SEC = 600 |
||||
|
||||
/** NIP-71 kinds published for videos longer than {@link LONG_VIDEO_MIN_DURATION_SEC}. */ |
||||
export function isLongFormNip71VideoEventKind(kind: number): boolean { |
||||
return kind === ExtendedKind.VIDEO || kind === ExtendedKind.VIDEO_ADDRESSABLE |
||||
} |
||||
|
||||
/** |
||||
* Feed / timeline: do not fetch long-form video bytes until the user opts in. |
||||
* Detail views pass `forceLoadMedia` / `mustLoadMedia` to bypass this. |
||||
*/ |
||||
export function shouldDeferLongVideoAutoload( |
||||
event: Event | null | undefined, |
||||
options?: { forceLoadMedia?: boolean } |
||||
): boolean { |
||||
if (options?.forceLoadMedia) return false |
||||
if (!event) return false |
||||
return isLongFormNip71VideoEventKind(event.kind) |
||||
} |
||||
Loading…
Reference in new issue