From eb652b2f05538c3708249dcbd2022e0808506898 Mon Sep 17 00:00:00 2001 From: kingrayhan Date: Wed, 1 Apr 2026 20:56:22 +0600 Subject: [PATCH 1/8] feat: enhance NavbarActions with dropdown menu for creating new entries - Replaced the direct button for creating a new diary with a dropdown menu that includes options for creating both a new diary and a new gist. - Added translations for "Create", "New diary", and "New gist" in Bengali language support. --- src/components/Navbar/NavbarActions.tsx | 40 ++++++++++++++++++++++--- src/i18n/bn.json | 2 ++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/components/Navbar/NavbarActions.tsx b/src/components/Navbar/NavbarActions.tsx index ba9742d..013251b 100644 --- a/src/components/Navbar/NavbarActions.tsx +++ b/src/components/Navbar/NavbarActions.tsx @@ -3,10 +3,16 @@ import { useTranslation } from "@/i18n/use-translation"; import { Button } from "../ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "../ui/dropdown-menu"; import ThemeSwitcher from "./ThemeSwitcher"; import { useSession } from "@/store/session.atom"; -import { SearchIcon } from "lucide-react"; +import { ChevronDown, SearchIcon } from "lucide-react"; import AuthenticatedUserMenu from "./AuthenticatedUserMenu"; import LanguageSwitcher from "./LanguageSwitcher"; import Link from "next/link"; @@ -32,9 +38,35 @@ const NavbarActions: React.FC = () => { {authSession?.session ? ( <> - + + + + + + + + {_t("New diary")} + + + + + {_t("New gist")} + + + + ) : ( diff --git a/src/i18n/bn.json b/src/i18n/bn.json index 4434e0d..cc0acf0 100644 --- a/src/i18n/bn.json +++ b/src/i18n/bn.json @@ -23,7 +23,9 @@ "All tags": "সকল ট্যাগ", "Home": "বাড়ি", "Bookmarks": "বুকমার্ক", + "Create": "তৈরি করুন", "New diary": "নতুন ডায়েরি", + "New gist": "নতুন গিস্ট", "Dashboard": "ড্যাসবোর্ড", "Profile": "প্রোফাইল", "Profile Settings": "প্রোফাইল সেটিংস", From 4528d1a76ab85746df371c99283f762df16c4125 Mon Sep 17 00:00:00 2001 From: kingrayhan Date: Wed, 1 Apr 2026 21:03:23 +0600 Subject: [PATCH 2/8] feat: add unpublished article notice and draft byline support - Integrated UnpublishedArticleNotice component to display a notice for unpublished articles. - Added ArticleDraftBylineLabel for drafts, enhancing user awareness of article status. - Updated Bengali translations for unpublished articles and related messages to improve localization. --- .../_components/UnpublishedArticleNotice.tsx | 63 +++++++++++++++++++ src/app/[username]/[articleHandle]/page.tsx | 32 +++++++--- src/i18n/bn.json | 3 + 3 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 src/app/[username]/[articleHandle]/_components/UnpublishedArticleNotice.tsx diff --git a/src/app/[username]/[articleHandle]/_components/UnpublishedArticleNotice.tsx b/src/app/[username]/[articleHandle]/_components/UnpublishedArticleNotice.tsx new file mode 100644 index 0000000..75fca6b --- /dev/null +++ b/src/app/[username]/[articleHandle]/_components/UnpublishedArticleNotice.tsx @@ -0,0 +1,63 @@ +"use client"; + +import { Badge } from "@/components/ui/badge"; +import { useTranslation } from "@/i18n/use-translation"; +import { useSession } from "@/store/session.atom"; +import { FileWarning } from "lucide-react"; + +type Props = { + publishedAt: Date | null | undefined; + authorId: string; +}; + +/** Inline label next to the byline date when the article has no `published_at`. */ +export function ArticleDraftBylineLabel() { + const { _t } = useTranslation(); + return ( + + {_t("Draft")} + + ); +} + +export function UnpublishedArticleNotice({ publishedAt, authorId }: Props) { + const { _t } = useTranslation(); + const session = useSession(); + + if (publishedAt) return null; + + const viewerId = session?.session?.user_id; + const isAuthor = Boolean(viewerId) && viewerId === authorId; + + return ( +
+
+ + + {_t("Draft")} + + + {_t("Unpublished article")} + +
+

+ {isAuthor + ? _t( + "This draft is not listed anywhere on the site. Only people with the link can open it. Publish from the editor when you want it on your profile and in feeds.", + ) + : _t( + "This article is unpublished. It is not listed on the site; only people with this link can view it.", + )} +

