fix: remove `useSingleton`

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei 2024-10-25 21:35:03 +08:00
parent b05ff50f14
commit d1d3fcf493
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
8 changed files with 54 additions and 56 deletions

View File

@ -4,7 +4,6 @@ import { useRefValue, useVideo } from "@follow/hooks"
import { nextFrame, stopPropagation } from "@follow/utils/dom"
import { cn } from "@follow/utils/utils"
import * as Slider from "@radix-ui/react-slider"
import { useSingleton } from "foxact/use-singleton"
import { m, useDragControls, useSpring } from "framer-motion"
import type { PropsWithChildren } from "react"
import {
@ -164,15 +163,14 @@ export const VideoPlayer = forwardRef<VideoPlayerRef, VideoPlayerProps>(
},
)
const BizControlOutsideMedia = () => {
const currentAudioPlayerIsPlayRef = useSingleton(() => AudioPlayer.get().status === "playing")
const currentAudioPlayerIsPlayRef = useMemo(() => AudioPlayer.get().status === "playing", [])
useEffect(() => {
const { current } = currentAudioPlayerIsPlayRef
if (current) {
if (currentAudioPlayerIsPlayRef) {
AudioPlayer.pause()
}
return () => {
if (current) {
if (currentAudioPlayerIsPlayRef) {
AudioPlayer.play()
}
}

View File

@ -1,42 +1,20 @@
import { getStorageNS } from "@follow/utils/ns"
import { repository } from "@pkg"
import { createElement } from "react"
import { toast } from "sonner"
import { appLog } from "~/lib/log"
import { waitAppReady } from "../queue"
const appVersionKey = getStorageNS("app_version")
declare global {
interface Window {
__app_is_upgraded__: boolean
}
}
export const doMigration = () => {
const lastVersion = localStorage.getItem(appVersionKey)
if (lastVersion && lastVersion !== APP_VERSION) {
appLog(`Upgrade from ${lastVersion} to ${APP_VERSION}`)
waitAppReady(() => {
toast.success(
// `App is upgraded to ${APP_VERSION}, enjoy the new features! 🎉`,
createElement("div", {
children: [
"App is upgraded to ",
createElement(
"a",
{
href: `${repository.url}/releases/tag/${APP_VERSION}`,
target: "_blank",
className: "underline",
},
createElement("strong", {
children: APP_VERSION,
}),
),
", enjoy the new features! 🎉",
],
}),
)
}, 1000)
window.__app_is_upgraded__ = true
// NOTE: Add migration logic here
}

View File

@ -9,13 +9,11 @@ import { Chain } from "@follow/utils/chain"
import { cn } from "@follow/utils/utils"
import { DotLottieReact } from "@lottiefiles/dotlottie-react"
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import type { SingletonRefObject } from "foxact/use-singleton"
import { useSingleton } from "foxact/use-singleton"
import type { PrimitiveAtom } from "jotai"
import { atom, useStore } from "jotai"
import { nanoid } from "nanoid"
import type { FC, ReactNode } from "react"
import { useEffect, useId, useMemo, useRef } from "react"
import { useEffect, useId, useMemo, useRef, useState } from "react"
import { Trans, useTranslation } from "react-i18next"
import { useServerConfigs } from "~/atoms/server-configs"
@ -79,7 +77,7 @@ type Achievement = ExtractBizResponse<typeof apiClient.achievement.$get>["data"]
export const AchievementModalContent: FC = () => {
const jotaiStore = useStore()
const defaultAchievements = useSingleton(buildDefaultAchievements)
const defaultAchievements = useState(buildDefaultAchievements)[0]
const {
data: achievements,
@ -97,10 +95,10 @@ export const AchievementModalContent: FC = () => {
},
})
jotaiStore.set(achievementsDataAtom.current, res.data)
jotaiStore.set(achievementsDataAtom, res.data)
return res.data
},
initialData: defaultAchievements.current as Achievement,
initialData: defaultAchievements as Achievement,
})
useEffect(() => {
@ -126,7 +124,7 @@ export const AchievementModalContent: FC = () => {
}
}, [achievements, isLoading, refetch])
const achievementsDataAtom = useSingleton(() => atom<typeof achievements>())
const achievementsDataAtom = useState(() => atom<typeof achievements>())[0]
const t = useI18n()
@ -257,7 +255,7 @@ const buildDefaultAchievements = () => {
}
const MintButton: FC<{
achievementsDataAtom: SingletonRefObject<PrimitiveAtom<Achievement | undefined>>
achievementsDataAtom: PrimitiveAtom<Achievement | undefined>
achievement: Achievement[number]
}> = ({ achievementsDataAtom, achievement }) => {
const { mutateAsync: mintAchievement, isPending: isMinting } = useMutation({
@ -280,7 +278,7 @@ const MintButton: FC<{
onClick={async () => {
const res = await mintAchievement(achievement.actionId)
const currentData = jotaiStore.get(achievementsDataAtom.current)
const currentData = jotaiStore.get(achievementsDataAtom)
if (!currentData) return
let shouldInvalidate = false
const newData = currentData.map((item) => {
@ -295,7 +293,7 @@ const MintButton: FC<{
}
return item
})
jotaiStore.set(achievementsDataAtom.current, newData)
jotaiStore.set(achievementsDataAtom, newData)
if (shouldInvalidate) {
queryClient.invalidateQueries({ queryKey: ["achievements"] })

View File

@ -14,11 +14,10 @@ import { RadioGroup } from "@follow/components/ui/radio-group/RadioGroup.jsx"
import type { FeedViewType } from "@follow/constants"
import { zodResolver } from "@hookform/resolvers/zod"
import { useMutation } from "@tanstack/react-query"
import { useSingleton } from "foxact/use-singleton"
import { produce } from "immer"
import { atom, useAtomValue, useStore } from "jotai"
import type { FC } from "react"
import { memo, useCallback, useEffect } from "react"
import { memo, useCallback, useEffect, useState } from "react"
import { useForm } from "react-hook-form"
import { useTranslation } from "react-i18next"
import { z } from "zod"
@ -90,7 +89,7 @@ export function DiscoverForm({ type = "search" }: { type?: string }) {
return data
},
})
const discoverSearchDataAtom = useSingleton(() => atom<DiscoverSearchData>()).current
const discoverSearchDataAtom = useState(() => atom<DiscoverSearchData>())[0]
const discoverSearchData = useAtomValue(discoverSearchDataAtom)

View File

@ -3,7 +3,6 @@ import { useScrollViewElement } from "@follow/components/ui/scroll-area/hooks.js
import { Skeleton } from "@follow/components/ui/skeleton/index.jsx"
import { useRefValue } from "@follow/hooks"
import { nextFrame } from "@follow/utils/dom"
import { useSingleton } from "foxact/use-singleton"
import { throttle } from "lodash-es"
import type { RenderComponentProps } from "masonic"
import { useInfiniteLoader } from "masonic"
@ -60,7 +59,7 @@ const gutter = 24
export const PictureMasonry: FC<MasonryProps> = (props) => {
const { data } = props
const cacheMap = useSingleton(() => new Map<string, object>()).current
const cacheMap = useState(() => new Map<string, object>())[0]
const [isInitDim, setIsInitDim] = useState(false)
const [isInitLayout, setIsInitLayout] = useState(false)
const [currentItemWidth, setCurrentItemWidth] = useState(0)
@ -277,7 +276,7 @@ interface MasonryProps {
const LoadingSkeletonItem = () => {
// random height, between 100-400px
const randomHeight = useSingleton(() => Math.random() * 300 + 100).current
const randomHeight = useState(() => Math.random() * 300 + 100)[0]
return (
<div className="relative flex gap-2 overflow-x-auto">
<div

View File

@ -1,6 +1,7 @@
import { useViewport } from "@follow/components/hooks/useViewport.js"
import { PanelSplitter } from "@follow/components/ui/divider/index.js"
import { RootPortal } from "@follow/components/ui/portal/index.jsx"
import { useOnce } from "@follow/hooks"
import { IN_ELECTRON } from "@follow/shared/constants"
import { preventDefault } from "@follow/utils/dom"
import { cn } from "@follow/utils/utils"
@ -14,6 +15,7 @@ import { useHotkeys } from "react-hotkeys-hook"
import { Trans, useTranslation } from "react-i18next"
import { useResizable } from "react-resizable-layout"
import { Outlet } from "react-router-dom"
import { toast } from "sonner"
import { setMainContainerElement } from "~/atoms/dom"
import { getUISettings, setUISetting, useUISettingKey } from "~/atoms/settings/ui"
@ -85,6 +87,22 @@ const errorTypes = [
ErrorComponentType.FeedNotFound,
] as ErrorComponentType[]
const useAppUpgraded = () => {
useOnce(() => {
if (!window.__app_is_upgraded__) {
setTimeout(() => {
toast.success(
<div>
App is upgraded to{" "}
<a href={`${repository.url}/releases/tag/${APP_VERSION}`}>{APP_VERSION}</a>, enjoy the
new features! 🎉
</div>,
)
})
}
})
}
const supportMinWidth = 1024
export function Component() {
const isAuthFail = useLoginModalShow()
@ -93,6 +111,7 @@ export function Component() {
const containerRef = useRef<HTMLDivElement>(null)
useDailyTask()
useAppUpgraded()
const isNotSupportWidth = useViewport((v) => v.w < supportMinWidth && v.w !== 0) && !IN_ELECTRON

View File

@ -50,8 +50,13 @@ const InvalidateQueryProviderElectron = () => {
`Window switch to visible, but skip invalidation, ${currentTimeRef.current ? now - currentTimeRef.current : 0}`,
)
} else {
appLog("Window switch to visible, invalidate all queries")
queryClient.invalidateQueries()
appLog("Window switch to visible, invalidate all queries except entries")
queryClient.invalidateQueries({
predicate(query) {
// Ignore entries queries
return query.queryKey[0] !== "entries"
},
})
}
currentTimeRef.current = 0
}

View File

@ -1,8 +1,10 @@
import { useSingleton } from "foxact/use-singleton"
import { useEffect, useRef } from "react"
export const useOnce = (fn: () => any) => {
useSingleton(async () => {
await fn()
return true
})
const isDone = useRef(false)
useEffect(() => {
if (isDone.current) return
fn()
isDone.current = true
}, [])
}