diff --git a/src/components/Timeline/Refresh.tsx b/src/components/Timeline/Refresh.tsx index 221cd6bb..1a183df4 100644 --- a/src/components/Timeline/Refresh.tsx +++ b/src/components/Timeline/Refresh.tsx @@ -20,7 +20,6 @@ import Animated, { SharedValue, useAnimatedReaction, useAnimatedStyle, - useDerivedValue, useSharedValue, withTiming } from 'react-native-reanimated' @@ -28,10 +27,10 @@ import Animated, { export interface Props { flRef: RefObject> queryKey: QueryKeyTimeline - fetchingActive: React.MutableRefObject + isFetchingPrev: SharedValue setFetchedCount: React.Dispatch> - scrollY: Animated.SharedValue - fetchingType: Animated.SharedValue<0 | 1 | 2> + scrollY: SharedValue + fetchingType: SharedValue<0 | 1 | 2> disableRefresh?: boolean readMarker?: 'read_marker_following' } @@ -43,7 +42,7 @@ export const SEPARATION_Y_2 = -(CONTAINER_HEIGHT * 1.5 + StyleConstants.Font.Siz const TimelineRefresh: React.FC = ({ flRef, queryKey, - fetchingActive, + isFetchingPrev, setFetchedCount, scrollY, fetchingType, @@ -58,20 +57,11 @@ const TimelineRefresh: React.FC = ({ } const PREV_PER_BATCH = 1 - const prevActive = useRef(false) const prevCache = useRef<(Mastodon.Status | Mastodon.Notification | Mastodon.Conversation)[]>() const prevStatusId = useRef() const queryClient = useQueryClient() - const { refetch, isRefetching } = useTimelineQuery({ ...queryKey[1] }) - - useDerivedValue(() => { - if (prevActive.current || isRefetching) { - fetchingActive.current = true - } else { - fetchingActive.current = false - } - }, [prevActive.current, isRefetching]) + const { refetch } = useTimelineQuery({ ...queryKey[1] }) const { t } = useTranslation('componentTimeline') const { colors } = useTheme() @@ -99,7 +89,7 @@ const TimelineRefresh: React.FC = ({ const arrowStage = useSharedValue(0) useAnimatedReaction( () => { - if (fetchingActive.current) { + if (isFetchingPrev.value) { return false } switch (arrowStage.value) { @@ -131,13 +121,12 @@ const TimelineRefresh: React.FC = ({ if (data) { runOnJS(haptics)('Light') } - }, - [fetchingActive.current] + } ) const fetchAndScrolled = useSharedValue(false) const runFetchPrevious = async () => { - if (prevActive.current) return + if (isFetchingPrev.value) return const firstPage = queryClient.getQueryData< @@ -146,7 +135,7 @@ const TimelineRefresh: React.FC = ({ > >(queryKey)?.pages[0] - prevActive.current = true + isFetchingPrev.value = true prevStatusId.current = firstPage?.body[0]?.id await queryFunctionTimeline({ @@ -154,7 +143,7 @@ const TimelineRefresh: React.FC = ({ pageParam: firstPage?.links?.prev, meta: {} }) - .then(res => { + .then(async res => { setFetchedCount(res.body.length) if (!res.body.length) return @@ -177,7 +166,7 @@ const TimelineRefresh: React.FC = ({ }) .then(async nextLength => { if (!nextLength) { - prevActive.current = false + isFetchingPrev.value = false return } @@ -214,7 +203,7 @@ const TimelineRefresh: React.FC = ({ } }) } - prevActive.current = false + isFetchingPrev.value = false }) } diff --git a/src/components/Timeline/Shared/FullConversation.tsx b/src/components/Timeline/Shared/FullConversation.tsx index 8842ad77..f3e0bbb1 100644 --- a/src/components/Timeline/Shared/FullConversation.tsx +++ b/src/components/Timeline/Shared/FullConversation.tsx @@ -15,8 +15,8 @@ const TimelineFullConversation = () => { return queryKey && queryKey[1].page !== 'Toot' && status.in_reply_to_account_id && - (status.mentions.length === 0 || - status.mentions.filter(mention => mention.id !== status.in_reply_to_account_id).length) ? ( + (status.mentions?.length === 0 || + status.mentions?.filter(mention => mention.id !== status.in_reply_to_account_id).length) ? ( { excludeMentions && (excludeMentions.current = mentionsBeginning?.length && status?.mentions - ? status.mentions.filter(mention => mentionsBeginning.includes(`@${mention.username}`)) + ? status.mentions?.filter(mention => mentionsBeginning.includes(`@${mention.username}`)) : []) return excludeMentions?.current.length ? ( diff --git a/src/components/Timeline/index.tsx b/src/components/Timeline/index.tsx index 7478727b..c307a131 100644 --- a/src/components/Timeline/index.tsx +++ b/src/components/Timeline/index.tsx @@ -18,6 +18,7 @@ import { FlatList, FlatListProps, Platform, RefreshControl } from 'react-native' import Animated, { Easing, runOnJS, + useAnimatedReaction, useAnimatedScrollHandler, useAnimatedStyle, useDerivedValue, @@ -70,26 +71,44 @@ const Timeline: React.FC = ({ }) const flRef = useRef(null) - const fetchingActive = useRef(false) + const isFetchingPrev = useSharedValue(false) const [fetchedCount, setFetchedCount] = useState(null) const fetchedNoticeHeight = useSharedValue(100) + const notifiedFetchedNotice = useSharedValue(false) + useAnimatedReaction( + () => isFetchingPrev.value, + (curr, prev) => { + if (curr === true && prev === false) { + notifiedFetchedNotice.value = true + } + } + ) + useAnimatedReaction( + () => fetchedCount, + (curr, prev) => { + if (curr !== null && prev === null) { + notifiedFetchedNotice.value = false + } + }, + [fetchedCount] + ) const fetchedNoticeTop = useDerivedValue(() => { - if ((!isLoading && !isRefetching && isFetching) || fetchedCount !== null) { + if (notifiedFetchedNotice.value || fetchedCount !== null) { return withSequence( withTiming(fetchedNoticeHeight.value + 16 + 4), withDelay( 2000, - withTiming(0, { easing: Easing.out(Easing.ease) }, finished => { - if (finished) { - runOnJS(setFetchedCount)(null) - } - }) + withTiming( + 0, + { easing: Easing.out(Easing.ease) }, + finished => finished && runOnJS(setFetchedCount)(null) + ) ) ) } else { return 0 } - }, [isLoading, isRefetching, isFetching, fetchedCount]) + }, [fetchedCount]) const fetchedNoticeAnimate = useAnimatedStyle(() => ({ transform: [{ translateY: fetchedNoticeTop.value }] })) @@ -130,7 +149,12 @@ const Timeline: React.FC = ({ const marker = readMarker ? getAccountStorage.string(readMarker) : undefined const firstItemId = viewableItems.filter(item => item.isViewable)[0]?.item.id - if (!fetchingActive.current && firstItemId && firstItemId > (marker || '0')) { + if ( + !isFetchingPrev.value && + !isRefetching && + firstItemId && + firstItemId > (marker || '0') + ) { setAccountStorage([{ key: readMarker, value: firstItemId }]) } else { // setAccountStorage([{ key: readMarker, value: '109519141378761752' }]) @@ -170,7 +194,7 @@ const Timeline: React.FC = ({ = ({ }) => (fetchedNoticeHeight.value = height)} > mention.acct === accountAcct && mention.username === accountAcct ) && !status.muted diff --git a/src/i18n/ca/components/timeline.json b/src/i18n/ca/components/timeline.json index b45d16a1..6b46c4d8 100644 --- a/src/i18n/ca/components/timeline.json +++ b/src/i18n/ca/components/timeline.json @@ -17,10 +17,10 @@ "refresh": { "fetchPreviousPage": "Més recent des d'aquí", "refetch": "A l'últim", - "fetching": "", + "fetching": "Obtenint publicacions...", "fetched": { - "none": "", - "found": "" + "none": "No n'hi ha de noves", + "found": "S'ha obtingut {{count}}" } }, "shared": { diff --git a/src/i18n/ca/screens/tabs.json b/src/i18n/ca/screens/tabs.json index 702ab7f5..1c1e7379 100644 --- a/src/i18n/ca/screens/tabs.json +++ b/src/i18n/ca/screens/tabs.json @@ -147,7 +147,7 @@ "title": "Marca el contingut com a sensible" }, "media": { - "title": "Visualització de multimèdia", + "title": "Multimèdia", "options": { "default": "Amaga els sensibles", "show_all": "Mostra'ls sempre", diff --git a/src/i18n/es/components/timeline.json b/src/i18n/es/components/timeline.json index a8dfe01c..0730a858 100644 --- a/src/i18n/es/components/timeline.json +++ b/src/i18n/es/components/timeline.json @@ -17,10 +17,10 @@ "refresh": { "fetchPreviousPage": "Más reciente desde aquí", "refetch": "Al último", - "fetching": "", + "fetching": "Obteniendo publicaciones...", "fetched": { - "none": "", - "found": "" + "none": "No hay nuevas", + "found": "Se ha obtenido {{count}}" } }, "shared": { diff --git a/src/i18n/es/screens/tabs.json b/src/i18n/es/screens/tabs.json index 7da12bde..9d828861 100644 --- a/src/i18n/es/screens/tabs.json +++ b/src/i18n/es/screens/tabs.json @@ -147,7 +147,7 @@ "title": "Marcar el contenido multimedia como sensibles por defecto" }, "media": { - "title": "Mostrar el contenido multimedia", + "title": "Multimedia", "options": { "default": "Ocultar los sensibles", "show_all": "Mostrar siempre", diff --git a/src/i18n/nl/components/timeline.json b/src/i18n/nl/components/timeline.json index 74069e16..131b6577 100644 --- a/src/i18n/nl/components/timeline.json +++ b/src/i18n/nl/components/timeline.json @@ -17,10 +17,10 @@ "refresh": { "fetchPreviousPage": "Nieuwere vanaf hier", "refetch": "Naar nieuwste", - "fetching": "", + "fetching": "Nieuwere toots ophalen...", "fetched": { - "none": "", - "found": "" + "none": "Geen nieuwere toot", + "found": "{{count}} toots opgehaald" } }, "shared": { diff --git a/src/i18n/pt_BR/components/contextMenu.json b/src/i18n/pt_BR/components/contextMenu.json index a6a7a9b4..616a3517 100644 --- a/src/i18n/pt_BR/components/contextMenu.json +++ b/src/i18n/pt_BR/components/contextMenu.json @@ -6,9 +6,9 @@ "action_false": "Seguir usuário", "action_true": "Deixar de seguir usuário" }, - "inLists": "", + "inLists": "Listas contendo usuário ...", "showBoosts": { - "action_false": "", + "action_false": "Mostrar boosts do usuário", "action_true": "" }, "mute": { diff --git a/src/i18n/pt_BR/components/timeline.json b/src/i18n/pt_BR/components/timeline.json index f899f23c..dcb57f62 100644 --- a/src/i18n/pt_BR/components/timeline.json +++ b/src/i18n/pt_BR/components/timeline.json @@ -17,9 +17,9 @@ "refresh": { "fetchPreviousPage": "Mais novo aqui", "refetch": "Mais recente", - "fetching": "", + "fetching": "Buscando toots mais recentes...", "fetched": { - "none": "", + "none": "Nenhum novo toot", "found": "" } }, diff --git a/src/i18n/pt_BR/screens/tabs.json b/src/i18n/pt_BR/screens/tabs.json index a481b838..38cb3ba1 100644 --- a/src/i18n/pt_BR/screens/tabs.json +++ b/src/i18n/pt_BR/screens/tabs.json @@ -61,7 +61,7 @@ "name": "Criar uma lista" }, "listEdit": { - "name": "" + "name": "Editar Detalhes da Lista" }, "lists": { "name": "Listas" @@ -116,7 +116,7 @@ "empty": "Nenhum usuário adicionado a esta lista" }, "listEdit": { - "heading": "", + "heading": "Editar detalhes da lista", "title": "Título", "repliesPolicy": { "heading": "Mostrar respostas para:", @@ -144,7 +144,7 @@ } }, "sensitive": { - "title": "" + "title": "Marcar mídia como sensível por padrão" }, "media": { "title": "", @@ -166,22 +166,22 @@ }, "web_only": { "title": "", - "description": "" + "description": "As configurações abaixo só podem ser atualizadas usando a interface web" } }, "preferencesFilters": { "expired": "", - "keywords_one": "", - "keywords_other": "", - "statuses_one": "", - "statuses_other": "", - "context": "", + "keywords_one": "{{count}} palavra-chave", + "keywords_other": "{{count}} palavras-chave", + "statuses_one": "{{count}} toot", + "statuses_other": "{{count}} toots", + "context": "Aplica-se em <0 />", "contexts": { - "home": "", - "notifications": "", + "home": "seguindo e listas", + "notifications": "notificação", "public": "global", "thread": "", - "account": "" + "account": "perfil" } }, "preferencesFilter": { @@ -196,22 +196,22 @@ "604800": "Após 1 semana", "18144000": "Após 1 mês" }, - "context": "", + "context": "Aplica-se em", "contexts": { - "home": "", - "notifications": "", + "home": "Seguindo e listas", + "notifications": "Notificação", "public": "Linha do tempo global", "thread": "", "account": "" }, "action": "", "actions": { - "warn": "", - "hide": "" + "warn": "Recolhido, mas pode ser revelado", + "hide": "Esconder completamente" }, "keywords": "", - "keyword": "", - "statuses": "" + "keyword": "Palavra-chave", + "statuses": "Corresponde a estes toots" }, "profile": { "feedback": { @@ -343,7 +343,7 @@ "heading": "Tema escuro", "options": { "lighter": "Padrão", - "darker": "" + "darker": "Preto verdadeiro" } }, "browser": { @@ -354,7 +354,7 @@ } }, "autoplayGifv": { - "heading": "" + "heading": "Reproduzir GIFs automaticamente na linha do tempo" }, "feedback": { "heading": "Pedidos de Funcionalidades" @@ -392,7 +392,7 @@ "suspended": "Conta suspensa pelos moderadores do seu servidor" }, "accountInLists": { - "name": "", + "name": "Listas de @{{username}}", "inLists": "", "notInLists": "Outras listas" }, @@ -400,8 +400,8 @@ "name": "<0 /><1>\"s mídia" }, "filter": { - "name": "", - "existed": "" + "name": "Adicionar ao filtro", + "existed": "Existe nestes filtros" }, "history": { "name": "Histórico de Edição" diff --git a/src/i18n/uk/components/timeline.json b/src/i18n/uk/components/timeline.json index b24fd3e8..036c5d9f 100644 --- a/src/i18n/uk/components/timeline.json +++ b/src/i18n/uk/components/timeline.json @@ -17,10 +17,10 @@ "refresh": { "fetchPreviousPage": "З цього моменту", "refetch": "До кінця", - "fetching": "", + "fetching": "Отримання нових дмухів ...", "fetched": { - "none": "", - "found": "" + "none": "Немає нових дмухів", + "found": "Отримано {{count}} дмухів" } }, "shared": { diff --git a/src/i18n/zh-Hant/components/timeline.json b/src/i18n/zh-Hant/components/timeline.json index 36a303a3..80043a6f 100644 --- a/src/i18n/zh-Hant/components/timeline.json +++ b/src/i18n/zh-Hant/components/timeline.json @@ -17,10 +17,10 @@ "refresh": { "fetchPreviousPage": "較新的嘟文", "refetch": "到最新的位置", - "fetching": "", + "fetching": "取得較新的嘟文 …", "fetched": { - "none": "", - "found": "" + "none": "沒有更新的嘟文", + "found": "已取得 {{count}} 條嘟文" } }, "shared": { diff --git a/src/screens/Compose/Root/Footer/Attachments.tsx b/src/screens/Compose/Root/Footer/Attachments.tsx index 3aae6988..4ce53446 100644 --- a/src/screens/Compose/Root/Footer/Attachments.tsx +++ b/src/screens/Compose/Root/Footer/Attachments.tsx @@ -169,7 +169,8 @@ const ComposeAttachments: React.FC = ({ accessibleRefAttachments }) => { haptics('Success') }} /> - {composeState.type === 'edit' && featureCheck('edit_media_details') ? ( + {composeState.type !== 'edit' || + (composeState.type === 'edit' && featureCheck('edit_media_details')) ? (