From bf8826fec43f7c29944a3bf0a7a645f82de68061 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sat, 19 Nov 2022 17:48:51 +0100 Subject: [PATCH 01/10] Fixed #469 --- .../Shared/HeaderShared/Visibility.tsx | 24 +++---------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/src/components/Timeline/Shared/HeaderShared/Visibility.tsx b/src/components/Timeline/Shared/HeaderShared/Visibility.tsx index 45639966..8fcfe33e 100644 --- a/src/components/Timeline/Shared/HeaderShared/Visibility.tsx +++ b/src/components/Timeline/Shared/HeaderShared/Visibility.tsx @@ -15,24 +15,10 @@ const HeaderSharedVisibility = React.memo( const { colors } = useTheme() switch (visibility) { - case 'public': - return ( - - ) case 'unlisted': return ( Date: Sun, 20 Nov 2022 14:41:41 +0100 Subject: [PATCH 02/10] Try fix #451 Android does not support true context menu anyway, thus removing per toot component. --- package.json | 2 +- src/components/Timeline/Default.tsx | 11 +- src/components/Timeline/Notifications.tsx | 241 ++++++++++++---------- 3 files changed, 140 insertions(+), 114 deletions(-) diff --git a/package.json b/package.json index fca7ccd7..5179551f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tooot", - "version": "4.6.1", + "version": "4.6.2", "description": "tooot for Mastodon", "author": "xmflsct ", "license": "GPL-3.0-or-later", diff --git a/src/components/Timeline/Default.tsx b/src/components/Timeline/Default.tsx index 8eb7876d..5adcf7e4 100644 --- a/src/components/Timeline/Default.tsx +++ b/src/components/Timeline/Default.tsx @@ -17,7 +17,7 @@ import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import { uniqBy } from 'lodash' import React, { useRef } from 'react' -import { Pressable, StyleProp, View, ViewStyle } from 'react-native' +import { Platform, Pressable, StyleProp, View, ViewStyle } from 'react-native' import { useSelector } from 'react-redux' import TimelineContextMenu from './Shared/ContextMenu' import TimelineFeedback from './Shared/Feedback' @@ -156,6 +156,15 @@ const TimelineDefault: React.FC = ({ return disableOnPress ? ( {main()} + ) : Platform.OS === 'android' ? ( + {}} + > + {main()} + ) : ( { - const copiableContent = useRef<{ content: string; complete: boolean }>({ - content: '', - complete: false +const TimelineNotifications: React.FC = ({ + notification, + queryKey, + highlighted = false +}) => { + const copiableContent = useRef<{ content: string; complete: boolean }>({ + content: '', + complete: false + }) + + const filtered = + notification.status && + shouldFilter({ + copiableContent, + status: notification.status, + queryKey }) + if (notification.status && filtered) { + return + } - const filtered = - notification.status && - shouldFilter({ - copiableContent, - status: notification.status, - queryKey + const { colors } = useTheme() + const instanceAccount = useSelector(getInstanceAccount, (prev, next) => prev?.id === next?.id) + const navigation = useNavigation>() + + const actualAccount = notification.status ? notification.status.account : notification.account + + const onPress = useCallback(() => { + analytics('timeline_notification_press') + notification.status && + navigation.push('Tab-Shared-Toot', { + toot: notification.status, + rootQueryKey: queryKey }) - if (notification.status && filtered) { - return - } - - const { colors } = useTheme() - const instanceAccount = useSelector(getInstanceAccount, (prev, next) => prev?.id === next?.id) - const navigation = useNavigation>() - - const actualAccount = notification.status ? notification.status.account : notification.account - - const onPress = useCallback(() => { - analytics('timeline_notification_press') - notification.status && - navigation.push('Tab-Shared-Toot', { - toot: notification.status, - rootQueryKey: queryKey - }) - }, []) + }, []) + const main = () => { return ( - - + {notification.type !== 'mention' ? ( + + ) : null} + + {}} > - {notification.type !== 'mention' ? ( - - ) : null} - - - - - - - - {notification.status ? ( - - {notification.status.content.length > 0 ? ( - - ) : null} - {notification.status.poll ? ( - - ) : null} - {notification.status.media_attachments.length > 0 ? ( - - ) : null} - {notification.status.card ? : null} - - - ) : null} + + + {notification.status ? ( - d?.id !== instanceAccount?.id), - d => d?.id - ).map(d => d?.acct)} - reblog={false} - /> + + {notification.status.content.length > 0 ? ( + + ) : null} + {notification.status.poll ? ( + + ) : null} + {notification.status.media_attachments.length > 0 ? ( + + ) : null} + {notification.status.card ? : null} + + ) : null} - - + + + {notification.status ? ( + d?.id !== instanceAccount?.id), + d => d?.id + ).map(d => d?.acct)} + reblog={false} + /> + ) : null} + ) - }, - (prev, next) => isEqual(prev.notification, next.notification) -) + } + + return Platform.OS === 'android' ? ( + {}} + > + {main()} + + ) : ( + + {}} + > + {main()} + + + ) +} export default TimelineNotifications From 18e7262f6f33374dbb397bcf3257210af643cb97 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 20 Nov 2022 16:14:08 +0100 Subject: [PATCH 03/10] Fixed #471 --- src/@types/mastodon.d.ts | 3 +- src/App.tsx | 17 ++- src/components/Message.tsx | 10 +- src/helpers/features.json | 5 + src/i18n/en/screens/tabs.json | 10 +- src/screens/AccountSelection.tsx | 105 +++++++-------- src/screens/Actions.tsx | 84 +++++------- src/screens/ImagesViewer.tsx | 6 +- src/screens/Tabs/Local.tsx | 4 +- src/screens/Tabs/Me.tsx | 4 +- src/screens/Tabs/Notifications.tsx | 4 +- src/screens/Tabs/Public.tsx | 4 +- src/screens/Tabs/Shared/Hashtag.tsx | 68 +++++++++- .../Tabs/Shared/{Root.tsx => index.tsx} | 57 +++----- src/utils/queryHooks/tags.ts | 59 +++++++++ src/utils/slices/instancesSlice.ts | 124 ++++++------------ 16 files changed, 297 insertions(+), 267 deletions(-) rename src/screens/Tabs/Shared/{Root.tsx => index.tsx} (83%) create mode 100644 src/utils/queryHooks/tags.ts diff --git a/src/@types/mastodon.d.ts b/src/@types/mastodon.d.ts index be1819b1..0e452f3a 100644 --- a/src/@types/mastodon.d.ts +++ b/src/@types/mastodon.d.ts @@ -475,7 +475,8 @@ declare namespace Mastodon { // Base name: string url: string - // history: types + history: { day: string; accounts: string; uses: string }[] + following: boolean // Since v4.0 } type WebSocketStream = diff --git a/src/App.tsx b/src/App.tsx index 01275460..2f26fdb8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -20,6 +20,7 @@ import * as SplashScreen from 'expo-splash-screen' import React, { useCallback, useEffect, useState } from 'react' import { LogBox, Platform } from 'react-native' import { GestureHandlerRootView } from 'react-native-gesture-handler' +import { SafeAreaProvider } from 'react-native-safe-area-context' import { enableFreeze } from 'react-native-screens' import { QueryClientProvider } from 'react-query' import { Provider } from 'react-redux' @@ -95,13 +96,15 @@ const App: React.FC = () => { } return ( - - - - - - - + + + + + + + + + ) } else { return null diff --git a/src/components/Message.tsx b/src/components/Message.tsx index fe706042..ddcdc5fa 100644 --- a/src/components/Message.tsx +++ b/src/components/Message.tsx @@ -4,10 +4,8 @@ import { useTheme } from '@utils/styles/ThemeManager' import { getColors, Theme } from '@utils/styles/themes' import React, { RefObject } from 'react' import { AccessibilityInfo } from 'react-native' -import FlashMessage, { - hideMessage, - showMessage -} from 'react-native-flash-message' +import FlashMessage, { hideMessage, showMessage } from 'react-native-flash-message' +import { useSafeAreaInsets } from 'react-native-safe-area-context' import haptics from './haptics' const displayMessage = ({ @@ -112,6 +110,7 @@ const removeMessage = () => { const Message = React.forwardRef((_, ref) => { const { colors, theme } = useTheme() + const insets = useSafeAreaInsets() return ( ((_, ref) => { shadowOffset: { width: 0, height: 0 }, shadowOpacity: theme === 'light' ? 0.16 : 0.24, shadowRadius: 4, - paddingRight: StyleConstants.Spacing.M * 2 + paddingRight: StyleConstants.Spacing.M * 2, + marginTop: insets.top }} titleStyle={{ color: colors.primaryDefault, diff --git a/src/helpers/features.json b/src/helpers/features.json index 53d2d982..147b20a4 100644 --- a/src/helpers/features.json +++ b/src/helpers/features.json @@ -23,5 +23,10 @@ "feature": "notification_types_positive_filter", "version": 3.5, "reference": "https://github.com/mastodon/mastodon/releases/tag/v3.5.0" + }, + { + "feature": "follow_tags", + "version": 4.0, + "reference": "https://github.com/mastodon/mastodon/releases/tag/v4.0.0" } ] \ No newline at end of file diff --git a/src/i18n/en/screens/tabs.json b/src/i18n/en/screens/tabs.json index eb72c7ab..ccef3557 100644 --- a/src/i18n/en/screens/tabs.json +++ b/src/i18n/en/screens/tabs.json @@ -310,6 +310,13 @@ "attachments": { "name": "<0 /><1>\"s media" }, + "hashtag": { + "follow": "Follow", + "unfollow": "Unfollow" + }, + "history": { + "name": "Edit History" + }, "search": { "header": { "prefix": "Searching", @@ -346,9 +353,6 @@ "reblogged_by": "{{count}} boosted", "favourited_by": "{{count}} favourited" } - }, - "history": { - "name": "Edit History" } } } \ No newline at end of file diff --git a/src/screens/AccountSelection.tsx b/src/screens/AccountSelection.tsx index ff5e99aa..98611a07 100644 --- a/src/screens/AccountSelection.tsx +++ b/src/screens/AccountSelection.tsx @@ -9,7 +9,6 @@ import * as VideoThumbnails from 'expo-video-thumbnails' import React, { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { FlatList, Image, ScrollView, View } from 'react-native' -import { SafeAreaProvider } from 'react-native-safe-area-context' import { useSelector } from 'react-redux' const Share = ({ @@ -76,9 +75,7 @@ const Share = ({ renderItem={({ item }) => ( )} - ItemSeparatorComponent={() => ( - - )} + ItemSeparatorComponent={() => } /> ) @@ -99,64 +96,60 @@ const ScreenAccountSelection = ({ const instances = useSelector(getInstances, () => true) return ( - - + - : null} + - {share ? : null} - - {t('content.select_account')} - - - {instances.length - ? instances - .slice() - .sort((a, b) => - `${a.uri}${a.account.acct}`.localeCompare( - `${b.uri}${b.account.acct}` - ) + {t('content.select_account')} + + + {instances.length + ? instances + .slice() + .sort((a, b) => + `${a.uri}${a.account.acct}`.localeCompare(`${b.uri}${b.account.acct}`) + ) + .map((instance, index) => { + return ( + { + navigationRef.navigate('Screen-Compose', { + type: 'share', + ...share + }) + }} + /> ) - .map((instance, index) => { - return ( - { - navigationRef.navigate('Screen-Compose', { - type: 'share', - ...share - }) - }} - /> - ) - }) - : null} - + }) + : null} - - + + ) } diff --git a/src/screens/Actions.tsx b/src/screens/Actions.tsx index c6db5ffa..54626356 100644 --- a/src/screens/Actions.tsx +++ b/src/screens/Actions.tsx @@ -3,11 +3,7 @@ import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import React, { useCallback, useEffect } from 'react' import { Dimensions, StyleSheet, View } from 'react-native' -import { - PanGestureHandler, - State, - TapGestureHandler -} from 'react-native-gesture-handler' +import { PanGestureHandler, State, TapGestureHandler } from 'react-native-gesture-handler' import Animated, { Extrapolate, interpolate, @@ -17,10 +13,7 @@ import Animated, { useSharedValue, withTiming } from 'react-native-reanimated' -import { - SafeAreaProvider, - useSafeAreaInsets -} from 'react-native-safe-area-context' +import { useSafeAreaInsets } from 'react-native-safe-area-context' import ActionsAltText from './Actions/AltText' import ActionsNotificationsFilter from './Actions/NotificationsFilter' @@ -39,12 +32,7 @@ const ScreenActions = ({ }, []) const styleTop = useAnimatedStyle(() => { return { - bottom: interpolate( - panY.value, - [0, screenHeight], - [0, -screenHeight], - Extrapolate.CLAMP - ) + bottom: interpolate(panY.value, [0, screenHeight], [0, -screenHeight], Extrapolate.CLAMP) } }) const dismiss = useCallback(() => { @@ -73,45 +61,35 @@ const ScreenActions = ({ } return ( - - - { - if (nativeEvent.state === State.ACTIVE) { - dismiss() - } - }} + + { + if (nativeEvent.state === State.ACTIVE) { + dismiss() + } + }} + > + - - - - - {actions()} - - - - - - + + + + {actions()} + + + + + ) } diff --git a/src/screens/ImagesViewer.tsx b/src/screens/ImagesViewer.tsx index 4771d265..f9d3b095 100644 --- a/src/screens/ImagesViewer.tsx +++ b/src/screens/ImagesViewer.tsx @@ -20,7 +20,7 @@ import { Directions, Gesture, LongPressGestureHandler } from 'react-native-gestu import { LiveTextImageView } from 'react-native-live-text-image-view' import { runOnJS, useSharedValue } from 'react-native-reanimated' import { Zoom, createZoomListComponent } from 'react-native-reanimated-zoom' -import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context' +import { useSafeAreaInsets } from 'react-native-safe-area-context' import saveImage from './ImageViewer/save' const ZoomFlatList = createZoomListComponent(FlatList) @@ -153,7 +153,7 @@ const ScreenImagesViewer = ({ ) return ( - + + ) } diff --git a/src/screens/Tabs/Local.tsx b/src/screens/Tabs/Local.tsx index acc03b1a..c5d5ac17 100644 --- a/src/screens/Tabs/Local.tsx +++ b/src/screens/Tabs/Local.tsx @@ -12,7 +12,7 @@ import React, { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { Platform } from 'react-native' import ContextMenu from 'react-native-context-menu-view' -import TabSharedRoot from './Shared/Root' +import TabShared from './Shared' const Stack = createNativeStackNavigator() @@ -96,7 +96,7 @@ const TabLocal = React.memo( /> )} /> - {TabSharedRoot({ Stack })} + {TabShared({ Stack })} ) }, diff --git a/src/screens/Tabs/Me.tsx b/src/screens/Tabs/Me.tsx index 27ffcc1f..d7d2ac86 100644 --- a/src/screens/Tabs/Me.tsx +++ b/src/screens/Tabs/Me.tsx @@ -16,7 +16,7 @@ import TabMeSettings from './Me/Settings' import TabMeSettingsFontsize from './Me/SettingsFontsize' import TabMeSettingsLanguage from './Me/SettingsLanguage' import TabMeSwitch from './Me/Switch' -import TabSharedRoot from './Shared/Root' +import TabShared from './Shared' const Stack = createNativeStackNavigator() @@ -187,7 +187,7 @@ const TabMe = React.memo( })} /> - {TabSharedRoot({ Stack })} + {TabShared({ Stack })} ) }, diff --git a/src/screens/Tabs/Notifications.tsx b/src/screens/Tabs/Notifications.tsx index da04b603..e3621e49 100644 --- a/src/screens/Tabs/Notifications.tsx +++ b/src/screens/Tabs/Notifications.tsx @@ -10,7 +10,7 @@ import { QueryKeyTimeline } from '@utils/queryHooks/timeline' import React, { useCallback, useMemo } from 'react' import { useTranslation } from 'react-i18next' import { Platform } from 'react-native' -import TabSharedRoot from './Shared/Root' +import TabShared from './Shared' const Stack = createNativeStackNavigator() @@ -65,7 +65,7 @@ const TabNotifications = React.memo( children={children} options={screenOptionsRoot} /> - {TabSharedRoot({ Stack })} + {TabShared({ Stack })} ) }, diff --git a/src/screens/Tabs/Public.tsx b/src/screens/Tabs/Public.tsx index 8c4a7bf7..bd493b17 100644 --- a/src/screens/Tabs/Public.tsx +++ b/src/screens/Tabs/Public.tsx @@ -12,7 +12,7 @@ import React, { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { Dimensions } from 'react-native' import { TabView } from 'react-native-tab-view' -import TabSharedRoot from './Shared/Root' +import TabShared from './Shared' const Stack = createNativeStackNavigator() @@ -107,7 +107,7 @@ const TabPublic = React.memo( return ( - {TabSharedRoot({ Stack })} + {TabShared({ Stack })} ) }, diff --git a/src/screens/Tabs/Shared/Hashtag.tsx b/src/screens/Tabs/Shared/Hashtag.tsx index 93cd5061..e905e8a7 100644 --- a/src/screens/Tabs/Shared/Hashtag.tsx +++ b/src/screens/Tabs/Shared/Hashtag.tsx @@ -1,24 +1,78 @@ +import haptics from '@components/haptics' +import { HeaderRight } from '@components/Header' +import { displayMessage } from '@components/Message' import Timeline from '@components/Timeline' import TimelineDefault from '@components/Timeline/Default' import { TabSharedStackScreenProps } from '@utils/navigation/navigators' +import { useTagsMutation, useTagsQuery } from '@utils/queryHooks/tags' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' -import React from 'react' +import { checkInstanceFeature } from '@utils/slices/instancesSlice' +import { useTheme } from '@utils/styles/ThemeManager' +import React, { useEffect } from 'react' +import { useTranslation } from 'react-i18next' +import { useSelector } from 'react-redux' -const TabSharedHashtag: React.FC< - TabSharedStackScreenProps<'Tab-Shared-Hashtag'> -> = ({ +const TabSharedHashtag: React.FC> = ({ + navigation, route: { params: { hashtag } } }) => { const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Hashtag', hashtag }] + + const { theme } = useTheme() + const { t } = useTranslation('screenTabs') + + const canFollowTags = useSelector(checkInstanceFeature('follow_tags')) + const { data, isFetching, refetch } = useTagsQuery({ + tag: hashtag, + options: { enabled: canFollowTags } + }) + const mutation = useTagsMutation({ + onSuccess: () => { + haptics('Success') + refetch() + }, + onError: (err: any, { to }) => { + displayMessage({ + theme, + type: 'error', + message: t('common:message.error.message', { + function: to ? t('shared.hashtag.follow') : t('shared.hashtag.unfollow') + }), + ...(err.status && + typeof err.status === 'number' && + err.data && + err.data.error && + typeof err.data.error === 'string' && { + description: err.data.error + }) + }) + } + }) + useEffect(() => { + if (!canFollowTags) return + + navigation.setOptions({ + headerRight: () => ( + + typeof data?.following === 'boolean' && + mutation.mutate({ tag: hashtag, type: 'follow', to: !data.following }) + } + /> + ) + }) + }, [canFollowTags, data?.following, isFetching]) + return ( ( - - ) + renderItem: ({ item }) => }} /> ) diff --git a/src/screens/Tabs/Shared/Root.tsx b/src/screens/Tabs/Shared/index.tsx similarity index 83% rename from src/screens/Tabs/Shared/Root.tsx rename to src/screens/Tabs/Shared/index.tsx index ec2ff51a..a98e71c9 100644 --- a/src/screens/Tabs/Shared/Root.tsx +++ b/src/screens/Tabs/Shared/index.tsx @@ -20,11 +20,7 @@ import { Trans, useTranslation } from 'react-i18next' import { Platform, TextInput, View } from 'react-native' import ContextMenu, { ContextMenuAction } from 'react-native-context-menu-view' -const TabSharedRoot = ({ - Stack -}: { - Stack: ReturnType -}) => { +const TabShared = ({ Stack }: { Stack: ReturnType }) => { const { colors, mode } = useTheme() const { t } = useTranslation('screenTabs') @@ -50,9 +46,7 @@ const TabSharedRoot = ({ backgroundColor: `rgba(255, 255, 255, 0)` }, title: '', - headerLeft: () => ( - navigation.goBack()} background /> - ), + headerLeft: () => navigation.goBack()} background />, headerRight: () => { const actions: ContextMenuAction[] = [] @@ -77,13 +71,10 @@ const TabSharedRoot = ({ dropdownMenuMode > {}} background @@ -132,9 +123,7 @@ const TabSharedRoot = ({ key='Tab-Shared-Hashtag' name='Tab-Shared-Hashtag' component={TabSharedHashtag} - options={({ - route - }: TabSharedStackScreenProps<'Tab-Shared-Hashtag'>) => ({ + options={({ route }: TabSharedStackScreenProps<'Tab-Shared-Hashtag'>) => ({ title: `#${decodeURIComponent(route.params.hashtag)}` })} /> @@ -150,24 +139,16 @@ const TabSharedRoot = ({ key='Tab-Shared-Search' name='Tab-Shared-Search' component={TabSharedSearch} - options={({ - navigation - }: TabSharedStackScreenProps<'Tab-Shared-Search'>) => ({ + options={({ navigation }: TabSharedStackScreenProps<'Tab-Shared-Search'>) => ({ ...(Platform.OS === 'ios' ? { - headerLeft: () => ( - navigation.goBack()} /> - ) + headerLeft: () => navigation.goBack()} /> } : { headerLeft: () => null }), headerTitle: () => { - const onChangeText = debounce( - (text: string) => navigation.setParams({ text }), - 1000, - { - trailing: true - } - ) + const onChangeText = debounce((text: string) => navigation.setParams({ text }), 1000, { + trailing: true + }) return ( - navigation.setParams({ text }) - } + onSubmitEditing={({ nativeEvent: { text } }) => navigation.setParams({ text })} placeholder={t('shared.search.header.placeholder')} placeholderTextColor={colors.secondary} returnKeyType='go' @@ -216,9 +195,7 @@ const TabSharedRoot = ({ key='Tab-Shared-Toot' name='Tab-Shared-Toot' component={TabSharedToot} - options={{ - title: t('shared.toot.name') - }} + options={{ title: t('shared.toot.name') }} /> ( - + ) }) })} @@ -244,4 +219,4 @@ const TabSharedRoot = ({ ) } -export default TabSharedRoot +export default TabShared diff --git a/src/utils/queryHooks/tags.ts b/src/utils/queryHooks/tags.ts new file mode 100644 index 00000000..d7fe37bc --- /dev/null +++ b/src/utils/queryHooks/tags.ts @@ -0,0 +1,59 @@ +import apiInstance from '@api/instance' +import { AxiosError } from 'axios' +import { + QueryFunctionContext, + useMutation, + UseMutationOptions, + useQuery, + UseQueryOptions +} from 'react-query' + +type QueryKeyFollowedTags = ['FollowedTags'] +const useFollowedTagsQuery = ({ + options +}: { + options?: UseQueryOptions +}) => { + const queryKey: QueryKeyFollowedTags = ['FollowedTags'] + return useQuery( + queryKey, + async ({ pageParam }: QueryFunctionContext) => { + const params: { [key: string]: string } = { ...pageParam } + const res = await apiInstance({ method: 'get', url: `followed_tags`, params }) + return res.body + }, + options + ) +} + +type QueryKeyTags = ['Tags', { tag: string }] +const queryFunction = ({ queryKey }: QueryFunctionContext) => { + const { tag } = queryKey[1] + + return apiInstance({ method: 'get', url: `tags/${tag}` }).then(res => res.body) +} +const useTagsQuery = ({ + options, + ...queryKeyParams +}: QueryKeyTags[1] & { + options?: UseQueryOptions +}) => { + const queryKey: QueryKeyTags = ['Tags', { ...queryKeyParams }] + return useQuery(queryKey, queryFunction, options) +} + +type MutationVarsAnnouncement = { tag: string; type: 'follow'; to: boolean } +const mutationFunction = async ({ tag, type, to }: MutationVarsAnnouncement) => { + switch (type) { + case 'follow': + return apiInstance<{}>({ + method: 'post', + url: `tags/${tag}/${to ? 'follow' : 'unfollow'}` + }) + } +} +const useTagsMutation = (options: UseMutationOptions<{}, AxiosError, MutationVarsAnnouncement>) => { + return useMutation(mutationFunction, options) +} + +export { useFollowedTagsQuery, useTagsQuery, useTagsMutation } diff --git a/src/utils/slices/instancesSlice.ts b/src/utils/slices/instancesSlice.ts index 48f56887..8747943f 100644 --- a/src/utils/slices/instancesSlice.ts +++ b/src/utils/slices/instancesSlice.ts @@ -29,10 +29,7 @@ const instancesSlice = createSlice({ name: 'instances', initialState: instancesInitialState, reducers: { - updateInstanceActive: ( - { instances }, - action: PayloadAction - ) => { + updateInstanceActive: ({ instances }, action: PayloadAction) => { instances = instances.map(instance => { instance.active = instance.url === action.payload.url && @@ -43,9 +40,7 @@ const instancesSlice = createSlice({ }, updateInstanceAccount: ( { instances }, - action: PayloadAction< - Pick - > + action: PayloadAction> ) => { const activeIndex = findInstanceActive(instances) instances[activeIndex].account = { @@ -60,10 +55,7 @@ const instancesSlice = createSlice({ const activeIndex = findInstanceActive(instances) instances[activeIndex].notifications_filter = action.payload }, - updateInstanceDraft: ( - { instances }, - action: PayloadAction - ) => { + updateInstanceDraft: ({ instances }, action: PayloadAction) => { const activeIndex = findInstanceActive(instances) const draftIndex = instances[activeIndex].drafts.findIndex( ({ timestamp }) => timestamp === action.payload.timestamp @@ -74,10 +66,7 @@ const instancesSlice = createSlice({ instances[activeIndex].drafts[draftIndex] = action.payload } }, - removeInstanceDraft: ( - { instances }, - action: PayloadAction - ) => { + removeInstanceDraft: ({ instances }, action: PayloadAction) => { const activeIndex = findInstanceActive(instances) instances[activeIndex].drafts = instances[activeIndex].drafts?.filter( draft => draft.timestamp !== action.payload @@ -126,9 +115,7 @@ const instancesSlice = createSlice({ action: PayloadAction ) => { const HALF_LIFE = 60 * 60 * 24 * 7 // 1 week - const calculateScore = ( - emoji: InstanceLatest['frequentEmojis'][0] - ): number => { + const calculateScore = (emoji: InstanceLatest['frequentEmojis'][0]): number => { var seconds = (new Date().getTime() - emoji.lastUsed) / 1000 var score = emoji.count + 1 var order = Math.log(Math.max(score, 1)) / Math.LN10 @@ -137,9 +124,7 @@ const instancesSlice = createSlice({ } const activeIndex = findInstanceActive(instances) const foundEmojiIndex = instances[activeIndex].frequentEmojis?.findIndex( - e => - e.emoji.shortcode === action.payload.shortcode && - e.emoji.url === action.payload.url + e => e.emoji.shortcode === action.payload.shortcode && e.emoji.url === action.payload.url ) let newEmojisSort: InstanceLatest['frequentEmojis'] if (foundEmojiIndex > -1) { @@ -147,11 +132,11 @@ const instancesSlice = createSlice({ .map((e, i) => i === foundEmojiIndex ? { - ...e, - score: calculateScore(e), - count: e.count + 1, - lastUsed: new Date().getTime() - } + ...e, + score: calculateScore(e), + count: e.count + 1, + lastUsed: new Date().getTime() + } : e ) .sort((a, b) => b.score - a.score) @@ -218,8 +203,7 @@ const instancesSlice = createSlice({ return true } }) - state.instances.length && - (state.instances[state.instances.length - 1].active = true) + state.instances.length && (state.instances[state.instances.length - 1].active = true) analytics('logout') }) @@ -250,8 +234,7 @@ const instancesSlice = createSlice({ .addCase(updateConfiguration.fulfilled, (state, action) => { const activeIndex = findInstanceActive(state.instances) state.instances[activeIndex].version = action.payload?.version || '0' - state.instances[activeIndex].configuration = - action.payload.configuration + state.instances[activeIndex].configuration = action.payload.configuration }) .addCase(updateConfiguration.rejected, (_, action) => { console.error(action.error) @@ -291,22 +274,16 @@ const instancesSlice = createSlice({ // Update Instance Push Individual Alert .addCase(updateInstancePushAlert.fulfilled, (state, action) => { const activeIndex = findInstanceActive(state.instances) - state.instances[activeIndex].push.alerts[ - action.meta.arg.changed - ].loading = false + state.instances[activeIndex].push.alerts[action.meta.arg.changed].loading = false state.instances[activeIndex].push.alerts = action.payload }) .addCase(updateInstancePushAlert.rejected, (state, action) => { const activeIndex = findInstanceActive(state.instances) - state.instances[activeIndex].push.alerts[ - action.meta.arg.changed - ].loading = false + state.instances[activeIndex].push.alerts[action.meta.arg.changed].loading = false }) .addCase(updateInstancePushAlert.pending, (state, action) => { const activeIndex = findInstanceActive(state.instances) - state.instances[activeIndex].push.alerts[ - action.meta.arg.changed - ].loading = true + state.instances[activeIndex].push.alerts[action.meta.arg.changed].loading = true }) // Check if frequently used emojis still exist @@ -317,8 +294,7 @@ const instancesSlice = createSlice({ activeIndex ].frequentEmojis?.filter(emoji => { return action.payload?.find( - e => - e.shortcode === emoji.emoji.shortcode && e.url === emoji.emoji.url + e => e.shortcode === emoji.emoji.shortcode && e.url === emoji.emoji.url ) }) }) @@ -331,8 +307,7 @@ const instancesSlice = createSlice({ export const getInstanceActive = ({ instances: { instances } }: RootState) => findInstanceActive(instances) -export const getInstances = ({ instances: { instances } }: RootState) => - instances +export const getInstances = ({ instances: { instances } }: RootState) => instances export const getInstance = ({ instances: { instances } }: RootState) => instances[findInstanceActive(instances)] @@ -350,42 +325,30 @@ export const getInstanceVersion = ({ instances: { instances } }: RootState) => instances[findInstanceActive(instances)]?.version export const checkInstanceFeature = (feature: string) => - ({ instances: { instances } }: RootState): Boolean => { - return ( - features - .filter(f => f.feature === feature) - .filter( - f => - parseFloat(instances[findInstanceActive(instances)]?.version) >= - f.version - )?.length > 0 - ) - } + ({ instances: { instances } }: RootState): boolean => { + return ( + features + .filter(f => f.feature === feature) + .filter(f => parseFloat(instances[findInstanceActive(instances)]?.version) >= f.version) + ?.length > 0 + ) + } /* Get Instance Configuration */ -export const getInstanceConfigurationStatusMaxChars = ({ - instances: { instances } -}: RootState) => - instances[findInstanceActive(instances)]?.configuration?.statuses - .max_characters || 500 +export const getInstanceConfigurationStatusMaxChars = ({ instances: { instances } }: RootState) => + instances[findInstanceActive(instances)]?.configuration?.statuses.max_characters || 500 export const getInstanceConfigurationStatusMaxAttachments = ({ instances: { instances } }: RootState) => - instances[findInstanceActive(instances)]?.configuration?.statuses - .max_media_attachments || 4 + instances[findInstanceActive(instances)]?.configuration?.statuses.max_media_attachments || 4 -export const getInstanceConfigurationStatusCharsURL = ({ - instances: { instances } -}: RootState) => - instances[findInstanceActive(instances)]?.configuration?.statuses - .characters_reserved_per_url || 23 +export const getInstanceConfigurationStatusCharsURL = ({ instances: { instances } }: RootState) => + instances[findInstanceActive(instances)]?.configuration?.statuses.characters_reserved_per_url || + 23 -export const getInstanceConfigurationMediaAttachments = ({ - instances: { instances } -}: RootState) => - instances[findInstanceActive(instances)]?.configuration - ?.media_attachments || { +export const getInstanceConfigurationMediaAttachments = ({ instances: { instances } }: RootState) => + instances[findInstanceActive(instances)]?.configuration?.media_attachments || { supported_mime_types: [ 'image/jpeg', 'image/png', @@ -418,9 +381,7 @@ export const getInstanceConfigurationMediaAttachments = ({ video_matrix_limit: 2304000 } -export const getInstanceConfigurationPoll = ({ - instances: { instances } -}: RootState) => +export const getInstanceConfigurationPoll = ({ instances: { instances } }: RootState) => instances[findInstanceActive(instances)]?.configuration?.polls || { max_options: 4, max_characters_per_option: 50, @@ -432,16 +393,14 @@ export const getInstanceConfigurationPoll = ({ export const getInstanceAccount = ({ instances: { instances } }: RootState) => instances[findInstanceActive(instances)]?.account -export const getInstanceNotificationsFilter = ({ - instances: { instances } -}: RootState) => instances[findInstanceActive(instances)]?.notifications_filter +export const getInstanceNotificationsFilter = ({ instances: { instances } }: RootState) => + instances[findInstanceActive(instances)]?.notifications_filter export const getInstancePush = ({ instances: { instances } }: RootState) => instances[findInstanceActive(instances)]?.push -export const getInstanceTimelinesLookback = ({ - instances: { instances } -}: RootState) => instances[findInstanceActive(instances)]?.timelinesLookback +export const getInstanceTimelinesLookback = ({ instances: { instances } }: RootState) => + instances[findInstanceActive(instances)]?.timelinesLookback export const getInstanceMePage = ({ instances: { instances } }: RootState) => instances[findInstanceActive(instances)]?.mePage @@ -449,9 +408,8 @@ export const getInstanceMePage = ({ instances: { instances } }: RootState) => export const getInstanceDrafts = ({ instances: { instances } }: RootState) => instances[findInstanceActive(instances)]?.drafts -export const getInstanceFrequentEmojis = ({ - instances: { instances } -}: RootState) => instances[findInstanceActive(instances)]?.frequentEmojis +export const getInstanceFrequentEmojis = ({ instances: { instances } }: RootState) => + instances[findInstanceActive(instances)]?.frequentEmojis export const { updateInstanceActive, From c6bdc08d0fcf471f88f1098955782c74c5c438ce Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 20 Nov 2022 16:42:11 +0100 Subject: [PATCH 04/10] New Crowdin updates (#468) * New translations tabs.json (Spanish) * New translations common.json (Spanish) * New translations instance.json (Spanish) * New translations timeline.json (Spanish) * New translations tabs.json (Spanish) * New translations mediaSelector.json (Spanish) * New translations contextMenu.json (Spanish) * New translations tabs.json (Spanish) * New translations mediaSelector.json (Italian) * New translations parse.json (Italian) * New translations relationship.json (Italian) * New translations timeline.json (Italian) * New translations actions.json (Italian) * New translations announcements.json (Italian) * New translations compose.json (Italian) * New translations accountSelection.json (Italian) * New translations common.json (Swedish) * New translations instance.json (Swedish) * New translations parse.json (Swedish) * New translations relationship.json (Swedish) * New translations timeline.json (Swedish) * New translations actions.json (Swedish) * New translations imageViewer.json (Swedish) * New translations announcements.json (Swedish) * New translations compose.json (Swedish) * New translations screens.json (Swedish) * New translations tabs.json (Swedish) * New translations mediaSelector.json (Swedish) * New translations emojis.json (Swedish) * New translations contextMenu.json (Swedish) * New translations accountSelection.json (Swedish) * New translations common.json (Swedish) * New translations instance.json (Swedish) * New translations instance.json (Swedish) * New translations parse.json (Swedish) * New translations relationship.json (Swedish) * New translations timeline.json (Swedish) * New translations timeline.json (Swedish) * New translations actions.json (Swedish) * New translations imageViewer.json (Swedish) * New translations announcements.json (Swedish) * New translations compose.json (Swedish) * New translations tabs.json (Swedish) * New translations mediaSelector.json (Swedish) * New translations emojis.json (Swedish) * New translations contextMenu.json (Swedish) * New translations accountSelection.json (Swedish) * New translations compose.json (Swedish) * New translations screens.json (Swedish) * New translations tabs.json (Swedish) * New translations tabs.json (German) * New translations tabs.json (Italian) * New translations tabs.json (Japanese) * New translations tabs.json (Korean) * New translations tabs.json (Chinese Simplified) * New translations tabs.json (Chinese Traditional) * New translations tabs.json (Vietnamese) * New translations tabs.json (Portuguese, Brazilian) * New translations tabs.json (French) * New translations tabs.json (Polish) * New translations tabs.json (Swedish) * New translations tabs.json (Spanish) * New translations tabs.json (German) * New translations tabs.json (Italian) * New translations tabs.json (Japanese) * New translations tabs.json (Korean) * New translations tabs.json (Chinese Simplified) * New translations tabs.json (Chinese Traditional) * New translations tabs.json (Vietnamese) * New translations tabs.json (Portuguese, Brazilian) * New translations tabs.json (French) * New translations tabs.json (Swedish) * New translations tabs.json (Spanish) --- src/i18n/de/screens/tabs.json | 10 +- src/i18n/es/common.json | 2 +- src/i18n/es/components/contextMenu.json | 2 +- src/i18n/es/components/instance.json | 2 +- src/i18n/es/components/mediaSelector.json | 2 +- src/i18n/es/components/timeline.json | 8 +- src/i18n/es/screens/tabs.json | 32 +- src/i18n/fr/screens/tabs.json | 10 +- src/i18n/it/components/mediaSelector.json | 2 +- src/i18n/it/components/parse.json | 6 +- src/i18n/it/components/relationship.json | 4 +- src/i18n/it/components/timeline.json | 14 +- src/i18n/it/screens/accountSelection.json | 2 +- src/i18n/it/screens/actions.json | 2 +- src/i18n/it/screens/announcements.json | 2 +- src/i18n/it/screens/compose.json | 24 +- src/i18n/it/screens/tabs.json | 10 +- src/i18n/ja/screens/tabs.json | 10 +- src/i18n/ko/screens/tabs.json | 10 +- src/i18n/pl/screens/tabs.json | 10 +- src/i18n/pt_BR/screens/tabs.json | 10 +- src/i18n/sv/common.json | 22 ++ src/i18n/sv/components/contextMenu.json | 76 +++++ src/i18n/sv/components/emojis.json | 3 + src/i18n/sv/components/instance.json | 30 ++ src/i18n/sv/components/mediaSelector.json | 10 + src/i18n/sv/components/parse.json | 8 + src/i18n/sv/components/relationship.json | 16 + src/i18n/sv/components/timeline.json | 152 +++++++++ src/i18n/sv/screens.json | 18 ++ src/i18n/sv/screens/accountSelection.json | 6 + src/i18n/sv/screens/actions.json | 20 ++ src/i18n/sv/screens/announcements.json | 10 + src/i18n/sv/screens/compose.json | 179 +++++++++++ src/i18n/sv/screens/imageViewer.json | 17 + src/i18n/sv/screens/tabs.json | 358 ++++++++++++++++++++++ src/i18n/vi/screens/tabs.json | 10 +- src/i18n/zh-Hans/screens/tabs.json | 10 +- src/i18n/zh-Hant/screens/tabs.json | 10 +- 39 files changed, 1049 insertions(+), 80 deletions(-) create mode 100644 src/i18n/sv/common.json create mode 100644 src/i18n/sv/components/contextMenu.json create mode 100644 src/i18n/sv/components/emojis.json create mode 100644 src/i18n/sv/components/instance.json create mode 100644 src/i18n/sv/components/mediaSelector.json create mode 100644 src/i18n/sv/components/parse.json create mode 100644 src/i18n/sv/components/relationship.json create mode 100644 src/i18n/sv/components/timeline.json create mode 100644 src/i18n/sv/screens.json create mode 100644 src/i18n/sv/screens/accountSelection.json create mode 100644 src/i18n/sv/screens/actions.json create mode 100644 src/i18n/sv/screens/announcements.json create mode 100644 src/i18n/sv/screens/compose.json create mode 100644 src/i18n/sv/screens/imageViewer.json create mode 100644 src/i18n/sv/screens/tabs.json diff --git a/src/i18n/de/screens/tabs.json b/src/i18n/de/screens/tabs.json index 44890943..c2808f00 100644 --- a/src/i18n/de/screens/tabs.json +++ b/src/i18n/de/screens/tabs.json @@ -310,6 +310,13 @@ "attachments": { "name": "<0 /><1>\"s Medien" }, + "hashtag": { + "follow": "Folgen", + "unfollow": "Entfolgen" + }, + "history": { + "name": "Bearbeitungsverlauf" + }, "search": { "header": { "prefix": "Suche", @@ -346,9 +353,6 @@ "reblogged_by": "{{count}} mal geboosted", "favourited_by": "{{count}} mal geherzt" } - }, - "history": { - "name": "Bearbeitungsverlauf" } } } \ No newline at end of file diff --git a/src/i18n/es/common.json b/src/i18n/es/common.json index 676f3efd..cd456dfe 100644 --- a/src/i18n/es/common.json +++ b/src/i18n/es/common.json @@ -9,7 +9,7 @@ }, "message": { "success": { - "message": "" + "message": "{{function}} con éxito" }, "warning": { "message": "" diff --git a/src/i18n/es/components/contextMenu.json b/src/i18n/es/components/contextMenu.json index fd3ef8bf..e879a855 100644 --- a/src/i18n/es/components/contextMenu.json +++ b/src/i18n/es/components/contextMenu.json @@ -1,5 +1,5 @@ { - "accessibilityHint": "", + "accessibilityHint": "Acciones para este toot, como su usuario o el toot en sí mismo", "account": { "title": "Acciones de usuario", "mute": { diff --git a/src/i18n/es/components/instance.json b/src/i18n/es/components/instance.json index e4ef89af..914f3c04 100644 --- a/src/i18n/es/components/instance.json +++ b/src/i18n/es/components/instance.json @@ -8,7 +8,7 @@ "name": "Nombre", "accounts": "Usuarios", "statuses": "Toots", - "domains": "" + "domains": "Universos" }, "disclaimer": { "base": "El inicio de sesión usa el navegador del sistema, y la información de la cuenta no será visible para tooot." diff --git a/src/i18n/es/components/mediaSelector.json b/src/i18n/es/components/mediaSelector.json index a8897333..0becd316 100644 --- a/src/i18n/es/components/mediaSelector.json +++ b/src/i18n/es/components/mediaSelector.json @@ -1,5 +1,5 @@ { - "title": "", + "title": "Elegir origen multimedia", "message": "Los datos multimedia EXIF no se han subido", "options": { "image": "Subir fotos", diff --git a/src/i18n/es/components/timeline.json b/src/i18n/es/components/timeline.json index 1adf59d3..3d6e3511 100644 --- a/src/i18n/es/components/timeline.json +++ b/src/i18n/es/components/timeline.json @@ -47,11 +47,11 @@ }, "favourited": { "accessibilityLabel": "Agregar este toot en favoritos", - "function": "" + "function": "Marcar toot como favorito" }, "bookmarked": { "accessibilityLabel": "Añadir este toot en marcadores", - "function": "" + "function": "Añadir toot a marcadores" } }, "actionsUsers": { @@ -78,7 +78,7 @@ }, "unsupported": { "text": "Error al cargar", - "button": "" + "button": "Probar con el enlace remoto" } }, "avatar": { @@ -101,7 +101,7 @@ "shared": { "account": { "name": { - "accessibilityHint": "" + "accessibilityHint": "Nombre de usuario" }, "account": { "accessibilityHint": "Cuenta de usuario" diff --git a/src/i18n/es/screens/tabs.json b/src/i18n/es/screens/tabs.json index e669cf45..5c282b4b 100644 --- a/src/i18n/es/screens/tabs.json +++ b/src/i18n/es/screens/tabs.json @@ -134,7 +134,7 @@ }, "lock": { "title": "Bloquear cuenta", - "description": "" + "description": "Necesitas aprobar manualmente los seguidores nuevos" }, "bot": { "title": "Cuenta bot", @@ -156,11 +156,11 @@ }, "global": { "heading": "Habilitar para {{acct}}", - "description": "" + "description": "Los mensajes se envían a través del servidor de tooot" }, "decode": { "heading": "Mostrar detalles del mensaje", - "description": "" + "description": "Los mensajes que se envían a través del servidor de tooot están encriptados, pero puedes optar por desencriptarlos en el servidor. El servidor es de código abierto y tenemos una política de cero registros." }, "default": { "heading": "Predeterminado" @@ -172,7 +172,7 @@ "heading": "Solicitud de seguimiento" }, "favourite": { - "heading": "" + "heading": "Favoritos" }, "reblog": { "heading": "Impulsado" @@ -186,14 +186,14 @@ "status": { "heading": "Toot de usuarios suscritos" }, - "howitworks": "" + "howitworks": "Más información sobre las notificaciones push" }, "root": { "announcements": { "content": { "unread": "{{amount}} no leídos", - "read": "", - "empty": "" + "read": "Todo leído", + "empty": "Nada" } }, "push": { @@ -203,7 +203,7 @@ } }, "update": { - "title": "" + "title": "Actualizar a la última versión" }, "logout": { "button": "Cerrar sesión", @@ -310,10 +310,17 @@ "attachments": { "name": "" }, + "hashtag": { + "follow": "Seguir", + "unfollow": "Dejar de seguir" + }, + "history": { + "name": "Historial de ediciones" + }, "search": { "header": { "prefix": "Buscando", - "placeholder": "" + "placeholder": "algo..." }, "empty": { "general": "Escribe para buscar $t(screenTabs:shared.search.sections.accounts), $t(screenTabs:shared.search.sections.hashtags) o $t(screenTabs:shared.search.sections.statuses)", @@ -332,10 +339,10 @@ "hashtags": "Hashtag", "statuses": "Toot" }, - "notFound": "" + "notFound": "No se pudo encontrar {{searchTerm}} relacionado con {{type}}" }, "toot": { - "name": "" + "name": "Discusiones" }, "users": { "accounts": { @@ -346,9 +353,6 @@ "reblogged_by": "{{count}} impulsados", "favourited_by": "{{count}} favoritos" } - }, - "history": { - "name": "" } } } \ No newline at end of file diff --git a/src/i18n/fr/screens/tabs.json b/src/i18n/fr/screens/tabs.json index 7ed79d7e..7934b677 100644 --- a/src/i18n/fr/screens/tabs.json +++ b/src/i18n/fr/screens/tabs.json @@ -310,6 +310,13 @@ "attachments": { "name": "<0 /><1>\"s media" }, + "hashtag": { + "follow": "Suivre", + "unfollow": "Ne plus suivre" + }, + "history": { + "name": "Modifier l'historique" + }, "search": { "header": { "prefix": "Recherche en cours", @@ -346,9 +353,6 @@ "reblogged_by": "{{count}} boosté", "favourited_by": "{{count}} mis en favori" } - }, - "history": { - "name": "Modifier l'historique" } } } \ No newline at end of file diff --git a/src/i18n/it/components/mediaSelector.json b/src/i18n/it/components/mediaSelector.json index a91b2894..06f3c082 100644 --- a/src/i18n/it/components/mediaSelector.json +++ b/src/i18n/it/components/mediaSelector.json @@ -1,6 +1,6 @@ { "title": "Seleziona origine media", - "message": "", + "message": "I dati EXIF multimediali non sono stati caricati", "options": { "image": "Carica foto", "image_max": "Carica foto (massimo {{max}})", diff --git a/src/i18n/it/components/parse.json b/src/i18n/it/components/parse.json index 2db10f00..e640def1 100644 --- a/src/i18n/it/components/parse.json +++ b/src/i18n/it/components/parse.json @@ -1,8 +1,8 @@ { "HTML": { - "accessibilityHint": "", + "accessibilityHint": "Tocca per espandere o comprimere il contenuto", "expanded": "{{hint}}{{moreLines}}", - "moreLines": "", - "defaultHint": "" + "moreLines": " (altre{{count}} linee)", + "defaultHint": "Toot lungo" } } \ No newline at end of file diff --git a/src/i18n/it/components/relationship.json b/src/i18n/it/components/relationship.json index 2b1cfeda..9307b6c0 100644 --- a/src/i18n/it/components/relationship.json +++ b/src/i18n/it/components/relationship.json @@ -7,10 +7,10 @@ }, "button": { "error": "Errore di caricamento", - "blocked_by": "L'utente ti ha bloccato", + "blocked_by": "Bloccato dall'utente", "blocking": "Sblocca", "following": "Smetti di seguire", - "requested": "Annulla richiesta di seguire", + "requested": "Annulla la richiesta", "default": "Segui" } } \ No newline at end of file diff --git a/src/i18n/it/components/timeline.json b/src/i18n/it/components/timeline.json index 512a79f1..3b1a40c6 100644 --- a/src/i18n/it/components/timeline.json +++ b/src/i18n/it/components/timeline.json @@ -16,21 +16,21 @@ }, "refresh": { "fetchPreviousPage": "Più recenti da qui", - "refetch": "Vai a recenti" + "refetch": "Al più recente" }, "shared": { "actioned": { "pinned": "Fissato in cima", "favourite": "{{name}} ha apprezzato il tuo toot", "status": "{{name}} ha appena pubblicato", - "follow": "{{name}} ti sta seguendo", + "follow": "{{name}} ti segue", "follow_request": "{{name}} ha chiesto di seguirti", "poll": "Un sondaggio in cui hai votato è terminato", "reblog": { "default": "{{name}} ha ricondiviso", "notification": "{{name}} ha ricondiviso il tuo toot" }, - "update": "Retoot ha subito una modifica" + "update": "Il link è stato modificato" }, "actions": { "reply": { @@ -40,9 +40,9 @@ "accessibilityLabel": "Ricondividi questo toot", "function": "Ricondividi toot", "options": { - "title": "", - "public": "", - "unlisted": "" + "title": "Scegli visibilità boost", + "public": "Boost pubblico", + "unlisted": "Rimuovi boost dall'elenco" } }, "favourited": { @@ -88,7 +88,7 @@ "content": { "expandHint": "Contenuto nascosto" }, - "filtered": "", + "filtered": "Filtrato: {{phrase}}.", "fullConversation": "Leggi la conversazione", "translate": { "default": "Traduci", diff --git a/src/i18n/it/screens/accountSelection.json b/src/i18n/it/screens/accountSelection.json index 770adb7a..c4680509 100644 --- a/src/i18n/it/screens/accountSelection.json +++ b/src/i18n/it/screens/accountSelection.json @@ -1,6 +1,6 @@ { "heading": "Condividi con...", "content": { - "select_account": "Seleziona conto" + "select_account": "Seleziona profilo" } } \ No newline at end of file diff --git a/src/i18n/it/screens/actions.json b/src/i18n/it/screens/actions.json index f6914024..b428b43c 100644 --- a/src/i18n/it/screens/actions.json +++ b/src/i18n/it/screens/actions.json @@ -7,7 +7,7 @@ "heading": "Filtra notifiche per tipo", "content": { "follow": "$t(screenTabs:me.push.follow.heading)", - "follow_request": "Richieste di seguirti", + "follow_request": "Richiesta di seguirti", "favourite": "$t(screenTabs:me.push.favourite.heading)", "reblog": "$t(screenTabs:me.push.reblog.heading)", "mention": "$t(screenTabs:me.push.mention.heading)", diff --git a/src/i18n/it/screens/announcements.json b/src/i18n/it/screens/announcements.json index c41719f6..75d1b07c 100644 --- a/src/i18n/it/screens/announcements.json +++ b/src/i18n/it/screens/announcements.json @@ -3,7 +3,7 @@ "content": { "published": "Pubblicato <0 />", "button": { - "read": "Già letto", + "read": "Letto", "unread": "Segna come letto" } } diff --git a/src/i18n/it/screens/compose.json b/src/i18n/it/screens/compose.json index 095ef96c..f84b9a13 100644 --- a/src/i18n/it/screens/compose.json +++ b/src/i18n/it/screens/compose.json @@ -1,12 +1,12 @@ { "heading": { "left": { - "button": "Scarta", + "button": "Annulla", "alert": { "title": "Scartare il toot?", "buttons": { - "save": "Salva come bozza", - "delete": "Scarta ed esci", + "save": "Salva bozza", + "delete": "Elimina bozza", "cancel": "Annulla" } } @@ -22,14 +22,14 @@ }, "alert": { "default": { - "title": "Invio fallito", + "title": "Pubblicazione fallita", "button": "Riprova" }, "removeReply": { "title": "Impossibile trovare il toot a cui si è risposto", "description": "Il toot a cui si è risposto potrebbe essere stato cancellato. Vuoi rimuoverne il riferimento?", "cancel": "$t(common:buttons.cancel)", - "confirm": "Rimuovi" + "confirm": "Rimuovi riferimento" } } } @@ -37,7 +37,7 @@ "content": { "root": { "header": { - "postingAs": "Pubblicando come @{{acct}}@{{domain}}", + "postingAs": "Pubblica come @{{acct}}@{{domain}}", "spoilerInput": { "placeholder": "Avviso di spoiler" }, @@ -65,24 +65,24 @@ } }, "emojis": { - "accessibilityHint": "Premi per aggiungere delle emoji a questo toot" + "accessibilityHint": "Tocca per aggiungere emoji al toot" }, "poll": { "option": { "placeholder": { - "accessibilityLabel": "Scelta di sondaggio {{index}}", + "accessibilityLabel": "Opzione sondaggio {{index}}", "single": "Risposta singola", "multiple": "Risposta multipla" } }, "quantity": { "reduce": { - "accessibilityLabel": "Riduci le scelte del sondaggio a {{amount}}", - "accessibilityHint": "Hai raggiunto il minimo di scelte possibili per il sondaggio ({{amount}})" + "accessibilityLabel": "Riduce le opzioni del sondaggio a {{amount}}", + "accessibilityHint": "Quantità minima di opzioni del sondaggio raggiunta, attualmente ne ha {{amount}}" }, "increase": { - "accessibilityLabel": "Aumenta le scelte del sondaggio a {{amount}}", - "accessibilityHint": "Hai raggiunto il massimo di scelte possibili per il sondaggio ({{amount}})" + "accessibilityLabel": "Aumenta le opzioni del sondaggio a {{amount}}", + "accessibilityHint": "Massima quantità di opzioni del sondaggio raggiunta, attualmente ne ha {{amount}}" } }, "multiple": { diff --git a/src/i18n/it/screens/tabs.json b/src/i18n/it/screens/tabs.json index 0229822d..dedbc789 100644 --- a/src/i18n/it/screens/tabs.json +++ b/src/i18n/it/screens/tabs.json @@ -310,6 +310,13 @@ "attachments": { "name": "Media di <0 /><1>\"" }, + "hashtag": { + "follow": "Segui", + "unfollow": "Smetti di seguire" + }, + "history": { + "name": "Cronologia delle modifiche" + }, "search": { "header": { "prefix": "Cerca", @@ -346,9 +353,6 @@ "reblogged_by": "{{count}} ricondivisioni", "favourited_by": "{{count}} apprezzamenti" } - }, - "history": { - "name": "Cronologia delle modifiche" } } } \ No newline at end of file diff --git a/src/i18n/ja/screens/tabs.json b/src/i18n/ja/screens/tabs.json index 52b6c8a2..8cdb69e9 100644 --- a/src/i18n/ja/screens/tabs.json +++ b/src/i18n/ja/screens/tabs.json @@ -310,6 +310,13 @@ "attachments": { "name": "<0 /><1>\" のメディア" }, + "hashtag": { + "follow": "フォロー", + "unfollow": "フォローをやめる" + }, + "history": { + "name": "編集履歴" + }, "search": { "header": { "prefix": "検索", @@ -346,9 +353,6 @@ "reblogged_by": "{{count}} ブースト", "favourited_by": "{{count}} お気に入り" } - }, - "history": { - "name": "編集履歴" } } } \ No newline at end of file diff --git a/src/i18n/ko/screens/tabs.json b/src/i18n/ko/screens/tabs.json index c08f1214..965f926d 100644 --- a/src/i18n/ko/screens/tabs.json +++ b/src/i18n/ko/screens/tabs.json @@ -310,6 +310,13 @@ "attachments": { "name": "<0 /><1>\"의 미디어" }, + "hashtag": { + "follow": "팔로우", + "unfollow": "팔로우 해제" + }, + "history": { + "name": "수정 이력" + }, "search": { "header": { "prefix": "무엇을", @@ -346,9 +353,6 @@ "reblogged_by": "{{count}} 부스트함", "favourited_by": "{{count}} 즐겨찾기함" } - }, - "history": { - "name": "수정 이력" } } } \ No newline at end of file diff --git a/src/i18n/pl/screens/tabs.json b/src/i18n/pl/screens/tabs.json index 5a8188c4..ed143487 100644 --- a/src/i18n/pl/screens/tabs.json +++ b/src/i18n/pl/screens/tabs.json @@ -310,6 +310,13 @@ "attachments": { "name": "" }, + "hashtag": { + "follow": "", + "unfollow": "" + }, + "history": { + "name": "" + }, "search": { "header": { "prefix": "", @@ -346,9 +353,6 @@ "reblogged_by": "", "favourited_by": "" } - }, - "history": { - "name": "" } } } \ No newline at end of file diff --git a/src/i18n/pt_BR/screens/tabs.json b/src/i18n/pt_BR/screens/tabs.json index 8f61070e..b44b69fe 100644 --- a/src/i18n/pt_BR/screens/tabs.json +++ b/src/i18n/pt_BR/screens/tabs.json @@ -310,6 +310,13 @@ "attachments": { "name": "<0 /><1>\"s mídia" }, + "hashtag": { + "follow": "Seguir", + "unfollow": "Deixar de seguir" + }, + "history": { + "name": "Histórico de Edição" + }, "search": { "header": { "prefix": "Procurando", @@ -346,9 +353,6 @@ "reblogged_by": "{{count}} boostou", "favourited_by": "{{count}} favoritados" } - }, - "history": { - "name": "Histórico de Edição" } } } \ No newline at end of file diff --git a/src/i18n/sv/common.json b/src/i18n/sv/common.json new file mode 100644 index 00000000..cb81f060 --- /dev/null +++ b/src/i18n/sv/common.json @@ -0,0 +1,22 @@ +{ + "buttons": { + "OK": "OK", + "apply": "Verkställ", + "cancel": "Avbryt" + }, + "customEmoji": { + "accessibilityLabel": "Anpassad emoji {{emoji}}" + }, + "message": { + "success": { + "message": "{{function}} lyckades" + }, + "warning": { + "message": "" + }, + "error": { + "message": "{{function}} misslyckades, försök igen" + } + }, + "separator": ", " +} \ No newline at end of file diff --git a/src/i18n/sv/components/contextMenu.json b/src/i18n/sv/components/contextMenu.json new file mode 100644 index 00000000..164e3beb --- /dev/null +++ b/src/i18n/sv/components/contextMenu.json @@ -0,0 +1,76 @@ +{ + "accessibilityHint": "Åtgärder för detta inlägg, som t.ex. dess författare, själva inlägget", + "account": { + "title": "Användaråtgärder", + "mute": { + "action_false": "Tysta användare", + "action_true": "Sluta tysta användare" + }, + "block": { + "action_false": "Blockera användare", + "action_true": "Avblockera användare" + }, + "reports": { + "action": "Rapportera och blockera" + } + }, + "copy": { + "action": "Kopiera inlägg", + "succeed": "Kopierat" + }, + "instance": { + "title": "Instansåtgärd", + "block": { + "action": "Blockera instansen {{instance}}", + "alert": { + "title": "Bekräfta blockering av instansen {{instance}}?", + "message": "Oftast kan du tysta eller blockera vissa användare.\n\nEfter blockering av en instans kommer allt innehåll inklusive följare från denna instans att tas bort!", + "buttons": { + "confirm": "Bekräfta" + } + } + } + }, + "share": { + "status": { + "action": "Dela inlägg" + }, + "account": { + "action": "Dela användare" + } + }, + "status": { + "title": "Inläggsåtgärder", + "edit": { + "action": "Redigera inlägg" + }, + "delete": { + "action": "Radera inlägg", + "alert": { + "title": "Bekräfta radering?", + "message": "Alla boostar och favoritmarkeringar kommer tas bort, inklusive alla svar.", + "buttons": { + "confirm": "Bekräfta" + } + } + }, + "deleteEdit": { + "action": "Radera inlägg och posta på nytt", + "alert": { + "title": "Bekräfta radera inlägg och posta på nytt?", + "message": "Alla boostar och favoritmarkeringar kommer tas bort, inklusive alla svar.", + "buttons": { + "confirm": "Bekräfta" + } + } + }, + "mute": { + "action_false": "Tysta inlägg och svar", + "action_true": "Sluta tysta inlägg och svar" + }, + "pin": { + "action_false": "Fäst inlägg", + "action_true": "Avfäst inlägg" + } + } +} \ No newline at end of file diff --git a/src/i18n/sv/components/emojis.json b/src/i18n/sv/components/emojis.json new file mode 100644 index 00000000..53ee7df7 --- /dev/null +++ b/src/i18n/sv/components/emojis.json @@ -0,0 +1,3 @@ +{ + "frequentUsed": "Ofta använda" +} \ No newline at end of file diff --git a/src/i18n/sv/components/instance.json b/src/i18n/sv/components/instance.json new file mode 100644 index 00000000..3f669dbf --- /dev/null +++ b/src/i18n/sv/components/instance.json @@ -0,0 +1,30 @@ +{ + "server": { + "textInput": { + "placeholder": "Domän för instansen" + }, + "button": "Logga in", + "information": { + "name": "Namn", + "accounts": "Användare", + "statuses": "Inlägg", + "domains": "Universum" + }, + "disclaimer": { + "base": "Inloggningsprocessen använder systemets webbläsare så ingen av din kontoinformation är synlig för appen." + }, + "terms": { + "base": "Genom att logga in godkänner du <0> integritetspolicyn och <1>användarvillkoren." + } + }, + "update": { + "alert": { + "title": "Inloggad till denna instans", + "message": "Du kan logga in på ett annat konto och behålla redan inloggade konton", + "buttons": { + "cancel": "$t(common:buttons.cancel)", + "continue": "Fortsätt" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/sv/components/mediaSelector.json b/src/i18n/sv/components/mediaSelector.json new file mode 100644 index 00000000..589332fc --- /dev/null +++ b/src/i18n/sv/components/mediaSelector.json @@ -0,0 +1,10 @@ +{ + "title": "Välj mediakälla", + "message": "EXIF-data för media laddas inte upp", + "options": { + "image": "Ladda upp bilder", + "image_max": "Ladda upp bilder (max {{max}})", + "video": "Ladda upp video", + "video_max": "Ladda upp video (max {{max}})" + } +} \ No newline at end of file diff --git a/src/i18n/sv/components/parse.json b/src/i18n/sv/components/parse.json new file mode 100644 index 00000000..8fde132a --- /dev/null +++ b/src/i18n/sv/components/parse.json @@ -0,0 +1,8 @@ +{ + "HTML": { + "accessibilityHint": "Tryck för att utöka eller dölja innehåll", + "expanded": "{{hint}}{{moreLines}}", + "moreLines": " ({{count}} rader till)", + "defaultHint": "Långt inlägg" + } +} \ No newline at end of file diff --git a/src/i18n/sv/components/relationship.json b/src/i18n/sv/components/relationship.json new file mode 100644 index 00000000..1dbcab28 --- /dev/null +++ b/src/i18n/sv/components/relationship.json @@ -0,0 +1,16 @@ +{ + "follow": { + "function": "Följ användare" + }, + "block": { + "function": "Blockera användare" + }, + "button": { + "error": "Laddningsfel", + "blocked_by": "Blockerad av användare", + "blocking": "Avblockera", + "following": "Sluta följ", + "requested": "Återkalla förfrågan", + "default": "Följ" + } +} \ No newline at end of file diff --git a/src/i18n/sv/components/timeline.json b/src/i18n/sv/components/timeline.json new file mode 100644 index 00000000..488048e4 --- /dev/null +++ b/src/i18n/sv/components/timeline.json @@ -0,0 +1,152 @@ +{ + "empty": { + "error": { + "message": "Laddningsfel", + "button": "Försök igen" + }, + "success": { + "message": "Tidslinjen är tom" + } + }, + "end": { + "message": "Slut, vad sägs om en kopp <0 />" + }, + "lookback": { + "message": "Senast läst" + }, + "refresh": { + "fetchPreviousPage": "Nyare härifrån", + "refetch": "Till senaste" + }, + "shared": { + "actioned": { + "pinned": "Fäst", + "favourite": "{{name}} favoritmarkerade ditt inlägg", + "status": "{{name}} publicerade just ett inlägg", + "follow": "{{name}} följde dig", + "follow_request": "{{name}} begärde att få följa dig", + "poll": "En omröstning du röstat i har avslutats", + "reblog": { + "default": "{{name}} boostade", + "notification": "{{name}} boostade ditt inlägg" + }, + "update": "Boosten har redigerats" + }, + "actions": { + "reply": { + "accessibilityLabel": "Svara på det här inlägget" + }, + "reblogged": { + "accessibilityLabel": "Boosta det här inlägget", + "function": "Boosta inlägg", + "options": { + "title": "Välj synlighet på boost", + "public": "Offentlig boost", + "unlisted": "Olistad boost" + } + }, + "favourited": { + "accessibilityLabel": "Lägg till detta inlägg till favoriter", + "function": "Favoritmarkera inlägg" + }, + "bookmarked": { + "accessibilityLabel": "Lägg till detta inlägg till dina bokmärken", + "function": "Bokmärk inlägg" + } + }, + "actionsUsers": { + "reblogged_by": { + "accessibilityLabel": "{{count}} användare har boostat det här inlägget", + "accessibilityHint": "Tryck för att lära känna användarna", + "text": "$t(screenTabs:shared.users.statuses.reblogged_by)" + }, + "favourited_by": { + "accessibilityLabel": "{{count}} användare har favoritmarkerat det här inlägget", + "accessibilityHint": "Tryck för att lära känna användarna", + "text": "$t(screenTabs:shared.users.statuses.favourited_by)" + }, + "history": { + "accessibilityLabel": "Detta inlägg har redigerats {{count}} gånger", + "accessibilityHint": "Tryck för att visa hela redigeringshistoriken", + "text_one": "{{count}} redigering", + "text_other": "{{count}} redigeringar" + } + }, + "attachment": { + "sensitive": { + "button": "Visa känslig media" + }, + "unsupported": { + "text": "Laddningsfel", + "button": "Prova fjärrlänk" + } + }, + "avatar": { + "accessibilityLabel": "{{name}}s avatar", + "accessibilityHint": "Tryck för att gå till {{name}}s sida" + }, + "content": { + "expandHint": "Dolt innehåll" + }, + "filtered": "Filtrerat: {{phrase}}.", + "fullConversation": "Läs konversationer", + "translate": { + "default": "Översätt", + "succeed": "Översatt av {{provider}} från {{source}}", + "failed": "Översättning misslyckades", + "source_not_supported": "inläggets språk stöds inte", + "target_not_supported": "Målspråket stöds inte" + }, + "header": { + "shared": { + "account": { + "name": { + "accessibilityHint": "Användarens visningsnamn" + }, + "account": { + "accessibilityHint": "Användarens konto" + } + }, + "application": "Via {{application}}", + "edited": { + "accessibilityLabel": "Inlägg redigerat" + }, + "muted": { + "accessibilityLabel": "Inlägg tystat" + }, + "visibility": { + "direct": { + "accessibilityLabel": "Inlägget är ett direktmeddelande" + }, + "private": { + "accessibilityLabel": "Inlägget syns endast för följare" + } + } + }, + "conversation": { + "withAccounts": "Med", + "delete": { + "function": "Ta bort direktmeddelande" + } + } + }, + "poll": { + "meta": { + "button": { + "vote": "Rösta", + "refresh": "Uppdatera" + }, + "count": { + "voters_one": "{{count}} användare har röstat", + "voters_other": "{{count}} användare har röstat", + "votes_one": "{{count}} röst", + "votes_other": "{{count}} röster" + }, + "expiration": { + "expired": "Omröstning har gått ut", + "until": "Förfaller <0 />" + } + } + } + } +} \ No newline at end of file diff --git a/src/i18n/sv/screens.json b/src/i18n/sv/screens.json new file mode 100644 index 00000000..0e1578f3 --- /dev/null +++ b/src/i18n/sv/screens.json @@ -0,0 +1,18 @@ +{ + "screenshot": { + "title": "Integritetsskydd", + "message": "Vänligen avslöja inte någon annan användares identitet, såsom användarnamn, profilbild etc. Tack!", + "button": "Bekräfta" + }, + "localCorrupt": { + "message": "Inloggningen har gått ut. Försök att logga in igen" + }, + "pushError": { + "message": "Fel i push-tjänster", + "description": "Vänligen återaktivera pushnotiser i inställningar" + }, + "shareError": { + "imageNotSupported": "Bildformatet {{type}} stöds inte", + "videoNotSupported": "Videoformatet {{type}} stöds inte" + } +} \ No newline at end of file diff --git a/src/i18n/sv/screens/accountSelection.json b/src/i18n/sv/screens/accountSelection.json new file mode 100644 index 00000000..873f66f0 --- /dev/null +++ b/src/i18n/sv/screens/accountSelection.json @@ -0,0 +1,6 @@ +{ + "heading": "Dela med ...", + "content": { + "select_account": "Välj konto" + } +} \ No newline at end of file diff --git a/src/i18n/sv/screens/actions.json b/src/i18n/sv/screens/actions.json new file mode 100644 index 00000000..347390cf --- /dev/null +++ b/src/i18n/sv/screens/actions.json @@ -0,0 +1,20 @@ +{ + "content": { + "altText": { + "heading": "Alternativtext" + }, + "notificationsFilter": { + "heading": "Visa notistyper", + "content": { + "follow": "$t(screenTabs:me.push.follow.heading)", + "follow_request": "Följarförfrågning", + "favourite": "$t(screenTabs:me.push.favourite.heading)", + "reblog": "$t(screenTabs:me.push.reblog.heading)", + "mention": "$t(screenTabs:me.push.mention.heading)", + "poll": "$t(screenTabs:me.push.poll.heading)", + "status": "Inlägg från följda användare", + "update": "Boosten har redigerats" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/sv/screens/announcements.json b/src/i18n/sv/screens/announcements.json new file mode 100644 index 00000000..dc0b379b --- /dev/null +++ b/src/i18n/sv/screens/announcements.json @@ -0,0 +1,10 @@ +{ + "heading": "Meddelanden", + "content": { + "published": "Publicerad <0 />", + "button": { + "read": "Läst", + "unread": "Markera som läst" + } + } +} \ No newline at end of file diff --git a/src/i18n/sv/screens/compose.json b/src/i18n/sv/screens/compose.json new file mode 100644 index 00000000..39869ede --- /dev/null +++ b/src/i18n/sv/screens/compose.json @@ -0,0 +1,179 @@ +{ + "heading": { + "left": { + "button": "Avbryt", + "alert": { + "title": "Avbryt redigering?", + "buttons": { + "save": "Spara utkast", + "delete": "Ta bort utkast", + "cancel": "Avbryt" + } + } + }, + "right": { + "button": { + "default": "Inlägg", + "conversation": "Skicka DM", + "reply": "Skicka svar", + "deleteEdit": "Inlägg", + "edit": "Publicera", + "share": "Inlägg" + }, + "alert": { + "default": { + "title": "Kunde inte publicera", + "button": "Försök igen" + }, + "removeReply": { + "title": "Inlägget kunde inte hittas", + "description": "Inlägget du svarar på kan ha raderats. Vill du ta bort referensen till det?", + "cancel": "$t(common:buttons.cancel)", + "confirm": "Ta bort referens" + } + } + } + }, + "content": { + "root": { + "header": { + "postingAs": "Skriver som @{{acct}}@{{domain}}", + "spoilerInput": { + "placeholder": "Spoilervarningsmeddelande" + }, + "textInput": { + "placeholder": "Vad tänker du på", + "keyboardImage": { + "exceedMaximum": { + "title": "Maximalt antal bilagor har uppnåtts", + "OK": "$t(common:buttons.OK)" + } + } + } + }, + "footer": { + "attachments": { + "sensitive": "Markera bilagor som känsliga", + "remove": { + "accessibilityLabel": "Ta bort uppladdad bilaga, nummer {{attachment}}" + }, + "edit": { + "accessibilityLabel": "Redigera uppladdad bilaga, nummer {{attachment}}" + }, + "upload": { + "accessibilityLabel": "Ladda upp fler bilagor" + } + }, + "emojis": { + "accessibilityHint": "Tryck för att lägga till emoji till inlägg" + }, + "poll": { + "option": { + "placeholder": { + "accessibilityLabel": "Omröstningsalternativ {{index}}", + "single": "Enval", + "multiple": "Flera val" + } + }, + "quantity": { + "reduce": { + "accessibilityLabel": "Minska omröstningsalternativ till {{amount}}", + "accessibilityHint": "Minsta antal omröstningsalternativ har uppnåtts, för närvarande {{amount}}" + }, + "increase": { + "accessibilityLabel": "Öka omröstningsalternativ till {{amount}}", + "accessibilityHint": "Maximalt antal omröstningsalternativ har uppnåtts, för närvarande {{amount}}" + } + }, + "multiple": { + "heading": "Typ av val", + "options": { + "single": "Enval", + "multiple": "Flera val", + "cancel": "$t(common:buttons.cancel)" + } + }, + "expiration": { + "heading": "Giltighet", + "options": { + "300": "5 minuter", + "1800": "30 minuter", + "3600": "1 timme", + "21600": "6 timmar", + "86400": "1 dag", + "259200": "3 dagar", + "604800": "7 dagar", + "cancel": "$t(common:buttons.cancel)" + } + } + } + }, + "actions": { + "attachment": { + "accessibilityLabel": "Ladda upp bilaga", + "accessibilityHint": "Omröstningsfunktionen kommer att inaktiveras om det finns bilagor", + "failed": { + "alert": { + "title": "Uppladdningen misslyckades", + "button": "Försök igen" + } + } + }, + "poll": { + "accessibilityLabel": "Lägg till omröstning", + "accessibilityHint": "Bilagefunktionen inaktiveras när en omröstning är aktiv" + }, + "visibility": { + "accessibilityLabel": "Inläggets synlighet är {{visibility}}", + "title": "Inläggssynlighet", + "options": { + "public": "Offentlig", + "unlisted": "Olistad", + "private": "Endast följare", + "direct": "Direktmeddelande", + "cancel": "$t(common:buttons.cancel)" + } + }, + "spoiler": { + "accessibilityLabel": "Spoiler" + }, + "emoji": { + "accessibilityLabel": "Lägg till emoji", + "accessibilityHint": "Öppna panelen för emoji-val, svep horisontellt för att byta sida" + } + }, + "drafts_one": "Utkast ({{count}})", + "drafts_other": "Utkast ({{count}})" + }, + "editAttachment": { + "header": { + "title": "Redigera bilaga", + "right": { + "accessibilityLabel": "Spara redigering av bilaga", + "failed": { + "title": "Kunde inte redigera", + "button": "Försök igen" + } + } + }, + "content": { + "altText": { + "heading": "Beskriv media för synskadade", + "placeholder": "Du kan lägga till en beskrivning, som ibland kallas alternativtext, till dina medier så att de är tillgängliga för ännu fler, inklusive dem som är blinda eller synskadade.\n\nBra beskrivningar är kortfattade men presenterar vad som finns i dina medier tillräckligt noggrant för att beskriva deras sammanhang." + }, + "imageFocus": "Dra i fokuscirkeln för att uppdatera fokuspunkten" + } + }, + "draftsList": { + "header": { + "title": "Utkast" + }, + "warning": "Utkasten lagras endast lokalt och kan gå förlorade i sällsynta fall. Ett tips är att inte använda utkast för långtidslagring.", + "content": { + "accessibilityHint": "Sparat utkast, tryck för att redigera detta utkast", + "textEmpty": "Innehållet är tomt" + }, + "checkAttachment": "Kontrollerar bilagor på servern..." + } + } +} \ No newline at end of file diff --git a/src/i18n/sv/screens/imageViewer.json b/src/i18n/sv/screens/imageViewer.json new file mode 100644 index 00000000..39ad2514 --- /dev/null +++ b/src/i18n/sv/screens/imageViewer.json @@ -0,0 +1,17 @@ +{ + "content": { + "actions": { + "accessibilityLabel": "Fler åtgärder för denna bild", + "accessibilityHint": "Du kan spara eller dela denna bild" + }, + "options": { + "save": "Spara bild", + "share": "Dela bild", + "cancel": "$t(common:buttons.cancel)" + }, + "save": { + "succeed": "Bild sparad", + "failed": "Kunde inte spara bild" + } + } +} \ No newline at end of file diff --git a/src/i18n/sv/screens/tabs.json b/src/i18n/sv/screens/tabs.json new file mode 100644 index 00000000..32626622 --- /dev/null +++ b/src/i18n/sv/screens/tabs.json @@ -0,0 +1,358 @@ +{ + "tabs": { + "local": { + "name": "Följer" + }, + "public": { + "name": "", + "segments": { + "left": "Federerat", + "right": "Lokalt" + } + }, + "notifications": { + "name": "Notiser" + }, + "me": { + "name": "Om mig" + } + }, + "common": { + "search": { + "accessibilityLabel": "Sök", + "accessibilityHint": "Sök efter hashtaggar, användare eller inlägg" + } + }, + "notifications": { + "filter": { + "accessibilityLabel": "Filter", + "accessibilityHint": "Filtrera visade notistyper" + } + }, + "me": { + "stacks": { + "bookmarks": { + "name": "Bokmärken" + }, + "conversations": { + "name": "Direktmeddelanden" + }, + "favourites": { + "name": "Favoriter" + }, + "fontSize": { + "name": "Storlek på teckensnitt i inlägg" + }, + "language": { + "name": "Språk" + }, + "lists": { + "name": "Listor" + }, + "list": { + "name": "Lista: {{list}}" + }, + "push": { + "name": "Pushnotiser" + }, + "profile": { + "name": "Redigera profil" + }, + "profileName": { + "name": "Redigera visningsnamn" + }, + "profileNote": { + "name": "Redigera beskrivning" + }, + "profileFields": { + "name": "Redigera metadata" + }, + "settings": { + "name": "Appinställningar" + }, + "webSettings": { + "name": "Fler kontoinställningar" + }, + "switch": { + "name": "Byt konto" + } + }, + "fontSize": { + "demo": "

