pstream is dead; long live pstream taciturnaxolotl.github.io/pstream-ng/
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor and simplify search bar positioning

Pas b6a8028e 544fe97c

+22 -57
+9 -25
src/pages/Settings.tsx
··· 1 1 import classNames from "classnames"; 2 2 import { useCallback, useEffect, useMemo, useRef, useState } from "react"; 3 3 import { useTranslation } from "react-i18next"; 4 - import { useAsyncFn, useWindowSize } from "react-use"; 4 + import { useAsyncFn } from "react-use"; 5 5 6 6 import { 7 7 base64ToBuffer, ··· 33 33 import { SidebarPart } from "@/pages/parts/settings/SidebarPart"; 34 34 import { PageTitle } from "@/pages/parts/util/PageTitle"; 35 35 import { AccountWithToken, useAuthStore } from "@/stores/auth"; 36 + import { useBannerSize } from "@/stores/banner"; 36 37 import { useLanguageStore } from "@/stores/language"; 37 38 import { usePreferencesStore } from "@/stores/preferences"; 38 39 import { useSubtitleStore } from "@/stores/subtitles"; ··· 56 57 const { t } = useTranslation(); 57 58 const { isMobile } = useIsMobile(); 58 59 const searchRef = useRef<HTMLInputElement>(null); 59 - const { width: windowWidth, height: windowHeight } = useWindowSize(); 60 - 61 - // Dynamic offset calculation like HeroPart 62 - const topSpacing = 16; // Base spacing 63 - const [stickyOffset, setStickyOffset] = useState(topSpacing); 64 - 65 - // Detect if running as a PWA on iOS 66 - const isIOSPWA = 67 - /iPad|iPhone|iPod/i.test(navigator.userAgent) && 68 - window.matchMedia("(display-mode: standalone)").matches; 69 - 70 - const adjustedTopSpacing = isIOSPWA ? 60 : topSpacing; 71 - const isLandscape = windowHeight < windowWidth && isIOSPWA; 72 - const adjustedOffset = isLandscape ? -40 : 0; 60 + const bannerSize = useBannerSize(); 73 61 74 - useEffect(() => { 75 - if (windowWidth > 1280) { 76 - // On large screens the bar goes inline with the nav elements 77 - setStickyOffset(adjustedTopSpacing); 78 - } else { 79 - // On smaller screens the bar goes below the nav elements 80 - setStickyOffset(adjustedTopSpacing + 60 + adjustedOffset); 81 - } 82 - }, [adjustedOffset, adjustedTopSpacing, windowWidth]); 62 + // Navbar height is 80px (h-20) 63 + const navbarHeight = 80; 64 + // On desktop: inline with navbar (same top position + 14px adjustment) 65 + // On mobile: below navbar (navbar height + banner) 66 + const topOffset = isMobile ? navbarHeight + bannerSize : bannerSize + 14; 83 67 84 68 return ( 85 69 <WideContainer ultraWide classNames="overflow-visible"> ··· 87 71 <div 88 72 className="fixed left-0 right-0 z-50" 89 73 style={{ 90 - top: `${stickyOffset}px`, 74 + top: `${topOffset}px`, 91 75 }} 92 76 > 93 77 <ThinContainer>
+13 -32
src/pages/parts/home/HeroPart.tsx
··· 1 1 import classNames from "classnames"; 2 - import { useCallback, useEffect, useRef, useState } from "react"; 2 + import { useCallback, useRef, useState } from "react"; 3 3 import Sticky from "react-sticky-el"; 4 - import { useWindowSize } from "react-use"; 5 4 6 5 import { SearchBarInput } from "@/components/form/SearchBar"; 7 6 import { ThinContainer } from "@/components/layout/ThinContainer"; 8 7 import { useSlashFocus } from "@/components/player/hooks/useSlashFocus"; 9 8 import { HeroTitle } from "@/components/text/HeroTitle"; 9 + import { useIsMobile } from "@/hooks/useIsMobile"; 10 10 import { useIsTV } from "@/hooks/useIsTv"; 11 11 import { useRandomTranslation } from "@/hooks/useRandomTranslation"; 12 12 import { useSearchQuery } from "@/hooks/useSearchQuery"; ··· 44 44 const [search, setSearch, setSearchUnFocus] = searchParams; 45 45 const [showBg, setShowBg] = useState(false); 46 46 const bannerSize = useBannerSize(); 47 + const { isMobile } = useIsMobile(); 48 + const { isTV } = useIsTV(); 47 49 48 50 const stickStateChanged = useCallback( 49 51 (isFixed: boolean) => { 50 52 setShowBg(isFixed); 51 53 setIsSticky(isFixed); 52 54 }, 53 - [setShowBg, setIsSticky], 55 + [setIsSticky], 54 56 ); 55 57 56 - const { width: windowWidth, height: windowHeight } = useWindowSize(); 57 - 58 - const { isTV } = useIsTV(); 59 - 60 - // Detect if running as a PWA on iOS 61 - const isIOSPWA = 62 - /iPad|iPhone|iPod/i.test(navigator.userAgent) && 63 - window.matchMedia("(display-mode: standalone)").matches; 64 - 65 - const topSpacing = isIOSPWA ? 60 : 16; 66 - const [stickyOffset, setStickyOffset] = useState(topSpacing); 67 - 68 - const isLandscape = windowHeight < windowWidth && isIOSPWA; 69 - const adjustedOffset = isLandscape 70 - ? -40 // landscape 71 - : 0; // portrait 72 - 73 - useEffect(() => { 74 - if (windowWidth > 1280) { 75 - // On large screens the bar goes inline with the nav elements 76 - setStickyOffset(topSpacing); 77 - } else { 78 - // On smaller screens the bar goes below the nav elements 79 - setStickyOffset(topSpacing + 60 + adjustedOffset); 80 - } 81 - }, [adjustedOffset, topSpacing, windowWidth]); 58 + // Navbar height is 80px (h-20) 59 + const navbarHeight = 80; 60 + // On desktop: inline with navbar (same top position) 61 + // On mobile: below navbar (navbar height + banner) 62 + const topOffset = isMobile ? navbarHeight + bannerSize : bannerSize + 14; 82 63 83 64 const time = getTimeOfDay(new Date()); 84 65 const title = randomT(`home.titles.${time}`); ··· 91 72 <div 92 73 className={classNames( 93 74 "space-y-16 text-center", 94 - showTitle ? "mt-44" : `mt-4`, 75 + showTitle ? "mt-44" : "mt-4", 95 76 )} 96 77 > 97 78 {showTitle && (!isTV || search.length === 0) ? ( ··· 102 83 103 84 <div className="relative h-20 z-30"> 104 85 <Sticky 105 - topOffset={stickyOffset * -1 + bannerSize} 86 + topOffset={-topOffset} 106 87 stickyStyle={{ 107 - paddingTop: `${stickyOffset + bannerSize}px`, 88 + paddingTop: `${topOffset}px`, 108 89 }} 109 90 onFixedToggle={stickStateChanged} 110 91 >