build: update lint config (#3234)

* build: update lint config

* update

* update

* update
This commit is contained in:
Stephen Zhou 2025-03-22 12:35:53 +08:00 committed by GitHub
parent 8b8487b1f7
commit fa3cce2fa9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 1327 additions and 1252 deletions

View File

@ -90,6 +90,7 @@
"sonner": "2.0.1",
"tldts": "6.1.84",
"use-context-selector": "2.0.0",
"use-sync-external-store": "1.4.0",
"usehooks-ts": "3.1.1",
"zod": "3.24.2",
"zustand": "5.0.3"

View File

@ -90,21 +90,19 @@ export const CollapseContent: Component<{
return v
}, [])
return (
<>
<AnimatePresence initial={false}>
{isOpened && (
<m.div
key="content"
initial="collapsed"
animate="open"
exit="collapsed"
variants={variants}
className={className}
>
{children}
</m.div>
)}
</AnimatePresence>
</>
<AnimatePresence initial={false}>
{isOpened && (
<m.div
key="content"
initial="collapsed"
animate="open"
exit="collapsed"
variants={variants}
className={className}
>
{children}
</m.div>
)}
</AnimatePresence>
)
}

View File

@ -96,15 +96,13 @@ const UnfollowInfo = ({ title, undo }: { title: string; undo: () => any }) => {
preventDefault: true,
})
return (
<>
<Trans
ns="app"
i18nKey="notify.unfollow_feed"
components={{
FeedItem: <i className="mr-px font-semibold">{title}</i>,
}}
/>
</>
<Trans
ns="app"
i18nKey="notify.unfollow_feed"
components={{
FeedItem: <i className="mr-px font-semibold">{title}</i>,
}}
/>
)
}

View File

@ -267,7 +267,7 @@ const createRelatedEntryLink = (variant: "toast" | "modal") => (props: LinkProps
autoFocus: false,
modalClassName:
"relative mx-auto mt-[10vh] scrollbar-none max-w-full overflow-auto px-2 lg:max-w-[65rem] lg:p-0",
// eslint-disable-next-line @eslint-react/no-nested-components
// eslint-disable-next-line @eslint-react/no-nested-component-definitions
CustomModalComponent: ({ children }) => {
const { feedId } = useEntry(entryId) || {}
return <PeekModal to={`/timeline/${feedId}/${entryId}`}>{children}</PeekModal>

View File

@ -145,55 +145,50 @@ const InboxInnerForm = ({
</CardHeader>
</Card>
)}
<>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className={cn("space-y-4")}
data-testid="discover-form"
>
{!inbox && (
<FormField
control={form.control}
name="handle"
render={({ field }) => (
<FormItem>
<FormLabel>{t("discover.inbox_handle")}</FormLabel>
<FormControl>
<div className={cn("flex w-64 items-center gap-2")}>
<Input autoFocus {...field} />
<span className="text-zinc-500">{env.VITE_INBOXES_EMAIL}</span>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
)}
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className={cn("space-y-4")}
data-testid="discover-form"
>
{!inbox && (
<FormField
control={form.control}
name="title"
name="handle"
render={({ field }) => (
<FormItem>
<FormLabel>{t("discover.inbox_title")}</FormLabel>
<FormLabel>{t("discover.inbox_handle")}</FormLabel>
<FormControl>
<Input {...field} />
<div className={cn("flex w-64 items-center gap-2")}>
<Input autoFocus {...field} />
<span className="text-zinc-500">{env.VITE_INBOXES_EMAIL}</span>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div
className={cn("center flex justify-end gap-4")}
data-testid="discover-form-actions"
>
<Button type="submit" isLoading={mutationCreate.isPending}>
{t(inbox ? "discover.inbox_update" : "discover.inbox_create")}
</Button>
</div>
</form>
</Form>
</>
)}
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem>
<FormLabel>{t("discover.inbox_title")}</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className={cn("center flex justify-end gap-4")} data-testid="discover-form-actions">
<Button type="submit" isLoading={mutationCreate.isPending}>
{t(inbox ? "discover.inbox_update" : "discover.inbox_create")}
</Button>
</div>
</form>
</Form>
</div>
)
}

View File

@ -41,17 +41,15 @@ export const EntryTranslation: Component<{
</HTML>
</>
) : (
<>
<div className={cn("inline align-middle", className)}>
{nextTarget && (
<>
<span className="align-middle">{nextTarget}</span>
<i className="i-mgc-translate-2-cute-re mr-2 align-middle" />
</>
)}
<span className="align-middle">{source}</span>
</div>
</>
<div className={cn("inline align-middle", className)}>
{nextTarget && (
<>
<span className="align-middle">{nextTarget}</span>
<i className="i-mgc-translate-2-cute-re mr-2 align-middle" />
</>
)}
<span className="align-middle">{source}</span>
</div>
)}
</div>
)

View File

@ -37,30 +37,28 @@ export const SourceContentView = ({ src }: { src: string }) => {
}, [src, showSourceContent])
return (
<>
<div className="relative flex size-full flex-col">
{loading && (
<div className="center mt-16 min-w-0">
<EntryContentLoading icon={src} />
</div>
)}
<m.div
<div className="relative flex size-full flex-col">
{loading && (
<div className="center mt-16 min-w-0">
<EntryContentLoading icon={src} />
</div>
)}
<m.div
className="size-full"
initial={{ opacity: 0 }}
animate={{ opacity: loading ? 0 : 1 }}
transition={softSpringPreset}
>
<ViewTag
ref={webviewRef}
className="size-full"
initial={{ opacity: 0 }}
animate={{ opacity: loading ? 0 : 1 }}
transition={softSpringPreset}
>
<ViewTag
ref={webviewRef}
className="size-full"
src={src}
sandbox="allow-scripts allow-same-origin"
// For iframe
onLoad={() => setLoading(false)}
/>
</m.div>
</div>
</>
src={src}
sandbox="allow-scripts allow-same-origin"
// For iframe
onLoad={() => setLoading(false)}
/>
</m.div>
</div>
)
}

