jevstrudel.git / website / src / repl / components / panel / FilesTab.jsx
FilesTab.jsx75 lines · 2.3 KB · raw
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}