Skip to content

Commit 007c241

Browse files
authored
Merge pull request #405 from ACM-VIT/dev
Dev
2 parents 671920c + 9e06961 commit 007c241

47 files changed

Lines changed: 6624 additions & 271 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,5 @@ packages/cli/node_modules
6464
.asc
6565
mobile/android/keystore.properties
6666
mobile/android/keystores/examcooker-upload.jks
67-
.deepsec
67+
.deepsec
68+
.wrangler

app/(app)/client-side.tsx

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"use client";
22
import React, { Suspense, useCallback, useEffect, useState } from "react";
3+
import dynamic from "next/dynamic";
34
import Link from "next/link";
45
import NavBar from "@/app/components/nav-bar";
56
import { usePathname, useSearchParams } from "next/navigation";
@@ -14,6 +15,12 @@ import {
1415
PaperSplitViewProvider,
1516
usePaperSplitView,
1617
} from "@/app/components/past_papers/paper-split-view";
18+
import { POSTHOG_FEATURE_FLAGS } from "@/lib/posthog/shared";
19+
import { usePostHogFeatureFlagEnabled } from "@/lib/posthog/use-feature-flag-enabled";
20+
21+
const CommandPalette = dynamic(() => import("@/app/components/command-palette"), {
22+
ssr: false,
23+
});
1724