Det här är ett demoinlägg😊. Du kan välja mellan flera alternativ nedan.

Denna inställning påverkar endast huvudinnehållet i inlägg men inte andra teckenstorlekar.

", + "sizes": { + "S": "S", + "M": "M - Standard", + "L": "L", + "XL": "XL", + "XXL": "XXL" + } + }, + "profile": { + "cancellation": { + "title": "Ändringen har inte sparats", + "message": "Din ändring har inte sparats. Vill du strunta i att spara ändringarna?", + "buttons": { + "cancel": "$t(common:buttons.cancel)", + "discard": "Kasta bort" + } + }, + "feedback": { + "succeed": "{{type}} uppdaterades", + "failed": "{{type}}-uppdateringen misslyckades, vänligen försök igen" + }, + "root": { + "name": { + "title": "Visningsnamn" + }, + "avatar": { + "title": "Profilbild", + "description": "Kommer att skalas ner till 400x400px" + }, + "header": { + "title": "Banderoll", + "description": "Kommer att skalas ner till 1500x500px" + }, + "note": { + "title": "Beskrivning" + }, + "fields": { + "title": "Metadata", + "total_one": "{{count}} fält", + "total_other": "{{count}} fält" + }, + "visibility": { + "title": "Inläggssynlighet", + "options": { + "public": "Offentlig", + "unlisted": "Olistad", + "private": "Endast följare", + "cancel": "$t(common:buttons.cancel)" + } + }, + "sensitive": { + "title": "Publicerar känslig media" + }, + "lock": { + "title": "Lås konto", + "description": "Kräver att du godkänner följare manuellt" + }, + "bot": { + "title": "Botkonto", + "description": "Detta konto utför huvudsakligen automatiserade åtgärder och kanske inte övervakas" + } + }, + "fields": { + "group": "Grupp {{index}}", + "label": "Etikett", + "content": "Innehåll" + }, + "mediaSelectionFailed": "Bildbearbetningen misslyckades. Försök igen." + }, + "push": { + "notAvailable": "Din telefon stöder inte pushnotiser från tooot", + "enable": { + "direct": "Aktivera pushnotiser", + "settings": "Aktivera i inställningar" + }, + "global": { + "heading": "Aktivera för {{acct}}", + "description": "Meddelanden dirigeras via tooots server" + }, + "decode": { + "heading": "Visa meddelandedetaljer", + "description": "Meddelanden som dirigeras via tooots server är krypterade men du kan välja att avkoda meddelandet på servern. Vår serverkällkod är öppen källkod och ingenting loggas på servern." + }, + "default": { + "heading": "Standard" + }, + "follow": { + "heading": "Ny följare" + }, + "follow_request": { + "heading": "Följarförfrågning" + }, + "favourite": { + "heading": "Favorit" + }, + "reblog": { + "heading": "Boostad" + }, + "mention": { + "heading": "Nämnde dig" + }, + "poll": { + "heading": "Uppdateringar för omröstning" + }, + "status": { + "heading": "Inlägg från följda användare" + }, + "howitworks": "Läs om hur routing fungerar" + }, + "root": { + "announcements": { + "content": { + "unread": "{{amount}} olästa", + "read": "Alla lästa", + "empty": "Inga" + } + }, + "push": { + "content": { + "enabled": "Aktiverad", + "disabled": "Inaktiverad" + } + }, + "update": { + "title": "Uppdatera till senaste versionen" + }, + "logout": { + "button": "Logga ut", + "alert": { + "title": "Logga ut?", + "message": "Efter att du loggat ut måste du logga in igen", + "buttons": { + "logout": "Logga ut", + "cancel": "$t(common:buttons.cancel)" + } + } + } + }, + "settings": { + "fontsize": { + "heading": "$t(me.stacks.fontSize.name)", + "content": { + "S": "$t(me.fontSize.sizes.S)", + "M": "$t(me.fontSize.sizes.M)", + "L": "$t(me.fontSize.sizes.L)", + "XL": "$t(me.fontSize.sizes.XL)", + "XXL": "$t(me.fontSize.sizes.XXL)" + } + }, + "language": { + "heading": "$t(me.stacks.language.name)", + "options": { + "cancel": "$t(common:buttons.cancel)" + } + }, + "theme": { + "heading": "Utseende", + "options": { + "auto": "Som systemet", + "light": "Ljust läge", + "dark": "Mörkt läge", + "cancel": "$t(common:buttons.cancel)" + } + }, + "darkTheme": { + "heading": "Mörkt tema", + "options": { + "lighter": "Ljusare", + "darker": "Mörkare", + "cancel": "$t(common:buttons.cancel)" + } + }, + "browser": { + "heading": "Öppnar länk", + "options": { + "internal": "Inuti appen", + "external": "Använd systemets webbläsare", + "cancel": "$t(common:buttons.cancel)" + } + }, + "staticEmoji": { + "heading": "Använd statisk emoji", + "description": "Om du stöter på frekventa appkrascher när du visar emoji-listan kan du testa att använda statisk emoji istället." + }, + "feedback": { + "heading": "Funktionsförslag" + }, + "support": { + "heading": "Stöd tooot" + }, + "review": { + "heading": "Recensera tooot" + }, + "contact": { + "heading": "Kontakta tooot" + }, + "analytics": { + "heading": "Hjälp oss att bli bättre", + "description": "Samlar endast in användningsdata som inte är kopplad till användaren" + }, + "version": "Version v{{version}}", + "instanceVersion": "Mastodon version v{{version}}" + }, + "switch": { + "existing": "Välj bland inloggade", + "new": "Logga in på instans" + } + }, + "shared": { + "account": { + "actions": { + "accessibilityLabel": "Åtgärder för användare {{user}}", + "accessibilityHint": "Du kan tysta, blockera, rapportera eller dela denna användare" + }, + "followed_by": " följer dig", + "moved": "Användaren har flyttat", + "created_at": "Gick med: {{date}}", + "summary": { + "statuses_count": "{{count}} inlägg", + "following_count": "$t(shared.users.accounts.following)", + "followers_count": "$t(shared.users.accounts.followers)" + }, + "toots": { + "default": "Inlägg", + "all": "Inlägg och svar" + }, + "suspended": "Kontot är avstängt av moderatorerna på din server" + }, + "attachments": { + "name": "<0 /><1>s media" + }, + "hashtag": { + "follow": "Följ", + "unfollow": "Sluta följ" + }, + "history": { + "name": "Redigeringshistorik" + }, + "search": { + "header": { + "prefix": "Söker", + "placeholder": "för..." + }, + "empty": { + "general": "Ange sökord för att söka efter $t(screenTabs:shared.search.sections.accounts), $t(screenTabs:shared.search.sections.hashtags) eller $t(screenTabs:shared.search.sections.statuses)", + "advanced": { + "header": "Avancerad sökning", + "example": { + "account": "$t(shared.search.header.prefix) $t(shared.search.sections.accounts)", + "hashtag": "$t(shared.search.header.prefix) $t(shared.search.sections.hashtags)", + "statusLink": "$t(shared.search.header.prefix) $t(shared.search.sections.statuses)", + "accountLink": "$t(shared.search.header.prefix) $t(shared.search.sections.accounts)" + } + } + }, + "sections": { + "accounts": "Användare", + "hashtags": "Hashtagg", + "statuses": "Inlägg" + }, + "notFound": "Kan inte hitta {{searchTerm}}-relaterade {{type}}" + }, + "toot": { + "name": "Diskussioner" + }, + "users": { + "accounts": { + "following": "Följer {{count}}", + "followers": "{{count}} följare" + }, + "statuses": { + "reblogged_by": "{{count}} boostade", + "favourited_by": "{{count}} favoriter" + } + } + } +} \ No newline at end of file diff --git a/src/i18n/vi/screens/tabs.json b/src/i18n/vi/screens/tabs.json index fdb93752..5a79d628 100644 --- a/src/i18n/vi/screens/tabs.json +++ b/src/i18n/vi/screens/tabs.json @@ -310,6 +310,13 @@ "attachments": { "name": "<0 /><1>'s media" }, + "hashtag": { + "follow": "Theo dõi", + "unfollow": "Ngưng theo dõi" + }, + "history": { + "name": "Lịch sử chỉnh sửa" + }, "search": { "header": { "prefix": "Tìm kiếm", @@ -346,9 +353,6 @@ "reblogged_by": "{{count}} đăng lại", "favourited_by": "{{count}} thích" } - }, - "history": { - "name": "Lịch sử chỉnh sửa" } } } \ No newline at end of file diff --git a/src/i18n/zh-Hans/screens/tabs.json b/src/i18n/zh-Hans/screens/tabs.json index f49caea6..131094ba 100644 --- a/src/i18n/zh-Hans/screens/tabs.json +++ b/src/i18n/zh-Hans/screens/tabs.json @@ -310,6 +310,13 @@ "attachments": { "name": "<0 /><1>的媒体" }, + "hashtag": { + "follow": "关注", + "unfollow": "取消关注" + }, + "history": { + "name": "编辑历史" + }, "search": { "header": { "prefix": "搜索", @@ -346,9 +353,6 @@ "reblogged_by": "{{count}} 人转嘟", "favourited_by": "{{count}} 人喜欢" } - }, - "history": { - "name": "编辑历史" } } } \ No newline at end of file diff --git a/src/i18n/zh-Hant/screens/tabs.json b/src/i18n/zh-Hant/screens/tabs.json index fdff687c..7eb60826 100644 --- a/src/i18n/zh-Hant/screens/tabs.json +++ b/src/i18n/zh-Hant/screens/tabs.json @@ -310,6 +310,13 @@ "attachments": { "name": "<0 /><1>的媒體" }, + "hashtag": { + "follow": "追蹤", + "unfollow": "取消追蹤" + }, + "history": { + "name": "編輯歷史" + }, "search": { "header": { "prefix": "搜尋", @@ -346,9 +353,6 @@ "reblogged_by": "{{count}} 人轉嘟", "favourited_by": "{{count}} 人喜歡" } - }, - "history": { - "name": "編輯歷史" } } } \ No newline at end of file From 668a1dc6a61970d583999c945b47d33ee808430a Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 20 Nov 2022 16:47:11 +0100 Subject: [PATCH 05/10] Added Swedish translation --- README.md | 2 ++ ios/sv.lproj/InfoPlist.strings | 2 ++ ios/tooot.xcodeproj/project.pbxproj | 3 +++ src/i18n/i18n.ts | 6 ++++++ src/i18n/locales.ts | 1 + src/i18n/sv/index.ts | 18 ++++++++++++++++++ 6 files changed, 32 insertions(+) create mode 100644 ios/sv.lproj/InfoPlist.strings create mode 100644 src/i18n/sv/index.ts diff --git a/README.md b/README.md index 2f08724a..ed0da06d 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ Please **do not** create a pull request to update translation. tooot's translati [@luizpicolo](https://github.com/luizpicolo) for Brazilian Portuguese +[@janlindblom](https://github.com/janlindblom) for Swedish + [@duy@mas.to](https://mas.to/@duy) for Vietnamese translation [@jimmyorz](https://github.com/jimmyorz) for Traditional Chinese translation diff --git a/ios/sv.lproj/InfoPlist.strings b/ios/sv.lproj/InfoPlist.strings new file mode 100644 index 00000000..ee44b7bd --- /dev/null +++ b/ios/sv.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +"NSPhotoLibraryAddUsageDescription" = "Låt toooot spara bilder på din kamerarulle"; +"NSPhotoLibraryUsageDescription" = "Låt toooot spara bilder på din kamerarulle"; diff --git a/ios/tooot.xcodeproj/project.pbxproj b/ios/tooot.xcodeproj/project.pbxproj index e2d6ab42..6af87ad9 100644 --- a/ios/tooot.xcodeproj/project.pbxproj +++ b/ios/tooot.xcodeproj/project.pbxproj @@ -76,6 +76,7 @@ E633A427281EAEAB000E540F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E633A42F281EAF38000E540F /* ShareViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShareViewController.swift; path = "../../node_modules/react-native-share-menu/ios/ShareViewController.swift"; sourceTree = ""; }; E633A431281EB55C000E540F /* ShareExtension-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ShareExtension-Bridging-Header.h"; sourceTree = ""; }; + E63E7FF0292A828100C76FD4 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/InfoPlist.strings; sourceTree = ""; }; E66C0842291F095800DFFF60 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = ""; }; E671BDF8290EAFB800287BD0 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/InfoPlist.strings"; sourceTree = ""; }; E690AF692926B737002C38A8 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -295,6 +296,7 @@ "zh-Hant", fr, es, + sv, ); mainGroup = 83CBB9F61A601CBA00E9B192; productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; @@ -525,6 +527,7 @@ E671BDF8290EAFB800287BD0 /* zh-Hant */, E66C0842291F095800DFFF60 /* fr */, E690AF692926B737002C38A8 /* es */, + E63E7FF0292A828100C76FD4 /* sv */, ); name = InfoPlist.strings; sourceTree = ""; diff --git a/src/i18n/i18n.ts b/src/i18n/i18n.ts index 45b4edeb..a1b0073c 100644 --- a/src/i18n/i18n.ts +++ b/src/i18n/i18n.ts @@ -9,6 +9,7 @@ import it from '@root/i18n/it' import ja from '@root/i18n/ja' import ko from '@root/i18n/ko' import pt_BR from '@root/i18n/pt_BR' +import sv from '@root/i18n/sv' import vi from '@root/i18n/vi' import zh_Hans from '@root/i18n/zh-Hans' import zh_Hant from '@root/i18n/zh-Hant' @@ -25,6 +26,7 @@ import '@formatjs/intl-pluralrules/locale-data/it' import '@formatjs/intl-pluralrules/locale-data/ja' import '@formatjs/intl-pluralrules/locale-data/ko' import '@formatjs/intl-pluralrules/locale-data/pt' +import '@formatjs/intl-pluralrules/locale-data/sv' import '@formatjs/intl-pluralrules/locale-data/vi' import '@formatjs/intl-pluralrules/locale-data/zh' @@ -37,6 +39,7 @@ import '@formatjs/intl-numberformat/locale-data/it' import '@formatjs/intl-numberformat/locale-data/ja' import '@formatjs/intl-numberformat/locale-data/ko' import '@formatjs/intl-numberformat/locale-data/pt' +import '@formatjs/intl-numberformat/locale-data/sv' import '@formatjs/intl-numberformat/locale-data/vi' import '@formatjs/intl-numberformat/locale-data/zh-Hans' import '@formatjs/intl-numberformat/locale-data/zh-Hant' @@ -50,6 +53,7 @@ import '@formatjs/intl-datetimeformat/locale-data/it' import '@formatjs/intl-datetimeformat/locale-data/ja' import '@formatjs/intl-datetimeformat/locale-data/ko' import '@formatjs/intl-datetimeformat/locale-data/pt' +import '@formatjs/intl-datetimeformat/locale-data/sv' import '@formatjs/intl-datetimeformat/locale-data/vi' import '@formatjs/intl-datetimeformat/locale-data/zh-Hans' import '@formatjs/intl-datetimeformat/locale-data/zh-Hant' @@ -64,6 +68,7 @@ import '@formatjs/intl-relativetimeformat/locale-data/it' import '@formatjs/intl-relativetimeformat/locale-data/ja' import '@formatjs/intl-relativetimeformat/locale-data/ko' import '@formatjs/intl-relativetimeformat/locale-data/pt' +import '@formatjs/intl-relativetimeformat/locale-data/sv' import '@formatjs/intl-relativetimeformat/locale-data/vi' import '@formatjs/intl-relativetimeformat/locale-data/zh-Hans' import '@formatjs/intl-relativetimeformat/locale-data/zh-Hant' @@ -84,6 +89,7 @@ i18n.use(initReactI18next).init({ ja, ko, 'pt-BR': pt_BR, + sv, vi, 'zh-Hans': zh_Hans, 'zh-Hant': zh_Hant diff --git a/src/i18n/locales.ts b/src/i18n/locales.ts index ab6e507a..80cba743 100644 --- a/src/i18n/locales.ts +++ b/src/i18n/locales.ts @@ -7,6 +7,7 @@ const LOCALES = { ja: '日本語', ko: '한국어', 'pt-br': 'Português (Brasil)', + sv: 'Svenska', vi: 'Tiếng Việt', 'zh-hans': '简体中文', 'zh-hant': '繁體中文' diff --git a/src/i18n/sv/index.ts b/src/i18n/sv/index.ts new file mode 100644 index 00000000..5f2a7a82 --- /dev/null +++ b/src/i18n/sv/index.ts @@ -0,0 +1,18 @@ +export default { + common: require('./common'), + + screens: require('./screens'), + screenActions: require('./screens/actions'), + screenAnnouncements: require('./screens/announcements'), + screenCompose: require('./screens/compose'), + screenImageViewer: require('./screens/imageViewer'), + screenTabs: require('./screens/tabs'), + + componentContextMenu: require('./components/contextMenu'), + componentEmojis: require('./components/emojis'), + componentInstance: require('./components/instance'), + componentMediaSelector: require('./components/mediaSelector'), + componentParse: require('./components/parse'), + componentRelationship: require('./components/relationship'), + componentTimeline: require('./components/timeline') +} From e8b3187f9e2a1d6ac6b97d8eddbb37d906dac689 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 20 Nov 2022 17:39:36 +0100 Subject: [PATCH 06/10] Try stopping video playback if audio issue could be fiexed --- .../Timeline/Shared/Attachment/Audio.tsx | 34 +++++++++++-------- .../Timeline/Shared/Attachment/Video.tsx | 2 +- src/startup/audio.ts | 6 ++-- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/components/Timeline/Shared/Attachment/Audio.tsx b/src/components/Timeline/Shared/Attachment/Audio.tsx index b7d0066b..ad19496e 100644 --- a/src/components/Timeline/Shared/Attachment/Audio.tsx +++ b/src/components/Timeline/Shared/Attachment/Audio.tsx @@ -5,8 +5,8 @@ import { Slider } from '@sharcoux/slider' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import { Audio } from 'expo-av' -import React, { useCallback, useState } from 'react' -import { StyleSheet, View } from 'react-native' +import React, { useCallback, useEffect, useRef, useState } from 'react' +import { AppState, AppStateStatus, StyleSheet, View } from 'react-native' import { Blurhash } from 'react-native-blurhash' import AttachmentAltText from './AltText' import attachmentAspectRatio from './aspectRatio' @@ -18,12 +18,7 @@ export interface Props { audio: Mastodon.AttachmentAudio } -const AttachmentAudio: React.FC = ({ - total, - index, - sensitiveShown, - audio -}) => { +const AttachmentAudio: React.FC = ({ total, index, sensitiveShown, audio }) => { const { colors } = useTheme() const [audioPlayer, setAudioPlayer] = useState() @@ -51,6 +46,20 @@ const AttachmentAudio: React.FC = ({ setAudioPlaying(false) }, [audioPlayer]) + const appState = useRef(AppState.currentState) + useEffect(() => { + const appState = AppState.addEventListener('change', _handleAppStateChange) + + return () => appState.remove() + }, []) + const _handleAppStateChange = async (nextAppState: AppStateStatus) => { + if (appState.current.match(/active/) && nextAppState.match(/inactive/)) { + await audioPlayer?.stopAsync() + } + + appState.current = nextAppState + } + return ( = ({ size='L' round overlay - {...(audioPlaying - ? { onPress: pauseAudio } - : { onPress: playAudio })} + {...(audioPlaying ? { onPress: pauseAudio } : { onPress: playAudio })} /> )} @@ -128,10 +135,7 @@ const AttachmentAudio: React.FC = ({ /> ) : null} - +
) } diff --git a/src/components/Timeline/Shared/Attachment/Video.tsx b/src/components/Timeline/Shared/Attachment/Video.tsx index 6771438d..4489efb1 100644 --- a/src/components/Timeline/Shared/Attachment/Video.tsx +++ b/src/components/Timeline/Shared/Attachment/Video.tsx @@ -64,7 +64,7 @@ const AttachmentVideo: React.FC = ({ }, []) const _handleAppStateChange = async (nextAppState: AppStateStatus) => { if (appState.current.match(/active/) && nextAppState.match(/inactive/)) { - await videoPlayer.current?.pauseAsync() + await videoPlayer.current?.stopAsync() } else if (gifv && appState.current.match(/background/) && nextAppState.match(/active/)) { await videoPlayer.current?.setIsMutedAsync(true) await videoPlayer.current?.playAsync() diff --git a/src/startup/audio.ts b/src/startup/audio.ts index aab659d2..228a7023 100644 --- a/src/startup/audio.ts +++ b/src/startup/audio.ts @@ -4,9 +4,9 @@ import log from './log' const audio = () => { log('log', 'audio', 'setting audio playback default options') Audio.setAudioModeAsync({ - playsInSilentModeIOS: true, - interruptionModeIOS: InterruptionModeIOS.MixWithOthers, - interruptionModeAndroid: InterruptionModeAndroid.DuckOthers + interruptionModeIOS: InterruptionModeIOS.DoNotMix, + interruptionModeAndroid: InterruptionModeAndroid.DuckOthers, + staysActiveInBackground: false }) } From 4f329d77240f09100d62ef0c3b299a65f60a06ba Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 20 Nov 2022 22:02:19 +0100 Subject: [PATCH 07/10] Update audio.ts --- src/startup/audio.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/startup/audio.ts b/src/startup/audio.ts index 228a7023..2f3c2b51 100644 --- a/src/startup/audio.ts +++ b/src/startup/audio.ts @@ -4,7 +4,7 @@ import log from './log' const audio = () => { log('log', 'audio', 'setting audio playback default options') Audio.setAudioModeAsync({ - interruptionModeIOS: InterruptionModeIOS.DoNotMix, + interruptionModeIOS: InterruptionModeIOS.MixWithOthers, interruptionModeAndroid: InterruptionModeAndroid.DuckOthers, staysActiveInBackground: false }) From bfd9e8d50c0ff8c01293302ce13191e26b651ea6 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 20 Nov 2022 22:27:15 +0100 Subject: [PATCH 08/10] Update Default.tsx --- src/components/Timeline/Default.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Timeline/Default.tsx b/src/components/Timeline/Default.tsx index 5adcf7e4..18d88803 100644 --- a/src/components/Timeline/Default.tsx +++ b/src/components/Timeline/Default.tsx @@ -64,6 +64,7 @@ const TimelineDefault: React.FC = ({ } const onPress = () => { + if (highlighted) return analytics('timeline_default_press', { page: queryKey ? queryKey[1].page : origin }) From 51165e47eac75ef4148c5481592f07d40e2bec59 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 20 Nov 2022 22:42:09 +0100 Subject: [PATCH 09/10] Fix Android sharing --- src/Screens.tsx | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Screens.tsx b/src/Screens.tsx index 82408307..330caf7e 100644 --- a/src/Screens.tsx +++ b/src/Screens.tsx @@ -166,9 +166,6 @@ const Screens: React.FC = ({ localCorrupt }) => { } | { data: string | string[]; mimeType: string } ) => { - if (Platform.OS === 'android') { - return - } if (instanceActive < 0) { return } @@ -233,14 +230,18 @@ const Screens: React.FC = ({ localCorrupt }) => { } } break - // case 'android': - // if (!item.mimeType) { - // return - // } - // for (const d of item.data) { - // filterMedia({ uri: d, mime: item.mimeType }) - // } - // break + case 'android': + if (!item.mimeType) { + return + } + if (Array.isArray(item.data)) { + for (const d of item.data) { + filterMedia({ uri: d, mime: item.mimeType }) + } + } else { + filterMedia({ uri: item.data, mime: item.mimeType }) + } + break } if (!text && !media.length) { From c07522f68b7e822c2a9388cb75ddd0665237b514 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Sun, 20 Nov 2022 22:49:36 +0100 Subject: [PATCH 10/10] New Crowdin updates (#474) * New translations relationship.json (Chinese Traditional) * New translations tabs.json (Chinese Traditional) * New translations tabs.json (Spanish) * New translations tabs.json (Spanish) * New translations timeline.json (Spanish) * New translations screens.json (Spanish) * New translations tabs.json (Spanish) --- src/i18n/es/components/timeline.json | 2 +- src/i18n/es/screens.json | 2 +- src/i18n/es/screens/tabs.json | 6 +++--- src/i18n/zh-Hant/components/relationship.json | 6 +++--- src/i18n/zh-Hant/screens/tabs.json | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/i18n/es/components/timeline.json b/src/i18n/es/components/timeline.json index 3d6e3511..50304540 100644 --- a/src/i18n/es/components/timeline.json +++ b/src/i18n/es/components/timeline.json @@ -27,7 +27,7 @@ "follow_request": "{{name}} ha solicitado seguirte", "poll": "Una encuesta en la que has votado ha terminado", "reblog": { - "default": "{{name}} impulsado", + "default": "{{name}} ha impulsado", "notification": "{{name}} ha impulsado tu toot" }, "update": "El impulso ha sido editado" diff --git a/src/i18n/es/screens.json b/src/i18n/es/screens.json index 7112c5ba..c6843011 100644 --- a/src/i18n/es/screens.json +++ b/src/i18n/es/screens.json @@ -1,7 +1,7 @@ { "screenshot": { "title": "Protección de la privacidad", - "message": "Por favor, no revele la identidad de otros usuarios, como nombre de usuario, avatar, etc. ¡Gracias!", + "message": "Por favor, no revele la identidad de otros usuarios, como el nombre de usuario, avatar, etc. ¡Gracias!", "button": "Confirmar" }, "localCorrupt": { diff --git a/src/i18n/es/screens/tabs.json b/src/i18n/es/screens/tabs.json index 5c282b4b..be1155a7 100644 --- a/src/i18n/es/screens/tabs.json +++ b/src/i18n/es/screens/tabs.json @@ -117,8 +117,8 @@ }, "fields": { "title": "Metadatos", - "total_one": "Campo {{count}}", - "total_other": "Campos {{count}}" + "total_one": "{{count}} campo", + "total_other": "{{count}} campos" }, "visibility": { "title": "Visibilidad de publicación", @@ -346,7 +346,7 @@ }, "users": { "accounts": { - "following": "Siguiendo {{count}}", + "following": "{{count}} seguidos", "followers": "{{count}} seguidores" }, "statuses": { diff --git a/src/i18n/zh-Hant/components/relationship.json b/src/i18n/zh-Hant/components/relationship.json index 613097c8..33d83ffa 100644 --- a/src/i18n/zh-Hant/components/relationship.json +++ b/src/i18n/zh-Hant/components/relationship.json @@ -1,6 +1,6 @@ { "follow": { - "function": "追蹤使用者" + "function": "跟隨使用者" }, "block": { "function": "封鎖使用者" @@ -9,8 +9,8 @@ "error": "載入錯誤", "blocked_by": "已被使用者封鎖", "blocking": "解除封鎖", - "following": "取消追蹤", + "following": "取消跟隨", "requested": "收回要求", - "default": "追蹤" + "default": "跟隨" } } \ No newline at end of file diff --git a/src/i18n/zh-Hant/screens/tabs.json b/src/i18n/zh-Hant/screens/tabs.json index 7eb60826..96fee96c 100644 --- a/src/i18n/zh-Hant/screens/tabs.json +++ b/src/i18n/zh-Hant/screens/tabs.json @@ -311,8 +311,8 @@ "name": "<0 /><1>的媒體" }, "hashtag": { - "follow": "追蹤", - "unfollow": "取消追蹤" + "follow": "跟隨", + "unfollow": "取消跟隨" }, "history": { "name": "編輯歷史"