@@ -11,11 +11,93 @@ type SelectableListProps = {
1111export default function SelectableList ( { images } : SelectableListProps ) {
1212 const [ selected , setElement ] = useSelectedElement ( ) ;
1313
14+ React . useEffect ( ( ) => {
15+ const handleGlobalDragOver = ( event : DragEvent ) => {
16+ event . preventDefault ( ) ;
17+ event . dataTransfer ! . dropEffect = "copy" ;
18+ } ;
19+
20+ const handleGlobalDrop = ( event : DragEvent ) => {
21+ event . preventDefault ( ) ;
22+ } ;
23+
24+ document . addEventListener ( "dragover" , handleGlobalDragOver ) ;
25+ document . addEventListener ( "drop" , handleGlobalDrop ) ;
26+
27+ return ( ) => {
28+ document . removeEventListener ( "dragover" , handleGlobalDragOver ) ;
29+ document . removeEventListener ( "drop" , handleGlobalDrop ) ;
30+ } ;
31+ } , [ ] ) ;
32+
33+ const handleDrop = async ( event : React . DragEvent < HTMLButtonElement > , index : number ) => {
34+ event . preventDefault ( ) ;
35+ event . stopPropagation ( ) ;
36+
37+ let filePath : string | undefined ;
38+
39+ if ( event . dataTransfer . files [ 0 ] ?. path ) {
40+ filePath = event . dataTransfer . files [ 0 ] . path ;
41+ } else if ( event . dataTransfer . items [ 0 ] ?. getAsFile ( ) ) {
42+ const file = event . dataTransfer . items [ 0 ] . getAsFile ( ) ;
43+ if ( file ) {
44+ const reader = new FileReader ( ) ;
45+ reader . onload = async ( e ) => {
46+ if ( e . target ?. result ) {
47+ try {
48+ const image = await window . api . replaceImageWithData ( index , e . target . result as ArrayBuffer ) ;
49+ if ( image ) {
50+ setElement ( event . currentTarget , image ) ;
51+ }
52+ } catch ( error ) {
53+ console . error ( "Error replacing image:" , error ) ;
54+ }
55+ }
56+ } ;
57+ reader . readAsArrayBuffer ( file ) ;
58+ return ;
59+ }
60+ }
61+
62+ if ( ! filePath ) return ;
63+
64+ try {
65+ const image = await window . api . replaceImage ( index , filePath ) ;
66+ if ( image ) {
67+ setElement ( event . currentTarget , image ) ;
68+ }
69+ } catch ( error ) {
70+ console . error ( "Error replacing image:" , error ) ;
71+ }
72+ } ;
73+
74+ const handleDragOver = ( event : React . DragEvent < HTMLButtonElement > ) => {
75+ event . preventDefault ( ) ;
76+ event . stopPropagation ( ) ;
77+ } ;
78+
79+ const handleDragStart = ( event : React . DragEvent < HTMLButtonElement > , image : Image ) => {
80+ event . dataTransfer . setData ( "text/plain" , image . name ) ;
81+ event . dataTransfer . setData ( "text/uri-list" , `data:image/png;base64,${ image . data } ` ) ;
82+ event . dataTransfer . setData ( "image/png" , `data:image/png;base64,${ image . data } ` ) ;
83+ event . dataTransfer . setData ( "application/octet-stream" , `data:image/png;base64,${ image . data } ` ) ;
84+
85+ const img = new Image ( ) ;
86+ img . src = `data:image/png;base64,${ image . data } ` ;
87+ event . dataTransfer . setDragImage ( img , 0 , 0 ) ;
88+
89+ event . dataTransfer . effectAllowed = "copyMove" ;
90+ event . dataTransfer . setData ( "DownloadURL" , `image/png:${ image . name } :data:image/png;base64,${ image . data } ` ) ;
91+ } ;
92+
1493 return (
1594 < div className = { styles . list } >
1695 { images . map ( ( image , index ) => (
1796 < ImageButton
1897 onClick = { ( event ) => setElement ( event . currentTarget , image ) }
98+ onDrop = { ( event ) => handleDrop ( event , index ) }
99+ onDragOver = { handleDragOver }
100+ onDragStart = { ( event ) => handleDragStart ( event , image ) }
19101 id = { `btn-${ index } ` }
20102 image = { image }
21103 key = { `btn-${ index } ` }
0 commit comments