View File

@ -6,7 +6,7 @@ import { parseSafeUrl } from "@follow/utils/utils"
import { Label } from "@radix-ui/react-label"
import { PopoverPortal } from "@radix-ui/react-popover"
import { atomWithStorage } from "jotai/utils"
import { forwardRef, Fragment, useState } from "react"
import { forwardRef, useState } from "react"
import { useGeneralSettingKey, useGeneralSettingValue } from "~/atoms/settings/general"
import { jotaiStore } from "~/lib/jotai"
@ -87,33 +87,31 @@ const WarnGoToExternalLinkImpl = forwardRef<
}
}
return (
<Fragment>
<Popover open={open} onOpenChange={(v) => !v && setOpen(false)}>
<PopoverTrigger asChild>
<a ref={ref} {...rest} onClick={handleOpen} />
</PopoverTrigger>
<PopoverPortal>
<PopoverContent>
<p className="max-w-[50ch] text-sm">
You are about to leave this site to go to an external page, do you trust this URL and
go to it?
</p>
<p className="mt-2 text-center text-sm underline">{rest.href}</p>
<Popover open={open} onOpenChange={(v) => !v && setOpen(false)}>
<PopoverTrigger asChild>
<a ref={ref} {...rest} onClick={handleOpen} />
</PopoverTrigger>
<PopoverPortal>
<PopoverContent>
<p className="max-w-[50ch] text-sm">
You are about to leave this site to go to an external page, do you trust this URL and go
to it?
</p>
<p className="mt-2 text-center text-sm underline">{rest.href}</p>
<div className="mt-3 flex justify-between">
<Label className="center flex">
<Checkbox checked={checked} onCheckedChange={setChecked} />
<span className="ml-2 text-[13px]">Trust this domain</span>
</Label>
<div className="mt-3 flex justify-between">
<Label className="center flex">
<Checkbox checked={checked} onCheckedChange={setChecked} />
<span className="ml-2 text-[13px]">Trust this domain</span>
</Label>
<IconButton icon={<i className="i-mingcute-arrow-right-line" />} onClick={handleGo}>
<span className="duration-200 group-hover:opacity-0">Go</span>
</IconButton>
</div>
</PopoverContent>
</PopoverPortal>
</Popover>
</Fragment>
<IconButton icon={<i className="i-mingcute-arrow-right-line" />} onClick={handleGo}>
<span className="duration-200 group-hover:opacity-0">Go</span>
</IconButton>
</div>
</PopoverContent>
</PopoverPortal>
</Popover>
)
})

View File

