diff --git a/app/(home-pages)/(writer)/WriterShell.tsx b/app/(home-pages)/(writer)/WriterShell.tsx
index 176dafe9..965406de 100644
--- a/app/(home-pages)/(writer)/WriterShell.tsx
+++ b/app/(home-pages)/(writer)/WriterShell.tsx
@@ -18,6 +18,7 @@ const PAGE_META = [
prefix: "/looseleafs",
id: "looseleafs",
title: "Looseleafs",
+ showBackButton: true,
},
{
prefix: "/notifications",
@@ -33,7 +34,14 @@ export function WriterShell(props: { children: React.ReactNode }) {
return (
}
+ pageTitle={
+ meta && (
+
+ )
+ }
actions={}
>
{props.children}
diff --git a/app/(home-pages)/p/[didOrHandle]/layout.tsx b/app/(home-pages)/p/[didOrHandle]/layout.tsx
index 8ee3c992..b84cfe71 100644
--- a/app/(home-pages)/p/[didOrHandle]/layout.tsx
+++ b/app/(home-pages)/p/[didOrHandle]/layout.tsx
@@ -89,6 +89,7 @@ export default async function ProfilePageLayout(props: {
tabs={{
Inbox: { href: "/reader" },
Trending: { href: "/reader/trending" },
+ New: { href: "/reader/new" },
}}
>
{props.children}
diff --git a/components/ActionBar/DesktopNavigation.tsx b/components/ActionBar/DesktopNavigation.tsx
index feb1840b..027ed8a2 100644
--- a/components/ActionBar/DesktopNavigation.tsx
+++ b/components/ActionBar/DesktopNavigation.tsx
@@ -25,22 +25,34 @@ type NavigationProps = {
tabs?: { [name: string]: { href: string; icon?: React.ReactNode } };
};
+function safeDecode(p: string): string {
+ try {
+ return decodeURIComponent(p);
+ } catch {
+ return p;
+ }
+}
+
function pickActiveTabHref(
pathname: string,
tabs: { [name: string]: { href: string } },
): string | null {
+ const decodedPathname = safeDecode(pathname);
const hrefs = Object.values(tabs).map((t) => t.href);
let best: string | null = null;
for (const href of hrefs) {
+ const decodedHref = safeDecode(href);
// If this href is a strict prefix of another tab's href, only allow exact
// match — otherwise a parent tab would always swallow sibling-but-unmatched
// paths (e.g. /reader/new highlighting /reader's Inbox tab).
const isPrefixOfAnother = hrefs.some(
- (other) => other !== href && other.startsWith(href + "/"),
+ (other) =>
+ other !== href && safeDecode(other).startsWith(decodedHref + "/"),
);
const matches = isPrefixOfAnother
- ? pathname === href
- : pathname === href || pathname.startsWith(href + "/");
+ ? decodedPathname === decodedHref
+ : decodedPathname === decodedHref ||
+ decodedPathname.startsWith(decodedHref + "/");
if (matches) {
if (!best || href.length > best.length) best = href;
}
diff --git a/components/ActionBar/NavigationButtons.tsx b/components/ActionBar/NavigationButtons.tsx
index 0b643c92..1befbd88 100644
--- a/components/ActionBar/NavigationButtons.tsx
+++ b/components/ActionBar/NavigationButtons.tsx
@@ -77,6 +77,7 @@ export const ReaderButton = (props: { subs: boolean }) => {
export function NotificationButton() {
let { identity } = useIdentityData();
let unreads = identity?.notifications[0]?.count;
+
let pathname = usePathname();
let searchParams = useSearchParams();
let router = useRouter();
@@ -94,24 +95,20 @@ export function NotificationButton() {
}
return (
-
+ labelOnMobile={false}
+ icon={
+ unreads ? (
+
+ ) : (
+
+ )
+ }
+ label="Notifications"
+ active={active}
+ className={unreads ? "text-accent-contrast! font-bold" : ""}
+ />
);
}
diff --git a/components/PageLayouts/DashboardPageLayout.tsx b/components/PageLayouts/DashboardPageLayout.tsx
index 08cbc186..7042aafb 100644
--- a/components/PageLayouts/DashboardPageLayout.tsx
+++ b/components/PageLayouts/DashboardPageLayout.tsx
@@ -1,5 +1,5 @@
"use client";
-import { PageHeader } from "../PageHeader";
+import { PageHeader } from "components/PageHeader";
import { MobileNavigation } from "../ActionBar/MobileNavigation";
import { usePreserveScroll } from "src/hooks/usePreserveScroll";
@@ -21,9 +21,9 @@ export function DashboardPageLayout(props: {
id="home-content"
>
{props.showHeader && (