fix: toggle translation settings, close #4187
This commit is contained in:
parent
1fdf482f35
commit
51a243eeea
|
|
@ -283,8 +283,13 @@ const MasonryRender: React.ComponentType<
|
|||
}>
|
||||
> = ({ data, index }) => {
|
||||
const firstScreenReady = use(FirstScreenReadyContext)
|
||||
const enableTranslation = useGeneralSettingKey("translation")
|
||||
const actionLanguage = useActionLanguage()
|
||||
const translation = useEntryTranslation(data.entryId, actionLanguage)
|
||||
const translation = useEntryTranslation({
|
||||
entryId: data.entryId,
|
||||
language: actionLanguage,
|
||||
setting: enableTranslation,
|
||||
})
|
||||
|
||||
if (data.entryId.startsWith("placeholder")) {
|
||||
return <LoadingSkeletonItem />
|
||||
|
|
|
|||
|
|
@ -173,13 +173,17 @@ const PreviewVideoModalContent: ModalContentComponent<{
|
|||
}> = ({ dismiss, src, entryId }) => {
|
||||
const entry = useEntry(entryId, (state) => ({ content: state.content }))
|
||||
|
||||
const actionLanguage = useActionLanguage()
|
||||
const enableTranslation = useGeneralSettingKey("translation")
|
||||
const translation = useEntryTranslation(entryId, actionLanguage)
|
||||
const actionLanguage = useActionLanguage()
|
||||
const translation = useEntryTranslation({
|
||||
entryId,
|
||||
language: actionLanguage,
|
||||
setting: enableTranslation,
|
||||
})
|
||||
usePrefetchEntryTranslation({
|
||||
entryIds: [entryId],
|
||||
checkLanguage,
|
||||
translation: enableTranslation,
|
||||
setting: enableTranslation,
|
||||
language: actionLanguage,
|
||||
withContent: true,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -22,13 +22,17 @@ const EntryItemImpl = memo(function EntryItemImpl({
|
|||
entryId: string
|
||||
view: FeedViewType
|
||||
}) {
|
||||
const actionLanguage = useActionLanguage()
|
||||
const enableTranslation = useGeneralSettingKey("translation")
|
||||
const translation = useEntryTranslation(entryId, actionLanguage)
|
||||
const actionLanguage = useActionLanguage()
|
||||
const translation = useEntryTranslation({
|
||||
entryId,
|
||||
language: actionLanguage,
|
||||
setting: enableTranslation,
|
||||
})
|
||||
usePrefetchEntryTranslation({
|
||||
entryIds: [entryId],
|
||||
checkLanguage,
|
||||
translation: enableTranslation,
|
||||
setting: enableTranslation,
|
||||
language: actionLanguage,
|
||||
withContent: view === FeedViewType.SocialMedia,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { useWhoami } from "@follow/store/user/hooks"
|
|||
import { formatEstimatedMins, formatTimeToSeconds } from "@follow/utils"
|
||||
import { titleCase } from "title-case"
|
||||
|
||||
import { useShowAITranslation } from "~/atoms/ai-translation"
|
||||
import { useActionLanguage } from "~/atoms/settings/general"
|
||||
import { useUISettingKey } from "~/atoms/settings/ui"
|
||||
import { RelativeTime } from "~/components/ui/datetime"
|
||||
|
|
@ -57,9 +58,13 @@ export const EntryTitle = ({ entryId, compact }: EntryLinkProps) => {
|
|||
const data = useEntryReadHistory(entryId)
|
||||
const entryHistory = data?.entryReadHistories
|
||||
const populatedFullHref = useFeedSafeUrl(entryId)
|
||||
const enableTranslation = useShowAITranslation()
|
||||
const actionLanguage = useActionLanguage()
|
||||
|
||||
const translation = useEntryTranslation(entryId, actionLanguage)
|
||||
const translation = useEntryTranslation({
|
||||
entryId,
|
||||
language: actionLanguage,
|
||||
setting: enableTranslation,
|
||||
})
|
||||
|
||||
const dateFormat = useUISettingKey("dateFormat")
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ import { createElement, useCallback, useMemo } from "react"
|
|||
import { useTranslation } from "react-i18next"
|
||||
import { toast } from "sonner"
|
||||
|
||||
import { useShowAITranslation } from "~/atoms/ai-translation"
|
||||
import { useEntryIsInReadability, useEntryIsInReadabilitySuccess } from "~/atoms/readability"
|
||||
import { useActionLanguage, useGeneralSettingKey } from "~/atoms/settings/general"
|
||||
import { useActionLanguage } from "~/atoms/settings/general"
|
||||
import { useModalStack } from "~/components/ui/modal/stacked/hooks"
|
||||
import { checkLanguage } from "~/lib/translate"
|
||||
|
||||
|
|
@ -46,13 +47,17 @@ export const useEntryContent = (entryId: string) => {
|
|||
const isInReadabilityMode = useEntryIsInReadability(entryId)
|
||||
const isReadabilitySuccess = useEntryIsInReadabilitySuccess(entryId)
|
||||
|
||||
const enableTranslation = useShowAITranslation()
|
||||
const actionLanguage = useActionLanguage()
|
||||
const enableTranslation = useGeneralSettingKey("translation")
|
||||
const contentTranslated = useEntryTranslation(entryId, actionLanguage)
|
||||
const contentTranslated = useEntryTranslation({
|
||||
entryId,
|
||||
language: actionLanguage,
|
||||
setting: enableTranslation,
|
||||
})
|
||||
usePrefetchEntryTranslation({
|
||||
entryIds: [entryId],
|
||||
checkLanguage,
|
||||
translation: enableTranslation,
|
||||
setting: enableTranslation,
|
||||
language: actionLanguage,
|
||||
withContent: true,
|
||||
target: isReadabilitySuccess ? "readabilityContent" : "content",
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ export function EntryContentWebView(props: EntryContentWebViewProps) {
|
|||
const { entryId, noMedia, showReadability, showTranslation } = props
|
||||
const entry = useEntry(entryId, (state) => state)
|
||||
const language = useActionLanguage()
|
||||
const translation = useEntryTranslation(entryId, language)
|
||||
const translation = useEntryTranslation({ entryId, language, setting: showTranslation ?? false })
|
||||
|
||||
const [mode, setMode] = React.useState<"normal" | "debug">("normal")
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { useEntryTranslation } from "@follow/store/translation/hooks"
|
|||
import { cn } from "@follow/utils"
|
||||
import { Text, View } from "react-native"
|
||||
|
||||
import { useActionLanguage } from "@/src/atoms/settings/general"
|
||||
import { useActionLanguage, useGeneralSettingKey } from "@/src/atoms/settings/general"
|
||||
import { RelativeDateTime } from "@/src/components/ui/datetime/RelativeDateTime"
|
||||
import { FeedIcon } from "@/src/components/ui/icon/feed-icon"
|
||||
|
||||
|
|
@ -27,8 +27,13 @@ export const EntryGridFooter = ({
|
|||
read: state.read,
|
||||
translation: state.settings?.translation,
|
||||
}))
|
||||
const enableTranslation = useGeneralSettingKey("translation")
|
||||
const actionLanguage = useActionLanguage()
|
||||
const translation = useEntryTranslation(entryId, actionLanguage)
|
||||
const translation = useEntryTranslation({
|
||||
entryId,
|
||||
language: actionLanguage,
|
||||
setting: enableTranslation,
|
||||
})
|
||||
const feed = useFeedById(entry?.feedId || "")
|
||||
|
||||
if (!entry) return null
|
||||
|
|
|
|||
|
|
@ -1,20 +1,27 @@
|
|||
import { useEntry } from "@follow/store/entry/hooks"
|
||||
import { useFeedById } from "@follow/store/feed/hooks"
|
||||
import { useEntryTranslation } from "@follow/store/translation/hooks"
|
||||
import { useSetAtom } from "jotai"
|
||||
import { useAtomValue, useSetAtom } from "jotai"
|
||||
import { use } from "react"
|
||||
import { Text, View } from "react-native"
|
||||
|
||||
import { useActionLanguage } from "@/src/atoms/settings/general"
|
||||
import { useActionLanguage, useGeneralSettingKey } from "@/src/atoms/settings/general"
|
||||
import { UserAvatar } from "@/src/components/ui/avatar/UserAvatar"
|
||||
import { FeedIcon } from "@/src/components/ui/icon/feed-icon"
|
||||
import { EntryContentContext } from "@/src/modules/entry-content/ctx"
|
||||
import { EntryContentContext, useEntryContentContext } from "@/src/modules/entry-content/ctx"
|
||||
|
||||
import { EntryTranslation } from "../entry-list/templates/EntryTranslation"
|
||||
|
||||
export const EntryTitle = ({ title, entryId }: { title: string; entryId: string }) => {
|
||||
const { showAITranslationAtom } = useEntryContentContext()
|
||||
const showTranslationOnce = useAtomValue(showAITranslationAtom)
|
||||
const enableTranslation = useGeneralSettingKey("translation") || showTranslationOnce
|
||||
const actionLanguage = useActionLanguage()
|
||||
const translation = useEntryTranslation(entryId, actionLanguage)
|
||||
const translation = useEntryTranslation({
|
||||
entryId,
|
||||
language: actionLanguage,
|
||||
setting: enableTranslation,
|
||||
})
|
||||
|
||||
const { titleHeightAtom } = use(EntryContentContext)
|
||||
const setTitleHeight = useSetAtom(titleHeightAtom)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ export const EntryListContentArticle = ({
|
|||
usePrefetchEntryTranslation({
|
||||
entryIds: active ? viewableItems.map((item) => item.key) : [],
|
||||
language: actionLanguage,
|
||||
translation,
|
||||
setting: translation,
|
||||
checkLanguage,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ export const EntryListContentPicture = ({
|
|||
entryIds: active ? viewableItems.map((item) => item.key) : [],
|
||||
language: actionLanguage,
|
||||
checkLanguage,
|
||||
translation,
|
||||
setting: translation,
|
||||
})
|
||||
|
||||
const renderItem = useTypeScriptHappyCallback(({ item }: { item: string }) => {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export const EntryListContentSocial = ({
|
|||
usePrefetchEntryTranslation({
|
||||
entryIds: active ? viewableItems.map((item) => item.key) : [],
|
||||
language: actionLanguage,
|
||||
translation,
|
||||
setting: translation,
|
||||
checkLanguage,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export const EntryListContentVideo = ({
|
|||
usePrefetchEntryTranslation({
|
||||
entryIds: active ? viewableItems.map((item) => item.key) : [],
|
||||
language: actionLanguage,
|
||||
translation,
|
||||
setting: translation,
|
||||
checkLanguage,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { memo, useCallback, useMemo, useRef, useState } from "react"
|
|||
import type { ImageErrorEventData } from "react-native"
|
||||
import { Text, View } from "react-native"
|
||||
|
||||
import { useActionLanguage } from "@/src/atoms/settings/general"
|
||||
import { useActionLanguage, useGeneralSettingKey } from "@/src/atoms/settings/general"
|
||||
import { useUISettingKey } from "@/src/atoms/settings/ui"
|
||||
import { preloadWebViewEntry } from "@/src/components/native/webview/EntryContentWebView"
|
||||
import { RelativeDateTime } from "@/src/components/ui/datetime/RelativeDateTime"
|
||||
|
|
@ -52,8 +52,13 @@ export const EntryNormalItem = memo(
|
|||
title: state.title,
|
||||
description: state.description,
|
||||
}))
|
||||
const enableTranslation = useGeneralSettingKey("translation")
|
||||
const actionLanguage = useActionLanguage()
|
||||
const translation = useEntryTranslation(entryId, actionLanguage)
|
||||
const translation = useEntryTranslation({
|
||||
entryId,
|
||||
language: actionLanguage,
|
||||
setting: enableTranslation,
|
||||
})
|
||||
const from = getInboxFrom(entry)
|
||||
const feed = useFeedById(entry?.feedId as string)
|
||||
const navigation = useNavigation()
|
||||
|
|
|
|||
|
|
@ -44,8 +44,13 @@ export const EntrySocialItem = memo(
|
|||
author: state.author,
|
||||
translation: state.settings?.translation,
|
||||
}))
|
||||
const enableTranslation = useGeneralSettingKey("translation")
|
||||
const actionLanguage = useActionLanguage()
|
||||
const translation = useEntryTranslation(entryId, actionLanguage)
|
||||
const translation = useEntryTranslation({
|
||||
entryId,
|
||||
language: actionLanguage,
|
||||
setting: enableTranslation,
|
||||
})
|
||||
const { openLightbox } = useLightboxControls()
|
||||
|
||||
const feed = useFeedById(entry?.feedId || "")
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ export const EntryTranslation = ({
|
|||
showTranslation?: boolean
|
||||
bilingual?: boolean
|
||||
} & TextProps) => {
|
||||
const showTranslationFinal = useGeneralSettingKey("translation") || showTranslation
|
||||
const bilingualFinal = useGeneralSettingKey("translationMode") === "bilingual" || bilingual
|
||||
|
||||
const nextSource = useMemo(() => {
|
||||
|
|
@ -30,15 +29,11 @@ export const EntryTranslation = ({
|
|||
return source.trim()
|
||||
}, [source])
|
||||
const nextTarget = useMemo(() => {
|
||||
if (
|
||||
!target ||
|
||||
!showTranslationFinal ||
|
||||
nextSource.replaceAll(/\s/g, "") === target.replaceAll(/\s/g, "")
|
||||
) {
|
||||
if (!target || nextSource.replaceAll(/\s/g, "") === target.replaceAll(/\s/g, "")) {
|
||||
return ""
|
||||
}
|
||||
return target.trim()
|
||||
}, [nextSource, target, showTranslationFinal])
|
||||
}, [nextSource, target])
|
||||
|
||||
if (!bilingualFinal) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -130,9 +130,9 @@ export const EntryDetailScreen: NavigationControllerView<{
|
|||
|
||||
const EntryContentWebViewWithContext = ({ entryId }: { entryId: string }) => {
|
||||
const { showReadabilityAtom, showAITranslationAtom } = useEntryContentContext()
|
||||
const showReadability = useAtomValue(showReadabilityAtom)
|
||||
const showReadabilityOnce = useAtomValue(showReadabilityAtom)
|
||||
const translationSetting = useGeneralSettingKey("translation")
|
||||
const showTranslation = useAtomValue(showAITranslationAtom)
|
||||
const showTranslationOnce = useAtomValue(showAITranslationAtom)
|
||||
const actionLanguage = useActionLanguage()
|
||||
const translation = useGeneralSettingKey("translation")
|
||||
|
||||
|
|
@ -144,10 +144,10 @@ const EntryContentWebViewWithContext = ({ entryId }: { entryId: string }) => {
|
|||
usePrefetchEntryTranslation({
|
||||
entryIds: [entryId],
|
||||
withContent: true,
|
||||
target: showReadability && entry?.readabilityContent ? "readabilityContent" : "content",
|
||||
target: showReadabilityOnce && entry?.readabilityContent ? "readabilityContent" : "content",
|
||||
language: actionLanguage,
|
||||
checkLanguage,
|
||||
translation,
|
||||
setting: translation,
|
||||
})
|
||||
|
||||
// Auto toggle readability when content is empty
|
||||
|
|
@ -160,16 +160,16 @@ const EntryContentWebViewWithContext = ({ entryId }: { entryId: string }) => {
|
|||
}, [isPending, entry?.content, setShowReadability])
|
||||
|
||||
useEffect(() => {
|
||||
if (showReadability) {
|
||||
if (showReadabilityOnce) {
|
||||
entrySyncServices.fetchEntryReadabilityContent(entryId)
|
||||
}
|
||||
}, [showReadability, entryId])
|
||||
}, [showReadabilityOnce, entryId])
|
||||
|
||||
return (
|
||||
<EntryContentWebView
|
||||
entryId={entryId}
|
||||
showReadability={showReadability}
|
||||
showTranslation={translationSetting || showTranslation}
|
||||
showReadability={showReadabilityOnce}
|
||||
showTranslation={translationSetting || showTranslationOnce}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import type { SupportedActionLanguage } from "@follow/shared"
|
|||
import { useQueries } from "@tanstack/react-query"
|
||||
import { useCallback } from "react"
|
||||
|
||||
import { useEntryList } from "../entry/hooks"
|
||||
import { useEntry, useEntryList } from "../entry/hooks"
|
||||
import type { EntryModel } from "../entry/types"
|
||||
import { translationSyncService, useTranslationStore } from "./store"
|
||||
|
||||
|
|
@ -11,19 +11,19 @@ export const usePrefetchEntryTranslation = ({
|
|||
entryIds,
|
||||
withContent,
|
||||
target = "content",
|
||||
translation,
|
||||
setting,
|
||||
language,
|
||||
checkLanguage,
|
||||
}: {
|
||||
entryIds: string[]
|
||||
withContent?: boolean
|
||||
target?: "content" | "readabilityContent"
|
||||
translation: boolean
|
||||
setting: boolean
|
||||
language: SupportedActionLanguage
|
||||
checkLanguage: (params: { content: string; language: SupportedActionLanguage }) => boolean
|
||||
}) => {
|
||||
const entryList = (useEntryList(entryIds)?.filter(
|
||||
(entry) => entry !== null && (translation || !!entry?.settings?.translation),
|
||||
(entry) => entry !== null && (setting || !!entry?.settings?.translation),
|
||||
) || []) as EntryModel[]
|
||||
|
||||
return useQueries({
|
||||
|
|
@ -48,13 +48,24 @@ export const usePrefetchEntryTranslation = ({
|
|||
})
|
||||
}
|
||||
|
||||
export const useEntryTranslation = (entryId: string, language: SupportedLanguages) => {
|
||||
export const useEntryTranslation = ({
|
||||
entryId,
|
||||
language,
|
||||
setting,
|
||||
}: {
|
||||
entryId: string
|
||||
language: SupportedLanguages
|
||||
setting: boolean
|
||||
}) => {
|
||||
const actionSetting = useEntry(entryId, (state) => state.settings?.translation)
|
||||
|
||||
return useTranslationStore(
|
||||
useCallback(
|
||||
(state) => {
|
||||
if (!setting && !actionSetting) return
|
||||
return state.data[entryId]?.[language]
|
||||
},
|
||||
[entryId, language],
|
||||
[actionSetting, entryId, language, setting],
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue