Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file removed public/images/001.jpeg
Binary file not shown.
Binary file added public/images/001.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/002.jpeg
Binary file not shown.
Binary file added public/images/002.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/003.jpeg
Binary file not shown.
Binary file added public/images/003.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/004.jpeg
Binary file not shown.
Binary file added public/images/004.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/005.jpeg
Binary file not shown.
Binary file added public/images/005.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/006.jpeg
Binary file not shown.
Binary file added public/images/006.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/007.jpeg
Binary file not shown.
Binary file added public/images/007.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/008.jpeg
Binary file not shown.
Binary file added public/images/008.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/009.jpeg
Binary file not shown.
Binary file added public/images/009.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/010.jpeg
Binary file not shown.
Binary file added public/images/010.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/011.jpeg
Binary file not shown.
Binary file added public/images/011.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/012.jpeg
Binary file not shown.
Binary file added public/images/012.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/images/013.jpeg
Binary file not shown.
Binary file added public/images/013.webp
Binary file removed public/images/014.jpeg
Diff not rendered.
Binary file added public/images/014.webp
Binary file removed public/images/015.jpeg
Diff not rendered.
Binary file added public/images/015.webp
Binary file removed public/images/016.jpeg
Diff not rendered.
Binary file added public/images/016.webp
Binary file removed public/images/017.jpeg
Diff not rendered.
Binary file added public/images/017.webp
Binary file removed public/images/018.jpeg
Diff not rendered.
Binary file added public/images/018.webp
Binary file removed public/images/019.jpeg
Diff not rendered.
Binary file added public/images/019.webp
Binary file removed public/images/020.jpeg
Diff not rendered.
Binary file added public/images/020.webp
Binary file removed public/images/021.jpeg
Diff not rendered.
Binary file added public/images/021.webp
Binary file removed public/images/022.jpeg
Diff not rendered.
Binary file added public/images/022.webp
Binary file removed public/images/023.jpeg
Diff not rendered.
Binary file added public/images/023.webp
Binary file removed public/images/024.jpeg
Diff not rendered.
Binary file added public/images/024.webp
Binary file removed public/images/025.jpeg
Diff not rendered.
Binary file added public/images/025.webp
Binary file removed public/images/026.jpeg
Diff not rendered.
Binary file added public/images/026.webp
Binary file removed public/images/027.jpeg
Diff not rendered.
Binary file added public/images/027.webp
Binary file removed public/images/028.jpeg
Diff not rendered.
Binary file added public/images/028.webp
Binary file removed public/images/029.jpeg
Diff not rendered.
Binary file added public/images/029.webp
Binary file removed public/images/030.jpeg
Diff not rendered.
Binary file added public/images/030.webp
Binary file removed public/images/031.jpeg
Diff not rendered.
Binary file added public/images/031.webp
Binary file removed public/images/032.jpeg
Diff not rendered.
Binary file added public/images/032.webp
Binary file removed public/images/033.jpeg
Diff not rendered.
Binary file added public/images/033.webp
Binary file removed public/images/034.jpeg
Diff not rendered.
Binary file added public/images/034.webp
Binary file removed public/images/035.jpeg
Diff not rendered.
Binary file added public/images/035.webp
Binary file removed public/images/036.jpeg
Diff not rendered.
Binary file added public/images/036.webp
Binary file removed public/images/037.jpeg
Diff not rendered.
Binary file added public/images/037.webp
3 changes: 2 additions & 1 deletion workspaces/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@
"webpack-bundle-analyzer": "4.10.2",
"webpack-cli": "5.1.4",
"webpack-dev-server": "5.1.0",
"wireit": "0.14.9"
"wireit": "0.14.9",
"terser-webpack-plugin": "5.3.14"
},
"wireit": {
"build": {
Expand Down
12 changes: 6 additions & 6 deletions workspaces/client/src/app/createRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function createRoutes(store: ReturnType<typeof createStore>): RouteObject
async lazy() {
const { HomePage, prefetch } = await lazy(
import('@wsh-2025/client/src/pages/home/components/HomePage'),
1000,
500,
);
return {
Component: HomePage,
Expand All @@ -27,7 +27,7 @@ export function createRoutes(store: ReturnType<typeof createStore>): RouteObject
async lazy() {
const { EpisodePage, prefetch } = await lazy(
import('@wsh-2025/client/src/pages/episode/components/EpisodePage'),
1000,
500,
);
return {
Component: EpisodePage,
Expand All @@ -42,7 +42,7 @@ export function createRoutes(store: ReturnType<typeof createStore>): RouteObject
async lazy() {
const { prefetch, ProgramPage } = await lazy(
import('@wsh-2025/client/src/pages/program/components/ProgramPage'),
1000,
500,
);
return {
Component: ProgramPage,
Expand All @@ -57,7 +57,7 @@ export function createRoutes(store: ReturnType<typeof createStore>): RouteObject
async lazy() {
const { prefetch, SeriesPage } = await lazy(
import('@wsh-2025/client/src/pages/series/components/SeriesPage'),
1000,
500,
);
return {
Component: SeriesPage,
Expand All @@ -72,7 +72,7 @@ export function createRoutes(store: ReturnType<typeof createStore>): RouteObject
async lazy() {
const { prefetch, TimetablePage } = await lazy(
import('@wsh-2025/client/src/pages/timetable/components/TimetablePage'),
1000,
500,
);
return {
Component: TimetablePage,
Expand All @@ -87,7 +87,7 @@ export function createRoutes(store: ReturnType<typeof createStore>): RouteObject
async lazy() {
const { NotFoundPage, prefetch } = await lazy(
import('@wsh-2025/client/src/pages/not_found/components/NotFoundPage'),
1000,
500,
);
return {
Component: NotFoundPage,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { lens } from '@dhmk/zustand-lens';
import { StandardSchemaV1 } from '@standard-schema/spec';
import * as schema from '@wsh-2025/schema/src/api/schema';
import { getChannelByIdResponse, getChannelsResponse } from '@wsh-2025/schema/src/api/schema';
import { produce } from 'immer';

import { channelService } from '@wsh-2025/client/src/features/channel/services/channelService';

type ChannelId = string;

interface ChannelState {
channels: Record<ChannelId, StandardSchemaV1.InferOutput<typeof schema.getChannelByIdResponse>>;
channels: Record<ChannelId, StandardSchemaV1.InferOutput<typeof getChannelByIdResponse>>;
}

interface ChannelActions {
fetchChannelById: (params: {
channelId: ChannelId;
}) => Promise<StandardSchemaV1.InferOutput<typeof schema.getChannelByIdResponse>>;
fetchChannels: () => Promise<StandardSchemaV1.InferOutput<typeof schema.getChannelsResponse>>;
}) => Promise<StandardSchemaV1.InferOutput<typeof getChannelByIdResponse>>;
fetchChannels: () => Promise<StandardSchemaV1.InferOutput<typeof getChannelsResponse>>;
}

export const createChannelStoreSlice = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createFetch, createSchema } from '@better-fetch/fetch';
import { StandardSchemaV1 } from '@standard-schema/spec';
import * as schema from '@wsh-2025/schema/src/api/schema';
import { getEpisodeByIdResponse, getEpisodesResponse, getEpisodesRequestQuery } from '@wsh-2025/schema/src/api/schema';
import * as batshit from '@yornaath/batshit';

import { schedulePlugin } from '@wsh-2025/client/src/features/requests/schedulePlugin';
Expand All @@ -10,11 +10,11 @@ const $fetch = createFetch({
plugins: [schedulePlugin],
schema: createSchema({
'/episodes': {
output: schema.getEpisodesResponse,
query: schema.getEpisodesRequestQuery,
output: getEpisodesResponse,
query: getEpisodesRequestQuery,
},
'/episodes/:episodeId': {
output: schema.getEpisodeByIdResponse,
output: getEpisodeByIdResponse,
},
}),
throw: true,
Expand Down Expand Up @@ -45,8 +45,8 @@ const batcher = batshit.create({
interface EpisodeService {
fetchEpisodeById: (query: {
episodeId: string;
}) => Promise<StandardSchemaV1.InferOutput<typeof schema.getEpisodeByIdResponse>>;
fetchEpisodes: () => Promise<StandardSchemaV1.InferOutput<typeof schema.getEpisodesResponse>>;
}) => Promise<StandardSchemaV1.InferOutput<typeof getEpisodeByIdResponse>>;
fetchEpisodes: () => Promise<StandardSchemaV1.InferOutput<typeof getEpisodesResponse>>;
}

export const episodeService: EpisodeService = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { lens } from '@dhmk/zustand-lens';
import { StandardSchemaV1 } from '@standard-schema/spec';
import * as schema from '@wsh-2025/schema/src/api/schema';
import { getEpisodeByIdResponse, getEpisodesResponse } from '@wsh-2025/schema/src/api/schema';
import { produce } from 'immer';

import { episodeService } from '@wsh-2025/client/src/features/episode/services/episodeService';

type EpisodeId = string;

interface EpisodeState {
episodes: Record<EpisodeId, StandardSchemaV1.InferOutput<typeof schema.getEpisodeByIdResponse>>;
episodes: Record<EpisodeId, StandardSchemaV1.InferOutput<typeof getEpisodeByIdResponse>>;
}

interface EpisodeActions {
fetchEpisodeById: (params: {
episodeId: EpisodeId;
}) => Promise<StandardSchemaV1.InferOutput<typeof schema.getEpisodeByIdResponse>>;
fetchEpisodes: () => Promise<StandardSchemaV1.InferOutput<typeof schema.getEpisodesResponse>>;
}) => Promise<StandardSchemaV1.InferOutput<typeof getEpisodeByIdResponse>>;
fetchEpisodes: () => Promise<StandardSchemaV1.InferOutput<typeof getEpisodesResponse>>;
}

export const createEpisodeStoreSlice = () => {
Expand Down
6 changes: 3 additions & 3 deletions workspaces/client/src/features/layout/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import classNames from 'classnames';
import { ReactNode, useEffect, useState } from 'react';
import { ReactNode, useEffect, useState, useCallback } from 'react';
import { Flipper } from 'react-flip-toolkit';
import { Link, useLocation, useNavigation } from 'react-router';

Expand Down Expand Up @@ -46,8 +46,8 @@ export const Layout = ({ children }: Props) => {
};
}, []);

useEffect(() => {
setShouldHeaderBeTransparent(scrollTopOffset > 80);
useCallback(() => {
setShouldHeaderBeTransparent(scrollTopOffset > 1000);
}, [scrollTopOffset]);

const isSignedIn = user != null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { ElementScrollRestoration } from '@epic-web/restore-scroll';
import { StandardSchemaV1 } from '@standard-schema/spec';
import * as schema from '@wsh-2025/schema/src/api/schema';
import { getRecommendedModulesResponse } from '@wsh-2025/schema/src/api/schema';
import React from 'react';
import { ArrayValues } from 'type-fest';
import { useMergeRefs } from 'use-callback-ref';

import { EpisodeItem } from '@wsh-2025/client/src/features/recommended/components/EpisodeItem';
import { SeriesItem } from '@wsh-2025/client/src/features/recommended/components/SeriesItem';
import { MemoEpisodeItem } from '@wsh-2025/client/src/features/recommended/components/EpisodeItem';
import { MemoSeriesItem } from '@wsh-2025/client/src/features/recommended/components/SeriesItem';
import { useCarouselItemWidth } from '@wsh-2025/client/src/features/recommended/hooks/useCarouselItemWidth';
import { useScrollSnap } from '@wsh-2025/client/src/features/recommended/hooks/useScrollSnap';

interface Props {
module: ArrayValues<StandardSchemaV1.InferOutput<typeof schema.getRecommendedModulesResponse>>;
module: ArrayValues<StandardSchemaV1.InferOutput<typeof getRecommendedModulesResponse>>;
}

export const CarouselSection = ({ module }: Props) => {
Expand All @@ -30,8 +31,8 @@ export const CarouselSection = ({ module }: Props) => {
>
{module.items.map((item) => (
<div key={item.id} className={`w-[${itemWidth}px] shrink-0 grow-0`}>
{item.series != null ? <SeriesItem series={item.series} /> : null}
{item.episode != null ? <EpisodeItem episode={item.episode} /> : null}
{item.series != null ? <MemoSeriesItem series={item.series} /> : null}
{item.episode != null ? <MemoEpisodeItem episode={item.episode} /> : null}
</div>
))}
</div>
Expand All @@ -41,3 +42,5 @@ export const CarouselSection = ({ module }: Props) => {
</>
);
};

export const MemoCarouselSection = React.memo(CarouselSection);
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React from 'react';
import Ellipsis from 'react-ellipsis-component';
import { Flipped } from 'react-flip-toolkit';
import { NavLink } from 'react-router';

import { Hoverable } from '@wsh-2025/client/src/features/layout/components/Hoverable';
import { alterExterntion } from '@wsh-2025/client/src/utility/file';

interface Props {
episode: {
Expand All @@ -25,7 +27,7 @@ export const EpisodeItem = ({ episode }: Props) => {
<>
<Flipped stagger flipId={isTransitioning ? `episode-${episode.id}` : 0}>
<div className="relative overflow-hidden rounded-[8px] border-[2px] border-solid border-[#FFFFFF1F] before:absolute before:inset-x-0 before:bottom-0 before:block before:h-[64px] before:bg-gradient-to-t before:from-[#212121] before:to-transparent before:content-['']">
<img alt="" className="h-auto w-full" src={episode.thumbnailUrl} />
<img alt="" className="h-auto w-full" loading="lazy" src={alterExterntion(episode.thumbnailUrl)} />
<span className="i-material-symbols:play-arrow-rounded absolute bottom-[4px] left-[4px] m-[4px] block size-[20px] text-[#ffffff]" />
{episode.premium ? (
<span className="absolute bottom-[8px] right-[4px] inline-flex items-center justify-center rounded-[4px] bg-[#1c43d1] p-[4px] text-[10px] text-[#ffffff]">
Expand All @@ -49,3 +51,5 @@ export const EpisodeItem = ({ episode }: Props) => {
</Hoverable>
);
};

export const MemoEpisodeItem = React.memo(EpisodeItem);
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { StandardSchemaV1 } from '@standard-schema/spec';
import * as schema from '@wsh-2025/schema/src/api/schema';
import { getRecommendedModulesResponse } from '@wsh-2025/schema/src/api/schema';
import { useRef } from 'react';
import React from 'react';
import Ellipsis from 'react-ellipsis-component';
import { Flipped } from 'react-flip-toolkit';
import { NavLink } from 'react-router';
Expand All @@ -14,7 +15,7 @@ import { PlayerWrapper } from '../../player/interfaces/player_wrapper';
import { Hoverable } from '@wsh-2025/client/src/features/layout/components/Hoverable';

interface Props {
module: ArrayValues<StandardSchemaV1.InferOutput<typeof schema.getRecommendedModulesResponse>>;
module: ArrayValues<StandardSchemaV1.InferOutput<typeof getRecommendedModulesResponse>>;
}

export const JumbotronSection = ({ module }: Props) => {
Expand Down Expand Up @@ -60,3 +61,6 @@ export const JumbotronSection = ({ module }: Props) => {
</Hoverable>
);
};


export const MemoJumbotronSection = React.memo(JumbotronSection);
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { StandardSchemaV1 } from '@standard-schema/spec';
import * as schema from '@wsh-2025/schema/src/api/schema';
import { getRecommendedModulesResponse } from '@wsh-2025/schema/src/api/schema';
import React from 'react';
import { ArrayValues } from 'type-fest';

import { CarouselSection } from '@wsh-2025/client/src/features/recommended/components/CarouselSection';
import { JumbotronSection } from '@wsh-2025/client/src/features/recommended/components/JumbotronSection';
import { MemoCarouselSection } from '@wsh-2025/client/src/features/recommended/components/CarouselSection';
import { MemoJumbotronSection } from '@wsh-2025/client/src/features/recommended/components/JumbotronSection';

interface Props {
module: ArrayValues<StandardSchemaV1.InferOutput<typeof schema.getRecommendedModulesResponse>>;
module: ArrayValues<StandardSchemaV1.InferOutput<typeof getRecommendedModulesResponse>>;
}

export const RecommendedSection = ({ module }: Props) => {
if (module.type === 'jumbotron') {
return <JumbotronSection module={module} />;
return <MemoJumbotronSection module={module} />;
} else {
return <CarouselSection module={module} />;
return <MemoCarouselSection module={module} />;
}
};

export const MemoRecommendedSection = React.memo(RecommendedSection);
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React from 'react';
import Ellipsis from 'react-ellipsis-component';
import { Flipped } from 'react-flip-toolkit';
import { NavLink } from 'react-router';

import { Hoverable } from '@wsh-2025/client/src/features/layout/components/Hoverable';
import { alterExterntion } from '@wsh-2025/client/src/utility/file';

interface Props {
series: {
Expand All @@ -21,7 +23,7 @@ export const SeriesItem = ({ series }: Props) => {
<>
<div className="relative overflow-hidden rounded-[8px] border-[2px] border-solid border-[#FFFFFF1F]">
<Flipped stagger flipId={isTransitioning ? `series-${series.id}` : 0}>
<img alt="" className="h-auto w-full" src={series.thumbnailUrl} />
<img alt="" className="h-auto w-full" loading="lazy" src={alterExterntion(series.thumbnailUrl)} />
</Flipped>
</div>
<div className="p-[8px]">
Expand All @@ -36,3 +38,5 @@ export const SeriesItem = ({ series }: Props) => {
</Hoverable>
);
};

export const MemoSeriesItem = React.memo(SeriesItem);
Loading
Loading