diff --git a/components/ActionBar/DesktopNavigation.tsx b/components/ActionBar/DesktopNavigation.tsx
--- a/components/ActionBar/DesktopNavigation.tsx
+++ b/components/ActionBar/DesktopNavigation.tsx
@@ -25,22 +25,34 @@
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
--- a/components/ActionBar/NavigationButtons.tsx
+++ b/components/ActionBar/NavigationButtons.tsx
@@ -77,6 +77,7 @@
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 @@
}
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
--- 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 @@
id="home-content"
>
{props.showHeader && (
diff --git a/app/(home-pages)/(writer)/WriterShell.tsx b/app/(home-pages)/(writer)/WriterShell.tsx
--- a/app/(home-pages)/(writer)/WriterShell.tsx
+++ b/app/(home-pages)/(writer)/WriterShell.tsx
@@ -18,6 +18,7 @@
prefix: "/looseleafs",
id: "looseleafs",
title: "Looseleafs",
+ showBackButton: true,
},
{
prefix: "/notifications",
@@ -33,7 +34,14 @@
return (
}
+ pageTitle={
+ meta && (
+
+ )
+ }
actions={}
>
{props.children}
diff --git a/app/(home-pages)/reader/layout.tsx b/app/(home-pages)/reader/layout.tsx
--- a/app/(home-pages)/reader/layout.tsx
+++ b/app/(home-pages)/reader/layout.tsx
@@ -10,6 +10,7 @@
const tabs: { [name: string]: { href: string } } = {};
if (identity?.atp_did) tabs.Inbox = { href: "/reader" };
tabs.Trending = { href: "/reader/trending" };
+ tabs.New = { href: "/reader/new" };
return (
{props.children}