refactor: enhance mobile settings modal and layout components
- Introduced `useTypeScriptHappyCallback` for improved tab change handling in the mobile settings modal. - Updated the `Content` component to utilize `useLoaderData` for better data management and added a dynamic `viewportClassName`. - Simplified the `SettingItemButtonImpl` by removing the `tab` prop and using an `isActive` flag for better clarity in active state management. Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
parent
00342e7a7d
commit
de00a1864e
|
|
@ -1,3 +1,4 @@
|
|||
import { useTypeScriptHappyCallback } from "@follow/hooks"
|
||||
import PKG from "@pkg"
|
||||
import { createElement, Suspense } from "react"
|
||||
import { Trans, useTranslation } from "react-i18next"
|
||||
|
|
@ -21,12 +22,15 @@ export const MobileSettingModalContent = () => {
|
|||
</div>
|
||||
|
||||
<SidebarItems
|
||||
onChange={(tab) => {
|
||||
present({
|
||||
title: "",
|
||||
content: () => <Content tab={tab} />,
|
||||
})
|
||||
}}
|
||||
onChange={useTypeScriptHappyCallback(
|
||||
(tab) => {
|
||||
present({
|
||||
title: "",
|
||||
content: () => <Content tab={tab} />,
|
||||
})
|
||||
},
|
||||
[present],
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
import { ScrollArea } from "@follow/components/ui/scroll-area/index.js"
|
||||
import { cn } from "@follow/utils"
|
||||
import { repository } from "@pkg"
|
||||
import type { FC } from "react"
|
||||
import { Suspense, useDeferredValue, useLayoutEffect, useState } from "react"
|
||||
import { Trans } from "react-i18next"
|
||||
import { useLoaderData } from "react-router"
|
||||
|
||||
import { ModalClose } from "~/components/ui/modal/stacked/components"
|
||||
import { SettingsTitle } from "~/modules/settings/title"
|
||||
|
||||
import { getSettingPages } from "../settings-glob"
|
||||
import type { SettingPageConfig } from "../utils"
|
||||
import { SettingTabProvider, useSettingTab } from "./context"
|
||||
import { SettingModalLayout } from "./layout"
|
||||
|
||||
|
|
@ -39,6 +42,7 @@ const Content = () => {
|
|||
}
|
||||
}, [key])
|
||||
|
||||
const config = (useLoaderData() || loader || {}) as SettingPageConfig
|
||||
if (!Component) return null
|
||||
|
||||
return (
|
||||
|
|
@ -49,12 +53,15 @@ const Content = () => {
|
|||
mask={false}
|
||||
ref={setScroller}
|
||||
rootClassName="h-full grow flex-1 shrink-0 overflow-auto pl-8 pr-7"
|
||||
viewportClassName="px-1 min-h-full [&>div]:min-h-full [&>div]:relative pb-8"
|
||||
viewportClassName={cn(
|
||||
"px-1 min-h-full [&>div]:min-h-full [&>div]:relative",
|
||||
config.viewportClassName,
|
||||
)}
|
||||
>
|
||||
<Component />
|
||||
|
||||
<div className="h-12" />
|
||||
<p className="absolute inset-x-0 bottom-0 flex items-center justify-center gap-1 text-xs opacity-80">
|
||||
<div className="h-16" />
|
||||
<p className="absolute inset-x-0 bottom-4 flex items-center justify-center gap-1 text-xs opacity-80">
|
||||
<Trans
|
||||
ns="settings"
|
||||
i18nKey="common.give_star"
|
||||
|
|
|
|||
|
|
@ -155,14 +155,13 @@ export function SettingModalLayout(
|
|||
}
|
||||
|
||||
const SettingItemButtonImpl = (props: {
|
||||
tab: string
|
||||
setTab: (tab: string) => void
|
||||
item: SettingPageConfig
|
||||
path: string
|
||||
|
||||
isActive: boolean
|
||||
onChange?: (tab: string) => void
|
||||
}) => {
|
||||
const { tab, setTab, item, path, onChange } = props
|
||||
const { setTab, item, path, onChange, isActive } = props
|
||||
const { disableIf } = item
|
||||
|
||||
const ctx = useSettingPageContext()
|
||||
|
|
@ -174,7 +173,7 @@ const SettingItemButtonImpl = (props: {
|
|||
<button
|
||||
className={cn(
|
||||
"text-text my-0.5 flex w-full items-center rounded-lg px-2.5 py-0.5 leading-loose",
|
||||
tab === path && "!bg-theme-item-active !text-text",
|
||||
isActive && "!bg-theme-item-active !text-text",
|
||||
!IN_ELECTRON && "hover:bg-theme-item-hover duration-200",
|
||||
disabled && "cursor-not-allowed opacity-50",
|
||||
)}
|
||||
|
|
@ -202,22 +201,22 @@ const SettingItemButtonImpl = (props: {
|
|||
|
||||
const SettingItemButton = memo(SettingItemButtonImpl)
|
||||
|
||||
export const SidebarItems = memo(
|
||||
(props: { onChange?: (tab: string) => void }) => {
|
||||
const { onChange } = props
|
||||
const setTab = useSetSettingTab()
|
||||
const tab = useSettingTab()
|
||||
const availableSettings = useAvailableSettings()
|
||||
return availableSettings.map((t) => (
|
||||
export const SidebarItems = memo((props: { onChange?: (tab: string) => void }) => {
|
||||
const { onChange } = props
|
||||
const setTab = useSetSettingTab()
|
||||
const tab = useSettingTab()
|
||||
const availableSettings = useAvailableSettings()
|
||||
return availableSettings.map((t) => {
|
||||
const isActive = tab === t.path
|
||||
return (
|
||||
<SettingItemButton
|
||||
key={t.path}
|
||||
tab={tab}
|
||||
isActive={isActive}
|
||||
setTab={setTab}
|
||||
item={t}
|
||||
path={t.path}
|
||||
onChange={onChange}
|
||||
/>
|
||||
))
|
||||
},
|
||||
() => true,
|
||||
)
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue