feat(playground): add session management and folder open icon in PlaygroundSidebar component

This commit is contained in:
ngc2207 2024-12-14 18:49:35 +08:00
parent 08831481b8
commit 20d790c5e0
4 changed files with 79 additions and 42 deletions

View File

@ -22,6 +22,7 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cross-fetch": "^4.0.0",
"devicons-react": "^1.4.0",
"gitea-js": "^1.22.0",
"jotai": "^2.10.3",
"lucide-react": "^0.468.0",

View File

@ -1,3 +1,5 @@
"use server";
import api from "@/lib/gitea";
import { GitEntry, APIError } from "gitea-js";

View File

@ -1,4 +1,5 @@
import { auth } from "@/auth";
"use client";
import * as React from "react";
import {
Sidebar,
@ -18,8 +19,10 @@ import {
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { retrieveTreeStructure } from "@/app/actions";
import { ChevronRight, File, Folder } from "lucide-react";
import { useSession } from "next-auth/react";
import { retrieveTreeStructure } from "@/actions";
import { COriginal, JavaOriginal } from "devicons-react";
import { ChevronRight, File, Folder, FolderOpen } from "lucide-react";
interface FileTree {
name: string;
@ -69,20 +72,32 @@ export function buildFileTree(tree: GitEntry[]): FileTree {
return root;
}
export async function PlaygroundSidebar({
export function PlaygroundSidebar({
...props
}: React.ComponentProps<typeof Sidebar>) {
const session = await auth();
const { data: session } = useSession();
const [fileTree, setFileTree] = React.useState<FileTree>({
name: "",
type: "tree",
children: {},
});
const username = session?.user?.name ?? "";
let fileTree: FileTree = { name: "", type: "tree", children: {} };
React.useEffect(() => {
async function fetchFileTree() {
if (username) {
const tree: GitEntry[] = await retrieveTreeStructure(
username,
"playground",
"main"
);
fileTree = buildFileTree(tree);
const newFileTree = buildFileTree(tree);
setFileTree(newFileTree);
}
}
fetchFileTree();
}, [username]);
return (
<Sidebar {...props}>
@ -106,10 +121,22 @@ export async function PlaygroundSidebar({
function Tree({ item }: { item: FileTree }) {
const { name, type, children } = item;
const fileExtension = name.split(".").pop();
let fileIcon = <File />;
if (fileExtension === "c") {
fileIcon = <COriginal />;
} else if (fileExtension === "java") {
fileIcon = <JavaOriginal />;
}
const [isOpen, setIsOpen] = React.useState(false);
if (type === "blob") {
return (
<SidebarMenuButton className="data-[active=true]:bg-transparent">
<File />
{fileIcon}
{name}
</SidebarMenuButton>
);
@ -117,11 +144,15 @@ function Tree({ item }: { item: FileTree }) {
return (
<SidebarMenuItem>
<Collapsible className="group/collapsible [&[data-state=open]>button>svg:first-child]:rotate-90">
<Collapsible
open={isOpen}
onOpenChange={setIsOpen}
className="group/collapsible [&[data-state=open]>button>svg:first-child]:rotate-90"
>
<CollapsibleTrigger asChild>
<SidebarMenuButton>
<ChevronRight className="transition-transform" />
<Folder />
{isOpen ? <FolderOpen /> : <Folder />}
{name}
</SidebarMenuButton>
</CollapsibleTrigger>

View File

@ -9,6 +9,7 @@ import {
BreadcrumbList,
BreadcrumbPage,
} from "@/components/ui/breadcrumb";
import { SessionProvider } from "next-auth/react";
import { Separator } from "@/components/ui/separator";
import { ModeSwitcher } from "@/components/mode-switcher";
import LanguageSwitcher from "@/components/language-switcher";
@ -18,6 +19,7 @@ export default function PlaygroundLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
return (
<SessionProvider>
<SidebarProvider>
<PlaygroundSidebar />
<SidebarInset>
@ -43,5 +45,6 @@ export default function PlaygroundLayout({
{children}
</SidebarInset>
</SidebarProvider>
</SessionProvider>
);
}