feat: add directory navigator

This commit is contained in:
WH64 2025-03-20 23:22:46 +09:00
parent ca8300b27c
commit f0a94070d2
12 changed files with 90 additions and 53 deletions

2
go.mod
View file

@ -7,6 +7,7 @@ require (
github.com/gin-contrib/static v1.1.3 github.com/gin-contrib/static v1.1.3
github.com/gin-gonic/gin v1.10.0 github.com/gin-gonic/gin v1.10.0
github.com/mattn/go-sqlite3 v1.14.24 github.com/mattn/go-sqlite3 v1.14.24
golang.org/x/term v0.30.0
) )
require ( require (
@ -33,7 +34,6 @@ require (
golang.org/x/crypto v0.36.0 // indirect golang.org/x/crypto v0.36.0 // indirect
golang.org/x/net v0.37.0 // indirect golang.org/x/net v0.37.0 // indirect
golang.org/x/sys v0.31.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/term v0.30.0 // indirect
golang.org/x/text v0.23.0 // indirect golang.org/x/text v0.23.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect

View file

@ -1,6 +1,17 @@
.ka-view { .ka-view {
width: 100%; width: 100%;
height: 100%; height: 100%;
animation: fadeIn 0.3s ease-in-out;
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
} }
.ka-nav { .ka-nav {
@ -44,6 +55,12 @@
span { span {
margin-left: 10px; margin-left: 10px;
} }
.username {
@media (max-width: 640px) {
display: none;
}
}
} }
.login-btn { .login-btn {

View file

@ -1,19 +1,18 @@
import Login from "./components/login";
import Logout from "./components/logout";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import Settings from "./components/settings";
import { useVersion } from "./store/version"; import { useVersion } from "./store/version";
import NotFound from "./components/notfound";
import FileView from "./components/file-view"; import FileView from "./components/file-view";
import Directory from "./components/directory"; import Directory from "./components/directory";
import { DirEntry, usePath } from "./store/path"; import { DirEntry, usePath } from "./store/path";
import { DynamicIcon } from "lucide-react/dynamic"; import { DynamicIcon } from "lucide-react/dynamic";
import { BrowserRouter, Route, Routes, useLocation } from "react-router"; import { BrowserRouter, Route, Routes, useLocation } from "react-router";
import { AccountData, useAuthStore } from "./store/auth";
import "./App.scss"; import "./App.scss";
import kuma from "./assets/kuma.png"; import kuma from "./assets/kuma.png";
import NotFound from "./components/notfound";
import Login from "./components/login";
import { AccountData, useAuthStore } from "./store/auth";
import Logout from "./components/logout";
import Settings from "./components/settings";
import { FileNavigator } from "./components/navigation";
function App() { function App() {
return ( return (
@ -32,7 +31,6 @@ function Dashboard({ children }: { children: React.ReactNode }) {
return ( return (
<main className="container-md ka-view"> <main className="container-md ka-view">
<Header /> <Header />
<FileNavigator />
{children} {children}
<Footer /> <Footer />
</main> </main>
@ -125,7 +123,7 @@ function Header() {
<DynamicIcon name="settings" size={15} /> <DynamicIcon name="settings" size={15} />
</a> </a>
<div className="login-info"> <div className="login-info">
<span>Logged in as {username}</span> <span className="username">Logged in as {username}</span>
<a className="login-btn" href="/logout"> <a className="login-btn" href="/logout">
Logout Logout
</a> </a>

View file

@ -2,7 +2,6 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
margin-top: 1rem;
flex-direction: column; flex-direction: column;
border-bottom: 1px solid var(--foreground); border-bottom: 1px solid var(--foreground);

View file

@ -6,6 +6,7 @@ import "./directory.scss";
import Markdown from "react-markdown"; import Markdown from "react-markdown";
import { Suspense, useEffect, useState } from "react"; import { Suspense, useEffect, useState } from "react";
import { useLocation } from "react-router"; import { useLocation } from "react-router";
import { FileNavigator } from "../navigation";
function Directory() { function Directory() {
const path = usePath(); const path = usePath();
@ -16,6 +17,7 @@ function Directory() {
return ( return (
<> <>
<div className="ka-dir"> <div className="ka-dir">
<FileNavigator />
<div className="ka-dir-row ka-dir-top"> <div className="ka-dir-row ka-dir-top">
<div className="ka-dir-item"></div> <div className="ka-dir-item"></div>
<b className="ka-dir-item">Name</b> <b className="ka-dir-item">Name</b>

View file

@ -5,21 +5,6 @@
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
.action-row {
width: 100%;
display: flex;
align-items: center;
.link {
display: flex;
align-items: center;
span {
margin: 0.2rem 0;
}
}
}
#icon { #icon {
margin: 3.5rem 0; margin: 3.5rem 0;
} }

View file

@ -5,6 +5,7 @@ import { usePath } from "../../store/path";
import { DynamicIcon, IconName } from "lucide-react/dynamic"; import { DynamicIcon, IconName } from "lucide-react/dynamic";
import "./fview.scss"; import "./fview.scss";
import { FileNavigator } from "../navigation";
function FileView() { function FileView() {
const path = usePath(); const path = usePath();
@ -93,15 +94,7 @@ function FileView() {
return ( return (
<div className="ka-fileview"> <div className="ka-fileview">
<div className="action-row"> <FileNavigator />
<a className="link" onClick={ev => {
ev.preventDefault();
document.location.href = document.location.href.substring(0, document.location.href.lastIndexOf("/"));
}}>
<DynamicIcon name="chevron-left" />
<span>Back to directory</span>
</a>
</div>
<DynamicIcon id="icon" name={type} size={120} /> <DynamicIcon id="icon" name={type} size={120} />
<b>{path.data.path}</b> <b>{path.data.path}</b>
{convert(path.data.total)} {convert(path.data.total)}

View file

@ -1,28 +1,42 @@
import { useLocation } from "react-router"; import { useLocation } from "react-router";
import "./navigation.scss";
export function FileNavigator() { export function FileNavigator() {
const location = useLocation(); const location = useLocation();
const split = location.pathname === "/" ? Array<string>() : location.pathname.substring(1, location.pathname.length).split("/"); const split = location.pathname === "/" ? Array<string>() : location.pathname.substring(1, location.pathname.length).split("/");
return ( return (
<div> <div className="ka-navigator">
<a href="/"> {location.pathname === "/" ? (
<span>Index Directory</span> <span className="current">Index Directory</span>
</a> ) : (
<a href="/">
<span>Index Directory</span>
</a>
)}
{split.map((path, i) => { {split.map((path, i) => {
if (i === split.length - 1) { let route = "";
return ( split.forEach((str, j) => {
<a key={i}> if (j > i)
<span>{path}</span> return;
</a>
); route += `/${str}`;
} });
return ( return (
<a key={i} href=""> <>
<span>{path}</span> <span className="heap">&gt;</span>
<span>&gt;&gt;</span> {i === split.length - 1 ? (
</a> <div key={i}>
<span className="current">{decodeURIComponent(path)}</span>
</div>
) : (
<a key={i} href={route}>
<span>{decodeURIComponent(path)}</span>
</a>
)}
</>
); );
})} })}
</div> </div>

View file

@ -0,0 +1,24 @@
.ka-navigator {
width: 100%;
display: flex;
margin: 10px 0;
align-items: center;
.current {
color: var(--foreground);
}
* {
color: var(--description-color);
transition-duration: 0.3s;
&:hover {
color: var(--foreground);
transition-duration: 0.3s;
}
}
.heap {
margin: 0 0.5rem;
}
}

View file

@ -35,10 +35,10 @@ function Settings() {
<h2 className="ka-title">General</h2> <h2 className="ka-title">General</h2>
<AccountSetting auth={auth} /> <AccountSetting auth={auth} />
<h2 className="ka-title">Private Directory</h2> {/* <h2 className="ka-title">Private Directory</h2> */}
<SettingBox> {/* <SettingBox> */}
<h3>Not provided features</h3> {/* TODO: create private directory setting */}
</SettingBox> {/* </SettingBox> */}
</div> </div>
); );
} }

View file

@ -11,6 +11,10 @@
width: 100%; width: 100%;
} }
.ka-desc {
color: var(--description-color);
}
.setting-box { .setting-box {
width: 100%; width: 100%;
display: flex; display: flex;

View file

@ -5,6 +5,7 @@
--background: #242424; --background: #242424;
--foreground: rgba(255, 255, 255, 0.87); --foreground: rgba(255, 255, 255, 0.87);
--sidebar-color: #2a2a2a; --sidebar-color: #2a2a2a;
--description-color: #818181;
--stroke: #3c3c3c; --stroke: #3c3c3c;
--nav-color: #191919; --nav-color: #191919;