Skip to content

Commit

Permalink
feat(lottie): star lottie
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <i@innei.in>
  • Loading branch information
Innei committed Sep 24, 2024
1 parent 68ad448 commit a61bd17
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 4 deletions.
7 changes: 7 additions & 0 deletions apps/renderer/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,11 @@ declare global {
platform: NodeJS.Platform
}
}

declare module "react" {
export interface AriaAttributes {
"data-testid"?: string
}
}

export {}
99 changes: 99 additions & 0 deletions apps/renderer/src/components/ui/lottie-container/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import type { DotLottie } from "@lottiefiles/dotlottie-react"
import { DotLottieReact } from "@lottiefiles/dotlottie-react"
import { atom, useAtomValue } from "jotai"
import type { FC, ReactNode, RefCallback } from "react"
import { useEffect, useState } from "react"

import { jotaiStore } from "~/lib/jotai"

import { RootPortal } from "../portal"

const portalElementsAtom = atom([] as ReactNode[])

export function LottieRenderContainer() {
const elements = useAtomValue(portalElementsAtom, { store: jotaiStore })

return (
<RootPortal>
<div className="pointer-events-none fixed z-[999]" data-testid="lottie-render-container">
{elements.map((element) => element)}
</div>
</RootPortal>
)
}

type LottieOptions = {
once?: boolean

x: number
y: number

height?: number
width?: number
className?: string

onComplete?: () => void

speed?: number
}
export const mountLottie = (url: string, options: LottieOptions) => {
const { once = true, height, width, x, y, className, speed } = options

const Lottie: FC = () => {
const [dotLottie, setDotLottie] = useState<DotLottie | null>(null)

useEffect(() => {
function onComplete() {
if (once) {
unmount()
}

options.onComplete?.()
}

if (dotLottie) {
dotLottie.addEventListener("complete", onComplete)
}

return () => {
if (dotLottie) {
dotLottie.removeEventListener("complete", onComplete)
}
}
}, [dotLottie])

const dotLottieRefCallback: RefCallback<DotLottie> = (dotLottie) => {
setDotLottie(dotLottie)
}

return (
<DotLottieReact
speed={speed}
dotLottieRefCallback={dotLottieRefCallback}
src={url}
autoplay
loop={false}
height={height}
width={width}
style={{
height,
width,
position: "fixed",

left: 0,
top: 0,
transform: `translate(${x}px, ${y}px)`,
}}
className={className}
/>
)
}

const element = <Lottie />
const unmount = () => {
jotaiStore.set(portalElementsAtom, (prev) => prev.filter((e) => e !== element))
}

jotaiStore.set(portalElementsAtom, (prev) => [...prev, element])
return unmount
}
15 changes: 13 additions & 2 deletions apps/renderer/src/hooks/biz/useEntryActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from "~/atoms/readability"
import { useIntegrationSettingKey } from "~/atoms/settings/integration"
import { whoami } from "~/atoms/user"
import { mountLottie } from "~/components/ui/lottie-container"
import {
SimpleIconsEagle,
SimpleIconsInstapaper,
Expand All @@ -23,12 +24,15 @@ import { shortcuts } from "~/constants/shortcuts"
import { tipcClient } from "~/lib/client"
import { nextFrame } from "~/lib/dom"
import { getOS } from "~/lib/utils"
import StarAnimationUri from "~/lottie/star.lottie?url"
import type { CombinedEntryModel } from "~/models"
import { useTipModal } from "~/modules/wallet/hooks"
import type { FlatEntryModel } from "~/store/entry"
import { entryActions } from "~/store/entry"
import { useFeedById } from "~/store/feed"

const absoluteStarAnimationUri = new URL(StarAnimationUri, import.meta.url).href

export const useEntryReadabilityToggle = ({ id, url }: { id: string; url: string }) =>
useCallback(async () => {
const status = getReadabilityStatus()[id]
Expand Down Expand Up @@ -165,7 +169,7 @@ export const useEntryActions = ({
hide?: boolean
active?: boolean
disabled?: boolean
onClick: () => void
onClick: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void
}[] = [
{
name: t("entry_actions.save_media_to_eagle"),
Expand Down Expand Up @@ -295,7 +299,14 @@ export const useEntryActions = ({
name: t("entry_actions.star"),
className: "i-mgc-star-cute-re",
hide: !!populatedEntry.collections,
onClick: () => {
onClick: (e) => {
mountLottie(absoluteStarAnimationUri, {
x: e.clientX - 90,
y: e.clientY - 70,
height: 126,
width: 252,
})

collect.mutate()
},
},
Expand Down
Binary file added apps/renderer/src/lottie/star.lottie
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export const EntryItemWrapper: FC<
.map((item) => ({
type: "text" as const,
label: item.name,
click: item.onClick,
click: () => item.onClick(e),
shortcut: item.shortcut,
})),
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ export function Component() {
</div>
<div className="mb-8 text-sm text-zinc-500">{user.data?.handle}</div>
</div>
<div className="mb-12 w-[70ch] max-w-full grow space-y-10">
<div
className="mb-12 w-[70ch] max-w-full grow space-y-10"
data-testid="profile-subscriptions"
>
{subscriptions.isLoading ? (
<LoadingCircle size="large" className="center fixed inset-0" />
) : (
Expand Down
2 changes: 2 additions & 0 deletions apps/renderer/src/providers/root-providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Provider } from "jotai"
import type { FC, PropsWithChildren } from "react"
import { HotkeysProvider } from "react-hotkeys-hook"

import { LottieRenderContainer } from "~/components/ui/lottie-container"
import { ModalStackProvider } from "~/components/ui/modal"
import { Toaster } from "~/components/ui/sonner"
import { HotKeyScopeMap } from "~/constants"
Expand Down Expand Up @@ -39,6 +40,7 @@ export const RootProviders: FC<PropsWithChildren> = ({ children }) => (
<SettingSync />
<ModalStackProvider />
<ContextMenuProvider />
<LottieRenderContainer />
<StableRouterProvider />
<FeatureFlagDebugger />
{import.meta.env.DEV && <Devtools />}
Expand Down

0 comments on commit a61bd17

Please sign in to comment.