1import { Fragment, useEffect } from 'react'; 2import React, { useMemo, useState } from 'react'; 3import { isAudioFile, readDir, dir, playFile } from '../../files.mjs'; 4 5export function FilesTab() { 6 const [path, setPath] = useState([]); 7 useEffect(() => { 8 let init = false; 9 readDir('', { dir, recursive: true }) 10 .then((children) => setPath([{ name: '~/music', children }])) 11 .catch((err) => { 12 console.log('error loadin files', err); 13 }); 14 return () => { 15 init = true; 16 }; 17 }, []); 18 const current = useMemo(() => path[path.length - 1], [path]); 19 const subpath = useMemo( 20 () => 21 path 22 .slice(1) 23 .map((p) => p.name) 24 .join('/'), 25 [path], 26 ); 27 const folders = useMemo(() => current?.children.filter((e) => !!e.children), [current]); 28 const files = useMemo(() => current?.children.filter((e) => !e.children && isAudioFile(e.name)), [current]); 29 const select = (e) => setPath((p) => p.concat([e])); 30 return ( 31 <div className="px-4 flex flex-col h-full"> 32 <div className="flex justify-between font-mono pb-1"> 33 <div> 34 <span>{`samples('`}</span> 35 {path?.map((p, i) => { 36 if (i < path.length - 1) { 37 return ( 38 <Fragment key={i}> 39 <span className="cursor-pointer underline" onClick={() => setPath((p) => p.slice(0, i + 1))}> 40 {p.name} 41 </span> 42 <span>/</span> 43 </Fragment> 44 ); 45 } else { 46 return ( 47 <span className="cursor-pointer underline" key={i}> 48 {p.name} 49 </span> 50 ); 51 } 52 })} 53 <span>{`')`}</span> 54 </div> 55 </div> 56 <div className="overflow-auto"> 57 {!folders?.length && !files?.length && <span className="text-gray-500">Nothing here</span>} 58 {folders?.map((e, i) => ( 59 <div className="cursor-pointer" key={i} onClick={() => select(e)}> 60 {e.name} 61 </div> 62 ))} 63 {files?.map((e, i) => ( 64 <div 65 className="text-gray-500 cursor-pointer select-none" 66 key={i} 67 onClick={async () => playFile(`${subpath}/${e.name}`)} 68 > 69 {e.name} 70 </div> 71 ))} 72 </div> 73 </div> 74 ); 75}