mirror of https://github.com/usememos/memos.git
refactor: update home layout
This commit is contained in:
parent
0da3859878
commit
5d1075a647
|
|
@ -0,0 +1,34 @@
|
|||
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||
import { Routes } from "@/router";
|
||||
import { workspaceStore } from "@/store/v2";
|
||||
import { cn } from "@/utils";
|
||||
import UserAvatar from "./UserAvatar";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
collapsed?: boolean;
|
||||
}
|
||||
|
||||
const BrandBanner = (props: Props) => {
|
||||
const { collapsed } = props;
|
||||
const navigateTo = useNavigateTo();
|
||||
const currentUser = useCurrentUser();
|
||||
const workspaceGeneralSetting = workspaceStore.state.generalSetting;
|
||||
const title = workspaceGeneralSetting.customProfile?.title || "Memos";
|
||||
const avatarUrl = workspaceGeneralSetting.customProfile?.logoUrl || "/full-logo.webp";
|
||||
|
||||
return (
|
||||
<div className={cn("relative w-full h-auto shrink-0", props.className)}>
|
||||
<div
|
||||
className={cn("w-auto flex flex-row justify-start items-center text-gray-800 dark:text-gray-400", collapsed ? "px-1" : "px-3")}
|
||||
onClick={() => navigateTo(currentUser ? Routes.ROOT : Routes.EXPLORE)}
|
||||
>
|
||||
<UserAvatar className="shrink-0" avatarUrl={avatarUrl} />
|
||||
{!collapsed && <span className="ml-2 text-lg font-medium text-slate-800 dark:text-gray-300 shrink truncate">{title}</span>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BrandBanner;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { Globe2Icon, HomeIcon, LogInIcon } from "lucide-react";
|
||||
import { Globe2Icon, HomeIcon } from "lucide-react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import useDebounce from "react-use/lib/useDebounce";
|
||||
import SearchBar from "@/components/SearchBar";
|
||||
|
|
@ -41,14 +41,8 @@ const HomeSidebar = (props: Props) => {
|
|||
title: t("common.explore"),
|
||||
icon: <Globe2Icon className="w-4 h-auto opacity-70 shrink-0" />,
|
||||
};
|
||||
const signInNavLink: NavLinkItem = {
|
||||
id: "header-auth",
|
||||
path: Routes.AUTH,
|
||||
title: t("common.sign-in"),
|
||||
icon: <LogInIcon className="w-4 h-auto opacity-70 shrink-0" />,
|
||||
};
|
||||
|
||||
const navLinks: NavLinkItem[] = currentUser ? [homeNavLink, exploreNavLink] : [exploreNavLink, signInNavLink];
|
||||
const navLinks: NavLinkItem[] = currentUser ? [homeNavLink, exploreNavLink] : [exploreNavLink];
|
||||
|
||||
useDebounce(
|
||||
async () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Tooltip } from "@mui/joy";
|
||||
import { ArchiveIcon, BellIcon, PaperclipIcon, SettingsIcon, SmileIcon } from "lucide-react";
|
||||
import { ArchiveIcon, BellIcon, PaperclipIcon, SettingsIcon, UserCircleIcon } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useEffect } from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
|
@ -9,6 +9,7 @@ import { userStore } from "@/store/v2";
|
|||
import { Inbox_Status } from "@/types/proto/api/v1/inbox_service";
|
||||
import { cn } from "@/utils";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import BrandBanner from "./BrandBanner";
|
||||
import UserBanner from "./UserBanner";
|
||||
|
||||
interface NavLinkItem {
|
||||
|
|
@ -26,11 +27,11 @@ interface Props {
|
|||
const Navigation = observer((props: Props) => {
|
||||
const { collapsed, className } = props;
|
||||
const t = useTranslate();
|
||||
const user = useCurrentUser();
|
||||
const currentUser = useCurrentUser();
|
||||
const hasUnreadInbox = userStore.state.inboxes.some((inbox) => inbox.status === Inbox_Status.UNREAD);
|
||||
|
||||
useEffect(() => {
|
||||
if (!user) {
|
||||
if (!currentUser) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -68,21 +69,24 @@ const Navigation = observer((props: Props) => {
|
|||
title: t("common.settings"),
|
||||
icon: <SettingsIcon className="w-6 h-auto opacity-70 shrink-0" />,
|
||||
};
|
||||
const aboutNavLink: NavLinkItem = {
|
||||
id: "header-about",
|
||||
path: Routes.ABOUT,
|
||||
title: t("common.about"),
|
||||
icon: <SmileIcon className="w-6 h-auto opacity-70 shrink-0" />,
|
||||
const signInNavLink: NavLinkItem = {
|
||||
id: "header-auth",
|
||||
path: Routes.AUTH,
|
||||
title: t("common.sign-in"),
|
||||
icon: <UserCircleIcon className="w-6 h-auto opacity-70 shrink-0" />,
|
||||
};
|
||||
|
||||
const navLinks: NavLinkItem[] = user ? [resourcesNavLink, inboxNavLink, archivedNavLink, settingNavLink] : [aboutNavLink];
|
||||
const navLinks: NavLinkItem[] = currentUser ? [resourcesNavLink, inboxNavLink, archivedNavLink, settingNavLink] : [signInNavLink];
|
||||
|
||||
return (
|
||||
<header
|
||||
className={cn("w-full h-full overflow-auto flex flex-col justify-start items-start py-4 md:pt-6 z-30 hide-scrollbar", className)}
|
||||
className={cn(
|
||||
"w-full h-full overflow-auto flex flex-col justify-between items-start gap-4 py-4 md:pt-6 z-30 hide-scrollbar",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<UserBanner collapsed={collapsed} />
|
||||
<div className="w-full mt-2 px-1 py-2 flex flex-col justify-start items-start shrink-0 space-y-2">
|
||||
<div className="w-full px-1 py-2 flex flex-col justify-start items-start space-y-2 overflow-auto hide-scrollbar shrink">
|
||||
<BrandBanner className="mb-2" collapsed={collapsed} />
|
||||
{navLinks.map((navLink) => (
|
||||
<NavLink
|
||||
className={({ isActive }) =>
|
||||
|
|
@ -108,6 +112,7 @@ const Navigation = observer((props: Props) => {
|
|||
</NavLink>
|
||||
))}
|
||||
</div>
|
||||
{currentUser && <UserBanner collapsed={collapsed} />}
|
||||
</header>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { Dropdown, Menu, MenuButton, MenuItem } from "@mui/joy";
|
||||
import { LogOutIcon, SmileIcon, User2Icon } from "lucide-react";
|
||||
import { LogOutIcon, User2Icon, SmileIcon } from "lucide-react";
|
||||
import { authServiceClient } from "@/grpcweb";
|
||||
import useCurrentUser from "@/hooks/useCurrentUser";
|
||||
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||
import { Routes } from "@/router";
|
||||
import { workspaceStore } from "@/store/v2";
|
||||
import { cn } from "@/utils";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
import UserAvatar from "./UserAvatar";
|
||||
|
|
@ -18,13 +17,10 @@ const UserBanner = (props: Props) => {
|
|||
const t = useTranslate();
|
||||
const navigateTo = useNavigateTo();
|
||||
const currentUser = useCurrentUser();
|
||||
const workspaceGeneralSetting = workspaceStore.state.generalSetting;
|
||||
const title = (currentUser ? currentUser.nickname || currentUser.username : workspaceGeneralSetting.customProfile?.title) || "Memos";
|
||||
const avatarUrl = (currentUser ? currentUser.avatarUrl : workspaceGeneralSetting.customProfile?.logoUrl) || "/full-logo.webp";
|
||||
|
||||
const handleSignOut = async () => {
|
||||
await authServiceClient.signOut({});
|
||||
window.location.href = "/auth";
|
||||
window.location.href = Routes.AUTH;
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -38,23 +34,27 @@ const UserBanner = (props: Props) => {
|
|||
)}
|
||||
onClick={() => navigateTo(currentUser ? Routes.ROOT : Routes.EXPLORE)}
|
||||
>
|
||||
<UserAvatar className="shrink-0" avatarUrl={avatarUrl} />
|
||||
{!collapsed && <span className="ml-2 text-lg font-medium text-slate-800 dark:text-gray-300 shrink truncate">{title}</span>}
|
||||
{currentUser.avatarUrl ? (
|
||||
<UserAvatar className="shrink-0" avatarUrl={currentUser.avatarUrl} />
|
||||
) : (
|
||||
<User2Icon className="w-6 mx-auto h-auto opacity-60" />
|
||||
)}
|
||||
{!collapsed && (
|
||||
<span className="ml-2 text-lg font-medium text-slate-800 dark:text-gray-300 grow truncate">
|
||||
{currentUser.nickname || currentUser.username}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</MenuButton>
|
||||
<Menu placement="bottom-start" style={{ zIndex: "9999" }}>
|
||||
<MenuItem onClick={() => navigateTo(`/u/${encodeURIComponent(currentUser.username)}`)}>
|
||||
<User2Icon className="w-4 h-auto opacity-60" />
|
||||
<SmileIcon className="w-4 h-auto opacity-60" />
|
||||
<span className="truncate">{t("common.profile")}</span>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={handleSignOut}>
|
||||
<LogOutIcon className="w-4 h-auto opacity-60" />
|
||||
<span className="truncate">{t("common.sign-out")}</span>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => navigateTo(Routes.ABOUT)}>
|
||||
<SmileIcon className="w-4 h-auto opacity-60" />
|
||||
<span className="truncate">{t("common.about")}</span>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,19 +15,19 @@ const HomeLayout = observer(() => {
|
|||
<HomeSidebarDrawer />
|
||||
</MobileHeader>
|
||||
)}
|
||||
<div className={cn("w-full min-h-full flex flex-row justify-start items-start")}>
|
||||
{md && (
|
||||
<div
|
||||
className={cn(
|
||||
"sticky top-0 left-0 shrink-0 h-[100svh] transition-all",
|
||||
"border-r border-gray-200 dark:border-zinc-800",
|
||||
lg ? "w-72" : "w-56",
|
||||
)}
|
||||
>
|
||||
<HomeSidebar className={cn("px-3 py-6")} />
|
||||
</div>
|
||||
)}
|
||||
<div className={cn("w-full mx-auto px-4 sm:px-6 sm:pt-3 md:pt-6 pb-8", md && "max-w-3xl")}>
|
||||
{md && (
|
||||
<div
|
||||
className={cn(
|
||||
"fixed top-0 left-16 shrink-0 h-[100svh] transition-all",
|
||||
"border-r border-gray-200 dark:border-zinc-800",
|
||||
lg ? "w-72" : "w-56",
|
||||
)}
|
||||
>
|
||||
<HomeSidebar className={cn("px-3 py-6")} />
|
||||
</div>
|
||||
)}
|
||||
<div className={cn("w-full min-h-full", lg ? "pl-72" : md ? "pl-56" : "")}>
|
||||
<div className={cn("w-full mx-auto px-4 sm:px-6 md:pt-6 pb-8", md && "max-w-3xl")}>
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
import { Link } from "@mui/joy";
|
||||
import { DotIcon } from "lucide-react";
|
||||
import MobileHeader from "@/components/MobileHeader";
|
||||
import { useTranslate } from "@/utils/i18n";
|
||||
|
||||
const About = () => {
|
||||
const t = useTranslate();
|
||||
|
||||
return (
|
||||
<section className="@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8">
|
||||
<MobileHeader />
|
||||
<div className="w-full px-4 sm:px-6">
|
||||
<div className="w-full shadow flex flex-col justify-start items-start px-4 py-3 rounded-xl bg-white dark:bg-zinc-800 text-black dark:text-gray-300">
|
||||
<a href="https://www.usememos.com" target="_blank">
|
||||
<img className="w-auto h-12" src="https://www.usememos.com/full-logo-landscape.png" alt="memos" />
|
||||
</a>
|
||||
<p className="text-base">{t("about.description")}</p>
|
||||
<div className="mt-1 flex flex-row items-center flex-wrap">
|
||||
<Link underline="always" href="https://www.github.com/usememos/memos" target="_blank">
|
||||
{t("about.github-repository")}
|
||||
</Link>
|
||||
<DotIcon className="w-4 h-auto opacity-60" />
|
||||
<Link underline="always" href="https://www.usememos.com/" target="_blank">
|
||||
{t("about.official-website")}
|
||||
</Link>
|
||||
<DotIcon className="w-4 h-auto opacity-60" />
|
||||
<Link underline="always" href="https://www.usememos.com/blog" target="_blank">
|
||||
{t("about.blogs")}
|
||||
</Link>
|
||||
<DotIcon className="w-4 h-auto opacity-60" />
|
||||
<Link underline="always" href="https://www.usememos.com/docs" target="_blank">
|
||||
{t("about.documents")}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default About;
|
||||
|
|
@ -6,7 +6,6 @@ import RootLayout from "@/layouts/RootLayout";
|
|||
import Home from "@/pages/Home";
|
||||
import Loading from "@/pages/Loading";
|
||||
|
||||
const About = lazy(() => import("@/pages/About"));
|
||||
const AdminSignIn = lazy(() => import("@/pages/AdminSignIn"));
|
||||
const Archived = lazy(() => import("@/pages/Archived"));
|
||||
const AuthCallback = lazy(() => import("@/pages/AuthCallback"));
|
||||
|
|
@ -29,7 +28,6 @@ export enum Routes {
|
|||
ARCHIVED = "/archived",
|
||||
SETTING = "/setting",
|
||||
EXPLORE = "/explore",
|
||||
ABOUT = "/about",
|
||||
AUTH = "/auth",
|
||||
}
|
||||
|
||||
|
|
@ -144,14 +142,6 @@ const router = createBrowserRouter([
|
|||
</Suspense>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: Routes.ABOUT,
|
||||
element: (
|
||||
<Suspense fallback={<Loading />}>
|
||||
<About />
|
||||
</Suspense>
|
||||
),
|
||||
},
|
||||
// Redirect old path to new path.
|
||||
{
|
||||
path: "m/:uid",
|
||||
|
|
|
|||
Loading…
Reference in New Issue