drop multitimeline support from gsap provider but keep scroller priority feature

This commit is contained in:
2026-03-31 14:12:29 +02:00
parent d567fa3e02
commit 009d2b8d60
3 changed files with 27 additions and 53 deletions

View File

@@ -2,6 +2,7 @@
import { Skeleton } from '~/components/ui/skeleton'; import { Skeleton } from '~/components/ui/skeleton';
import ChatModal from './_components/ChatModal' import ChatModal from './_components/ChatModal'
import { trpc } from '~/app/_trpc/Client' import { trpc } from '~/app/_trpc/Client'
import { useTimeLine } from '~/app/_providers/GsapProvicer';
export default function AssistantModalPage() { export default function AssistantModalPage() {
const { data: session, error, isLoading } = trpc.chat.getSession.useQuery(); const { data: session, error, isLoading } = trpc.chat.getSession.useQuery();

View File

@@ -2,20 +2,20 @@
import { useGSAP } from '@gsap/react' import { useGSAP } from '@gsap/react'
import gsap from 'gsap' import gsap from 'gsap'
import { SplitText } from 'gsap/SplitText' import { SplitText } from 'gsap/SplitText'
import { ScrollTrigger } from 'gsap/all' import { ScrollTrigger, GSDevTools } from 'gsap/all'
import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useRef, type ReactNode } from 'react' import { createContext, useCallback, useContext, useEffect, useRef, type ReactNode } from 'react'
gsap.registerPlugin(useGSAP) gsap.registerPlugin(useGSAP)
gsap.registerPlugin(ScrollTrigger) gsap.registerPlugin(ScrollTrigger)
gsap.registerPlugin(SplitText) gsap.registerPlugin(SplitText)
gsap.registerPlugin(GSDevTools)
const GsapContext = createContext<{ const GsapContext = createContext<{
addAnimation: ( addAnimation: (
animation: gsap.core.TimelineChild, animation: gsap.core.TimelineChild,
position: gsap.Position, position: gsap.Position
tlId?:string
) => void, ) => void,
resetTimeline: (tlId?:string) => void, resetTimeline: () => void,
resumeTimeline: (tlId?:string) => void, resumeTimeline: () => void,
getScroller: () => Element | Window | null getScroller: () => Element | Window | null
} | null>(null) } | null>(null)
@@ -23,31 +23,29 @@ export function useGsapContext() {
return useContext(GsapContext) return useContext(GsapContext)
} }
export const useTimeLine = (dep?:any,all?:boolean,tlId?:string,) => { export const useTimeLine = (dep:any,all?:boolean) => {
console.log(tlId)
const gsapContext = useGsapContext() const gsapContext = useGsapContext()
useEffect(() => { useEffect(() => {
if (dep instanceof Array && all) { if (dep instanceof Array && all) {
let acc = true; let acc = true;
let allDepsSatisfied = dep.reduce((p,c) => c !== undefined && p ,acc ) let allDepsSatisfied = dep.reduce((p,c) => c !== undefined && p ,acc )
if (allDepsSatisfied) { if (allDepsSatisfied) {
gsapContext?.resumeTimeline(tlId) gsapContext?.resumeTimeline()
} }
} else { } else {
if (dep) { if (dep) {
gsapContext?.resumeTimeline(tlId) gsapContext?.resumeTimeline()
} }
} }
},[dep]) },[dep])
useLayoutEffect(() => { useEffect(() => {
return () => { return () => {
gsapContext?.resetTimeline(tlId) gsapContext?.resetTimeline()
} }
},[]) },[])
} }
export default function GsapProvider({ children,timelines }: { children: ReactNode,timelines?:string[] }) { export default function GsapProvider({ children }: { children: ReactNode }) {
const timeLines = useRef<Map<string,gsap.core.Timeline>|null>(null)
const tl = useRef<gsap.core.Timeline | null>(null) const tl = useRef<gsap.core.Timeline | null>(null)
const scrollerRef = useRef<Element | Window | null>(null) const scrollerRef = useRef<Element | Window | null>(null)
const getScroller = useCallback(() => { const getScroller = useCallback(() => {
@@ -73,53 +71,28 @@ export default function GsapProvider({ children,timelines }: { children: ReactNo
return scrollerRef.current return scrollerRef.current
}, []) }, [])
useGSAP(() => { useGSAP(() => {
if (!timeLines.current && timelines) {
timeLines.current = new Map()
}
timelines?.forEach((tlId) => {
timeLines.current?.set(tlId,gsap.timeline({id:tlId,paused:true}))
})
if (!tl.current) { if (!tl.current) {
tl.current = gsap.timeline({ paused: true }) tl.current = gsap.timeline({ paused: true, id:'mainTimeline', onComplete: ()=>{
console.log('timeline revert')
gsap.getById('mainTimeline')?.revert()
} })
} }
return () => { console.log("gsap cleanup") } return () => { console.log("gsap cleanup") }
}) })
const addAnimation = useCallback((animation: gsap.core.TimelineChild, position: gsap.Position,tlId?:string) => { const addAnimation = useCallback((animation: gsap.core.TimelineChild, position: gsap.Position) => {
if(tlId) {
const selectedTimeLine = timeLines.current?.get(tlId)
console.log("add animation to:", position, selectedTimeLine !== undefined)
selectedTimeLine?.add(animation,position)
return;
}
console.log("add animation to:", position, tl.current !== undefined) console.log("add animation to:", position, tl.current !== undefined)
tl.current?.add(animation, position); tl.current?.add(animation, position);
},[]) },[])
const resetTimeline = useCallback((tlId?:string) => { const resetTimeline = useCallback(() => {
console.log("resetting timeline",tlId) tl.current?.kill()
if (tlId) { tl.current?.revert()
let selectedTimeLine = timeLines.current?.get(tlId) ScrollTrigger.getAll().forEach(st => st.kill())
selectedTimeLine?.kill() tl.current = gsap.timeline({paused:true})
selectedTimeLine?.revert()
timeLines.current?.set(tlId,gsap.timeline({id:tlId,paused:true}))
} else {
tl.current?.kill()
tl.current?.revert()
tl.current = gsap.timeline({paused:true})
}
ScrollTrigger.getAll().forEach(st => {
st.kill()
})
},[]) },[])
const resumeTimeline = useCallback((tlId?:string) => { const resumeTimeline = useCallback(() => {
if (tlId) { console.log("resuming timeline:",tl.current)
console.log("trying to resume timeline",tlId) tl.current?.resume()
let selectedTimeLine = timeLines.current?.get(tlId)
selectedTimeLine?.resume()
} else {
console.log("resuming default timeline")
tl.current?.resume()
}
},[]) },[])
return ( return (
<GsapContext.Provider value={{ addAnimation, resetTimeline, resumeTimeline, getScroller }}> <GsapContext.Provider value={{ addAnimation, resetTimeline, resumeTimeline, getScroller }}>

View File

@@ -38,7 +38,7 @@ export default async function RootLayout({
return ( return (
<ClerkProvider> <ClerkProvider>
<TrpcProvider> <TrpcProvider>
<GsapProvider timelines={['chat']}> <GsapProvider>
<html lang="en" className={cn(geist.variable, "font-sans", inter.variable)} suppressHydrationWarning> <html lang="en" className={cn(geist.variable, "font-sans", inter.variable)} suppressHydrationWarning>
<head> <head>
<CodeHighlightStyle /> <CodeHighlightStyle />