@@ -8,6 +8,7 @@ class FileVault {
88 this . username = username ;
99 this . password = password ;
1010 this . index = null ;
11+ this . sharedIndex = null ;
1112 this . currentPath = '' ;
1213 this . repoURL = `https://raw.githubusercontent.com/${ username } /.zephyrus/master` ;
1314 }
@@ -29,6 +30,10 @@ class FileVault {
2930 const jsonString = new TextDecoder ( ) . decode ( decryptedBuffer ) ;
3031
3132 this . index = JSON . parse ( jsonString ) ;
33+
34+ // Also try to load the shared index
35+ await this . loadSharedIndex ( ) ;
36+
3237 return this . index ;
3338 } catch ( error ) {
3439 if ( error instanceof SyntaxError ) {
@@ -38,6 +43,62 @@ class FileVault {
3843 }
3944 }
4045
46+ /**
47+ * Fetch and decrypt the shared index
48+ */
49+ async loadSharedIndex ( ) {
50+ try {
51+ const sharedIndexUrl = `${ this . repoURL } /shared/.config/index` ;
52+ const response = await fetch ( sharedIndexUrl ) ;
53+
54+ if ( ! response . ok ) {
55+ // Shared index might not exist if no files have been shared
56+ console . log ( 'No shared index found' ) ;
57+ this . sharedIndex = null ;
58+ return ;
59+ }
60+
61+ const encryptedBuffer = await response . arrayBuffer ( ) ;
62+ const decryptedBuffer = await CRYPTO . decryptWithPassword ( encryptedBuffer , this . password ) ;
63+ const jsonString = new TextDecoder ( ) . decode ( decryptedBuffer ) ;
64+
65+ this . sharedIndex = JSON . parse ( jsonString ) ;
66+ console . log ( 'Shared index loaded:' , this . sharedIndex ) ;
67+ } catch ( error ) {
68+ console . warn ( 'Failed to load shared index:' , error ) ;
69+ this . sharedIndex = null ;
70+ }
71+ }
72+
73+ /**
74+ * Get all shared files
75+ */
76+ getSharedFiles ( ) {
77+ if ( ! this . sharedIndex || ! this . sharedIndex . files ) {
78+ return [ ] ;
79+ }
80+
81+ const entries = Object . values ( this . sharedIndex . files ) ;
82+ return entries . sort ( ( a , b ) => {
83+ const dateA = new Date ( a . shared_at || a . SharedAt || 0 ) ;
84+ const dateB = new Date ( b . shared_at || b . SharedAt || 0 ) ;
85+ return dateB - dateA ; // Most recent first
86+ } ) ;
87+ }
88+
89+ /**
90+ * Generate share link from shared entry
91+ */
92+ generateShareLink ( sharedEntry ) {
93+ const filename = sharedEntry . name || sharedEntry . Name || '' ;
94+ const encodedFilename = btoa ( filename ) ;
95+ const reference = sharedEntry . reference || sharedEntry . Reference ;
96+ const password = sharedEntry . password || sharedEntry . Password ;
97+
98+ // Format: username:reference:password:base64filename
99+ return `${ this . username } :${ reference } :${ password } :${ encodedFilename } ` ;
100+ }
101+
41102 /**
42103 * Get the current directory contents
43104 */
@@ -361,8 +422,66 @@ class FileBrowserUI {
361422 const fileList = document . getElementById ( 'fileList' ) ;
362423 fileList . innerHTML = '' ;
363424
364- if ( items . length === 0 ) {
365- fileList . innerHTML = `
425+ // If in root, show "Shared Files" section first
426+ if ( ! this . vault . currentPath && this . vault . sharedIndex ) {
427+ const sharedFiles = this . vault . getSharedFiles ( ) ;
428+ if ( sharedFiles . length > 0 ) {
429+ const sharedSection = document . createElement ( 'div' ) ;
430+ sharedSection . className = 'shared-files-section' ;
431+
432+ const header = document . createElement ( 'div' ) ;
433+ header . className = 'shared-files-header' ;
434+ header . innerHTML = `<span class="shared-files-toggle">▼</span> 📤 Your Shared Files (${ sharedFiles . length } )` ;
435+
436+ const listContainer = document . createElement ( 'div' ) ;
437+ listContainer . className = 'shared-files-list' ;
438+ listContainer . id = 'sharedFilesList' ;
439+
440+ // Add shared files to list
441+ for ( const shared of sharedFiles ) {
442+ const shareLink = this . vault . generateShareLink ( shared ) ;
443+ // Build correct URL: from /pages/files/ to /pages/shared/#hash
444+ const basePath = window . location . pathname . replace ( '/files/' , '/shared/' ) ;
445+ const shareUrl = `${ basePath } #${ shareLink } ` ;
446+
447+ const element = document . createElement ( 'div' ) ;
448+ element . className = 'file-item' ;
449+ element . innerHTML = `
450+ <div class="file-icon">📤</div>
451+ <div class="file-info">
452+ <div class="file-name">${ this . escapeHtml ( shared . name || shared . Name ) } </div>
453+ <div class="file-path">${ this . escapeHtml ( shared . original_path || shared . OriginalPath ) } </div>
454+ </div>
455+ <div class="file-actions">
456+ <button class="btn-secondary btn-small" onclick="fileBrowser.copyShareLink('${ this . escapeAttr ( shareUrl ) } ')">
457+ 🔗 Copy Link
458+ </button>
459+ </div>
460+ ` ;
461+ listContainer . appendChild ( element ) ;
462+ }
463+
464+ // Add separator after shared files
465+ const separator = document . createElement ( 'div' ) ;
466+ separator . className = 'shared-files-separator' ;
467+ listContainer . appendChild ( separator ) ;
468+
469+ // Toggle handler
470+ header . addEventListener ( 'click' , ( ) => {
471+ const toggle = header . querySelector ( '.shared-files-toggle' ) ;
472+ listContainer . classList . toggle ( 'visible' ) ;
473+ toggle . classList . toggle ( 'expanded' ) ;
474+ } ) ;
475+
476+ sharedSection . appendChild ( header ) ;
477+ sharedSection . appendChild ( listContainer ) ;
478+ fileList . appendChild ( sharedSection ) ;
479+ }
480+ }
481+
482+ // Show files and folders
483+ if ( items . length === 0 && ( ! this . vault . currentPath || ! this . vault . sharedIndex ) ) {
484+ fileList . innerHTML += `
366485 <div class="empty-state">
367486 <div class="empty-icon">📁</div>
368487 <div class="empty-text">This directory is empty</div>
@@ -438,6 +557,18 @@ class FileBrowserUI {
438557 }
439558 }
440559
560+ /**
561+ * Copy share link to clipboard
562+ */
563+ copyShareLink ( shareUrl ) {
564+ navigator . clipboard . writeText ( shareUrl ) . then ( ( ) => {
565+ this . showSuccess ( 'Share link copied to clipboard!' ) ;
566+ } ) . catch ( err => {
567+ console . error ( 'Failed to copy link:' , err ) ;
568+ this . showError ( 'Failed to copy link' ) ;
569+ } ) ;
570+ }
571+
441572 /**
442573 * Download and display a file
443574 */
0 commit comments