mirror of
https://github.com/p-stream/p-stream.git
synced 2026-01-11 20:10:32 +00:00
fix homepage layout and carousels
This commit is contained in:
parent
3cc435332c
commit
b8ca66b4cb
7 changed files with 60 additions and 177 deletions
|
|
@ -70,7 +70,6 @@ export function HomePage() {
|
|||
const enableCarouselView = usePreferencesStore(
|
||||
(state) => state.enableCarouselView,
|
||||
);
|
||||
const isMobile = window.innerWidth < 768;
|
||||
|
||||
const handleClick = (path: To) => {
|
||||
window.scrollTo(0, 0);
|
||||
|
|
@ -85,23 +84,8 @@ export function HomePage() {
|
|||
detailsModal.show();
|
||||
};
|
||||
|
||||
// const { loggedIn } = useAuth(); // Adjust padding for popup show button based on logged in state
|
||||
|
||||
return (
|
||||
<HomeLayout showBg={showBg}>
|
||||
{/* <a
|
||||
onClick={() => modal.show()}
|
||||
className={` text-white tabbable rounded-full z-50 fixed top-5 ${
|
||||
loggedIn
|
||||
? "right-[7.5rem] lg:right-[12.5rem] lg:text-2xl"
|
||||
: "right-[7.5rem] text-xl lg:text-lg"
|
||||
}`}
|
||||
style={{ animation: "pulse 1s infinite" }}
|
||||
>
|
||||
<IconPill icon={Icons.WARNING}>
|
||||
<span className="font-bold select-none">READ</span>
|
||||
</IconPill>
|
||||
</a> */}
|
||||
<div className="mb-2">
|
||||
<Helmet>
|
||||
<style type="text/css">{`
|
||||
|
|
@ -112,97 +96,7 @@ export function HomePage() {
|
|||
<title>{t("global.name")}</title>
|
||||
</Helmet>
|
||||
|
||||
{/* Popup
|
||||
<FancyModal
|
||||
id="notice"
|
||||
title="We're changing our backend server!"
|
||||
oneTime
|
||||
>
|
||||
<div>
|
||||
<p>
|
||||
On <strong>January 8th</strong>, the backend server will change
|
||||
from:
|
||||
</p>
|
||||
<p>
|
||||
<strong>server.vidbinge.com</strong> →{" "}
|
||||
<strong>server.fifthwit.tech</strong>
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
You will need to <strong>migrate your account </strong> to the new
|
||||
server or choose to continue using the old server by updating your
|
||||
settings.
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
<strong>What You Need to Know:</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
1. <strong>Migrating Your Account:</strong> Your data (e.g.,
|
||||
bookmarks) will not be automatically transferred. You'll
|
||||
need to migrate your account from the settings page. Or from
|
||||
below.
|
||||
</li>
|
||||
<li>
|
||||
2. <strong>Staying on the Old Server:</strong> If you don't
|
||||
want to change to the new server, your data will remain safe on{" "}
|
||||
<strong>server.vidbinge.com</strong>. You can change the Backend
|
||||
URL in your settings to "https://server.vidbinge.com".
|
||||
</li>
|
||||
</ul>
|
||||
<br />
|
||||
<p>
|
||||
<strong>Steps to Move Your Data:</strong>
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
1. Log into your account on <strong>server.vidbinge.com</strong>
|
||||
.
|
||||
</li>
|
||||
<li>
|
||||
(If you already are logged in, press here:{" "}
|
||||
<a href="/migration" className="text-type-link">
|
||||
Migrate my data.
|
||||
</a>
|
||||
)
|
||||
</li>
|
||||
<li>
|
||||
2. Go to the <strong>Settings</strong> page.
|
||||
</li>
|
||||
<li>
|
||||
3. Scroll down to{" "}
|
||||
<strong>Connections > Custom Server</strong>.
|
||||
</li>
|
||||
<li>
|
||||
3. Press the "Migrate my data to a new server."
|
||||
button.
|
||||
</li>
|
||||
<li>
|
||||
4. Enter the new server url:{" "}
|
||||
<strong>https://server.fifthwit.tech</strong> and press
|
||||
"Migrate".
|
||||
</li>
|
||||
<li>5. Login to your account with the same passphrase!</li>
|
||||
</ol>
|
||||
<br />
|
||||
<p>
|
||||
Thank you for your understanding and support during this
|
||||
transition! If you have questions or need help, feel free to reach
|
||||
out on the{" "}
|
||||
<a
|
||||
href="https://discord.com/invite/7z6znYgrTG"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-type-link"
|
||||
>
|
||||
P-Stream Discord
|
||||
</a>
|
||||
!
|
||||
</p>
|
||||
</div>
|
||||
</FancyModal>
|
||||
*/}
|
||||
{/* Page Header */}
|
||||
{enableFeatured ? (
|
||||
<FeaturedCarousel
|
||||
forcedCategory="editorpicks"
|
||||
|
|
@ -223,59 +117,64 @@ export function HomePage() {
|
|||
showTitle
|
||||
/>
|
||||
)}
|
||||
|
||||
{conf().SHOW_AD ? <AdsPart /> : null}
|
||||
</div>
|
||||
<WideContainer ultraWide={enableCarouselView}>
|
||||
{s.loading ? (
|
||||
<SearchLoadingPart />
|
||||
) : s.searching ? (
|
||||
enableCarouselView ? (
|
||||
<WideContainer>
|
||||
|
||||
{/* Search */}
|
||||
{search && (
|
||||
<WideContainer>
|
||||
{s.loading ? (
|
||||
<SearchLoadingPart />
|
||||
) : (
|
||||
s.searching && (
|
||||
<SearchListPart
|
||||
searchQuery={search}
|
||||
onShowDetails={handleShowDetails}
|
||||
/>
|
||||
</WideContainer>
|
||||
) : (
|
||||
<SearchListPart
|
||||
searchQuery={search}
|
||||
)
|
||||
)}
|
||||
</WideContainer>
|
||||
)}
|
||||
|
||||
{/* User Content */}
|
||||
{!search &&
|
||||
(enableCarouselView ? (
|
||||
<WideContainer ultraWide>
|
||||
<WatchingCarousel
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
/>
|
||||
)
|
||||
<BookmarksCarousel
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
/>
|
||||
</WideContainer>
|
||||
) : (
|
||||
<div className="flex flex-col gap-8">
|
||||
{enableCarouselView ? (
|
||||
<>
|
||||
<WatchingCarousel
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
/>
|
||||
<BookmarksCarousel
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<WatchingPart
|
||||
onItemsChange={setShowWatching}
|
||||
onShowDetails={handleShowDetails}
|
||||
/>
|
||||
<BookmarksPart
|
||||
onItemsChange={setShowBookmarks}
|
||||
onShowDetails={handleShowDetails}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<WideContainer>
|
||||
<div className="flex flex-col gap-8">
|
||||
<WatchingPart
|
||||
onItemsChange={setShowWatching}
|
||||
onShowDetails={handleShowDetails}
|
||||
/>
|
||||
<BookmarksPart
|
||||
onItemsChange={setShowBookmarks}
|
||||
onShowDetails={handleShowDetails}
|
||||
/>
|
||||
</div>
|
||||
</WideContainer>
|
||||
))}
|
||||
|
||||
{/* Under user content */}
|
||||
<WideContainer ultraWide>
|
||||
{/* Empty text */}
|
||||
{!(showBookmarks || showWatching) && !enableDiscover ? (
|
||||
<div className="flex flex-col translate-y-[-30px] items-center justify-center pt-20">
|
||||
<p className="text-[18.5px] pb-3">{emptyText}</p>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Discover Spacing */}
|
||||
{enableDiscover &&
|
||||
(enableFeatured ? (
|
||||
<div className="pb-4" />
|
||||
|
|
@ -285,6 +184,8 @@ export function HomePage() {
|
|||
<div className="pb-20" />
|
||||
))}
|
||||
{/* there... perfect. */}
|
||||
|
||||
{/* Discover section or discover button */}
|
||||
{enableDiscover && !search ? (
|
||||
<DiscoverContent />
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ interface LazyMediaCarouselProps {
|
|||
category?: Category;
|
||||
genre?: Genre;
|
||||
mediaType: "movie" | "tv";
|
||||
isMobile: boolean;
|
||||
carouselRefs: React.MutableRefObject<{
|
||||
[key: string]: HTMLDivElement | null;
|
||||
}>;
|
||||
|
|
@ -37,7 +36,6 @@ export function LazyMediaCarousel({
|
|||
category,
|
||||
genre,
|
||||
mediaType,
|
||||
isMobile,
|
||||
carouselRefs,
|
||||
onShowDetails,
|
||||
preloadedMedia,
|
||||
|
|
@ -121,7 +119,6 @@ export function LazyMediaCarousel({
|
|||
medias={medias}
|
||||
category={categoryName}
|
||||
isTVShow={mediaType === "tv"}
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={onShowDetails}
|
||||
genreId={genreId}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { Dropdown, OptionItem } from "@/components/form/Dropdown";
|
|||
import { Icon, Icons } from "@/components/Icon";
|
||||
import { MediaCard } from "@/components/media/MediaCard";
|
||||
import { Flare } from "@/components/utils/Flare";
|
||||
import { useIsMobile } from "@/hooks/useIsMobile";
|
||||
import { Media } from "@/pages/discover/common";
|
||||
import { useDiscoverStore } from "@/stores/discover";
|
||||
import { MediaItem } from "@/utils/mediaTypes";
|
||||
|
|
@ -19,7 +20,6 @@ interface MediaCarouselProps {
|
|||
medias: Media[];
|
||||
category: string;
|
||||
isTVShow: boolean;
|
||||
isMobile: boolean;
|
||||
carouselRefs: React.MutableRefObject<{
|
||||
[key: string]: HTMLDivElement | null;
|
||||
}>;
|
||||
|
|
@ -79,7 +79,6 @@ export function MediaCarousel({
|
|||
medias,
|
||||
category,
|
||||
isTVShow,
|
||||
isMobile,
|
||||
carouselRefs,
|
||||
onShowDetails,
|
||||
genreId,
|
||||
|
|
@ -99,6 +98,8 @@ export function MediaCarousel({
|
|||
);
|
||||
const categorySlug = `${category.toLowerCase().replace(/[^a-z0-9]+/g, "-")}-${isTVShow ? "tv" : "movie"}`;
|
||||
const browser = !!window.chrome;
|
||||
const { isMobile } = useIsMobile();
|
||||
|
||||
let isScrolling = false;
|
||||
|
||||
const handleWheel = (e: React.WheelEvent) => {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { get } from "@/backend/metadata/tmdb";
|
|||
import { WideContainer } from "@/components/layout/WideContainer";
|
||||
import { DetailsModal } from "@/components/overlays/DetailsModal";
|
||||
import { useModal } from "@/components/overlays/Modal";
|
||||
import { useIsMobile } from "@/hooks/useIsMobile";
|
||||
import {
|
||||
Genre,
|
||||
Movie,
|
||||
|
|
@ -168,8 +167,6 @@ export function DiscoverContent() {
|
|||
|
||||
const carouselRefs = useRef<{ [key: string]: HTMLDivElement | null }>({});
|
||||
|
||||
const { isMobile } = useIsMobile();
|
||||
|
||||
const userLanguage = useLanguageStore.getState().language;
|
||||
const formattedLanguage = getTmdbLanguageCode(userLanguage);
|
||||
|
||||
|
|
@ -505,7 +502,6 @@ export function DiscoverContent() {
|
|||
preloadedMedia={filteredGenreMovies}
|
||||
title="Editor Picks"
|
||||
mediaType="movie"
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
moreContent
|
||||
|
|
@ -514,7 +510,6 @@ export function DiscoverContent() {
|
|||
preloadedMedia={filteredGenreTVShows}
|
||||
title="Editor Picks"
|
||||
mediaType="tv"
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
moreContent
|
||||
|
|
@ -533,7 +528,6 @@ export function DiscoverContent() {
|
|||
medias={movieRecommendations}
|
||||
category={movieRecommendationTitle}
|
||||
isTVShow={false}
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
moreLink={`/discover/more/recommendations/${movieRecommendationSourceId}/movie`}
|
||||
|
|
@ -548,7 +542,6 @@ export function DiscoverContent() {
|
|||
<LazyMediaCarousel
|
||||
category={categories[0]}
|
||||
mediaType="movie"
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
moreContent
|
||||
|
|
@ -558,7 +551,6 @@ export function DiscoverContent() {
|
|||
<LazyMediaCarousel
|
||||
category={categories[1]}
|
||||
mediaType="movie"
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
moreContent
|
||||
|
|
@ -568,7 +560,6 @@ export function DiscoverContent() {
|
|||
<LazyMediaCarousel
|
||||
category={categories[2]}
|
||||
mediaType="movie"
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
moreContent
|
||||
|
|
@ -579,7 +570,6 @@ export function DiscoverContent() {
|
|||
medias={providerMovies}
|
||||
category={`Movies on ${selectedProvider.name || ""}`}
|
||||
isTVShow={false}
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
relatedButtons={MOVIE_PROVIDERS.map((p) => ({
|
||||
|
|
@ -596,7 +586,6 @@ export function DiscoverContent() {
|
|||
medias={filteredGenreMovies}
|
||||
category={`${selectedGenre.name || ""}`}
|
||||
isTVShow={false}
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
relatedButtons={genres.map((g) => ({
|
||||
|
|
@ -621,7 +610,6 @@ export function DiscoverContent() {
|
|||
medias={tvRecommendations}
|
||||
category={tvRecommendationTitle}
|
||||
isTVShow
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
moreLink={`/discover/more/recommendations/${tvRecommendationSourceId}/tv`}
|
||||
|
|
@ -636,7 +624,6 @@ export function DiscoverContent() {
|
|||
<LazyMediaCarousel
|
||||
category={tvCategories[0]}
|
||||
mediaType="tv"
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
moreContent
|
||||
|
|
@ -646,7 +633,6 @@ export function DiscoverContent() {
|
|||
<LazyMediaCarousel
|
||||
category={tvCategories[1]}
|
||||
mediaType="tv"
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
moreContent
|
||||
|
|
@ -656,7 +642,6 @@ export function DiscoverContent() {
|
|||
<LazyMediaCarousel
|
||||
category={tvCategories[2]}
|
||||
mediaType="tv"
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
moreContent
|
||||
|
|
@ -667,7 +652,6 @@ export function DiscoverContent() {
|
|||
medias={providerTVShows}
|
||||
category={`Shows on ${selectedProvider.name || ""}`}
|
||||
isTVShow
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
relatedButtons={TV_PROVIDERS.map((p) => ({
|
||||
|
|
@ -684,7 +668,6 @@ export function DiscoverContent() {
|
|||
medias={filteredGenreTVShows}
|
||||
category={`${selectedGenre.name || ""}`}
|
||||
isTVShow
|
||||
isMobile={isMobile}
|
||||
carouselRefs={carouselRefs}
|
||||
onShowDetails={handleShowDetails}
|
||||
relatedButtons={tvGenres.map((g) => ({
|
||||
|
|
|
|||
|
|
@ -4,15 +4,14 @@ import { useTranslation } from "react-i18next";
|
|||
import { EditButton } from "@/components/buttons/EditButton";
|
||||
import { Icons } from "@/components/Icon";
|
||||
import { SectionHeading } from "@/components/layout/SectionHeading";
|
||||
import { MediaCard } from "@/components/media/MediaCard";
|
||||
import { WatchedMediaCard } from "@/components/media/WatchedMediaCard";
|
||||
import { useIsMobile } from "@/hooks/useIsMobile";
|
||||
import { CarouselNavButtons } from "@/pages/discover/components/CarouselNavButtons";
|
||||
import { useBookmarkStore } from "@/stores/bookmarks";
|
||||
import { useProgressStore } from "@/stores/progress";
|
||||
import { MediaItem } from "@/utils/mediaTypes";
|
||||
|
||||
interface BookmarksCarouselProps {
|
||||
isMobile: boolean;
|
||||
carouselRefs: React.MutableRefObject<{
|
||||
[key: string]: HTMLDivElement | null;
|
||||
}>;
|
||||
|
|
@ -33,7 +32,6 @@ function MediaCardSkeleton() {
|
|||
}
|
||||
|
||||
export function BookmarksCarousel({
|
||||
isMobile,
|
||||
carouselRefs,
|
||||
onShowDetails,
|
||||
}: BookmarksCarouselProps) {
|
||||
|
|
@ -44,6 +42,8 @@ export function BookmarksCarousel({
|
|||
const removeBookmark = useBookmarkStore((s) => s.removeBookmark);
|
||||
const pressTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const { isMobile } = useIsMobile();
|
||||
|
||||
const bookmarksLength = useBookmarkStore(
|
||||
(state) => Object.keys(state.bookmarks).length,
|
||||
);
|
||||
|
|
@ -133,7 +133,7 @@ export function BookmarksCarousel({
|
|||
<SectionHeading
|
||||
title={t("home.bookmarks.sectionTitle") || "Bookmarks"}
|
||||
icon={Icons.BOOKMARK}
|
||||
className="ml-2 md:ml-8 mt-2 -mb-10"
|
||||
className="ml-2 md:ml-8 mt-2 -mb-5"
|
||||
>
|
||||
<div className="mr-6">
|
||||
<EditButton
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ import { EditButton } from "@/components/buttons/EditButton";
|
|||
import { Icons } from "@/components/Icon";
|
||||
import { SectionHeading } from "@/components/layout/SectionHeading";
|
||||
import { WatchedMediaCard } from "@/components/media/WatchedMediaCard";
|
||||
import { useIsMobile } from "@/hooks/useIsMobile";
|
||||
import { CarouselNavButtons } from "@/pages/discover/components/CarouselNavButtons";
|
||||
import { useProgressStore } from "@/stores/progress";
|
||||
import { shouldShowProgress } from "@/stores/progress/utils";
|
||||
import { MediaItem } from "@/utils/mediaTypes";
|
||||
|
||||
interface WatchingCarouselProps {
|
||||
isMobile: boolean;
|
||||
carouselRefs: React.MutableRefObject<{
|
||||
[key: string]: HTMLDivElement | null;
|
||||
}>;
|
||||
|
|
@ -32,7 +32,6 @@ function MediaCardSkeleton() {
|
|||
}
|
||||
|
||||
export function WatchingCarousel({
|
||||
isMobile,
|
||||
carouselRefs,
|
||||
onShowDetails,
|
||||
}: WatchingCarouselProps) {
|
||||
|
|
@ -43,6 +42,8 @@ export function WatchingCarousel({
|
|||
const removeItem = useProgressStore((s) => s.removeItem);
|
||||
const pressTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const { isMobile } = useIsMobile();
|
||||
|
||||
const itemsLength = useProgressStore((state) => {
|
||||
return Object.entries(state.items).filter(
|
||||
(entry) => shouldShowProgress(entry[1]).show,
|
||||
|
|
@ -125,7 +126,7 @@ export function WatchingCarousel({
|
|||
<SectionHeading
|
||||
title={t("home.continueWatching.sectionTitle")}
|
||||
icon={Icons.CLOCK}
|
||||
className="ml-2 md:ml-8 mt-2 -mb-10"
|
||||
className="ml-2 md:ml-8 mt-2 -mb-5"
|
||||
>
|
||||
<div className="mr-6">
|
||||
<EditButton
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ function SearchSuffix(props: { failed?: boolean; results?: number }) {
|
|||
const icon: Icons = props.failed ? Icons.WARNING : Icons.EYE_SLASH;
|
||||
|
||||
return (
|
||||
<div className="mb-24 mt-40 flex flex-col items-center justify-center space-y-3 text-center">
|
||||
<div className="mt-40 flex flex-col items-center justify-center space-y-3 text-center">
|
||||
<IconPatch
|
||||
icon={icon}
|
||||
className={`text-xl ${
|
||||
|
|
@ -35,7 +35,7 @@ function SearchSuffix(props: { failed?: boolean; results?: number }) {
|
|||
<>
|
||||
<p>{t("home.search.allResults")}</p>
|
||||
<Button
|
||||
className="px-py p-[0.3em] mt-3 rounded-xl text-type-dimmed box-content text-[17px] bg-largeCard-background text-buttons-secondaryText justify-center items-center"
|
||||
className="px-py p-[0.3em] mt-3 rounded-xl text-type-dimmed box-content text-[17px] bg-largeCard-background justify-center items-center"
|
||||
onClick={() => navigate("/discover")}
|
||||
>
|
||||
{t("home.search.discoverMore")}
|
||||
|
|
|
|||
Loading…
Reference in a new issue