@ -70,148 +70,146 @@ export const ProfileButton: FC<ProfileButtonProps> = memo((props) => {
}
return (
<>
<DropdownMenu onOpenChange={setDropdown}>
<DropdownMenuTrigger
asChild
className="focus-visible:bg-theme-item-hover !outline-none data-[state=open]:bg-transparent"
<DropdownMenu onOpenChange={setDropdown}>
<DropdownMenuTrigger
asChild
className="focus-visible:bg-theme-item-hover !outline-none data-[state=open]:bg-transparent"
>
{props.animatedAvatar ? (
<TransitionAvatar stage={dropdown ? "zoom-in" : ""} />
) : (
<UserAvatar hideName className="size-6 p-0 [&_*]:border-0" />
)}
</DropdownMenuTrigger>
<DropdownMenuContent
className="min-w-[180px] overflow-visible px-1 pt-6"
side="bottom"
align="center"
>
<DropdownMenuLabel>
<div className="text-center leading-none">
<EllipsisHorizontalTextWithTooltip className="mx-auto max-w-[20ch] truncate text-lg">
{user?.name}
</EllipsisHorizontalTextWithTooltip>
{!!user?.handle && (
<a href={UrlBuilder.profile(user.handle)} target="_blank" className="block">
<EllipsisHorizontalTextWithTooltip className="mt-0.5 truncate text-xs font-medium text-zinc-500">
@{user.handle}
</EllipsisHorizontalTextWithTooltip>
</a>
)}
</div>
</DropdownMenuLabel>
<DropdownMenuItem
onClick={() => {
navigate("/power")
}}
>
{props.animatedAvatar ? (
<TransitionAvatar stage={dropdown ? "zoom-in" : ""} />
) : (
<UserAvatar hideName className="size-6 p-0 [&_*]:border-0" />
)}
</DropdownMenuTrigger>
<div className="flex w-full items-center justify-between gap-6 px-1.5 font-semibold">
<PowerButton isLoading={isLoadingWallet} myWallet={myWallet} />
<Level level={myWallet?.level?.level || 0} isLoading={isLoadingWallet} />
<ActivityPoints
className="text-sm"
points={myWallet?.level?.prevActivityPoints || 0}
isLoading={isLoadingWallet}
/>
</div>
</DropdownMenuItem>
<DropdownMenuContent
className="min-w-[180px] overflow-visible px-1 pt-6"
side="bottom"
align="center"
<DropdownMenuSeparator />
<DropdownMenuItem
className="pl-3"
onClick={() => {
presentUserProfile(user?.id)
}}
icon={<i className="i-mgc-user-3-cute-re" />}
>
<DropdownMenuLabel>
<div className="text-center leading-none">
<EllipsisHorizontalTextWithTooltip className="mx-auto max-w-[20ch] truncate text-lg">
{user?.name}
</EllipsisHorizontalTextWithTooltip>
{!!user?.handle && (
<a href={UrlBuilder.profile(user.handle)} target="_blank" className="block">
<EllipsisHorizontalTextWithTooltip className="mt-0.5 truncate text-xs font-medium text-zinc-500">
@{user.handle}
</EllipsisHorizontalTextWithTooltip>
</a>
)}
</div>
</DropdownMenuLabel>
{t("user_button.profile")}
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => {
navigate("/power")
}}
>
<div className="flex w-full items-center justify-between gap-6 px-1.5 font-semibold">
<PowerButton isLoading={isLoadingWallet} myWallet={myWallet} />
<Level level={myWallet?.level?.level || 0} isLoading={isLoadingWallet} />
<ActivityPoints
className="text-sm"
points={myWallet?.level?.prevActivityPoints || 0}
isLoading={isLoadingWallet}
/>
</div>
</DropdownMenuItem>
<DropdownMenuItem
className="pl-3"
onClick={() => {
if (role !== UserRole.Trial) {
presentAchievement()
} else {
presentActivationModal()
}
}}
icon={<i className="i-mgc-trophy-cute-re" />}
>
{t("user_button.achievement")}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuSeparator />
{!zenModeSetting && (
<DropdownMenuItem
className="pl-3"
onClick={() => {
presentUserProfile(user?.id)
setZenMode(true)
}}
icon={<i className="i-mgc-user-3-cute-re" />}
icon={<MdiMeditation className="size-4" />}
>
{t("user_button.profile")}
{t("user_button.zen_mode")}
</DropdownMenuItem>
)}
<DropdownMenuItem
className="pl-3"
onClick={() => {
navigate("/action")
}}
icon={<i className="i-mgc-magic-2-cute-re" />}
>
{t("words.actions")}
</DropdownMenuItem>
<DropdownMenuItem
className="pl-3"
onClick={() => {
navigate("/rsshub")
}}
icon={<img src={rsshubLogo} className="size-3 grayscale" />}
>
{t("words.rsshub")}
</DropdownMenuItem>
<DropdownMenuItem
className="pl-3"
onClick={() => {
if (role !== UserRole.Trial) {
presentAchievement()
} else {
presentActivationModal()
}
}}
icon={<i className="i-mgc-trophy-cute-re" />}
>
{t("user_button.achievement")}
</DropdownMenuItem>
<DropdownMenuSeparator />
{!zenModeSetting && (
<DropdownMenuSeparator />
<DropdownMenuItem
className="pl-3"
onClick={() => {
settingModalPresent()
}}
icon={<i className="i-mgc-settings-7-cute-re" />}
>
{t("user_button.preferences")}
</DropdownMenuItem>
<DropdownMenuSeparator />
{!window.electron && (
<>
<DropdownMenuItem
className="pl-3"
onClick={() => {
setZenMode(true)
window.open(`${repository.url}/releases`)
}}
icon={<MdiMeditation className="size-4" />}
icon={<i className="i-mgc-download-2-cute-re" />}
>
{t("user_button.zen_mode")}
{t("user_button.download_desktop_app")}
</DropdownMenuItem>
)}
<DropdownMenuItem
className="pl-3"
onClick={() => {
navigate("/action")
}}
icon={<i className="i-mgc-magic-2-cute-re" />}
>
{t("words.actions")}
</DropdownMenuItem>
<DropdownMenuItem
className="pl-3"
onClick={() => {
navigate("/rsshub")
}}
icon={<img src={rsshubLogo} className="size-3 grayscale" />}
>
{t("words.rsshub")}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
className="pl-3"
onClick={() => {
settingModalPresent()
}}
icon={<i className="i-mgc-settings-7-cute-re" />}
>
{t("user_button.preferences")}
</DropdownMenuItem>
<DropdownMenuSeparator />
{!window.electron && (
<>
<DropdownMenuItem
className="pl-3"
onClick={() => {
window.open(`${repository.url}/releases`)
}}
icon={<i className="i-mgc-download-2-cute-re" />}
>
{t("user_button.download_desktop_app")}
</DropdownMenuItem>
<DropdownMenuSeparator />
</>
)}
<DropdownMenuItem
className="pl-3"
onClick={signOut}
icon={<i className="i-mgc-exit-cute-re" />}
>
{t("user_button.log_out")}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</>
<DropdownMenuSeparator />
</>
)}
<DropdownMenuItem
className="pl-3"
onClick={signOut}
icon={<i className="i-mgc-exit-cute-re" />}
>
{t("user_button.log_out")}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
})
ProfileButton.displayName = "ProfileButton"

