refactor: rework assets fetching
This commit is contained in:
@@ -116,7 +116,6 @@ const InnerCava = (props: InnerKittyProps<typeof Cava>) => {
|
||||
const analyser = audioContext.createAnalyser();
|
||||
analyser.fftSize = 256;
|
||||
|
||||
console.log("ok");
|
||||
void audioElement.play().then(() => void audioContext.resume());
|
||||
|
||||
if (!sourceRef.current) {
|
||||
@@ -132,7 +131,7 @@ const InnerCava = (props: InnerKittyProps<typeof Cava>) => {
|
||||
return () => {
|
||||
if (requestRef.current) cancelAnimationFrame(requestRef.current);
|
||||
};
|
||||
}, [props.cols, props.audio]);
|
||||
}, [props.cols, props.audio, calculateBarHeights]);
|
||||
|
||||
return barHeights.map((value, i) => (
|
||||
<FrequencyBar key={i} value={value} max={255 / 2} height={props.rows} />
|
||||
|
||||
@@ -1,41 +1,9 @@
|
||||
import axios from "axios";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export const NvimEditor = (props: { source: string | undefined }) => {
|
||||
const [cache, setCache] = useState(new Map<string, string>());
|
||||
const [data, setData] = useState<string>();
|
||||
const [loading, setLoading] = useState(false);
|
||||
import { useState } from "react";
|
||||
|
||||
export const NvimEditor = (props: { content: string | undefined }) => {
|
||||
const [selectedLine, setSelectedLine] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.source) return;
|
||||
|
||||
const cached = cache.get(props.source);
|
||||
if (cached) {
|
||||
console.log("cache hit");
|
||||
setData(cached);
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
axios
|
||||
.get<string>(props.source)
|
||||
.then(({ data }) => {
|
||||
setData(data);
|
||||
setLoading(false);
|
||||
|
||||
setCache((cache) => {
|
||||
cache.set(props.source!, data);
|
||||
return cache;
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}, [props.source]);
|
||||
|
||||
let rows = data?.split("\n") ?? [];
|
||||
let rows = props.content?.split("\n") ?? [];
|
||||
// trim end empty lines
|
||||
for (let i = rows.length - 1; i >= 0; i--) {
|
||||
if (rows[i].trim().length === 0) {
|
||||
@@ -51,9 +19,7 @@ export const NvimEditor = (props: { source: string | undefined }) => {
|
||||
}
|
||||
}
|
||||
|
||||
return loading ? (
|
||||
<p>Loading...</p>
|
||||
) : (
|
||||
return (
|
||||
<table>
|
||||
<tbody>
|
||||
{rows.map((row, i) => (
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { ICONS, getIcon } from "~/utils/icons";
|
||||
import { DEFAULT_ICON } from "~/utils/icons";
|
||||
import { type Icon } from "~/utils/tree";
|
||||
|
||||
export const NvimStatusBar = (props: {
|
||||
label: string;
|
||||
labelColor: string;
|
||||
fileIcon?: string;
|
||||
fileName: string;
|
||||
fileIcon?: Icon;
|
||||
fileName?: string;
|
||||
}) => (
|
||||
<div className="select-none bg-[#29293c]">
|
||||
<span className="text-[#272332]" style={{ background: props.labelColor }}>
|
||||
@@ -15,14 +16,8 @@ export const NvimStatusBar = (props: {
|
||||
</span>
|
||||
<span className="bg-[#474353] text-[#373040]">{"\ue0ba"}</span>
|
||||
<span className="bg-[#373040]">{` ${
|
||||
getIcon({
|
||||
type: "file",
|
||||
name: props.fileName,
|
||||
icon: props.fileIcon,
|
||||
fileName: props.fileName,
|
||||
repo: "",
|
||||
}).char
|
||||
}${props.fileName} `}</span>
|
||||
props.fileIcon?.char ?? DEFAULT_ICON.char
|
||||
}${props.fileName ?? "Empty"} `}</span>
|
||||
<span className="bg-[#373040] text-[#29293c]">{"\ue0ba"}</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
34
src/components/Nvim/NvimTree/NvimTreeChild.tsx
Normal file
34
src/components/Nvim/NvimTree/NvimTreeChild.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import { DEFAULT_ICON } from "~/utils/icons";
|
||||
import { type Child } from "~/utils/tree";
|
||||
|
||||
export const NvimTreeChild = (props: {
|
||||
child: Child;
|
||||
y: number;
|
||||
selected: boolean;
|
||||
inDirectory: boolean | "last";
|
||||
onSelect: (y: number) => void;
|
||||
onOpen: (file: Child) => void;
|
||||
}) => {
|
||||
const icon = props.child.icon ?? DEFAULT_ICON;
|
||||
|
||||
return (
|
||||
<li
|
||||
style={{ background: props.selected ? "#504651" : "" }}
|
||||
onMouseDown={() => props.onSelect(props.y)}
|
||||
onDoubleClick={() => props.onOpen(props.child)}
|
||||
>
|
||||
{" "}
|
||||
{props.inDirectory && (
|
||||
<span className="text-[#5b515b]">
|
||||
{props.inDirectory === "last" ? "└ " : "│ "}
|
||||
</span>
|
||||
)}
|
||||
<span style={{ color: icon.color }}>{`${icon.char}`}</span>
|
||||
{props.child.name === "README.md" ? (
|
||||
<span className="font-bold text-[#d8c5a1]">README.md</span>
|
||||
) : (
|
||||
<span>{props.child.name}</span>
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
};
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Directory } from "~/utils/types";
|
||||
import { type Folder } from "~/utils/tree";
|
||||
|
||||
export const NvimTreeDirectory = (props: {
|
||||
directory: Directory;
|
||||
directory: Folder;
|
||||
y: number;
|
||||
selected: boolean;
|
||||
onSelect: (y: number) => void;
|
||||
onOpen: (directory: Directory) => void;
|
||||
onOpen: (directory: Folder) => void;
|
||||
}) => (
|
||||
<li
|
||||
className="text-[#a0b6ee]"
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { getIcon } from "~/utils/icons";
|
||||
import { File } from "~/utils/types";
|
||||
|
||||
export const NvimTreeFile = (props: {
|
||||
file: File;
|
||||
y: number;
|
||||
selected: boolean;
|
||||
inDirectory: boolean | "last";
|
||||
onSelect: (y: number) => void;
|
||||
onOpen: (file: File) => void;
|
||||
}) => (
|
||||
<li
|
||||
style={{ background: props.selected ? "#504651" : "" }}
|
||||
onMouseDown={() => props.onSelect(props.y)}
|
||||
onDoubleClick={() => props.onOpen(props.file)}
|
||||
>
|
||||
{" "}
|
||||
{props.inDirectory && (
|
||||
<span className="text-[#5b515b]">
|
||||
{props.inDirectory === "last" ? "└ " : "│ "}
|
||||
</span>
|
||||
)}
|
||||
<span style={{ color: getIcon(props.file).color }}>{`${
|
||||
getIcon(props.file).char
|
||||
}`}</span>
|
||||
{props.file.name === "README.md" ? (
|
||||
<span className="font-bold text-[#d8c5a1]">README.md</span>
|
||||
) : (
|
||||
<span>{props.file.name}</span>
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
@@ -1,65 +1,44 @@
|
||||
import { useApp } from "~/hooks/useApp";
|
||||
import { CHAR_HEIGHT, CHAR_WIDTH } from "../../Kitty";
|
||||
import { type ReactNode, useEffect, useState } from "react";
|
||||
import {
|
||||
type File,
|
||||
type InnerKittyProps,
|
||||
type RootManifest,
|
||||
type Directory,
|
||||
} from "~/utils/types";
|
||||
import { type InnerKittyProps } from "~/utils/types";
|
||||
import { type Nvim } from "..";
|
||||
import { NvimTreeDirectory } from "./NvimTreeDirectory";
|
||||
import { NvimTreeFile } from "./NvimTreeFile";
|
||||
import { NvimTreeChild } from "./NvimTreeChild";
|
||||
import { assets } from "~/assets";
|
||||
import { getIcon } from "~/utils/icons";
|
||||
import {
|
||||
file,
|
||||
folder,
|
||||
project,
|
||||
sortFiles,
|
||||
link,
|
||||
type Child,
|
||||
} from "~/utils/tree";
|
||||
|
||||
const sortFiles = (files: Array<File | Directory>) =>
|
||||
files
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
.sort((a, b) =>
|
||||
a.type === "directory" && b.type !== "directory"
|
||||
? -1
|
||||
: a.type !== "directory" && b.type === "directory"
|
||||
? 1
|
||||
: 0,
|
||||
);
|
||||
|
||||
const manifestToTree = (manifest: RootManifest) =>
|
||||
const buildTree = () =>
|
||||
sortFiles([
|
||||
{
|
||||
type: "directory",
|
||||
name: "links",
|
||||
opened: false,
|
||||
files: manifest.links.map((link) => ({
|
||||
type: "link" as const,
|
||||
...link,
|
||||
})),
|
||||
},
|
||||
{
|
||||
type: "directory",
|
||||
name: "projects",
|
||||
opened: false,
|
||||
files: manifest.projects.map((project) => ({
|
||||
type: "file" as const,
|
||||
repo: project.name,
|
||||
fileName: "README.md",
|
||||
...project,
|
||||
})),
|
||||
},
|
||||
...manifest.files.map((file) => ({
|
||||
type: "file" as const,
|
||||
name: file,
|
||||
repo: "pihkaal",
|
||||
fileName: file,
|
||||
})),
|
||||
folder(
|
||||
"links",
|
||||
assets.links.map((l) => link(l.name, l.url, l.icon)),
|
||||
),
|
||||
folder(
|
||||
"projects",
|
||||
assets.projects.map((p) =>
|
||||
project(p.name, p.content, p.url, p.language, p.private),
|
||||
),
|
||||
),
|
||||
file("README.md", "hey", getIcon("README.md")),
|
||||
]);
|
||||
|
||||
export const NvimTree = (
|
||||
props: InnerKittyProps<typeof Nvim> & {
|
||||
onOpen: (file: File) => void;
|
||||
onOpen: (file: Child) => void;
|
||||
},
|
||||
) => {
|
||||
const { rootManifest, activeKitty } = useApp();
|
||||
const { activeKitty } = useApp();
|
||||
|
||||
const [files, setFiles] = useState(manifestToTree(rootManifest));
|
||||
const [files, setFiles] = useState(buildTree());
|
||||
const [selectedY, setSelectedY] = useState(0);
|
||||
|
||||
const tree: Array<ReactNode> = [];
|
||||
@@ -67,7 +46,7 @@ export const NvimTree = (
|
||||
let selectedFile = files[0];
|
||||
for (const file of files) {
|
||||
if (selectedY === y) selectedFile = file;
|
||||
if (file.type === "directory") {
|
||||
if (file.type === "folder") {
|
||||
tree.push(
|
||||
<NvimTreeDirectory
|
||||
key={y}
|
||||
@@ -83,15 +62,15 @@ export const NvimTree = (
|
||||
);
|
||||
|
||||
if (file.opened) {
|
||||
file.files.forEach((childFile, i) => {
|
||||
file.children.forEach((child, i) => {
|
||||
y++;
|
||||
if (selectedY === y) selectedFile = childFile;
|
||||
if (selectedY === y) selectedFile = child;
|
||||
tree.push(
|
||||
<NvimTreeFile
|
||||
<NvimTreeChild
|
||||
key={y}
|
||||
file={childFile}
|
||||
child={child}
|
||||
y={y}
|
||||
inDirectory={i === file.files.length - 1 ? "last" : true}
|
||||
inDirectory={i === file.children.length - 1 ? "last" : true}
|
||||
selected={selectedY === y}
|
||||
onSelect={setSelectedY}
|
||||
onOpen={props.onOpen}
|
||||
@@ -101,9 +80,9 @@ export const NvimTree = (
|
||||
}
|
||||
} else {
|
||||
tree.push(
|
||||
<NvimTreeFile
|
||||
<NvimTreeChild
|
||||
key={y}
|
||||
file={file}
|
||||
child={file}
|
||||
y={y}
|
||||
inDirectory={false}
|
||||
selected={selectedY === y}
|
||||
@@ -129,7 +108,7 @@ export const NvimTree = (
|
||||
break;
|
||||
|
||||
case "Enter":
|
||||
if (selectedFile.type === "directory") {
|
||||
if (selectedFile.type === "folder") {
|
||||
selectedFile.opened = !selectedFile.opened;
|
||||
setFiles([...files]);
|
||||
} else {
|
||||
|
||||
@@ -5,30 +5,27 @@ import { NvimInput } from "./NvimInput";
|
||||
import { NvimStatusBar } from "./NvimStatusBar";
|
||||
import { NvimTree } from "./NvimTree";
|
||||
import { useState } from "react";
|
||||
import { File, InnerKittyProps } from "~/utils/types";
|
||||
import { type InnerKittyProps } from "~/utils/types";
|
||||
import { type Child, type Icon } from "~/utils/tree";
|
||||
|
||||
export const Nvim = (_props: {}) => {
|
||||
export const Nvim = (_props: unknown) => {
|
||||
const kitty = useKitty();
|
||||
|
||||
return kitty && <InnerNvimTree {...kitty} />;
|
||||
};
|
||||
|
||||
const InnerNvimTree = (props: InnerKittyProps<typeof Nvim>) => {
|
||||
const [activeFile, setActiveFile] = useState<{
|
||||
const [activeChild, setActiveChild] = useState<{
|
||||
name: string;
|
||||
url: string;
|
||||
icon?: string;
|
||||
content: string;
|
||||
icon: Icon;
|
||||
}>();
|
||||
|
||||
const handleOpenFile = (file: File) => {
|
||||
if (file.type === "link") {
|
||||
window.open(file.url, "_blank")?.focus();
|
||||
const handleOpenChild = (child: Child) => {
|
||||
if (child.type === "link") {
|
||||
window.open(child.url, "_blank")?.focus();
|
||||
} else {
|
||||
setActiveFile({
|
||||
name: file.repo === "pihkaal" ? file.fileName : file.repo,
|
||||
icon: file.icon,
|
||||
url: `https://raw.githubusercontent.com/pihkaal/${file.repo}/main/${file.fileName}`,
|
||||
});
|
||||
setActiveChild(child);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -43,7 +40,7 @@ const InnerNvimTree = (props: InnerKittyProps<typeof Nvim>) => {
|
||||
}}
|
||||
>
|
||||
<div style={{ gridArea: "1 / 1 / 1 / 2" }}>
|
||||
<NvimTree {...props} onOpen={handleOpenFile} />
|
||||
<NvimTree {...props} onOpen={handleOpenChild} />
|
||||
</div>
|
||||
<div
|
||||
className="overflow-y-auto break-all"
|
||||
@@ -53,14 +50,14 @@ const InnerNvimTree = (props: InnerKittyProps<typeof Nvim>) => {
|
||||
wordWrap: "break-word",
|
||||
}}
|
||||
>
|
||||
<NvimEditor source={activeFile?.url} />
|
||||
<NvimEditor content={activeChild?.content} />
|
||||
</div>
|
||||
<div style={{ gridArea: "2 / 1 / 2 / 3" }}>
|
||||
<NvimStatusBar
|
||||
label=" NORMAL"
|
||||
labelColor="#7ea7ca"
|
||||
fileIcon={activeFile?.icon}
|
||||
fileName={activeFile?.name ?? `NvimTree_1`}
|
||||
fileIcon={activeChild?.icon}
|
||||
fileName={activeChild?.name}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ gridArea: "3 / 1 / 3 / 3" }}>
|
||||
|
||||
Reference in New Issue
Block a user