refactor: update home layout

pull/4439/merge
Johnny 2 days ago
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…
Cancel
Save