mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
Merge branch 'main' into candidate
This commit is contained in:
@@ -2,7 +2,7 @@ import { StyleConstants } from '@utils/styles/constants'
|
|||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import { Fragment } from 'react'
|
import { Fragment } from 'react'
|
||||||
import { Trans, useTranslation } from 'react-i18next'
|
import { Trans, useTranslation } from 'react-i18next'
|
||||||
import { View } from 'react-native'
|
import { View, ViewStyle } from 'react-native'
|
||||||
import { TouchableNativeFeedback } from 'react-native-gesture-handler'
|
import { TouchableNativeFeedback } from 'react-native-gesture-handler'
|
||||||
import Icon from './Icon'
|
import Icon from './Icon'
|
||||||
import CustomText from './Text'
|
import CustomText from './Text'
|
||||||
@@ -11,9 +11,10 @@ export type Props = {
|
|||||||
onPress: () => void
|
onPress: () => void
|
||||||
filter: Mastodon.Filter<'v2'>
|
filter: Mastodon.Filter<'v2'>
|
||||||
button?: React.ReactNode
|
button?: React.ReactNode
|
||||||
|
style?: ViewStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Filter: React.FC<Props> = ({ onPress, filter, button }) => {
|
export const Filter: React.FC<Props> = ({ onPress, filter, button, style }) => {
|
||||||
const { t } = useTranslation(['common', 'screenTabs'])
|
const { t } = useTranslation(['common', 'screenTabs'])
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
@@ -24,7 +25,8 @@ export const Filter: React.FC<Props> = ({ onPress, filter, button }) => {
|
|||||||
paddingVertical: StyleConstants.Spacing.S,
|
paddingVertical: StyleConstants.Spacing.S,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
backgroundColor: colors.backgroundDefault
|
backgroundColor: colors.backgroundDefault,
|
||||||
|
...style
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={{ flex: 1 }}>
|
<View style={{ flex: 1 }}>
|
||||||
@@ -83,12 +85,7 @@ export const Filter: React.FC<Props> = ({ onPress, filter, button }) => {
|
|||||||
{filter.context.map((c, index) => (
|
{filter.context.map((c, index) => (
|
||||||
<Fragment key={index}>
|
<Fragment key={index}>
|
||||||
<CustomText
|
<CustomText
|
||||||
style={{
|
style={{ color: colors.secondary }}
|
||||||
color: colors.secondary,
|
|
||||||
textDecorationColor: colors.disabled,
|
|
||||||
textDecorationLine: 'underline',
|
|
||||||
textDecorationStyle: 'solid'
|
|
||||||
}}
|
|
||||||
children={t(`screenTabs:me.preferencesFilters.contexts.${c}`)}
|
children={t(`screenTabs:me.preferencesFilters.contexts.${c}`)}
|
||||||
/>
|
/>
|
||||||
<CustomText children={t('common:separator')} />
|
<CustomText children={t('common:separator')} />
|
||||||
|
@@ -12,7 +12,7 @@ const Hr: React.FC<{ style?: ViewStyle }> = ({ style }) => {
|
|||||||
borderTopColor: colors.border,
|
borderTopColor: colors.border,
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
height: 1,
|
height: 1,
|
||||||
marginVertical: StyleConstants.Spacing.S
|
paddingVertical: StyleConstants.Spacing.S
|
||||||
},
|
},
|
||||||
style
|
style
|
||||||
]}
|
]}
|
||||||
|
57
src/components/SwipeToActions.tsx
Normal file
57
src/components/SwipeToActions.tsx
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
|
import { ColorValue, TouchableNativeFeedback, View } from 'react-native'
|
||||||
|
import { SwipeListView } from 'react-native-swipe-list-view'
|
||||||
|
import haptics from './haptics'
|
||||||
|
import Icon, { IconName } from './Icon'
|
||||||
|
import ComponentSeparator from './Separator'
|
||||||
|
|
||||||
|
export type Props = {
|
||||||
|
actions: {
|
||||||
|
onPress: (item: any) => void
|
||||||
|
color: ColorValue
|
||||||
|
icon: IconName
|
||||||
|
haptic?: Parameters<typeof haptics>['0']
|
||||||
|
}[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SwipeToActions = <T extends unknown>({
|
||||||
|
actions,
|
||||||
|
...rest
|
||||||
|
}: Props & SwipeListView<T>['props']) => {
|
||||||
|
const perActionWidth = StyleConstants.Spacing.L * 2 + StyleConstants.Font.Size.L
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SwipeListView
|
||||||
|
renderHiddenItem={({ item }) => (
|
||||||
|
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'flex-end' }}>
|
||||||
|
{actions.map((action, index) => (
|
||||||
|
<TouchableNativeFeedback
|
||||||
|
key={index}
|
||||||
|
onPress={() => {
|
||||||
|
haptics(action.haptic || 'Light')
|
||||||
|
action.onPress({ item })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: StyleConstants.Spacing.L,
|
||||||
|
flexBasis: perActionWidth,
|
||||||
|
backgroundColor: action.color,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon name={action.icon} color='white' size={StyleConstants.Font.Size.L} />
|
||||||
|
</View>
|
||||||
|
</TouchableNativeFeedback>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
rightOpenValue={-perActionWidth * actions.length}
|
||||||
|
disableRightSwipe
|
||||||
|
closeOnRowPress
|
||||||
|
ItemSeparatorComponent={ComponentSeparator}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
@@ -6,7 +6,7 @@
|
|||||||
"action_false": "Segueix l'usuari",
|
"action_false": "Segueix l'usuari",
|
||||||
"action_true": "Deixa de seguir l'usuari"
|
"action_true": "Deixa de seguir l'usuari"
|
||||||
},
|
},
|
||||||
"inLists": "",
|
"inLists": "Llistes que hi sigui l'usuari...",
|
||||||
"showBoosts": {
|
"showBoosts": {
|
||||||
"action_false": "Mostra els impulsos de l'usuari",
|
"action_false": "Mostra els impulsos de l'usuari",
|
||||||
"action_true": "Oculta els impulsos de l'usuari"
|
"action_true": "Oculta els impulsos de l'usuari"
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
"succeed_locked": "Enviada la sol·licitud de seguiment a @{{target}} com {{source}}, pendent d'aprovar-la",
|
"succeed_locked": "Enviada la sol·licitud de seguiment a @{{target}} com {{source}}, pendent d'aprovar-la",
|
||||||
"failed": "Segueix com"
|
"failed": "Segueix com"
|
||||||
},
|
},
|
||||||
"blockReport": "",
|
"blockReport": "Bloqueja i denuncia",
|
||||||
"block": {
|
"block": {
|
||||||
"action_false": "Bloqueja l'usuari",
|
"action_false": "Bloqueja l'usuari",
|
||||||
"action_true": "Deixa de bloquejar l'usuari",
|
"action_true": "Deixa de bloquejar l'usuari",
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
},
|
},
|
||||||
"hashtag": {
|
"hashtag": {
|
||||||
"follow": {
|
"follow": {
|
||||||
"action_false": "",
|
"action_false": "Segueix",
|
||||||
"action_true": ""
|
"action_true": "Deixa de seguir"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action": ""
|
"action": "Filtra l'etiqueta..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"share": {
|
"share": {
|
||||||
@@ -99,8 +99,8 @@
|
|||||||
"action_true": "Deixa de fixar la publicació"
|
"action_true": "Deixa de fixar la publicació"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action_false": "",
|
"action_false": "Filtra la publicació...",
|
||||||
"action_true": ""
|
"action_true": "Gestiona els filtres..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -211,7 +211,7 @@
|
|||||||
},
|
},
|
||||||
"keywords": "Coincidències per aquestes paraules claus",
|
"keywords": "Coincidències per aquestes paraules claus",
|
||||||
"keyword": "Paraula clau",
|
"keyword": "Paraula clau",
|
||||||
"statuses": ""
|
"statuses": "Coincideixen aquestes publicacions"
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"feedback": {
|
"feedback": {
|
||||||
@@ -400,14 +400,14 @@
|
|||||||
"name": "Multimèdia de <0 /><1></1>"
|
"name": "Multimèdia de <0 /><1></1>"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"name": "",
|
"name": "Afegeix al filtre",
|
||||||
"existed": ""
|
"existed": "Existia sota aquests filtres"
|
||||||
},
|
},
|
||||||
"history": {
|
"history": {
|
||||||
"name": "Edita l'historial"
|
"name": "Edita l'historial"
|
||||||
},
|
},
|
||||||
"report": {
|
"report": {
|
||||||
"name": "Denuncia {{acct}}",
|
"name": "Denúncia a {{acct}}",
|
||||||
"report": "Denúncia",
|
"report": "Denúncia",
|
||||||
"forward": {
|
"forward": {
|
||||||
"heading": "Envia anònimament al servidor remot {{instance}}"
|
"heading": "Envia anònimament al servidor remot {{instance}}"
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
"action_false": "Seguir usuario",
|
"action_false": "Seguir usuario",
|
||||||
"action_true": "Dejar de seguir usuario"
|
"action_true": "Dejar de seguir usuario"
|
||||||
},
|
},
|
||||||
"inLists": "",
|
"inLists": "Listas que contienen el usuario...",
|
||||||
"showBoosts": {
|
"showBoosts": {
|
||||||
"action_false": "Mostrar los impulsos del usuario",
|
"action_false": "Mostrar los impulsos del usuario",
|
||||||
"action_true": "Ocultar los impulsos del usuario"
|
"action_true": "Ocultar los impulsos del usuario"
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
"succeed_locked": "Enviado la solicitud de seguimiento a @{{target}} como {{source}}, pendiente de aprobación",
|
"succeed_locked": "Enviado la solicitud de seguimiento a @{{target}} como {{source}}, pendiente de aprobación",
|
||||||
"failed": "Seguir como"
|
"failed": "Seguir como"
|
||||||
},
|
},
|
||||||
"blockReport": "",
|
"blockReport": "Bloquear y denunciar",
|
||||||
"block": {
|
"block": {
|
||||||
"action_false": "Bloquear usuario",
|
"action_false": "Bloquear usuario",
|
||||||
"action_true": "Desbloquear usuario",
|
"action_true": "Desbloquear usuario",
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
},
|
},
|
||||||
"hashtag": {
|
"hashtag": {
|
||||||
"follow": {
|
"follow": {
|
||||||
"action_false": "",
|
"action_false": "Seguir",
|
||||||
"action_true": ""
|
"action_true": "Dejar de seguir"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action": ""
|
"action": "Filtrar la etiqueta..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"share": {
|
"share": {
|
||||||
@@ -99,8 +99,8 @@
|
|||||||
"action_true": "Desfijar toot"
|
"action_true": "Desfijar toot"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action_false": "",
|
"action_false": "Filtrar la publicación...",
|
||||||
"action_true": ""
|
"action_true": "Gestiona los filtros..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -70,16 +70,16 @@
|
|||||||
"name": "Notificaciones push"
|
"name": "Notificaciones push"
|
||||||
},
|
},
|
||||||
"preferences": {
|
"preferences": {
|
||||||
"name": ""
|
"name": "Preferencias"
|
||||||
},
|
},
|
||||||
"preferencesFilters": {
|
"preferencesFilters": {
|
||||||
"name": ""
|
"name": "Todos los filtros de contenido"
|
||||||
},
|
},
|
||||||
"preferencesFilterAdd": {
|
"preferencesFilterAdd": {
|
||||||
"name": ""
|
"name": "Crear filtro"
|
||||||
},
|
},
|
||||||
"preferencesFilterEdit": {
|
"preferencesFilterEdit": {
|
||||||
"name": ""
|
"name": "Editar filtro"
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"name": "Editar perfil"
|
"name": "Editar perfil"
|
||||||
@@ -136,82 +136,82 @@
|
|||||||
},
|
},
|
||||||
"preferences": {
|
"preferences": {
|
||||||
"visibility": {
|
"visibility": {
|
||||||
"title": "",
|
"title": "Visibilidad de publicación predeterminada",
|
||||||
"options": {
|
"options": {
|
||||||
"public": "",
|
"public": "Público",
|
||||||
"unlisted": "",
|
"unlisted": "No listado",
|
||||||
"private": ""
|
"private": "Solo seguidores"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sensitive": {
|
"sensitive": {
|
||||||
"title": ""
|
"title": "Marcar el contenido multimedia como sensibles por defecto"
|
||||||
},
|
},
|
||||||
"media": {
|
"media": {
|
||||||
"title": "",
|
"title": "Mostrar el contenido multimedia",
|
||||||
"options": {
|
"options": {
|
||||||
"default": "",
|
"default": "Ocultar los contenidos multimedia marcados como sensibles",
|
||||||
"show_all": "",
|
"show_all": "Mostrar siempre el contenido multimedia",
|
||||||
"hide_all": ""
|
"hide_all": "Siempre ocultar el contenido multimedia"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"spoilers": {
|
"spoilers": {
|
||||||
"title": ""
|
"title": "Siempre expandir las publicaciones marcadas con advertencias de contenido"
|
||||||
},
|
},
|
||||||
"autoplay_gifs": {
|
"autoplay_gifs": {
|
||||||
"title": ""
|
"title": "Reproduce automáticamente los GIF"
|
||||||
},
|
},
|
||||||
"filters": {
|
"filters": {
|
||||||
"title": "",
|
"title": "Filtros de contenido",
|
||||||
"content": ""
|
"content": "{{count}} activo"
|
||||||
},
|
},
|
||||||
"web_only": {
|
"web_only": {
|
||||||
"title": "",
|
"title": "Actualizar ajustes",
|
||||||
"description": ""
|
"description": "Los ajustes a continuación solo se pueden actualizar mediante la interfaz web"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"preferencesFilters": {
|
"preferencesFilters": {
|
||||||
"expired": "",
|
"expired": "Expirado",
|
||||||
"keywords_one": "",
|
"keywords_one": "{{count}} palabra clave",
|
||||||
"keywords_other": "",
|
"keywords_other": "{{count}} palabras clave",
|
||||||
"statuses_one": "",
|
"statuses_one": "{{count}} publicación",
|
||||||
"statuses_other": "",
|
"statuses_other": "{{count}} publicaciones",
|
||||||
"context": "",
|
"context": "Se aplica en <0 />",
|
||||||
"contexts": {
|
"contexts": {
|
||||||
"home": "",
|
"home": "Seguidos y listas",
|
||||||
"notifications": "",
|
"notifications": "Notificación",
|
||||||
"public": "",
|
"public": "Federado",
|
||||||
"thread": "",
|
"thread": "Conversación",
|
||||||
"account": ""
|
"account": "Perfil"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"preferencesFilter": {
|
"preferencesFilter": {
|
||||||
"name": "",
|
"name": "Nombre",
|
||||||
"expiration": "",
|
"expiration": "Vencimiento",
|
||||||
"expirationOptions": {
|
"expirationOptions": {
|
||||||
"0": "",
|
"0": "Nunca",
|
||||||
"1800": "",
|
"1800": "Después de 30 minutos",
|
||||||
"3600": "",
|
"3600": "Después de 1 hora",
|
||||||
"43200": "",
|
"43200": "Después de 12 horas",
|
||||||
"86400": "",
|
"86400": "Después de 1 día",
|
||||||
"604800": "",
|
"604800": "Después de 1 semana",
|
||||||
"18144000": ""
|
"18144000": "Después de 1 mes"
|
||||||
},
|
},
|
||||||
"context": "",
|
"context": "Se aplica en",
|
||||||
"contexts": {
|
"contexts": {
|
||||||
"home": "",
|
"home": "Seguidos y listas",
|
||||||
"notifications": "",
|
"notifications": "Notificación",
|
||||||
"public": "",
|
"public": "Cronología federada",
|
||||||
"thread": "",
|
"thread": "Vista de conversación",
|
||||||
"account": ""
|
"account": "Vista de perfil"
|
||||||
},
|
},
|
||||||
"action": "",
|
"action": "Al coincidir",
|
||||||
"actions": {
|
"actions": {
|
||||||
"warn": "",
|
"warn": "",
|
||||||
"hide": ""
|
"hide": "Oculto completamente"
|
||||||
},
|
},
|
||||||
"keywords": "",
|
"keywords": "Coincide con estas palabras clave",
|
||||||
"keyword": "",
|
"keyword": "Palabra clave",
|
||||||
"statuses": ""
|
"statuses": "Coincide con estas publicaciones"
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"feedback": {
|
"feedback": {
|
||||||
@@ -400,8 +400,8 @@
|
|||||||
"name": "Multimedia de <0 /><1></1>"
|
"name": "Multimedia de <0 /><1></1>"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"name": "",
|
"name": "Añadir al filtro",
|
||||||
"existed": ""
|
"existed": "Existe en estos filtros"
|
||||||
},
|
},
|
||||||
"history": {
|
"history": {
|
||||||
"name": "Historial de ediciones"
|
"name": "Historial de ediciones"
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
"action_false": "",
|
"action_false": "",
|
||||||
"action_true": ""
|
"action_true": ""
|
||||||
},
|
},
|
||||||
"inLists": "",
|
"inLists": "Erabiltzaile hau zerrenda hauetan dago...",
|
||||||
"showBoosts": {
|
"showBoosts": {
|
||||||
"action_false": "",
|
"action_false": "",
|
||||||
"action_true": ""
|
"action_true": ""
|
||||||
@@ -16,12 +16,12 @@
|
|||||||
"action_true": ""
|
"action_true": ""
|
||||||
},
|
},
|
||||||
"followAs": {
|
"followAs": {
|
||||||
"trigger": "",
|
"trigger": "Honela jarraitu...",
|
||||||
"succeed_default": "",
|
"succeed_default": "",
|
||||||
"succeed_locked": "",
|
"succeed_locked": "",
|
||||||
"failed": ""
|
"failed": ""
|
||||||
},
|
},
|
||||||
"blockReport": "",
|
"blockReport": "Blokeatu eta salatu",
|
||||||
"block": {
|
"block": {
|
||||||
"action_false": "",
|
"action_false": "",
|
||||||
"action_true": "",
|
"action_true": "",
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
},
|
},
|
||||||
"hashtag": {
|
"hashtag": {
|
||||||
"follow": {
|
"follow": {
|
||||||
"action_false": "",
|
"action_false": "Jarraitu",
|
||||||
"action_true": ""
|
"action_true": "Jarraitzeari utzi"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action": ""
|
"action": "Traola iragazi..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"share": {
|
"share": {
|
||||||
@@ -99,8 +99,8 @@
|
|||||||
"action_true": ""
|
"action_true": ""
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action_false": "",
|
"action_false": "Tuta iragazi...",
|
||||||
"action_true": ""
|
"action_true": "Iragazkiak kudeatu..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -6,7 +6,7 @@
|
|||||||
"action_false": "Volg gebruiker",
|
"action_false": "Volg gebruiker",
|
||||||
"action_true": "Ontvolg"
|
"action_true": "Ontvolg"
|
||||||
},
|
},
|
||||||
"inLists": "",
|
"inLists": "Lijsten met gebruiker...",
|
||||||
"showBoosts": {
|
"showBoosts": {
|
||||||
"action_false": "Boosts van gebruiker weergeven",
|
"action_false": "Boosts van gebruiker weergeven",
|
||||||
"action_true": "Boosts van gebruiker verbergen"
|
"action_true": "Boosts van gebruiker verbergen"
|
||||||
@@ -16,12 +16,12 @@
|
|||||||
"action_true": "Dempen opheffen voor gebruiker"
|
"action_true": "Dempen opheffen voor gebruiker"
|
||||||
},
|
},
|
||||||
"followAs": {
|
"followAs": {
|
||||||
"trigger": "",
|
"trigger": "Volg als ...",
|
||||||
"succeed_default": "Je volgt nu @{{target}} met @{{source}}",
|
"succeed_default": "Je volgt nu @{{target}} met @{{source}}",
|
||||||
"succeed_locked": "Verstuurde het volgverzoek naar @{{target}} met {{source}}, in afwachting van goedkeuring",
|
"succeed_locked": "Verstuurde het volgverzoek naar @{{target}} met {{source}}, in afwachting van goedkeuring",
|
||||||
"failed": "Volg als"
|
"failed": "Volg als"
|
||||||
},
|
},
|
||||||
"blockReport": "",
|
"blockReport": "Blokkeren en rapporten",
|
||||||
"block": {
|
"block": {
|
||||||
"action_false": "Gebruiker blokkeren",
|
"action_false": "Gebruiker blokkeren",
|
||||||
"action_true": "Gebruiker deblokkeren",
|
"action_true": "Gebruiker deblokkeren",
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
},
|
},
|
||||||
"hashtag": {
|
"hashtag": {
|
||||||
"follow": {
|
"follow": {
|
||||||
"action_false": "",
|
"action_false": "Volg",
|
||||||
"action_true": ""
|
"action_true": "Ontvolg"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action": ""
|
"action": "Filter hashtag ..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"share": {
|
"share": {
|
||||||
@@ -99,8 +99,8 @@
|
|||||||
"action_true": "Toot losmaken"
|
"action_true": "Toot losmaken"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action_false": "",
|
"action_false": "Filter toot ...",
|
||||||
"action_true": ""
|
"action_true": "Filters beheren ..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -70,16 +70,16 @@
|
|||||||
"name": "Push Melding"
|
"name": "Push Melding"
|
||||||
},
|
},
|
||||||
"preferences": {
|
"preferences": {
|
||||||
"name": ""
|
"name": "Voorkeuren"
|
||||||
},
|
},
|
||||||
"preferencesFilters": {
|
"preferencesFilters": {
|
||||||
"name": ""
|
"name": "Alle inhoudsfilters"
|
||||||
},
|
},
|
||||||
"preferencesFilterAdd": {
|
"preferencesFilterAdd": {
|
||||||
"name": ""
|
"name": "Filter Maken"
|
||||||
},
|
},
|
||||||
"preferencesFilterEdit": {
|
"preferencesFilterEdit": {
|
||||||
"name": ""
|
"name": "Bewerk filter"
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"name": "Profiel bewerken"
|
"name": "Profiel bewerken"
|
||||||
@@ -136,82 +136,82 @@
|
|||||||
},
|
},
|
||||||
"preferences": {
|
"preferences": {
|
||||||
"visibility": {
|
"visibility": {
|
||||||
"title": "",
|
"title": "Standaard zichtbaarheid van berichten",
|
||||||
"options": {
|
"options": {
|
||||||
"public": "",
|
"public": "Openbaar",
|
||||||
"unlisted": "",
|
"unlisted": "Niet openbaar",
|
||||||
"private": ""
|
"private": "Alleen volgers"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sensitive": {
|
"sensitive": {
|
||||||
"title": ""
|
"title": "Media standaard als gevoelig markeren"
|
||||||
},
|
},
|
||||||
"media": {
|
"media": {
|
||||||
"title": "",
|
"title": "Mediaweergave",
|
||||||
"options": {
|
"options": {
|
||||||
"default": "",
|
"default": "Als gevoelig gemarkeerde media verbergen",
|
||||||
"show_all": "",
|
"show_all": "Media altijd tonen",
|
||||||
"hide_all": ""
|
"hide_all": "Media altijd verbergen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"spoilers": {
|
"spoilers": {
|
||||||
"title": ""
|
"title": "Altijd toots met tekstwaarschuwingen uitklappen"
|
||||||
},
|
},
|
||||||
"autoplay_gifs": {
|
"autoplay_gifs": {
|
||||||
"title": ""
|
"title": "GIF automatisch afspelen in toots"
|
||||||
},
|
},
|
||||||
"filters": {
|
"filters": {
|
||||||
"title": "",
|
"title": "Inhoud Filters",
|
||||||
"content": ""
|
"content": "{{count}} actief"
|
||||||
},
|
},
|
||||||
"web_only": {
|
"web_only": {
|
||||||
"title": "",
|
"title": "Instellingen bijwerken",
|
||||||
"description": ""
|
"description": "Instellingen hieronder kunnen alleen met behulp van de webUI worden bijgewerkt"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"preferencesFilters": {
|
"preferencesFilters": {
|
||||||
"expired": "",
|
"expired": "Verlopen",
|
||||||
"keywords_one": "",
|
"keywords_one": "{{count}} trefwoord",
|
||||||
"keywords_other": "",
|
"keywords_other": "{{count}} trefwoorden",
|
||||||
"statuses_one": "",
|
"statuses_one": "{{count}} toot",
|
||||||
"statuses_other": "",
|
"statuses_other": "{{count}} toots",
|
||||||
"context": "",
|
"context": "Van toepassing in <0 />",
|
||||||
"contexts": {
|
"contexts": {
|
||||||
"home": "",
|
"home": "volgend en lijsten",
|
||||||
"notifications": "",
|
"notifications": "melding",
|
||||||
"public": "",
|
"public": "gefedereerd",
|
||||||
"thread": "",
|
"thread": "gesprek",
|
||||||
"account": ""
|
"account": "profiel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"preferencesFilter": {
|
"preferencesFilter": {
|
||||||
"name": "",
|
"name": "Naam",
|
||||||
"expiration": "",
|
"expiration": "Vervaldatum",
|
||||||
"expirationOptions": {
|
"expirationOptions": {
|
||||||
"0": "",
|
"0": "Nooit",
|
||||||
"1800": "",
|
"1800": "Na 30 minuten",
|
||||||
"3600": "",
|
"3600": "Na 1 uur",
|
||||||
"43200": "",
|
"43200": "Na 12 uur",
|
||||||
"86400": "",
|
"86400": "Na 1 dag",
|
||||||
"604800": "",
|
"604800": "Na 1 week",
|
||||||
"18144000": ""
|
"18144000": "Na 1 maand"
|
||||||
},
|
},
|
||||||
"context": "",
|
"context": "Van toepassing in",
|
||||||
"contexts": {
|
"contexts": {
|
||||||
"home": "",
|
"home": "Volgend en lijsten",
|
||||||
"notifications": "",
|
"notifications": "Melding",
|
||||||
"public": "",
|
"public": "Federale tijdlijn",
|
||||||
"thread": "",
|
"thread": "Gesprek weergave",
|
||||||
"account": ""
|
"account": "Profiel weergave"
|
||||||
},
|
},
|
||||||
"action": "",
|
"action": "Bij een overeenkomst",
|
||||||
"actions": {
|
"actions": {
|
||||||
"warn": "",
|
"warn": "Ingeklapt maar kan worden onthuld",
|
||||||
"hide": ""
|
"hide": "Volledig verborgen"
|
||||||
},
|
},
|
||||||
"keywords": "",
|
"keywords": "Komt overeen met deze trefwoorden",
|
||||||
"keyword": "",
|
"keyword": "Trefwoord",
|
||||||
"statuses": ""
|
"statuses": "Komt overeen met deze toots"
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"feedback": {
|
"feedback": {
|
||||||
@@ -400,8 +400,8 @@
|
|||||||
"name": "<0 /><1>'s media</1>"
|
"name": "<0 /><1>'s media</1>"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"name": "",
|
"name": "Toevoegen aan filter",
|
||||||
"existed": ""
|
"existed": "Bestaat in deze filters"
|
||||||
},
|
},
|
||||||
"history": {
|
"history": {
|
||||||
"name": "Geschiedenis bewerken"
|
"name": "Geschiedenis bewerken"
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
"action_false": "Підписатися на користувача",
|
"action_false": "Підписатися на користувача",
|
||||||
"action_true": "Відписатися від користувача"
|
"action_true": "Відписатися від користувача"
|
||||||
},
|
},
|
||||||
"inLists": "",
|
"inLists": "Списки, в яких є користувач ...",
|
||||||
"showBoosts": {
|
"showBoosts": {
|
||||||
"action_false": "Показати передмухи користувача",
|
"action_false": "Показати передмухи користувача",
|
||||||
"action_true": "Приховати передмухи користувача"
|
"action_true": "Приховати передмухи користувача"
|
||||||
@@ -16,12 +16,12 @@
|
|||||||
"action_true": "Зняти заглушення з користувача"
|
"action_true": "Зняти заглушення з користувача"
|
||||||
},
|
},
|
||||||
"followAs": {
|
"followAs": {
|
||||||
"trigger": "",
|
"trigger": "Стежити як ...",
|
||||||
"succeed_default": "Тепер ви стежите за @{{target}} з @{{source}}",
|
"succeed_default": "Тепер ви стежите за @{{target}} з @{{source}}",
|
||||||
"succeed_locked": "Запит на стеження за @{{target}} з {{source}} надіслано, очікується затвердження",
|
"succeed_locked": "Запит на стеження за @{{target}} з {{source}} надіслано, очікується затвердження",
|
||||||
"failed": "Стежити як"
|
"failed": "Стежити як"
|
||||||
},
|
},
|
||||||
"blockReport": "",
|
"blockReport": "Заблокувати й поскаржитися",
|
||||||
"block": {
|
"block": {
|
||||||
"action_false": "Заблокувати користувача",
|
"action_false": "Заблокувати користувача",
|
||||||
"action_true": "Розблокувати користувача",
|
"action_true": "Розблокувати користувача",
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
},
|
},
|
||||||
"hashtag": {
|
"hashtag": {
|
||||||
"follow": {
|
"follow": {
|
||||||
"action_false": "",
|
"action_false": "Підписатися",
|
||||||
"action_true": ""
|
"action_true": "Відписатися"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action": ""
|
"action": "Фільтрувати хештеґ ..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"share": {
|
"share": {
|
||||||
@@ -99,8 +99,8 @@
|
|||||||
"action_true": "Відкріпити дмух"
|
"action_true": "Відкріпити дмух"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action_false": "",
|
"action_false": "Фільтрувати дмух ...",
|
||||||
"action_true": ""
|
"action_true": "Керувати фільтрами ..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -211,7 +211,7 @@
|
|||||||
},
|
},
|
||||||
"keywords": "Збіг із цими ключовими словами",
|
"keywords": "Збіг із цими ключовими словами",
|
||||||
"keyword": "Ключове слово",
|
"keyword": "Ключове слово",
|
||||||
"statuses": ""
|
"statuses": "Збігається з цими дмухами"
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"feedback": {
|
"feedback": {
|
||||||
@@ -400,8 +400,8 @@
|
|||||||
"name": "<0 /><1> медіа</1>"
|
"name": "<0 /><1> медіа</1>"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"name": "",
|
"name": "Додати фільтр",
|
||||||
"existed": ""
|
"existed": "Існує в цих фільтрах"
|
||||||
},
|
},
|
||||||
"history": {
|
"history": {
|
||||||
"name": "Редагувати історію"
|
"name": "Редагувати історію"
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
"action_false": "跟隨使用者",
|
"action_false": "跟隨使用者",
|
||||||
"action_true": "取消跟隨使用者"
|
"action_true": "取消跟隨使用者"
|
||||||
},
|
},
|
||||||
"inLists": "",
|
"inLists": "包含使用者的列表 ...",
|
||||||
"showBoosts": {
|
"showBoosts": {
|
||||||
"action_false": "顯示使用者的轉嘟",
|
"action_false": "顯示使用者的轉嘟",
|
||||||
"action_true": "隱藏使用者的轉嘟"
|
"action_true": "隱藏使用者的轉嘟"
|
||||||
@@ -16,12 +16,12 @@
|
|||||||
"action_true": "解除靜音使用者"
|
"action_true": "解除靜音使用者"
|
||||||
},
|
},
|
||||||
"followAs": {
|
"followAs": {
|
||||||
"trigger": "",
|
"trigger": "用其它帳號跟隨 ...",
|
||||||
"succeed_default": "@{{source}} 正在跟隨 @{{target}}",
|
"succeed_default": "@{{source}} 正在跟隨 @{{target}}",
|
||||||
"succeed_locked": "已從 {{source}} 發送跟隨請求至 @{{target}},等待同意",
|
"succeed_locked": "已從 {{source}} 發送跟隨請求至 @{{target}},等待同意",
|
||||||
"failed": "用其它帳號跟隨"
|
"failed": "用其它帳號跟隨"
|
||||||
},
|
},
|
||||||
"blockReport": "",
|
"blockReport": "封鎖並檢舉",
|
||||||
"block": {
|
"block": {
|
||||||
"action_false": "封鎖使用者",
|
"action_false": "封鎖使用者",
|
||||||
"action_true": "解除封鎖使用者",
|
"action_true": "解除封鎖使用者",
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
},
|
},
|
||||||
"hashtag": {
|
"hashtag": {
|
||||||
"follow": {
|
"follow": {
|
||||||
"action_false": "",
|
"action_false": "跟隨",
|
||||||
"action_true": ""
|
"action_true": "取消跟隨"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action": ""
|
"action": "過濾主題標籤 ..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"share": {
|
"share": {
|
||||||
@@ -99,8 +99,8 @@
|
|||||||
"action_true": "取消釘選嘟文"
|
"action_true": "取消釘選嘟文"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"action_false": "",
|
"action_false": "過濾嘟文 ...",
|
||||||
"action_true": ""
|
"action_true": "管理過濾器 ..."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -211,7 +211,7 @@
|
|||||||
},
|
},
|
||||||
"keywords": "符合這些關鍵字",
|
"keywords": "符合這些關鍵字",
|
||||||
"keyword": "關鍵字",
|
"keyword": "關鍵字",
|
||||||
"statuses": ""
|
"statuses": "符合這些嘟文"
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"feedback": {
|
"feedback": {
|
||||||
@@ -400,8 +400,8 @@
|
|||||||
"name": "<0 /><1>的媒體</1>"
|
"name": "<0 /><1>的媒體</1>"
|
||||||
},
|
},
|
||||||
"filter": {
|
"filter": {
|
||||||
"name": "",
|
"name": "新增至過濾器",
|
||||||
"existed": ""
|
"existed": "已被過濾"
|
||||||
},
|
},
|
||||||
"history": {
|
"history": {
|
||||||
"name": "編輯歷史"
|
"name": "編輯歷史"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { HeaderLeft } from '@components/Header'
|
import { HeaderLeft } from '@components/Header'
|
||||||
import Icon from '@components/Icon'
|
import Icon from '@components/Icon'
|
||||||
import ComponentSeparator from '@components/Separator'
|
import { SwipeToActions } from '@components/SwipeToActions'
|
||||||
import CustomText from '@components/Text'
|
import CustomText from '@components/Text'
|
||||||
import HeaderSharedCreated from '@components/Timeline/Shared/HeaderShared/Created'
|
import HeaderSharedCreated from '@components/Timeline/Shared/HeaderShared/Created'
|
||||||
import apiInstance from '@utils/api/instance'
|
import apiInstance from '@utils/api/instance'
|
||||||
@@ -10,10 +10,8 @@ import { StyleConstants } from '@utils/styles/constants'
|
|||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React, { useContext, useEffect, useState } from 'react'
|
import React, { useContext, useEffect, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Dimensions, Modal, Platform, Pressable, View } from 'react-native'
|
import { Dimensions, Modal, Pressable, View } from 'react-native'
|
||||||
import FastImage from 'react-native-fast-image'
|
import FastImage from 'react-native-fast-image'
|
||||||
import { PanGestureHandler } from 'react-native-gesture-handler'
|
|
||||||
import { SwipeListView } from 'react-native-swipe-list-view'
|
|
||||||
import ComposeContext from './utils/createContext'
|
import ComposeContext from './utils/createContext'
|
||||||
import { formatText } from './utils/processText'
|
import { formatText } from './utils/processText'
|
||||||
import { ComposeStateDraft, ExtendedAttachment } from './utils/types'
|
import { ComposeStateDraft, ExtendedAttachment } from './utils/types'
|
||||||
@@ -39,9 +37,7 @@ const ComposeDraftsList: React.FC<ScreenComposeStackScreenProps<'Screen-Compose-
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
title: t('content.draftsList.header.title'),
|
title: t('content.draftsList.header.title'),
|
||||||
headerLeft: () => (
|
headerLeft: () => <HeaderLeft content='chevron-down' onPress={() => navigation.goBack()} />
|
||||||
<HeaderLeft content='chevron-down' onPress={() => navigation.goBack()} />
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@@ -49,8 +45,6 @@ const ComposeDraftsList: React.FC<ScreenComposeStackScreenProps<'Screen-Compose-
|
|||||||
const [drafts] = useAccountStorage.object('drafts')
|
const [drafts] = useAccountStorage.object('drafts')
|
||||||
const [checkingAttachments, setCheckingAttachments] = useState(false)
|
const [checkingAttachments, setCheckingAttachments] = useState(false)
|
||||||
|
|
||||||
const actionWidth = StyleConstants.Font.Size.L + StyleConstants.Spacing.Global.PagePadding * 4
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<View
|
<View
|
||||||
@@ -61,7 +55,8 @@ const ComposeDraftsList: React.FC<ScreenComposeStackScreenProps<'Screen-Compose-
|
|||||||
padding: StyleConstants.Spacing.S,
|
padding: StyleConstants.Spacing.S,
|
||||||
borderColor: colors.border,
|
borderColor: colors.border,
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
borderRadius: StyleConstants.Spacing.S
|
borderRadius: StyleConstants.Spacing.S,
|
||||||
|
marginBottom: StyleConstants.Spacing.S
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
@@ -74,135 +69,104 @@ const ComposeDraftsList: React.FC<ScreenComposeStackScreenProps<'Screen-Compose-
|
|||||||
{t('content.draftsList.warning')}
|
{t('content.draftsList.warning')}
|
||||||
</CustomText>
|
</CustomText>
|
||||||
</View>
|
</View>
|
||||||
<PanGestureHandler enabled={Platform.OS === 'ios'}>
|
<SwipeToActions
|
||||||
<SwipeListView
|
actions={[
|
||||||
data={drafts.filter(draft => draft.timestamp !== timestamp)}
|
{ onPress: ({ item }) => removeDraft(item.timestamp), color: colors.red, icon: 'trash' }
|
||||||
renderItem={({ item }: { item: ComposeStateDraft }) => {
|
]}
|
||||||
return (
|
data={drafts.filter(draft => draft.timestamp !== timestamp)}
|
||||||
<Pressable
|
renderItem={({ item }: { item: ComposeStateDraft }) => {
|
||||||
accessibilityHint={t('content.draftsList.content.accessibilityHint')}
|
return (
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
padding: StyleConstants.Spacing.Global.PagePadding,
|
|
||||||
backgroundColor: colors.backgroundDefault
|
|
||||||
}}
|
|
||||||
onPress={async () => {
|
|
||||||
setCheckingAttachments(true)
|
|
||||||
let tempDraft = item
|
|
||||||
let tempUploads: ExtendedAttachment[] = []
|
|
||||||
if (item.attachments && item.attachments.uploads.length) {
|
|
||||||
for (const attachment of item.attachments.uploads) {
|
|
||||||
await apiInstance<Mastodon.Attachment>({
|
|
||||||
method: 'get',
|
|
||||||
url: `media/${attachment.remote?.id}`
|
|
||||||
})
|
|
||||||
.then(res => {
|
|
||||||
if (res.body.id === attachment.remote?.id) {
|
|
||||||
tempUploads.push(attachment)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => {})
|
|
||||||
}
|
|
||||||
tempDraft = {
|
|
||||||
...tempDraft,
|
|
||||||
attachments: { ...item.attachments, uploads: tempUploads }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tempDraft.spoiler?.length &&
|
|
||||||
formatText({ textInput: 'text', composeDispatch, content: tempDraft.spoiler })
|
|
||||||
tempDraft.text?.length &&
|
|
||||||
formatText({ textInput: 'text', composeDispatch, content: tempDraft.text })
|
|
||||||
composeDispatch({
|
|
||||||
type: 'loadDraft',
|
|
||||||
payload: tempDraft
|
|
||||||
})
|
|
||||||
removeDraft(item.timestamp)
|
|
||||||
navigation.goBack()
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View style={{ flex: 1 }}>
|
|
||||||
<HeaderSharedCreated created_at={item.timestamp} />
|
|
||||||
<CustomText
|
|
||||||
fontStyle='M'
|
|
||||||
numberOfLines={2}
|
|
||||||
style={{
|
|
||||||
marginTop: StyleConstants.Spacing.XS,
|
|
||||||
color: colors.primaryDefault
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{item.text || item.spoiler || t('content.draftsList.content.textEmpty')}
|
|
||||||
</CustomText>
|
|
||||||
{item.attachments?.uploads.length ? (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
marginTop: StyleConstants.Spacing.S
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{item.attachments.uploads.map((attachment, index) => (
|
|
||||||
<FastImage
|
|
||||||
key={index}
|
|
||||||
style={{
|
|
||||||
width:
|
|
||||||
(Dimensions.get('window').width -
|
|
||||||
StyleConstants.Spacing.Global.PagePadding * 2 -
|
|
||||||
StyleConstants.Spacing.S * 3) /
|
|
||||||
4,
|
|
||||||
height:
|
|
||||||
(Dimensions.get('window').width -
|
|
||||||
StyleConstants.Spacing.Global.PagePadding * 2 -
|
|
||||||
StyleConstants.Spacing.S * 3) /
|
|
||||||
4,
|
|
||||||
marginLeft: index !== 0 ? StyleConstants.Spacing.S : 0
|
|
||||||
}}
|
|
||||||
source={{
|
|
||||||
uri: attachment.local?.thumbnail || attachment.remote?.preview_url
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</View>
|
|
||||||
) : null}
|
|
||||||
</View>
|
|
||||||
</Pressable>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
renderHiddenItem={({ item }) => (
|
|
||||||
<Pressable
|
<Pressable
|
||||||
|
accessibilityHint={t('content.draftsList.content.accessibilityHint')}
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row',
|
padding: StyleConstants.Spacing.Global.PagePadding,
|
||||||
justifyContent: 'flex-end',
|
backgroundColor: colors.backgroundDefault
|
||||||
backgroundColor: colors.red
|
|
||||||
}}
|
}}
|
||||||
onPress={() => removeDraft(item.timestamp)}
|
onPress={async () => {
|
||||||
children={
|
setCheckingAttachments(true)
|
||||||
<View
|
let tempDraft = item
|
||||||
style={{
|
let tempUploads: ExtendedAttachment[] = []
|
||||||
flexBasis:
|
if (item.attachments && item.attachments.uploads.length) {
|
||||||
StyleConstants.Font.Size.L + StyleConstants.Spacing.Global.PagePadding * 4,
|
for (const attachment of item.attachments.uploads) {
|
||||||
justifyContent: 'center',
|
await apiInstance<Mastodon.Attachment>({
|
||||||
alignItems: 'center'
|
method: 'get',
|
||||||
}}
|
url: `media/${attachment.remote?.id}`
|
||||||
children={
|
})
|
||||||
<Icon
|
.then(res => {
|
||||||
name='trash'
|
if (res.body.id === attachment.remote?.id) {
|
||||||
size={StyleConstants.Font.Size.L}
|
tempUploads.push(attachment)
|
||||||
color={colors.primaryOverlay}
|
}
|
||||||
/>
|
})
|
||||||
|
.catch(() => {})
|
||||||
}
|
}
|
||||||
/>
|
tempDraft = {
|
||||||
}
|
...tempDraft,
|
||||||
/>
|
attachments: { ...item.attachments, uploads: tempUploads }
|
||||||
)}
|
}
|
||||||
disableRightSwipe={true}
|
}
|
||||||
rightOpenValue={-actionWidth}
|
|
||||||
previewOpenValue={-actionWidth / 2}
|
tempDraft.spoiler?.length &&
|
||||||
ItemSeparatorComponent={ComponentSeparator}
|
formatText({ textInput: 'text', composeDispatch, content: tempDraft.spoiler })
|
||||||
keyExtractor={item => item.timestamp?.toString()}
|
tempDraft.text?.length &&
|
||||||
/>
|
formatText({ textInput: 'text', composeDispatch, content: tempDraft.text })
|
||||||
</PanGestureHandler>
|
composeDispatch({
|
||||||
|
type: 'loadDraft',
|
||||||
|
payload: tempDraft
|
||||||
|
})
|
||||||
|
removeDraft(item.timestamp)
|
||||||
|
navigation.goBack()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<HeaderSharedCreated created_at={item.timestamp} />
|
||||||
|
<CustomText
|
||||||
|
fontStyle='M'
|
||||||
|
numberOfLines={2}
|
||||||
|
style={{
|
||||||
|
marginTop: StyleConstants.Spacing.XS,
|
||||||
|
color: colors.primaryDefault
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.text || item.spoiler || t('content.draftsList.content.textEmpty')}
|
||||||
|
</CustomText>
|
||||||
|
{item.attachments?.uploads.length ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: 'row',
|
||||||
|
marginTop: StyleConstants.Spacing.S
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.attachments.uploads.map((attachment, index) => (
|
||||||
|
<FastImage
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
width:
|
||||||
|
(Dimensions.get('window').width -
|
||||||
|
StyleConstants.Spacing.Global.PagePadding * 2 -
|
||||||
|
StyleConstants.Spacing.S * 3) /
|
||||||
|
4,
|
||||||
|
height:
|
||||||
|
(Dimensions.get('window').width -
|
||||||
|
StyleConstants.Spacing.Global.PagePadding * 2 -
|
||||||
|
StyleConstants.Spacing.S * 3) /
|
||||||
|
4,
|
||||||
|
marginLeft: index !== 0 ? StyleConstants.Spacing.S : 0
|
||||||
|
}}
|
||||||
|
source={{
|
||||||
|
uri: attachment.local?.thumbnail || attachment.remote?.preview_url
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
</Pressable>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
keyExtractor={item => item.timestamp?.toString()}
|
||||||
|
/>
|
||||||
<Modal
|
<Modal
|
||||||
transparent
|
transparent
|
||||||
animationType='fade'
|
animationType='fade'
|
||||||
|
@@ -416,12 +416,12 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
|
|||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name='Screen-Compose-DraftsList'
|
name='Screen-Compose-DraftsList'
|
||||||
component={ComposeDraftsList}
|
component={ComposeDraftsList}
|
||||||
options={{ presentation: 'modal' }}
|
options={{ presentation: 'modal', headerShadowVisible: false }}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name='Screen-Compose-EditAttachment'
|
name='Screen-Compose-EditAttachment'
|
||||||
component={ComposeEditAttachment}
|
component={ComposeEditAttachment}
|
||||||
options={{ presentation: 'modal' }}
|
options={{ presentation: 'modal', headerShadowVisible: false }}
|
||||||
/>
|
/>
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
</ComposeContext.Provider>
|
</ComposeContext.Provider>
|
||||||
|
@@ -1,22 +1,17 @@
|
|||||||
import { Filter } from '@components/Filter'
|
import { Filter } from '@components/Filter'
|
||||||
import { HeaderLeft, HeaderRight } from '@components/Header'
|
import { HeaderLeft, HeaderRight } from '@components/Header'
|
||||||
import Icon from '@components/Icon'
|
import { SwipeToActions } from '@components/SwipeToActions'
|
||||||
import ComponentSeparator from '@components/Separator'
|
|
||||||
import apiInstance from '@utils/api/instance'
|
import apiInstance from '@utils/api/instance'
|
||||||
import { TabMePreferencesStackScreenProps } from '@utils/navigation/navigators'
|
import { TabMePreferencesStackScreenProps } from '@utils/navigation/navigators'
|
||||||
import { useFiltersQuery } from '@utils/queryHooks/filters'
|
import { useFiltersQuery } from '@utils/queryHooks/filters'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import { Pressable, View } from 'react-native'
|
|
||||||
import { SwipeListView } from 'react-native-swipe-list-view'
|
|
||||||
|
|
||||||
const TabMePreferencesFilters: React.FC<
|
const TabMePreferencesFilters: React.FC<
|
||||||
TabMePreferencesStackScreenProps<'Tab-Me-Preferences-Filters'>
|
TabMePreferencesStackScreenProps<'Tab-Me-Preferences-Filters'>
|
||||||
> = ({ navigation }) => {
|
> = ({ navigation }) => {
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { t } = useTranslation(['common', 'screenTabs'])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
@@ -38,40 +33,31 @@ const TabMePreferencesFilters: React.FC<
|
|||||||
const { data, refetch } = useFiltersQuery<'v2'>({ version: 'v2' })
|
const { data, refetch } = useFiltersQuery<'v2'>({ version: 'v2' })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SwipeListView
|
<SwipeToActions
|
||||||
contentContainerStyle={{ padding: StyleConstants.Spacing.Global.PagePadding }}
|
actions={[
|
||||||
renderHiddenItem={({ item }) => (
|
{
|
||||||
<Pressable
|
onPress: ({ item }) => {
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'flex-end',
|
|
||||||
backgroundColor: colors.red
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
apiInstance({ method: 'delete', version: 'v2', url: `filters/${item.id}` }).then(() =>
|
apiInstance({ method: 'delete', version: 'v2', url: `filters/${item.id}` }).then(() =>
|
||||||
refetch()
|
refetch()
|
||||||
)
|
)
|
||||||
}}
|
},
|
||||||
>
|
color: colors.red,
|
||||||
<View style={{ paddingHorizontal: StyleConstants.Spacing.L }}>
|
icon: 'trash'
|
||||||
<Icon name='trash' color='white' size={StyleConstants.Font.Size.L} />
|
}
|
||||||
</View>
|
]}
|
||||||
</Pressable>
|
|
||||||
)}
|
|
||||||
rightOpenValue={-(StyleConstants.Spacing.L * 2 + StyleConstants.Font.Size.L)}
|
|
||||||
disableRightSwipe
|
|
||||||
closeOnRowPress
|
|
||||||
data={data?.sort(filter =>
|
data={data?.sort(filter =>
|
||||||
filter.expires_at ? new Date().getTime() - new Date(filter.expires_at).getTime() : 1
|
filter.expires_at ? new Date().getTime() - new Date(filter.expires_at).getTime() : 1
|
||||||
)}
|
)}
|
||||||
renderItem={({ item: filter }) => (
|
renderItem={({ item: filter }) => (
|
||||||
<Filter
|
<Filter
|
||||||
|
style={{
|
||||||
|
padding: StyleConstants.Spacing.Global.PagePadding,
|
||||||
|
paddingVertical: StyleConstants.Spacing.M
|
||||||
|
}}
|
||||||
filter={filter}
|
filter={filter}
|
||||||
onPress={() => navigation.navigate('Tab-Me-Preferences-Filter', { type: 'edit', filter })}
|
onPress={() => navigation.navigate('Tab-Me-Preferences-Filter', { type: 'edit', filter })}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
ItemSeparatorComponent={ComponentSeparator}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
import { HeaderLeft } from '@components/Header'
|
import { HeaderLeft } from '@components/Header'
|
||||||
import { Message } from '@components/Message'
|
import { Message } from '@components/Message'
|
||||||
|
import { useNavigationState } from '@react-navigation/native'
|
||||||
import { createNativeStackNavigator } from '@react-navigation/native-stack'
|
import { createNativeStackNavigator } from '@react-navigation/native-stack'
|
||||||
import { TabMePreferencesStackParamList, TabMeStackScreenProps } from '@utils/navigation/navigators'
|
import { TabMePreferencesStackParamList, TabMeStackScreenProps } from '@utils/navigation/navigators'
|
||||||
import React, { useRef } from 'react'
|
import React, { useEffect, useRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import FlashMessage from 'react-native-flash-message'
|
import FlashMessage from 'react-native-flash-message'
|
||||||
import TabMePreferencesFilter from './Filter'
|
import TabMePreferencesFilter from './Filter'
|
||||||
@@ -17,6 +18,15 @@ const TabMePreferences: React.FC<TabMeStackScreenProps<'Tab-Me-Preferences'>> =
|
|||||||
const { t } = useTranslation('screenTabs')
|
const { t } = useTranslation('screenTabs')
|
||||||
const messageRef = useRef<FlashMessage>(null)
|
const messageRef = useRef<FlashMessage>(null)
|
||||||
|
|
||||||
|
const isNested =
|
||||||
|
(useNavigationState(
|
||||||
|
state => state.routes.find(route => route.name === 'Tab-Me-Preferences')?.state?.routes.length
|
||||||
|
) || 0) > 1
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
navigation.setOptions({ gestureEnabled: !isNested })
|
||||||
|
}, [isNested])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack.Navigator screenOptions={{ headerShadowVisible: false }}>
|
<Stack.Navigator screenOptions={{ headerShadowVisible: false }}>
|
||||||
|
@@ -314,6 +314,55 @@ const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
|
|||||||
const curr = item._level || 0
|
const curr = item._level || 0
|
||||||
const next = query.data?.pages[0].body[index + 1]?._level || 0
|
const next = query.data?.pages[0].body[index + 1]?._level || 0
|
||||||
|
|
||||||
|
const height = heights[index] || 300
|
||||||
|
let path = ''
|
||||||
|
|
||||||
|
if (curr > 1 || next > 1) {
|
||||||
|
Array.from({ length: curr }).forEach((_, i) => {
|
||||||
|
if (i > MAX_LEVEL) return null
|
||||||
|
|
||||||
|
const lastLine = curr === i + 1
|
||||||
|
if (lastLine) {
|
||||||
|
if (curr === prev + 1 || curr === next - 1) {
|
||||||
|
if (curr > next) return
|
||||||
|
|
||||||
|
path =
|
||||||
|
path +
|
||||||
|
` M ${curr * StyleConstants.Spacing.S + ARC} ${
|
||||||
|
StyleConstants.Spacing.M + StyleConstants.Avatar.XS / 2
|
||||||
|
} ` +
|
||||||
|
`a ${ARC} ${ARC} 0 0 0 -${ARC} ${ARC} ` +
|
||||||
|
`v ${height}`
|
||||||
|
} else {
|
||||||
|
if (i >= curr - 2) return
|
||||||
|
|
||||||
|
path =
|
||||||
|
path +
|
||||||
|
` M ${(i + 1) * StyleConstants.Spacing.S} 0 ` +
|
||||||
|
`v ${
|
||||||
|
height -
|
||||||
|
(StyleConstants.Spacing.S * 1.5 + StyleConstants.Font.Size.L) / 2 -
|
||||||
|
StyleConstants.Avatar.XS / 2
|
||||||
|
} ` +
|
||||||
|
`a ${ARC} ${ARC} 0 0 0 ${ARC} ${ARC}`
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (i >= next - 1) {
|
||||||
|
path =
|
||||||
|
path +
|
||||||
|
` M ${(i + 1) * StyleConstants.Spacing.S} 0 ` +
|
||||||
|
`v ${
|
||||||
|
height -
|
||||||
|
(StyleConstants.Spacing.S * 1.5 + StyleConstants.Font.Size.L * 1.35) / 2
|
||||||
|
} ` +
|
||||||
|
`h ${ARC}`
|
||||||
|
} else {
|
||||||
|
path = path + ` M ${(i + 1) * StyleConstants.Spacing.S} 0 ` + `v ${height}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{ paddingLeft: Math.min(curr - 1, MAX_LEVEL) * StyleConstants.Spacing.S }}
|
style={{ paddingLeft: Math.min(curr - 1, MAX_LEVEL) * StyleConstants.Spacing.S }}
|
||||||
@@ -323,92 +372,11 @@ const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
|
|||||||
}
|
}
|
||||||
}) => setHeights({ ...heights, [index]: height })}
|
}) => setHeights({ ...heights, [index]: height })}
|
||||||
>
|
>
|
||||||
{curr > 1 || next > 1
|
{path.length ? (
|
||||||
? [...new Array(curr)].map((_, i) => {
|
<Svg style={{ position: 'absolute' }} fill='none'>
|
||||||
if (i > MAX_LEVEL) return null
|
<Path d={path} strokeWidth={1} stroke={colors.border} strokeOpacity={0.6} />
|
||||||
|
</Svg>
|
||||||
const lastLine = curr === i + 1
|
) : null}
|
||||||
if (lastLine) {
|
|
||||||
if (curr === prev + 1 || curr === next - 1) {
|
|
||||||
if (curr > next) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Svg key={i} style={{ position: 'absolute' }} fill='none'>
|
|
||||||
<Path
|
|
||||||
d={
|
|
||||||
`M ${curr * StyleConstants.Spacing.S + ARC} ${
|
|
||||||
StyleConstants.Spacing.M + StyleConstants.Avatar.XS / 2
|
|
||||||
} ` +
|
|
||||||
`a ${ARC} ${ARC} 0 0 0 -${ARC} ${ARC} ` +
|
|
||||||
`v ${heights[index] || 300}`
|
|
||||||
}
|
|
||||||
strokeWidth={1}
|
|
||||||
stroke={colors.border}
|
|
||||||
strokeOpacity={0.6}
|
|
||||||
/>
|
|
||||||
</Svg>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
if (i >= curr - 2) return null
|
|
||||||
return (
|
|
||||||
<Svg key={i} style={{ position: 'absolute' }} fill='none'>
|
|
||||||
<Path
|
|
||||||
d={
|
|
||||||
`M ${(i + 1) * StyleConstants.Spacing.S} 0 ` +
|
|
||||||
`v ${
|
|
||||||
(heights[index] || 300) -
|
|
||||||
(StyleConstants.Spacing.S * 1.5 + StyleConstants.Font.Size.L) / 2 -
|
|
||||||
StyleConstants.Avatar.XS / 2
|
|
||||||
} ` +
|
|
||||||
`a ${ARC} ${ARC} 0 0 0 ${ARC} ${ARC}`
|
|
||||||
}
|
|
||||||
strokeWidth={1}
|
|
||||||
stroke={colors.border}
|
|
||||||
strokeOpacity={0.6}
|
|
||||||
/>
|
|
||||||
</Svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (i >= next - 1) {
|
|
||||||
return (
|
|
||||||
<Svg key={i} style={{ position: 'absolute' }} fill='none'>
|
|
||||||
<Path
|
|
||||||
d={
|
|
||||||
`M ${(i + 1) * StyleConstants.Spacing.S} 0 ` +
|
|
||||||
`v ${
|
|
||||||
(heights[index] || 300) -
|
|
||||||
(StyleConstants.Spacing.S * 1.5 +
|
|
||||||
StyleConstants.Font.Size.L * 1.35) /
|
|
||||||
2
|
|
||||||
} ` +
|
|
||||||
`h ${ARC}`
|
|
||||||
}
|
|
||||||
strokeWidth={1}
|
|
||||||
stroke={colors.border}
|
|
||||||
strokeOpacity={0.6}
|
|
||||||
/>
|
|
||||||
</Svg>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<Svg key={i} style={{ position: 'absolute' }} fill='none'>
|
|
||||||
<Path
|
|
||||||
d={
|
|
||||||
`M ${(i + 1) * StyleConstants.Spacing.S} 0 ` +
|
|
||||||
`v ${heights[index] || 300}`
|
|
||||||
}
|
|
||||||
strokeWidth={1}
|
|
||||||
stroke={colors.border}
|
|
||||||
strokeOpacity={0.6}
|
|
||||||
/>
|
|
||||||
</Svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
: null}
|
|
||||||
<TimelineDefault
|
<TimelineDefault
|
||||||
item={item}
|
item={item}
|
||||||
queryKey={item._remote ? queryKey.remote : queryKey.local}
|
queryKey={item._remote ? queryKey.remote : queryKey.local}
|
||||||
|
Reference in New Issue
Block a user