View File

@ -108,6 +108,7 @@
"react-native-webview": "13.13.4",
"shiki": "3.2.1",
"tailwindcss": "3.4.17",
"use-sync-external-store": "1.4.0",
"usehooks-ts": "3.1.1",
"zeego": "3.0.5",
"zod": "3.24.2",

View File

@ -59,19 +59,17 @@ export function BaseSearchPageFlatList<T>({
const windowWidth = useWindowDimensions().width
return (
<>
<ReAnimated.FlatList
itemLayoutAnimation={LinearTransition}
className="flex-1"
style={{ width: windowWidth }}
contentContainerStyle={{ paddingTop: offsetTop + 8 }}
scrollIndicatorInsets={{ bottom: insets.bottom, top: offsetTop }}
automaticallyAdjustContentInsets
contentInsetAdjustmentBehavior="always"
scrollEventThrottle={16}
{...props}
/>
</>
<ReAnimated.FlatList
itemLayoutAnimation={LinearTransition}
className="flex-1"
style={{ width: windowWidth }}
contentContainerStyle={{ paddingTop: offsetTop + 8 }}
scrollIndicatorInsets={{ bottom: insets.bottom, top: offsetTop }}
automaticallyAdjustContentInsets
contentInsetAdjustmentBehavior="always"
scrollEventThrottle={16}
{...props}
/>
)
}

View File

@ -100,14 +100,12 @@ export const UnreadOnlyActionButton = ({ variant = "primary" }: HeaderActionButt
export const AddFeedButton = () => {
return (
<>
<UIBarButton
label="Add Feed"
normalIcon={<AddCuteReIcon color={accentColor} />}
onPress={() => {
Dialog.show(AddFeedDialog)
}}
/>
</>
<UIBarButton
label="Add Feed"
normalIcon={<AddCuteReIcon color={accentColor} />}
onPress={() => {
Dialog.show(AddFeedDialog)
}}
/>
)
}

View File

@ -1,17 +1,12 @@
import { atom, useAtomValue, useSetAtom } from "jotai"
import type { FC, PropsWithChildren } from "react"
import { Fragment } from "react"
import { createPortal } from "react-dom"
const portalAtoms = atom(null as HTMLElement | null)
export const TeleportalDestination = () => {
const setPortal = useSetAtom(portalAtoms)
return (
<Fragment>
<div className="flex flex-col" ref={setPortal} />
</Fragment>
)
return <div className="flex flex-col" ref={setPortal} />
}
export const TeleportalTakeOff: FC<PropsWithChildren> = ({ children }) => {

View File

@ -35,11 +35,7 @@ export function Component() {
useTitle(feed.data?.feed.title)
if (feed.isLoading || !feed.data?.feed || !feedData) {
return (
<>
<LoadingCircle size="large" className="center fixed inset-0" />
</>
)
return <LoadingCircle size="large" className="center fixed inset-0" />
}
return (

View File

@ -44,9 +44,9 @@
"@iconify/tools": "4.1.1",
"@tailwindcss/container-queries": "0.1.1",
"@tailwindcss/typography": "0.5.16",
"@tsslint/cli": "1.5.8",
"@tsslint/config": "1.5.8",
"@tsslint/eslint": "1.5.8",
"@tsslint/cli": "1.5.11",
"@tsslint/config": "1.5.11",
"@tsslint/eslint": "1.5.11",
"@types/node": "22.13.10",
"@types/react": "18.3.12",
"@types/react-dom": "18.3.1",
@ -55,8 +55,8 @@
"autoprefixer": "10.4.21",
"cross-env": "7.0.3",
"cssnano": "7.0.6",
"eslint": "9.22.0",
"eslint-config-hyoban": "4.0.1",
"eslint": "9.23.0",
"eslint-config-hyoban": "4.0.2",
"eslint-plugin-react-native": "5.0.0",
"fast-glob": "3.3.3",
"lint-staged": "15.5.0",

View File

@ -10,39 +10,39 @@ export function SimpleIconsReadeck(props: SVGProps<SVGSVGElement>) {
{...props}
>
<path
fill-rule="nonzero"
fillRule="nonzero"
fill="currentColor"
fill-opacity="1"
fillOpacity="1"
d="M 191.011719 69.769531 L 91.191406 116.308594 L 91.191406 187.800781 L 218.394531 128.492188 Z M 191.011719 69.769531 "
/>
<path
fill-rule="nonzero"
fillRule="nonzero"
fill="currentColor"
fill-opacity="1"
fillOpacity="1"
d="M 91.191406 117.808594 L 91.191406 189.304688 L 197.078125 238.671875 L 190.730469 199.960938 L 224.460938 179.949219 Z M 91.191406 117.808594 "
/>
<path
fill-rule="nonzero"
fillRule="nonzero"
fill="currentColor"
fill-opacity="1"
fillOpacity="1"
d="M 26.386719 38.96875 L 91.191406 38.96875 L 91.191406 230.949219 L 26.386719 230.949219 Z M 26.386719 38.96875 "
/>
<path
fill-rule="nonzero"
fillRule="nonzero"
fill="currentColor"
fill-opacity="0.313726"
fillOpacity="0.313726"
d="M 26.382812 38.96875 L 26.382812 43.105469 L 213.953125 130.5625 L 218.398438 128.488281 Z M 26.382812 38.96875 "
/>
<path
fill-rule="nonzero"
fillRule="nonzero"
fill="currentColor"
fill-opacity="1"
fillOpacity="1"
d="M 91.191406 3.222656 L 26.386719 38.96875 L 218.394531 128.492188 L 218.394531 57 Z M 91.191406 3.222656 "
/>
<path
fill-rule="nonzero"
fillRule="nonzero"
fill="white"
fill-opacity="1"
fillOpacity="1"
d="M 91.191406 69.1875 L 91.191406 116.308594 L 141.726562 92.75 Z M 91.191406 69.1875 "
/>
</svg>

File diff suppressed because it is too large Load Diff