1825
function RouteEffects({ onPathChange }: { onPathChange: () => void }) {
1926
const pathname = usePathname();
@@ -174,11 +181,30 @@ function ClientShell({
174181
children,
175182
isNavOn,
176183
toggleNavbar,
184+
commandPaletteOpen,
185+
setCommandPaletteOpen,
177186
}: {
178187
children: React.ReactNode;
179188
isNavOn: boolean;
180189
toggleNavbar: () => void;
190+
commandPaletteOpen: boolean;
191+
setCommandPaletteOpen: (open: boolean) => void;
181192
}) {
193+
const commandPaletteEnabled =
194+
usePostHogFeatureFlagEnabled(POSTHOG_FEATURE_FLAGS.commandPalette) ?? false;
195+
196+
useEffect(() => {
197+
if (!commandPaletteEnabled && commandPaletteOpen) {
198+
setCommandPaletteOpen(false);
199+
}
200+
}, [commandPaletteEnabled, commandPaletteOpen, setCommandPaletteOpen]);
201+
202+
const openCommandPalette = useCallback(() => {
203+
if (commandPaletteEnabled) {
204+
setCommandPaletteOpen(true);
205+
}
206+
}, [commandPaletteEnabled, setCommandPaletteOpen]);
207+
182208
return (
183209
<Suspense fallback={<div className="relative flex" />}>
184210
<NavFromProvider>
@@ -192,8 +218,19 @@ function ClientShell({
192218
/>
193219
}
194220
>
195-
<NavBar isNavOn={isNavOn} toggleNavbar={toggleNavbar} />
221+
<NavBar
222+
isNavOn={isNavOn}
223+
toggleNavbar={toggleNavbar}
224+
commandPaletteEnabled={commandPaletteEnabled}
225+
onOpenCommandPalette={openCommandPalette}
226+
/>
196227
</Suspense>
228+
{commandPaletteEnabled ? (
229+
<CommandPalette
230+
open={commandPaletteOpen}
231+
onOpenChange={setCommandPaletteOpen}
232+
/>
233+
) : null}
197234
<main className="ec-app-main min-w-0 flex-1 pb-[calc(4.25rem+env(safe-area-inset-bottom))] pt-[env(safe-area-inset-top)] lg:pb-0 lg:pl-14 lg:pt-0">
198235
<PaperSplitViewProvider>
199236
<Suspense fallback={null}>
@@ -217,6 +254,7 @@ export default function ClientSide({
217254
children: React.ReactNode;
218255
}) {
219256
const [isNavOn, setIsNavOn] = useState(false);
257+
const [commandPaletteOpen, setCommandPaletteOpen] = useState(false);
220258

221259
useEffect(() => {
222260
if (typeof window === "undefined") return;
@@ -251,6 +289,8 @@ export default function ClientSide({
251289
<ClientShell
252290
isNavOn={isNavOn}
253291
toggleNavbar={toggleNavbar}
292+
commandPaletteOpen={commandPaletteOpen}
293+
setCommandPaletteOpen={setCommandPaletteOpen}
254294
>
255295
<Suspense fallback={null}>
256296
<RouteEffects onPathChange={handlePathChange} />

app/(app)/home/exams-marquee.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ function MarqueeItem({
1717
href={`/past_papers/${encodeURIComponent(item.courseCode)}`}
1818
prefetch={prefetch}
1919
transitionTypes={["nav-forward"]}
20-
className="group inline-flex items-center gap-3 whitespace-nowrap text-base text-black/75 transition-colors hover:text-[#253EE0] dark:text-[#D5D5D5]/70 dark:hover:text-[#3BF4C7] md:text-lg md:text-white/85 md:hover:text-[#3BF4C7] dark:md:text-white/85"
20+
className="ec-home-marquee-link group inline-flex items-center gap-3 whitespace-nowrap text-base text-black/75 transition-colors hover:text-[#253EE0] dark:text-[#D5D5D5]/70 dark:hover:text-[#3BF4C7] md:text-lg md:text-white/85 md:hover:text-[#3BF4C7] dark:md:text-white/85"
2121
>
22-
<span className="font-mono text-xs font-semibold uppercase tracking-[0.16em] text-black/55 dark:text-[#D5D5D5]/55 group-hover:text-current md:text-sm md:text-white/65 dark:md:text-white/65">
22+
<span className="ec-home-marquee-code font-mono text-xs font-semibold uppercase tracking-[0.16em] text-black/55 dark:text-[#D5D5D5]/55 group-hover:text-current md:text-sm md:text-white/65 dark:md:text-white/65">
2323
{item.courseCode}
2424
</span>
2525
<span className="font-semibold underline-offset-4 decoration-1 group-hover:underline">
@@ -53,7 +53,7 @@ function MarqueeRow({
5353
<MarqueeItem item={item} prefetch={prefetch === true && copy === "base"} />
5454
<span
5555
aria-hidden="true"
56-
className="select-none text-xs text-black/25 dark:text-[#D5D5D5]/20 md:text-white/30 dark:md:text-white/30"
56+
className="ec-home-marquee-divider select-none text-xs text-black/25 dark:text-[#D5D5D5]/20 md:text-white/30 dark:md:text-white/30"
5757
>
5858
5959
</span>

app/(app)/home/hero-backdrop-video.tsx

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
"use client";
22

33
import { useEffect, useRef, useState } from "react";
4+
import dynamic from "next/dynamic";
45
import ReactPlayer from "react-player";
56
import { scheduleIdleWork } from "@/lib/schedule-idle-work";
67

8+
const PixelBlast = dynamic(() => import("./pixel-bg"), { ssr: false });
9+
export type HeroBackdropKind = "local" | "youtube" | "pixel";
10+
711
const VIDEOS = [
812
{ kind: "local", webm: "/rainy.webm", mp4: "/rainy.mp4", poster: "/rainy.jpg" },
913
{ kind: "local", webm: "/midnight.webm", mp4: "/midnight.mp4", poster: "/midnight.jpg" },
1014
{ kind: "local", webm: "/night.webm", mp4: "/night.mp4", poster: "/night.jpg" },
1115
{ kind: "local", webm: "/night-city.webm", mp4: "/night-city.mp4", poster: "/night-city.jpg" },
16+
{ kind: "pixel" },
1217
{
1318
kind: "youtube",
1419
id: "AUQKjgKQF7w",
@@ -20,9 +25,10 @@ const TABLET_MIN_WIDTH_MEDIA = "(min-width: 600px)";
2025
interface Props {
2126
onReady?: () => void;
2227
onYouTubeEngaged?: () => void;
28+
onVariantChange?: (kind: HeroBackdropKind | null) => void;
2329
}
2430

25-
export default function HeroBackdropVideo({ onReady, onYouTubeEngaged }: Props) {
31+
export default function HeroBackdropVideo({ onReady, onYouTubeEngaged, onVariantChange }: Props) {
2632
const containerRef = useRef<HTMLDivElement | null>(null);
2733
const [isVisible, setIsVisible] = useState(false);
2834
const [video, setVideo] = useState<(typeof VIDEOS)[number] | null>(null);
@@ -96,6 +102,15 @@ export default function HeroBackdropVideo({ onReady, onYouTubeEngaged }: Props)
96102
onYouTubeEngaged?.();
97103
}, [isYouTubeEngaged, onYouTubeEngaged]);
98104

105+
useEffect(() => {
106+
onVariantChange?.(video?.kind ?? null);
107+
}, [onVariantChange, video]);
108+
109+
useEffect(() => {
110+
if (video?.kind !== "pixel") return;
111+
onReady?.();
112+
}, [onReady, video]);
113+
99114
const handleYouTubeReady = () => {
100115
setIsYouTubeReady(true);
101116
onReady?.();
@@ -149,6 +164,38 @@ export default function HeroBackdropVideo({ onReady, onYouTubeEngaged }: Props)
149164
);
150165
}
151166

167+
if (video.kind === "pixel") {
168+
return (
169+
<div
170+
ref={containerRef}
171+
className="absolute inset-0 overflow-hidden"
172+
aria-hidden="true"
173+
>
174+
<div className="relative h-full w-full">
175+
<PixelBlast
176+
variant="square"
177+
pixelSize={4}
178+
color="#B497CF"
179+
patternScale={2}
180+
patternDensity={1}
181+
pixelSizeJitter={0}
182+
enableRipples
183+
rippleSpeed={0.4}
184+
rippleThickness={0.12}
185+
rippleIntensityScale={1.5}
186+
liquid={false}
187+
liquidStrength={0.12}
188+
liquidRadius={1.2}
189+
liquidWobbleSpeed={5}
190+
speed={0.5}
191+
edgeFade={0.25}
192+
transparent
193+
/>
194+
</div>
195+
</div>
196+
);
197+
}
198+
152199
return (
153200
<div ref={containerRef} className="absolute inset-0" aria-hidden="true">
154201
<video

app/(app)/home/hero-frame.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
"use client";
22

33
import { ReactNode, useCallback, useState } from "react";
4-
import HeroBackdropVideo from "./hero-backdrop-video";
4+
import HeroBackdropVideo, { type HeroBackdropKind } from "./hero-backdrop-video";
55

66
export default function HeroFrame({ children }: { children: ReactNode }) {
77
const [videoReady, setVideoReady] = useState(false);
88
const [youtubeEngaged, setYoutubeEngaged] = useState(false);
9+
const [backdropKind, setBackdropKind] = useState<HeroBackdropKind | null>(null);
910
const handleBackdropReady = useCallback(() => setVideoReady(true), []);
1011
const handleYouTubeEngaged = useCallback(() => setYoutubeEngaged(true), []);
12+
const isPixelBackdrop = backdropKind === "pixel";
1113

1214
return (
1315
<div
16+
data-hero-backdrop={backdropKind ?? undefined}
1417
className={`relative transition-colors duration-500 ${
15-
videoReady ? "min-[600px]:text-white dark:min-[600px]:text-white" : ""
18+
videoReady && !isPixelBackdrop ? "min-[600px]:text-white dark:min-[600px]:text-white" : ""
1619
}`}
1720
>
1821
<div
@@ -22,6 +25,7 @@ export default function HeroFrame({ children }: { children: ReactNode }) {
2225
<HeroBackdropVideo
2326
onReady={handleBackdropReady}
2427
onYouTubeEngaged={handleYouTubeEngaged}
28+
onVariantChange={setBackdropKind}
2529
/>
2630
<div
2731
className={`absolute inset-0 transition-colors duration-700 ${

app/(app)/home/home.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ async function HomeMarqueeSection() {
3030
}
3131

3232
const subtitleClass =
33-
"text-sm sm:text-base lg:text-xl text-black/70 dark:text-[#D5D5D5]/70 md:text-white/85 dark:md:text-white/85 mb-6 sm:mb-8 lg:mb-10 max-w-2xl mx-auto";
33+
"ec-home-subtitle text-sm sm:text-base lg:text-xl text-black/70 dark:text-[#D5D5D5]/70 md:text-white/85 dark:md:text-white/85 mb-6 sm:mb-8 lg:mb-10 max-w-2xl mx-auto";
3434

3535
function HomeSubtitle({ userName }: { userName: string | null }) {
3636
if (!userName) {

0 commit comments

Comments
 (0)