+
+ ); +} diff --git a/src/app/[username]/[articleHandle]/page.tsx b/src/app/[username]/[articleHandle]/page.tsx index 4c38eb8..2e3bfd6 100644 --- a/src/app/[username]/[articleHandle]/page.tsx +++ b/src/app/[username]/[articleHandle]/page.tsx @@ -24,6 +24,10 @@ import type { Article, WithContext } from "schema-dts"; import { eq } from "sqlkit"; import ArticleSidebar from "./_components/ArticleSidebar"; import EditArticleButton from "./_components/EditArticleButton"; +import { + ArticleDraftBylineLabel, + UnpublishedArticleNotice, +} from "./_components/UnpublishedArticleNotice"; interface ArticlePageProps { params: Promise<{ @@ -136,6 +140,10 @@ const Page: NextPage = async ({ params }) => { > {/* {!article &&
Article not found
} */}
+ {article?.cover_image && (
= async ({ params }) => { {article?.user?.name}
- + {article?.published_at ? ( + + ) : ( + + )} · {readingTime(article?.body ?? "")} min read
diff --git a/src/i18n/bn.json b/src/i18n/bn.json index cc0acf0..0d8b638 100644 --- a/src/i18n/bn.json +++ b/src/i18n/bn.json @@ -52,6 +52,9 @@ "Total post comments": "সর্বমোট কমেন্ট", "Articles": "আর্টিক্যাল সমূহ", "Draft": "খসড়া", + "Unpublished article": "অপ্রকাশিত লেখা", + "This draft is not listed anywhere on the site. Only people with the link can open it. Publish from the editor when you want it on your profile and in feeds.": "এই খসড়া সাইটের কোথাও তালিকাভুক্ত নয়। লিংক যাদের আছে শুধু তারাই এটি খুলতে পারবে। প্রোফাইল ও ফিডতে দেখাতে চাইলে এডিটর থেকে প্রকাশ করুন।", + "This article is unpublished. It is not listed on the site; only people with this link can view it.": "এই লেখাটি অপ্রকাশিত। সাইটে এটি তালিকাভুক্ত নয়; যাদের এই লিংক আছে শুধু তারাই দেখতে পারবে।", "Edit": "সম্পাদনা", "Sure to unpublish": "অপ্রকাশিত করতে চাচ্ছেন?", "If you unpublish the article, this will be excluded in home page and search results, however direct links to the article will still work": "আপনি যদি আর্টিকেলটি আনপাব্লিশ করেন তবে এটি হোম পেজে এবং সার্চ ফলাফলে দেখাবে না, তবে আর্টিকেলটির সরাসরি লিঙ্ক সব সময় কাজ করবে", From 524ebc48a093395bde72fd207e7b0f2f21cfdc14 Mon Sep 17 00:00:00 2001 From: kingrayhan Date: Wed, 1 Apr 2026 21:22:30 +0600 Subject: [PATCH 3/8] refactor: update theme handling and improve layout structure - Removed the `next-themes` dependency and replaced it with a custom theme provider for better control over theme preferences. - Enhanced the `CommonProviders` component to support initial theme settings and migration from local storage. - Updated the `RootLayout` to include a theme initialization script and improved suspense handling for child components. - Refactored the `ThemeSwitcher` to utilize the new theme provider, ensuring consistent theme management across the application. --- package.json | 1 - src/app/layout.tsx | 31 ++++-- src/backend/services/theme.actions.ts | 31 ++++++ src/components/Navbar/ThemeSwitcher.tsx | 2 +- src/components/providers/CommonProviders.tsx | 20 +++- src/components/providers/root-providers.tsx | 24 ++++ src/components/providers/theme-provider.tsx | 110 +++++++++++++++++++ src/lib/theme-cookie.ts | 13 +++ src/lib/theme-init-script.ts | 5 + 9 files changed, 225 insertions(+), 12 deletions(-) create mode 100644 src/backend/services/theme.actions.ts create mode 100644 src/components/providers/root-providers.tsx create mode 100644 src/components/providers/theme-provider.tsx create mode 100644 src/lib/theme-cookie.ts create mode 100644 src/lib/theme-init-script.ts diff --git a/package.json b/package.json index bb87c9b..f07b9cb 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,6 @@ "meilisearch": "^0.51.0", "modern-screenshot": "^4.6.8", "next": "^16.2.1", - "next-themes": "^0.4.6", "pg": "^8.14.1", "react": "^19", "react-advanced-cropper": "^0.20.1", diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 5da45d3..cf0c331 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -3,11 +3,13 @@ import { AuthKitProvider } from "@workos-inc/authkit-nextjs/components"; import "../styles/app.css"; import CommonProviders from "@/components/providers/CommonProviders"; +import RootProviders from "@/components/providers/root-providers"; import LanguageHydrator from "@/components/providers/LanguageHydrator"; import SessionHydrator from "@/components/providers/SessionHydrator"; import { CookieConsentPopup } from "@/components/CookieConsentPopup"; import { fontKohinoorBanglaRegular } from "@/lib/fonts"; import { Toaster } from "@/components/toast"; +import { THEME_INIT_SCRIPT } from "@/lib/theme-init-script"; import Script from "next/script"; import React, { PropsWithChildren, Suspense } from "react"; @@ -41,6 +43,9 @@ const RootLayout: React.FC = ({ children }) => { return ( +