mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
@@ -4,7 +4,7 @@
|
|||||||
"native": "220603",
|
"native": "220603",
|
||||||
"major": 4,
|
"major": 4,
|
||||||
"minor": 1,
|
"minor": 1,
|
||||||
"patch": 1,
|
"patch": 2,
|
||||||
"expo": "45.0.0"
|
"expo": "45.0.0"
|
||||||
},
|
},
|
||||||
"description": "tooot app for Mastodon",
|
"description": "tooot app for Mastodon",
|
||||||
|
@@ -271,8 +271,9 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
|||||||
return (
|
return (
|
||||||
<IntlProvider locale={i18n.language}>
|
<IntlProvider locale={i18n.language}>
|
||||||
<StatusBar
|
<StatusBar
|
||||||
{...(Platform.OS === 'ios' && {
|
backgroundColor={colors.backgroundDefault}
|
||||||
backgroundColor: colors.backgroundDefault
|
{...(Platform.OS === 'android' && {
|
||||||
|
barStyle: theme === 'light' ? 'dark-content' : 'light-content'
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
<NavigationContainer
|
<NavigationContainer
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import analytics from '@components/analytics'
|
import analytics from '@components/analytics'
|
||||||
import { displayMessage } from '@components/Message'
|
import { displayMessage } from '@components/Message'
|
||||||
|
import { useRelationshipQuery } from '@utils/queryHooks/relationship'
|
||||||
import {
|
import {
|
||||||
MutationVarsTimelineUpdateAccountProperty,
|
MutationVarsTimelineUpdateAccountProperty,
|
||||||
QueryKeyTimeline,
|
QueryKeyTimeline,
|
||||||
@@ -8,13 +9,13 @@ import {
|
|||||||
import { getInstanceAccount } from '@utils/slices/instancesSlice'
|
import { getInstanceAccount } from '@utils/slices/instancesSlice'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Platform } from 'react-native'
|
|
||||||
import { ContextMenuAction } from 'react-native-context-menu-view'
|
import { ContextMenuAction } from 'react-native-context-menu-view'
|
||||||
import { useQueryClient } from 'react-query'
|
import { useQueryClient } from 'react-query'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
actions: ContextMenuAction[]
|
actions: ContextMenuAction[]
|
||||||
|
type: 'status' | 'account' // Do not need to fetch relationship in timeline
|
||||||
queryKey?: QueryKeyTimeline
|
queryKey?: QueryKeyTimeline
|
||||||
rootQueryKey?: QueryKeyTimeline
|
rootQueryKey?: QueryKeyTimeline
|
||||||
id: Mastodon.Account['id']
|
id: Mastodon.Account['id']
|
||||||
@@ -22,6 +23,7 @@ export interface Props {
|
|||||||
|
|
||||||
const contextMenuAccount = ({
|
const contextMenuAccount = ({
|
||||||
actions,
|
actions,
|
||||||
|
type,
|
||||||
queryKey,
|
queryKey,
|
||||||
rootQueryKey,
|
rootQueryKey,
|
||||||
id: accountId
|
id: accountId
|
||||||
@@ -32,12 +34,17 @@ const contextMenuAccount = ({
|
|||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const mutateion = useTimelineMutation({
|
const mutateion = useTimelineMutation({
|
||||||
onSuccess: (_, params) => {
|
onSuccess: (_, params) => {
|
||||||
|
queryClient.refetchQueries(['Relationship', { id: accountId }])
|
||||||
const theParams = params as MutationVarsTimelineUpdateAccountProperty
|
const theParams = params as MutationVarsTimelineUpdateAccountProperty
|
||||||
displayMessage({
|
displayMessage({
|
||||||
theme,
|
theme,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: t('common:message.success.message', {
|
message: t('common:message.success.message', {
|
||||||
function: t(`account.${theParams.payload.property}.action`)
|
function: t(`account.${theParams.payload.property}.action`, {
|
||||||
|
...(typeof theParams.payload.currentValue === 'boolean' && {
|
||||||
|
context: theParams.payload.currentValue.toString()
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -47,7 +54,11 @@ const contextMenuAccount = ({
|
|||||||
theme,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: t('common:message.error.message', {
|
message: t('common:message.error.message', {
|
||||||
function: t(`account.${theParams.payload.property}.action`)
|
function: t(`account.${theParams.payload.property}.action`, {
|
||||||
|
...(typeof theParams.payload.currentValue === 'boolean' && {
|
||||||
|
context: theParams.payload.currentValue.toString()
|
||||||
|
})
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
...(err.status &&
|
...(err.status &&
|
||||||
typeof err.status === 'number' &&
|
typeof err.status === 'number' &&
|
||||||
@@ -70,44 +81,25 @@ const contextMenuAccount = ({
|
|||||||
)
|
)
|
||||||
const ownAccount = instanceAccount?.id === accountId
|
const ownAccount = instanceAccount?.id === accountId
|
||||||
|
|
||||||
if (!ownAccount) {
|
const { data: relationship } = useRelationshipQuery({
|
||||||
switch (Platform.OS) {
|
id: accountId,
|
||||||
case 'ios':
|
options: { enabled: type === 'account' }
|
||||||
actions.push({
|
|
||||||
id: 'account',
|
|
||||||
title: t('account.title'),
|
|
||||||
inlineChildren: true,
|
|
||||||
actions: [
|
|
||||||
{
|
|
||||||
id: 'account-mute',
|
|
||||||
title: t('account.mute.action'),
|
|
||||||
systemIcon: 'eye.slash'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'account-block',
|
|
||||||
title: t('account.block.action'),
|
|
||||||
systemIcon: 'xmark.circle',
|
|
||||||
destructive: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'account-reports',
|
|
||||||
title: t('account.reports.action'),
|
|
||||||
systemIcon: 'flag',
|
|
||||||
destructive: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
break
|
|
||||||
default:
|
if (!ownAccount) {
|
||||||
actions.push(
|
actions.push(
|
||||||
{
|
{
|
||||||
id: 'account-mute',
|
id: 'account-mute',
|
||||||
title: t('account.mute.action'),
|
title: t('account.mute.action', {
|
||||||
|
context: (relationship?.muting || false).toString()
|
||||||
|
}),
|
||||||
systemIcon: 'eye.slash'
|
systemIcon: 'eye.slash'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'account-block',
|
id: 'account-block',
|
||||||
title: t('account.block.action'),
|
title: t('account.block.action', {
|
||||||
|
context: (relationship?.blocking || false).toString()
|
||||||
|
}),
|
||||||
systemIcon: 'xmark.circle',
|
systemIcon: 'xmark.circle',
|
||||||
destructive: true
|
destructive: true
|
||||||
},
|
},
|
||||||
@@ -118,13 +110,10 @@ const contextMenuAccount = ({
|
|||||||
destructive: true
|
destructive: true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (id: string) => {
|
return (index: number) => {
|
||||||
switch (id) {
|
if (actions[index].id === 'account-mute') {
|
||||||
case 'account-mute':
|
|
||||||
analytics('timeline_shared_headeractions_account_mute_press', {
|
analytics('timeline_shared_headeractions_account_mute_press', {
|
||||||
page: queryKey && queryKey[1].page
|
page: queryKey && queryKey[1].page
|
||||||
})
|
})
|
||||||
@@ -132,10 +121,10 @@ const contextMenuAccount = ({
|
|||||||
type: 'updateAccountProperty',
|
type: 'updateAccountProperty',
|
||||||
queryKey,
|
queryKey,
|
||||||
id: accountId,
|
id: accountId,
|
||||||
payload: { property: 'mute' }
|
payload: { property: 'mute', currentValue: relationship?.muting }
|
||||||
})
|
})
|
||||||
break
|
}
|
||||||
case 'account-block':
|
if (actions[index].id === 'account-block') {
|
||||||
analytics('timeline_shared_headeractions_account_block_press', {
|
analytics('timeline_shared_headeractions_account_block_press', {
|
||||||
page: queryKey && queryKey[1].page
|
page: queryKey && queryKey[1].page
|
||||||
})
|
})
|
||||||
@@ -143,10 +132,10 @@ const contextMenuAccount = ({
|
|||||||
type: 'updateAccountProperty',
|
type: 'updateAccountProperty',
|
||||||
queryKey,
|
queryKey,
|
||||||
id: accountId,
|
id: accountId,
|
||||||
payload: { property: 'block' }
|
payload: { property: 'block', currentValue: relationship?.blocking }
|
||||||
})
|
})
|
||||||
break
|
}
|
||||||
case 'account-report':
|
if (actions[index].id === 'account-report') {
|
||||||
analytics('timeline_shared_headeractions_account_reports_press', {
|
analytics('timeline_shared_headeractions_account_reports_press', {
|
||||||
page: queryKey && queryKey[1].page
|
page: queryKey && queryKey[1].page
|
||||||
})
|
})
|
||||||
@@ -156,7 +145,6 @@ const contextMenuAccount = ({
|
|||||||
id: accountId,
|
id: accountId,
|
||||||
payload: { property: 'reports' }
|
payload: { property: 'reports' }
|
||||||
})
|
})
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -71,9 +71,12 @@ const contextMenuInstance = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (id: string) => {
|
return (index: number) => {
|
||||||
switch (id) {
|
if (
|
||||||
case 'instance-block':
|
actions[index].id === 'instance-block' ||
|
||||||
|
(actions[index].id === 'instance' &&
|
||||||
|
actions[index].actions?.[0].id === 'instance-block')
|
||||||
|
) {
|
||||||
analytics('timeline_shared_headeractions_domain_block_press', {
|
analytics('timeline_shared_headeractions_domain_block_press', {
|
||||||
page: queryKey[1].page
|
page: queryKey[1].page
|
||||||
})
|
})
|
||||||
@@ -85,10 +88,9 @@ const contextMenuInstance = ({
|
|||||||
text: t('instance.block.alert.buttons.confirm'),
|
text: t('instance.block.alert.buttons.confirm'),
|
||||||
style: 'destructive',
|
style: 'destructive',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
analytics(
|
analytics('timeline_shared_headeractions_domain_block_confirm', {
|
||||||
'timeline_shared_headeractions_domain_block_confirm',
|
page: queryKey && queryKey[1].page
|
||||||
{ page: queryKey && queryKey[1].page }
|
})
|
||||||
)
|
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'domainBlock',
|
type: 'domainBlock',
|
||||||
queryKey,
|
queryKey,
|
||||||
|
@@ -18,9 +18,8 @@ const contextMenuShare = ({ actions, type, url }: Props) => {
|
|||||||
systemIcon: 'square.and.arrow.up'
|
systemIcon: 'square.and.arrow.up'
|
||||||
})
|
})
|
||||||
|
|
||||||
return (id: string) => {
|
return (index: number) => {
|
||||||
switch (id) {
|
if (actions[index].id === 'share') {
|
||||||
case 'share':
|
|
||||||
analytics('timeline_shared_headeractions_share_press')
|
analytics('timeline_shared_headeractions_share_press')
|
||||||
switch (Platform.OS) {
|
switch (Platform.OS) {
|
||||||
case 'ios':
|
case 'ios':
|
||||||
@@ -30,7 +29,6 @@ const contextMenuShare = ({ actions, type, url }: Props) => {
|
|||||||
Share.share({ message: url })
|
Share.share({ message: url })
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@ import {
|
|||||||
} from '@utils/slices/instancesSlice'
|
} from '@utils/slices/instancesSlice'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Alert, Platform } from 'react-native'
|
import { Alert } from 'react-native'
|
||||||
import { ContextMenuAction } from 'react-native-context-menu-view'
|
import { ContextMenuAction } from 'react-native-context-menu-view'
|
||||||
import { useQueryClient } from 'react-query'
|
import { useQueryClient } from 'react-query'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
@@ -88,7 +88,7 @@ const contextMenuStatus = ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'status-mute',
|
id: 'status-mute',
|
||||||
title: t('status.mute.action-muted', {
|
title: t('status.mute.action', {
|
||||||
context: status.muted.toString()
|
context: status.muted.toString()
|
||||||
}),
|
}),
|
||||||
systemIcon: status.muted ? 'speaker' : 'speaker.slash'
|
systemIcon: status.muted ? 'speaker' : 'speaker.slash'
|
||||||
@@ -107,31 +107,18 @@ const contextMenuStatus = ({
|
|||||||
if (status.visibility === 'public' || status.visibility === 'unlisted') {
|
if (status.visibility === 'public' || status.visibility === 'unlisted') {
|
||||||
accountMenuItems.push({
|
accountMenuItems.push({
|
||||||
id: 'status-pin',
|
id: 'status-pin',
|
||||||
title: t('status.pin.action-pinned', {
|
title: t('status.pin.action', {
|
||||||
context: status.pinned.toString()
|
context: status.pinned.toString()
|
||||||
}),
|
}),
|
||||||
systemIcon: status.pinned ? 'pin.slash' : 'pin'
|
systemIcon: status.pinned ? 'pin.slash' : 'pin'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (Platform.OS) {
|
|
||||||
case 'ios':
|
|
||||||
actions.push({
|
|
||||||
id: 'status',
|
|
||||||
title: t('status.title'),
|
|
||||||
inlineChildren: true,
|
|
||||||
actions: accountMenuItems
|
|
||||||
})
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
actions.push(...accountMenuItems)
|
actions.push(...accountMenuItems)
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return async (id: string) => {
|
return async (index: number) => {
|
||||||
switch (id) {
|
if (actions[index].id === 'status-delete') {
|
||||||
case 'status-delete':
|
|
||||||
analytics('timeline_shared_headeractions_status_delete_press', {
|
analytics('timeline_shared_headeractions_status_delete_press', {
|
||||||
page: queryKey && queryKey[1].page
|
page: queryKey && queryKey[1].page
|
||||||
})
|
})
|
||||||
@@ -143,12 +130,9 @@ const contextMenuStatus = ({
|
|||||||
text: t('status.delete.alert.buttons.confirm'),
|
text: t('status.delete.alert.buttons.confirm'),
|
||||||
style: 'destructive',
|
style: 'destructive',
|
||||||
onPress: async () => {
|
onPress: async () => {
|
||||||
analytics(
|
analytics('timeline_shared_headeractions_status_delete_confirm', {
|
||||||
'timeline_shared_headeractions_status_delete_confirm',
|
|
||||||
{
|
|
||||||
page: queryKey && queryKey[1].page
|
page: queryKey && queryKey[1].page
|
||||||
}
|
})
|
||||||
)
|
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'deleteItem',
|
type: 'deleteItem',
|
||||||
source: 'statuses',
|
source: 'statuses',
|
||||||
@@ -163,8 +147,8 @@ const contextMenuStatus = ({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
break
|
}
|
||||||
case 'status-delete-edit':
|
if (actions[index].id === 'status-delete-edit') {
|
||||||
analytics('timeline_shared_headeractions_status_deleteedit_press', {
|
analytics('timeline_shared_headeractions_status_deleteedit_press', {
|
||||||
page: queryKey && queryKey[1].page
|
page: queryKey && queryKey[1].page
|
||||||
})
|
})
|
||||||
@@ -211,8 +195,8 @@ const contextMenuStatus = ({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
break
|
}
|
||||||
case 'status-mute':
|
if (actions[index].id === 'status-mute') {
|
||||||
analytics('timeline_shared_headeractions_status_mute_press', {
|
analytics('timeline_shared_headeractions_status_mute_press', {
|
||||||
page: queryKey && queryKey[1].page
|
page: queryKey && queryKey[1].page
|
||||||
})
|
})
|
||||||
@@ -228,8 +212,8 @@ const contextMenuStatus = ({
|
|||||||
countValue: undefined
|
countValue: undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
break
|
}
|
||||||
case 'status-edit':
|
if (actions[index].id === 'status-edit') {
|
||||||
analytics('timeline_shared_headeractions_status_edit_press', {
|
analytics('timeline_shared_headeractions_status_edit_press', {
|
||||||
page: queryKey && queryKey[1].page
|
page: queryKey && queryKey[1].page
|
||||||
})
|
})
|
||||||
@@ -260,8 +244,8 @@ const contextMenuStatus = ({
|
|||||||
rootQueryKey
|
rootQueryKey
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
break
|
}
|
||||||
case 'status-pin':
|
if (actions[index].id === 'status-pin') {
|
||||||
// Also note that reblogs cannot be pinned.
|
// Also note that reblogs cannot be pinned.
|
||||||
analytics('timeline_shared_headeractions_status_pin_press', {
|
analytics('timeline_shared_headeractions_status_pin_press', {
|
||||||
page: queryKey && queryKey[1].page
|
page: queryKey && queryKey[1].page
|
||||||
@@ -278,7 +262,6 @@ const contextMenuStatus = ({
|
|||||||
countValue: undefined
|
countValue: undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,11 +3,10 @@ import { FormattedRelativeTime } from 'react-intl'
|
|||||||
import { AppState } from 'react-native'
|
import { AppState } from 'react-native'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
type: 'past' | 'future'
|
|
||||||
time: string | number
|
time: string | number
|
||||||
}
|
}
|
||||||
|
|
||||||
const RelativeTime: React.FC<Props> = ({ type, time }) => {
|
const RelativeTime: React.FC<Props> = ({ time }) => {
|
||||||
const [now, setNow] = useState(new Date().getTime())
|
const [now, setNow] = useState(new Date().getTime())
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const appStateListener = AppState.addEventListener('change', state => {
|
const appStateListener = AppState.addEventListener('change', state => {
|
||||||
@@ -21,9 +20,7 @@ const RelativeTime: React.FC<Props> = ({ type, time }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FormattedRelativeTime
|
<FormattedRelativeTime
|
||||||
value={
|
value={(new Date(time).getTime() - now) / 1000}
|
||||||
((type === 'past' ? -1 : 1) * (now - new Date(time).getTime())) / 1000
|
|
||||||
}
|
|
||||||
updateIntervalInSeconds={1}
|
updateIntervalInSeconds={1}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@@ -47,6 +47,7 @@ const TimelineContextMenu: React.FC<Props & ContextMenuProps> = ({
|
|||||||
})
|
})
|
||||||
const accountOnPress = contextMenuAccount({
|
const accountOnPress = contextMenuAccount({
|
||||||
actions,
|
actions,
|
||||||
|
type: 'status',
|
||||||
queryKey,
|
queryKey,
|
||||||
rootQueryKey,
|
rootQueryKey,
|
||||||
id: status.account.id
|
id: status.account.id
|
||||||
@@ -62,14 +63,14 @@ const TimelineContextMenu: React.FC<Props & ContextMenuProps> = ({
|
|||||||
<ContextMenuContext.Provider value={actions}>
|
<ContextMenuContext.Provider value={actions}>
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
actions={actions}
|
actions={actions}
|
||||||
onPress={({ nativeEvent: { id } }) => {
|
onPress={({ nativeEvent: { index } }) => {
|
||||||
for (const on of [
|
for (const on of [
|
||||||
shareOnPress,
|
shareOnPress,
|
||||||
statusOnPress,
|
statusOnPress,
|
||||||
accountOnPress,
|
accountOnPress,
|
||||||
instanceOnPress
|
instanceOnPress
|
||||||
]) {
|
]) {
|
||||||
on && on(id)
|
on && on(index)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
children={children}
|
children={children}
|
||||||
|
@@ -32,7 +32,7 @@ const HeaderSharedCreated = React.memo(
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<RelativeTime type='past' time={actualTime} />
|
<RelativeTime time={actualTime} />
|
||||||
)}
|
)}
|
||||||
</CustomText>
|
</CustomText>
|
||||||
{edited_at ? (
|
{edited_at ? (
|
||||||
|
@@ -269,7 +269,7 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
))
|
))
|
||||||
}, [theme, allOptions])
|
}, [theme, allOptions])
|
||||||
|
|
||||||
const pollVoteCounts = useMemo(() => {
|
const pollVoteCounts = () => {
|
||||||
if (poll.voters_count !== null) {
|
if (poll.voters_count !== null) {
|
||||||
return (
|
return (
|
||||||
t('shared.poll.meta.count.voters', { count: poll.voters_count }) + ' • '
|
t('shared.poll.meta.count.voters', { count: poll.voters_count }) + ' • '
|
||||||
@@ -279,9 +279,9 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
t('shared.poll.meta.count.votes', { count: poll.votes_count }) + ' • '
|
t('shared.poll.meta.count.votes', { count: poll.votes_count }) + ' • '
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}, [poll.voters_count, poll.votes_count])
|
}
|
||||||
|
|
||||||
const pollExpiration = useMemo(() => {
|
const pollExpiration = () => {
|
||||||
if (poll.expired) {
|
if (poll.expired) {
|
||||||
return t('shared.poll.meta.expiration.expired')
|
return t('shared.poll.meta.expiration.expired')
|
||||||
} else {
|
} else {
|
||||||
@@ -289,12 +289,12 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
return (
|
return (
|
||||||
<Trans
|
<Trans
|
||||||
i18nKey='componentTimeline:shared.poll.meta.expiration.until'
|
i18nKey='componentTimeline:shared.poll.meta.expiration.until'
|
||||||
components={[<RelativeTime type='future' time={poll.expires_at} />]}
|
components={[<RelativeTime time={poll.expires_at} />]}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [theme, i18n.language, poll.expired, poll.expires_at])
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ marginTop: StyleConstants.Spacing.M }}>
|
<View style={{ marginTop: StyleConstants.Spacing.M }}>
|
||||||
@@ -312,8 +312,8 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
fontStyle='S'
|
fontStyle='S'
|
||||||
style={{ flexShrink: 1, color: colors.secondary }}
|
style={{ flexShrink: 1, color: colors.secondary }}
|
||||||
>
|
>
|
||||||
{pollVoteCounts}
|
{pollVoteCounts()}
|
||||||
{pollExpiration}
|
{pollExpiration()}
|
||||||
</CustomText>
|
</CustomText>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
@@ -3,10 +3,12 @@
|
|||||||
"account": {
|
"account": {
|
||||||
"title": "User actions",
|
"title": "User actions",
|
||||||
"mute": {
|
"mute": {
|
||||||
"action": "Mute user"
|
"action_false": "Mute user",
|
||||||
|
"action_true": "Unmute user"
|
||||||
},
|
},
|
||||||
"block": {
|
"block": {
|
||||||
"action": "Block user"
|
"action_false": "Block user",
|
||||||
|
"action_true": "Unblock user"
|
||||||
},
|
},
|
||||||
"reports": {
|
"reports": {
|
||||||
"action": "Report user"
|
"action": "Report user"
|
||||||
@@ -59,12 +61,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mute": {
|
"mute": {
|
||||||
"action-muted_false": "Mute toot and replies",
|
"action_false": "Mute toot and replies",
|
||||||
"action-muted_true": "Unmute toot and replies"
|
"action_true": "Unmute toot and replies"
|
||||||
},
|
},
|
||||||
"pin": {
|
"pin": {
|
||||||
"action-pinned_false": "Pin toot",
|
"action_false": "Pin toot",
|
||||||
"action-pinned_true": "Unpin toot"
|
"action_true": "Unpin toot"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -139,7 +139,7 @@
|
|||||||
},
|
},
|
||||||
"expiration": {
|
"expiration": {
|
||||||
"expired": "Vote expired",
|
"expired": "Vote expired",
|
||||||
"until": "Expires in <0 />"
|
"until": "Expires <0 />"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -93,7 +93,7 @@ const ScreenAnnouncements: React.FC<
|
|||||||
<Trans
|
<Trans
|
||||||
i18nKey='screenAnnouncements:content.published'
|
i18nKey='screenAnnouncements:content.published'
|
||||||
components={[
|
components={[
|
||||||
<RelativeTime type='past' time={item.published_at} />
|
<RelativeTime time={item.published_at} />
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</CustomText>
|
</CustomText>
|
||||||
|
@@ -99,7 +99,8 @@ const TabSharedAccount: React.FC<
|
|||||||
customProps={{
|
customProps={{
|
||||||
renderItem,
|
renderItem,
|
||||||
onScroll,
|
onScroll,
|
||||||
ListHeaderComponent
|
ListHeaderComponent,
|
||||||
|
maintainVisibleContentPosition: undefined
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@@ -63,15 +63,16 @@ const TabSharedRoot = ({
|
|||||||
})
|
})
|
||||||
const accountOnPress = contextMenuAccount({
|
const accountOnPress = contextMenuAccount({
|
||||||
actions,
|
actions,
|
||||||
|
type: 'account',
|
||||||
id: account.id
|
id: account.id
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
actions={actions}
|
actions={actions}
|
||||||
onPress={({ nativeEvent: { id } }) => {
|
onPress={({ nativeEvent: { index } }) => {
|
||||||
shareOnPress(id)
|
shareOnPress(index)
|
||||||
accountOnPress(id)
|
accountOnPress(index)
|
||||||
}}
|
}}
|
||||||
dropdownMenuMode
|
dropdownMenuMode
|
||||||
>
|
>
|
||||||
|
@@ -314,6 +314,7 @@ export type MutationVarsTimelineUpdateAccountProperty = {
|
|||||||
id: Mastodon.Account['id']
|
id: Mastodon.Account['id']
|
||||||
payload: {
|
payload: {
|
||||||
property: 'mute' | 'block' | 'reports'
|
property: 'mute' | 'block' | 'reports'
|
||||||
|
currentValue?: boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +384,9 @@ const mutationFunction = async (params: MutationVarsTimeline) => {
|
|||||||
case 'mute':
|
case 'mute':
|
||||||
return apiInstance<Mastodon.Account>({
|
return apiInstance<Mastodon.Account>({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: `accounts/${params.id}/${params.payload.property}`
|
url: `accounts/${params.id}/${
|
||||||
|
params.payload.currentValue ? 'un' : ''
|
||||||
|
}${params.payload.property}`
|
||||||
})
|
})
|
||||||
case 'reports':
|
case 'reports':
|
||||||
return apiInstance<Mastodon.Account>({
|
return apiInstance<Mastodon.Account>({
|
||||||
|
Reference in New Issue
Block a user