scroll up on active NavLink click, mobile messages & footer
This commit is contained in:
parent
dda38ab824
commit
689839e043
20
packages/app/src/Element/Button/NavLink.tsx
Normal file
20
packages/app/src/Element/Button/NavLink.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { NavLink as RouterNavLink, NavLinkProps, useLocation } from "react-router-dom";
|
||||||
|
|
||||||
|
export default function NavLink(props: NavLinkProps) {
|
||||||
|
const { to, onClick, ...rest } = props;
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
const isActive = location.pathname === to.toString();
|
||||||
|
|
||||||
|
const handleClick = (event) => {
|
||||||
|
if (onClick) {
|
||||||
|
onClick(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isActive) {
|
||||||
|
window.scrollTo({ top: 0, behavior: "instant" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return <RouterNavLink to={to} onClick={handleClick} {...rest} />;
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { NavLink } from "react-router-dom";
|
import NavLink from "@/Element/Button/NavLink";
|
||||||
import useLogin from "@/Hooks/useLogin";
|
import useLogin from "@/Hooks/useLogin";
|
||||||
import Icon from "@/Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { ProfileLink } from "@/Element/User/ProfileLink";
|
import { ProfileLink } from "@/Element/User/ProfileLink";
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { LogoHeader } from "./LogoHeader";
|
import { LogoHeader } from "./LogoHeader";
|
||||||
import { NavLink, useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Icon from "@/Icons/Icon";
|
import Icon from "@/Icons/Icon";
|
||||||
import { ProfileLink } from "../../Element/User/ProfileLink";
|
import { ProfileLink } from "../../Element/User/ProfileLink";
|
||||||
import Avatar from "../../Element/User/Avatar";
|
import Avatar from "../../Element/User/Avatar";
|
||||||
@ -10,6 +10,7 @@ import { FormattedMessage, useIntl } from "react-intl";
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { getCurrentSubscription } from "@/Subscription";
|
import { getCurrentSubscription } from "@/Subscription";
|
||||||
import { HasNotificationsMarker } from "@/Pages/Layout/HasNotificationsMarker";
|
import { HasNotificationsMarker } from "@/Pages/Layout/HasNotificationsMarker";
|
||||||
|
import NavLink from "@/Element/Button/NavLink";
|
||||||
|
|
||||||
const MENU_ITEMS = [
|
const MENU_ITEMS = [
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Link, useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { base64 } from "@scure/base";
|
import { base64 } from "@scure/base";
|
||||||
import { unwrap } from "@snort/shared";
|
import { unwrap } from "@snort/shared";
|
||||||
import { FormattedMessage } from "react-intl";
|
import { FormattedMessage } from "react-intl";
|
||||||
@ -9,6 +9,7 @@ import useLogin from "@/Hooks/useLogin";
|
|||||||
import useEventPublisher from "@/Hooks/useEventPublisher";
|
import useEventPublisher from "@/Hooks/useEventPublisher";
|
||||||
import SnortApi from "@/External/SnortApi";
|
import SnortApi from "@/External/SnortApi";
|
||||||
import { HasNotificationsMarker } from "@/Pages/Layout/HasNotificationsMarker";
|
import { HasNotificationsMarker } from "@/Pages/Layout/HasNotificationsMarker";
|
||||||
|
import NavLink from "@/Element/Button/NavLink";
|
||||||
|
|
||||||
const NotificationsHeader = () => {
|
const NotificationsHeader = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -70,10 +71,10 @@ const NotificationsHeader = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<Link className="btn" to="/notifications" onClick={goToNotifications}>
|
<NavLink className="btn" to="/notifications" onClick={goToNotifications}>
|
||||||
<Icon name="bell-02" size={24} />
|
<Icon name="bell-02" size={24} />
|
||||||
<HasNotificationsMarker />
|
<HasNotificationsMarker />
|
||||||
</Link>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,6 @@ import Footer from "@/Pages/Layout/Footer";
|
|||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [pageClass, setPageClass] = useState("page");
|
|
||||||
const { id, stalker } = useLogin(s => ({ id: s.id, stalker: s.stalker ?? false }));
|
const { id, stalker } = useLogin(s => ({ id: s.id, stalker: s.stalker ?? false }));
|
||||||
|
|
||||||
useTheme();
|
useTheme();
|
||||||
@ -29,22 +28,9 @@ export default function Index() {
|
|||||||
useLoginFeed();
|
useLoginFeed();
|
||||||
|
|
||||||
const hideHeaderPaths = ["/login", "/new"];
|
const hideHeaderPaths = ["/login", "/new"];
|
||||||
|
const shouldHideFooter = location.pathname.startsWith("/messages/");
|
||||||
const shouldHideHeader = hideHeaderPaths.some(path => location.pathname.startsWith(path));
|
const shouldHideHeader = hideHeaderPaths.some(path => location.pathname.startsWith(path));
|
||||||
|
|
||||||
const pageClassPaths = useMemo(
|
|
||||||
() => ({
|
|
||||||
widePage: ["/login", "/messages"],
|
|
||||||
noScroll: ["/messages"],
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const isWidePage = pageClassPaths.widePage.some(path => location.pathname.startsWith(path));
|
|
||||||
const isNoScroll = pageClassPaths.noScroll.some(path => location.pathname.startsWith(path));
|
|
||||||
setPageClass(isWidePage ? (isNoScroll ? "scroll-lock" : "") : "page");
|
|
||||||
}, [location, pageClassPaths]);
|
|
||||||
|
|
||||||
const handleKeyboardShortcut = useCallback(event => {
|
const handleKeyboardShortcut = useCallback(event => {
|
||||||
if (event.target && !isFormElement(event.target as HTMLElement)) {
|
if (event.target && !isFormElement(event.target as HTMLElement)) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -58,7 +44,7 @@ export default function Index() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<div className={`${pageClass} w-full max-w-screen-xl`}>
|
<div className="w-full max-w-screen-xl">
|
||||||
{!shouldHideHeader && <Header />}
|
{!shouldHideHeader && <Header />}
|
||||||
<div className="flex flex-row w-full">
|
<div className="flex flex-row w-full">
|
||||||
<NavSidebar />
|
<NavSidebar />
|
||||||
@ -73,7 +59,7 @@ export default function Index() {
|
|||||||
</div>
|
</div>
|
||||||
<LoginUnlock />
|
<LoginUnlock />
|
||||||
{isStalker && <StalkerModal id={id} />}
|
{isStalker && <StalkerModal id={id} />}
|
||||||
<Footer />
|
{!shouldHideFooter && <Footer/>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -88,9 +88,9 @@ export default function MessagesPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-1 h-screen overflow-hidden">
|
<div className="flex flex-1 md:h-screen md:overflow-hidden">
|
||||||
{(pageWidth >= TwoCol || !chat) && (
|
{(pageWidth >= TwoCol || !chat) && (
|
||||||
<div className="overflow-y-auto h-screen p-1 w-full md:w-1/3 flex-shrink-0">
|
<div className="overflow-y-auto md:h-screen p-1 w-full md:w-1/3 flex-shrink-0">
|
||||||
<div className="flex items-center justify-between p-2">
|
<div className="flex items-center justify-between p-2">
|
||||||
<button disabled={unreadCount <= 0} type="button" className="text-sm font-semibold">
|
<button disabled={unreadCount <= 0} type="button" className="text-sm font-semibold">
|
||||||
<FormattedMessage defaultMessage="Mark all read" id="ShdEie" />
|
<FormattedMessage defaultMessage="Mark all read" id="ShdEie" />
|
||||||
|
@ -357,7 +357,6 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
|
|||||||
return <TabElement key={v.value} t={v} tab={tab} setTab={setTab} />;
|
return <TabElement key={v.value} t={v} tab={tab} setTab={setTab} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const w = window.document.querySelector(".page")?.clientWidth;
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="profile">
|
<div className="profile">
|
||||||
@ -366,7 +365,7 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
|
|||||||
alt="banner"
|
alt="banner"
|
||||||
className="banner pointer"
|
className="banner pointer"
|
||||||
src={user.banner}
|
src={user.banner}
|
||||||
size={w}
|
size={940}
|
||||||
onClick={() => setModalImage(user.banner || "")}
|
onClick={() => setModalImage(user.banner || "")}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
Loading…
Reference in New Issue
Block a user