@@ -10,6 +10,7 @@ export interface WanderItem {
1010 title : string ;
1111 content : string ;
1212 cover ?: string ;
13+ video ?: string ;
1314 meta : any ;
1415}
1516
@@ -50,12 +51,45 @@ export async function getAllKnowledgeItems(): Promise<WanderItem[]> {
5051 cover = toAppAssetUrl ( absolutePath ) ;
5152 }
5253
54+ // Resolve video: check images/video.json first, then fall back to any .mp4 in images
55+ let video : string | undefined ;
56+ if ( meta . images ) {
57+ // Priority: images/video.json (structured metadata)
58+ const videoJsonPath = path . join ( redbookDir , dir . name , 'images' , 'video.json' ) ;
59+ try {
60+ const videoJsonContent = await fs . readFile ( videoJsonPath , 'utf-8' ) ;
61+ const videoJson = JSON . parse ( videoJsonContent ) ;
62+ if ( videoJson && videoJson . url ) {
63+ if ( videoJson . url . startsWith ( 'http' ) ) {
64+ video = videoJson . url ;
65+ } else {
66+ const absolutePath = path . join ( redbookDir , dir . name , videoJson . url ) ;
67+ video = toAppAssetUrl ( absolutePath ) ;
68+ }
69+ }
70+ } catch {
71+ // video.json not found, fall through to .mp4 scan
72+ }
73+
74+ // Fallback: scan images for .mp4
75+ if ( ! video ) {
76+ for ( const img of meta . images ) {
77+ if ( typeof img === 'string' && img . endsWith ( '.mp4' ) ) {
78+ const absolutePath = path . join ( redbookDir , dir . name , img ) ;
79+ video = toAppAssetUrl ( absolutePath ) ;
80+ break ;
81+ }
82+ }
83+ }
84+ }
85+
5386 items . push ( {
5487 id : dir . name ,
55- type : 'note' ,
88+ type : video ? 'video' : 'note' ,
5689 title : meta . title || 'Untitled Note' ,
5790 content : meta . content || '' ,
5891 cover,
92+ video,
5993 meta,
6094 } ) ;
6195 } catch {
0 commit comments