22import { html , useCallback , useEffect , useMemo , useRef , useState } from '../vendor/preact-htm.js' ;
33import { getLocalStorageBoolean , getLocalStorageItem , getLocalStorageNumber , setLocalStorageItem } from '../utils/storage.js' ;
44import {
5- attachWorkspaceFile ,
65 createWorkspaceFile ,
76 deleteWorkspaceFile ,
8- getMediaInfo ,
9- getMediaUrl ,
107 getWorkspaceDownloadUrl ,
118 getWorkspaceFile ,
9+ getWorkspaceFileDownloadUrl ,
1210 getWorkspaceTree ,
1311 moveWorkspaceEntry ,
1412 renameWorkspaceFile ,
@@ -524,40 +522,16 @@ function FolderStarburstChart({ payload }) {
524522 ` ;
525523}
526524
527- // ── FileAttachmentCard ────────────────────────────────────────────────────────
528-
529- function FileAttachmentCard ( { mediaId } ) {
530- const [ info , setInfo ] = useState ( null ) ;
531- useEffect ( ( ) => {
532- if ( ! mediaId ) return ;
533- getMediaInfo ( mediaId ) . then ( setInfo ) . catch ( ( ) => {
534- /* expected: attachment metadata is best-effort for workspace cards. */
535- } ) ;
536- } , [ mediaId ] ) ;
537- if ( ! info ) return null ;
538- const filename = info . filename || 'file' ;
539- const sizeStr = info . metadata ?. size ? formatFileSize ( info . metadata . size ) : '' ;
540- return html `
541- < a href =${ getMediaUrl ( mediaId ) } download =${ filename } class="file-attachment"
542- onClick=${ ( e ) => e . stopPropagation ( ) } >
543- < svg class ="file-icon " viewBox ="0 0 24 24 " fill ="none " stroke ="currentColor " stroke-width ="2 ">
544- < path d ="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z "/>
545- < polyline points ="14 2 14 8 20 8 "/>
546- < line x1 ="16 " y1 ="13 " x2 ="8 " y2 ="13 "/>
547- < line x1 ="16 " y1 ="17 " x2 ="8 " y2 ="17 "/>
548- < polyline points ="10 9 9 9 8 9 "/>
549- </ svg >
550- < div class ="file-info ">
551- < span class ="file-name "> ${ filename } </ span >
552- ${ sizeStr && html `< span class ="file-size "> ${ sizeStr } </ span > ` }
553- </ div >
554- < svg class ="download-icon " viewBox ="0 0 24 24 " fill ="none " stroke ="currentColor " stroke-width ="2 ">
555- < path d ="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4 "/>
556- < polyline points ="7 10 12 15 17 10 "/>
557- < line x1 ="12 " y1 ="15 " x2 ="12 " y2 ="3 "/>
558- </ svg >
559- </ a >
560- ` ;
525+ function triggerWorkspaceDownload ( url ) {
526+ if ( typeof document === 'undefined' || ! url ) return ;
527+ const link = document . createElement ( 'a' ) ;
528+ link . href = url ;
529+ link . setAttribute ( 'download' , '' ) ;
530+ link . rel = 'noopener' ;
531+ link . style . display = 'none' ;
532+ document . body . appendChild ( link ) ;
533+ link . click ( ) ;
534+ link . remove ( ) ;
561535}
562536
563537// ── WorkspaceExplorer ─────────────────────────────────────────────────────────
@@ -579,7 +553,7 @@ export function WorkspaceExplorer({
579553 const [ renamingPath , setRenamingPath ] = useState ( null ) ;
580554 const [ renameValue , setRenameValue ] = useState ( '' ) ;
581555 const [ preview , setPreview ] = useState ( null ) ;
582- const [ downloadId , setDownloadId ] = useState ( null ) ;
556+ const [ , setDownloadId ] = useState ( null ) ;
583557 const [ initialLoad , setInitialLoad ] = useState ( true ) ;
584558 const [ loadingPreview , setLoadingPreview ] = useState ( false ) ;
585559 const [ error , setError ] = useState ( null ) ;
@@ -1756,15 +1730,10 @@ export function WorkspaceExplorer({
17561730 document . addEventListener ( 'touchcancel' , onUp ) ;
17571731 } ) . current ;
17581732
1759- const handleDownload = async ( ) => {
1760- if ( ! selectedPath ) return ;
1761- try {
1762- const res = await attachWorkspaceFile ( selectedPath ) ;
1763- if ( res . media_id ) setDownloadId ( res . media_id ) ;
1764- } catch ( err ) {
1765- setPreview ( prev => ( { ...( prev || { } ) , error : err . message || 'Failed to attach' } ) ) ;
1766- }
1767- } ;
1733+ const handleDownload = useCallback ( ( path = selectedPath ) => {
1734+ if ( ! path ) return ;
1735+ triggerWorkspaceDownload ( getWorkspaceFileDownloadUrl ( path ) ) ;
1736+ } , [ selectedPath ] ) ;
17681737
17691738 const handleDeleteFile = async ( ) => {
17701739 if ( ! selectedPath || selectedIsDir ) return ;
@@ -1967,9 +1936,7 @@ export function WorkspaceExplorer({
19671936 const handleMenuDownloadFolder = useCallback ( ( ) => {
19681937 if ( ! selectedFolderDownloadUrl ) return ;
19691938 closeHeaderMenu ( ) ;
1970- if ( typeof window !== 'undefined' ) {
1971- window . open ( selectedFolderDownloadUrl , '_blank' , 'noopener' ) ;
1972- }
1939+ triggerWorkspaceDownload ( selectedFolderDownloadUrl ) ;
19731940 } , [ closeHeaderMenu , selectedFolderDownloadUrl ] ) ;
19741941
19751942 const handleMenuOpenTerminalTab = useCallback ( ( ) => {
@@ -2320,7 +2287,7 @@ export function WorkspaceExplorer({
23202287 < line x1 ="12 " y1 ="3 " x2 ="12 " y2 ="15 "/>
23212288 </ svg >
23222289 </ button >
2323- < a class ="workspace-download " href =${ getWorkspaceDownloadUrl ( selectedPath , showHidden ) }
2290+ < a class ="workspace-download " href =${ getWorkspaceDownloadUrl ( selectedPath , showHidden ) } download
23242291 title ="Download folder as zip " onClick =${ ( e ) => e . stopPropagation ( ) } >
23252292 < svg viewBox ="0 0 24 24 " fill ="none " stroke ="currentColor " stroke-width ="2 "
23262293 stroke-linecap ="round " stroke-linejoin ="round " aria-hidden ="true ">
@@ -2329,14 +2296,15 @@ export function WorkspaceExplorer({
23292296 < line x1 ="12 " y1 ="15 " x2 ="12 " y2 ="3 "/>
23302297 </ svg >
23312298 </ a > `
2332- : html `< button class ="workspace-download " onClick =${ handleDownload } title ="Download">
2299+ : html `< a class ="workspace-download " href =${ getWorkspaceFileDownloadUrl ( selectedPath ) } download
2300+ title ="Download " onClick =${ ( e ) => e . stopPropagation ( ) } >
23332301 < svg viewBox ="0 0 24 24 " fill ="none " stroke ="currentColor " stroke-width ="2 "
23342302 stroke-linecap ="round " stroke-linejoin ="round " aria-hidden ="true ">
23352303 < path d ="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4 "/>
23362304 < polyline points ="7 10 12 15 17 10 "/>
23372305 < line x1 ="12 " y1 ="15 " x2 ="12 " y2 ="3 "/>
23382306 </ svg >
2339- </ button > ` }
2307+ </ a > ` }
23402308 </ div >
23412309 </ div >
23422310 ${ loadingPreview && html `< div class ="workspace-loading "> Loading preview…</ div > ` }
@@ -2355,11 +2323,6 @@ export function WorkspaceExplorer({
23552323 ${ preview && ! preview . error && ! selectedIsDir && html `
23562324 < div class ="workspace-preview-body " ref =${ previewPaneHostRef } > </ div >
23572325 ` }
2358- ${ downloadId && html `
2359- < div class ="workspace-download-card ">
2360- < ${ FileAttachmentCard } mediaId =${ downloadId } />
2361- </ div >
2362- ` }
23632326 </ div >
23642327 ` }
23652328 ${ dragGhost && html `
0 commit comments