mirror of
https://github.com/tooot-app/app
synced 2025-02-22 06:37:57 +01:00
commit
f873e12bcc
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@ -27,11 +27,9 @@ jobs:
|
|||||||
token: ${{ secrets.EXPO_TOKEN }}
|
token: ${{ secrets.EXPO_TOKEN }}
|
||||||
- name: -- Step 4 -- Install node dependencies
|
- name: -- Step 4 -- Install node dependencies
|
||||||
run: yarn install
|
run: yarn install
|
||||||
- name: -- Step 5 -- Install native dependencies
|
- name: -- Step 5 -- Install ruby dependencies
|
||||||
run: npx pod-install
|
|
||||||
- name: -- Step 6 -- Install ruby dependencies
|
|
||||||
run: bundle install
|
run: bundle install
|
||||||
- name: -- Step 7 -- Run fastlane
|
- name: -- Step 6 -- Run fastlane
|
||||||
env:
|
env:
|
||||||
DEVELOPER_DIR: /Applications/Xcode_13.2.1.app/Contents/Developer
|
DEVELOPER_DIR: /Applications/Xcode_13.2.1.app/Contents/Developer
|
||||||
ENVIRONMENT: ${{ steps.branch.outputs.branch }}
|
ENVIRONMENT: ${{ steps.branch.outputs.branch }}
|
||||||
|
20
Gemfile.lock
20
Gemfile.lock
@ -17,17 +17,17 @@ GEM
|
|||||||
artifactory (3.0.15)
|
artifactory (3.0.15)
|
||||||
atomos (0.1.3)
|
atomos (0.1.3)
|
||||||
aws-eventstream (1.2.0)
|
aws-eventstream (1.2.0)
|
||||||
aws-partitions (1.551.0)
|
aws-partitions (1.554.0)
|
||||||
aws-sdk-core (3.125.5)
|
aws-sdk-core (3.126.0)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
aws-partitions (~> 1, >= 1.525.0)
|
aws-partitions (~> 1, >= 1.525.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
jmespath (~> 1.0)
|
jmespath (~> 1.0)
|
||||||
aws-sdk-kms (1.53.0)
|
aws-sdk-kms (1.54.0)
|
||||||
aws-sdk-core (~> 3, >= 3.125.0)
|
aws-sdk-core (~> 3, >= 3.126.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
aws-sdk-s3 (1.111.3)
|
aws-sdk-s3 (1.112.0)
|
||||||
aws-sdk-core (~> 3, >= 3.125.0)
|
aws-sdk-core (~> 3, >= 3.126.0)
|
||||||
aws-sdk-kms (~> 1)
|
aws-sdk-kms (~> 1)
|
||||||
aws-sigv4 (~> 1.4)
|
aws-sigv4 (~> 1.4)
|
||||||
aws-sigv4 (1.4.0)
|
aws-sigv4 (1.4.0)
|
||||||
@ -86,7 +86,7 @@ GEM
|
|||||||
escape (0.0.4)
|
escape (0.0.4)
|
||||||
ethon (0.15.0)
|
ethon (0.15.0)
|
||||||
ffi (>= 1.15.0)
|
ffi (>= 1.15.0)
|
||||||
excon (0.90.0)
|
excon (0.91.0)
|
||||||
faraday (1.9.3)
|
faraday (1.9.3)
|
||||||
faraday-em_http (~> 1.0)
|
faraday-em_http (~> 1.0)
|
||||||
faraday-em_synchrony (~> 1.0)
|
faraday-em_synchrony (~> 1.0)
|
||||||
@ -116,7 +116,7 @@ GEM
|
|||||||
faraday_middleware (1.2.0)
|
faraday_middleware (1.2.0)
|
||||||
faraday (~> 1.0)
|
faraday (~> 1.0)
|
||||||
fastimage (2.2.6)
|
fastimage (2.2.6)
|
||||||
fastlane (2.203.0)
|
fastlane (2.204.2)
|
||||||
CFPropertyList (>= 2.3, < 4.0.0)
|
CFPropertyList (>= 2.3, < 4.0.0)
|
||||||
addressable (>= 2.8, < 3.0.0)
|
addressable (>= 2.8, < 3.0.0)
|
||||||
artifactory (~> 3.0)
|
artifactory (~> 3.0)
|
||||||
@ -155,8 +155,8 @@ GEM
|
|||||||
xcodeproj (>= 1.13.0, < 2.0.0)
|
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||||
xcpretty (~> 0.3.0)
|
xcpretty (~> 0.3.0)
|
||||||
xcpretty-travis-formatter (>= 0.0.3)
|
xcpretty-travis-formatter (>= 0.0.3)
|
||||||
fastlane-plugin-json (1.0.0)
|
fastlane-plugin-json (1.1.0)
|
||||||
fastlane-plugin-sentry (1.11.0)
|
fastlane-plugin-sentry (1.11.1)
|
||||||
fastlane-plugin-versioning_android (0.1.0)
|
fastlane-plugin-versioning_android (0.1.0)
|
||||||
fastlane-plugin-yarn (1.2)
|
fastlane-plugin-yarn (1.2)
|
||||||
ffi (1.15.4)
|
ffi (1.15.4)
|
||||||
|
@ -224,6 +224,7 @@ lane :build do
|
|||||||
puts("Release #{GITHUB_RELEASE} exists. Continue with building React Native only.")
|
puts("Release #{GITHUB_RELEASE} exists. Continue with building React Native only.")
|
||||||
else
|
else
|
||||||
puts("Release #{GITHUB_RELEASE} does not exist. Create new release as well as new native build.")
|
puts("Release #{GITHUB_RELEASE} does not exist. Create new release as well as new native build.")
|
||||||
|
cocoapods(clean_install: true, podfile: "./ios/Podfile", deployment: true)
|
||||||
build_ios
|
build_ios
|
||||||
build_android
|
build_android
|
||||||
case ENVIRONMENT
|
case ENVIRONMENT
|
||||||
|
@ -14,6 +14,7 @@ import pushUseConnect from '@utils/push/useConnect'
|
|||||||
import pushUseReceive from '@utils/push/useReceive'
|
import pushUseReceive from '@utils/push/useReceive'
|
||||||
import pushUseRespond from '@utils/push/useRespond'
|
import pushUseRespond from '@utils/push/useRespond'
|
||||||
import { updatePreviousTab } from '@utils/slices/contextsSlice'
|
import { updatePreviousTab } from '@utils/slices/contextsSlice'
|
||||||
|
import { checkEmojis } from '@utils/slices/instances/checkEmojis'
|
||||||
import { updateAccountPreferences } from '@utils/slices/instances/updateAccountPreferences'
|
import { updateAccountPreferences } from '@utils/slices/instances/updateAccountPreferences'
|
||||||
import { updateConfiguration } from '@utils/slices/instances/updateConfiguration'
|
import { updateConfiguration } from '@utils/slices/instances/updateConfiguration'
|
||||||
import { updateFilters } from '@utils/slices/instances/updateFilters'
|
import { updateFilters } from '@utils/slices/instances/updateFilters'
|
||||||
@ -26,7 +27,6 @@ import { addScreenshotListener } from 'expo-screen-capture'
|
|||||||
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Alert, Platform, StatusBar } from 'react-native'
|
import { Alert, Platform, StatusBar } from 'react-native'
|
||||||
import { useQueryClient } from 'react-query'
|
|
||||||
import { useDispatch, useSelector } from 'react-redux'
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
import * as Sentry from 'sentry-expo'
|
import * as Sentry from 'sentry-expo'
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
|||||||
const { t } = useTranslation('screens')
|
const { t } = useTranslation('screens')
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const instanceActive = useSelector(getInstanceActive)
|
const instanceActive = useSelector(getInstanceActive)
|
||||||
const { mode, theme } = useTheme()
|
const { colors, mode, theme } = useTheme()
|
||||||
enum barStyle {
|
enum barStyle {
|
||||||
light = 'dark-content',
|
light = 'dark-content',
|
||||||
dark = 'light-content'
|
dark = 'light-content'
|
||||||
@ -53,7 +53,6 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
|||||||
getInstances,
|
getInstances,
|
||||||
(prev, next) => prev.length === next.length
|
(prev, next) => prev.length === next.length
|
||||||
)
|
)
|
||||||
const queryClient = useQueryClient()
|
|
||||||
pushUseConnect({ t, instances })
|
pushUseConnect({ t, instances })
|
||||||
pushUseReceive({ instances })
|
pushUseReceive({ instances })
|
||||||
pushUseRespond({ instances })
|
pushUseRespond({ instances })
|
||||||
@ -77,8 +76,9 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
|||||||
message: t('localCorrupt.message'),
|
message: t('localCorrupt.message'),
|
||||||
description: localCorrupt.length ? localCorrupt : undefined,
|
description: localCorrupt.length ? localCorrupt : undefined,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
mode
|
theme
|
||||||
})
|
})
|
||||||
|
// @ts-ignore
|
||||||
navigationRef.navigate('Screen-Tabs', {
|
navigationRef.navigate('Screen-Tabs', {
|
||||||
screen: 'Tab-Me'
|
screen: 'Tab-Me'
|
||||||
})
|
})
|
||||||
@ -93,6 +93,7 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
|||||||
dispatch(updateConfiguration())
|
dispatch(updateConfiguration())
|
||||||
dispatch(updateFilters())
|
dispatch(updateFilters())
|
||||||
dispatch(updateAccountPreferences())
|
dispatch(updateAccountPreferences())
|
||||||
|
dispatch(checkEmojis())
|
||||||
}
|
}
|
||||||
}, [instanceActive])
|
}, [instanceActive])
|
||||||
|
|
||||||
@ -164,11 +165,11 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
|||||||
<>
|
<>
|
||||||
<StatusBar
|
<StatusBar
|
||||||
barStyle={barStyle[mode]}
|
barStyle={barStyle[mode]}
|
||||||
backgroundColor={theme.backgroundDefault}
|
backgroundColor={colors.backgroundDefault}
|
||||||
/>
|
/>
|
||||||
<NavigationContainer
|
<NavigationContainer
|
||||||
ref={navigationRef}
|
ref={navigationRef}
|
||||||
theme={themes[mode]}
|
theme={themes[theme]}
|
||||||
onReady={navigationContainerOnReady}
|
onReady={navigationContainerOnReady}
|
||||||
onStateChange={navigationContainerOnStateChange}
|
onStateChange={navigationContainerOnStateChange}
|
||||||
>
|
>
|
||||||
|
@ -19,7 +19,7 @@ export type Params = {
|
|||||||
|
|
||||||
export const TOOOT_API_DOMAIN = mapEnvironment({
|
export const TOOOT_API_DOMAIN = mapEnvironment({
|
||||||
release: 'api.tooot.app',
|
release: 'api.tooot.app',
|
||||||
candidate: 'api-candidate.tooot.app',
|
candidate: 'api.tooot.app',
|
||||||
development: 'api-development.tooot.app'
|
development: 'api-development.tooot.app'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -20,10 +20,9 @@ const ComponentAccount: React.FC<Props> = ({
|
|||||||
onPress: customOnPress,
|
onPress: customOnPress,
|
||||||
origin
|
origin
|
||||||
}) => {
|
}) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const navigation = useNavigation<
|
const navigation =
|
||||||
StackNavigationProp<TabLocalStackParamList>
|
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
|
||||||
>()
|
|
||||||
|
|
||||||
const onPress = useCallback(() => {
|
const onPress = useCallback(() => {
|
||||||
analytics('search_account_press', { page: origin })
|
analytics('search_account_press', { page: origin })
|
||||||
@ -37,7 +36,7 @@ const ComponentAccount: React.FC<Props> = ({
|
|||||||
onPress={customOnPress || onPress}
|
onPress={customOnPress || onPress}
|
||||||
>
|
>
|
||||||
<GracefullyImage
|
<GracefullyImage
|
||||||
uri={{ original: account.avatar_static }}
|
uri={{ original: account.avatar, static: account.avatar_static }}
|
||||||
style={styles.itemAccountAvatar}
|
style={styles.itemAccountAvatar}
|
||||||
/>
|
/>
|
||||||
<View>
|
<View>
|
||||||
@ -51,7 +50,7 @@ const ComponentAccount: React.FC<Props> = ({
|
|||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={[styles.itemAccountAcct, { color: theme.secondary }]}
|
style={[styles.itemAccountAcct, { color: colors.secondary }]}
|
||||||
>
|
>
|
||||||
@{account.acct}
|
@{account.acct}
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -54,7 +54,7 @@ const Button: React.FC<Props> = ({
|
|||||||
overlay = false,
|
overlay = false,
|
||||||
onPress
|
onPress
|
||||||
}) => {
|
}) => {
|
||||||
const { mode, theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
|
|
||||||
const mounted = useRef(false)
|
const mounted = useRef(false)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -68,35 +68,35 @@ const Button: React.FC<Props> = ({
|
|||||||
const loadingSpinkit = useMemo(
|
const loadingSpinkit = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<View style={{ position: 'absolute' }}>
|
<View style={{ position: 'absolute' }}>
|
||||||
<Flow size={StyleConstants.Font.Size[size]} color={theme.secondary} />
|
<Flow size={StyleConstants.Font.Size[size]} color={colors.secondary} />
|
||||||
</View>
|
</View>
|
||||||
),
|
),
|
||||||
[mode]
|
[theme]
|
||||||
)
|
)
|
||||||
|
|
||||||
const mainColor = useMemo(() => {
|
const mainColor = useMemo(() => {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
return theme.blue
|
return colors.blue
|
||||||
} else if (overlay) {
|
} else if (overlay) {
|
||||||
return theme.primaryOverlay
|
return colors.primaryOverlay
|
||||||
} else if (disabled || loading) {
|
} else if (disabled || loading) {
|
||||||
return theme.disabled
|
return colors.disabled
|
||||||
} else {
|
} else {
|
||||||
if (destructive) {
|
if (destructive) {
|
||||||
return theme.red
|
return colors.red
|
||||||
} else {
|
} else {
|
||||||
return theme.primaryDefault
|
return colors.primaryDefault
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [mode, disabled, loading, selected])
|
}, [theme, disabled, loading, selected])
|
||||||
|
|
||||||
const colorBackground = useMemo(() => {
|
const colorBackground = useMemo(() => {
|
||||||
if (overlay) {
|
if (overlay) {
|
||||||
return theme.backgroundOverlayInvert
|
return colors.backgroundOverlayInvert
|
||||||
} else {
|
} else {
|
||||||
return theme.backgroundDefault
|
return colors.backgroundDefault
|
||||||
}
|
}
|
||||||
}, [mode])
|
}, [theme])
|
||||||
|
|
||||||
const children = useMemo(() => {
|
const children = useMemo(() => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -130,7 +130,7 @@ const Button: React.FC<Props> = ({
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}, [mode, content, loading, disabled])
|
}, [theme, content, loading, disabled])
|
||||||
|
|
||||||
const [layoutHeight, setLayoutHeight] = useState<number | undefined>()
|
const [layoutHeight, setLayoutHeight] = useState<number | undefined>()
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import EmojisButton from '@components/Emojis/Button'
|
|||||||
import EmojisList from '@components/Emojis/List'
|
import EmojisList from '@components/Emojis/List'
|
||||||
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
||||||
import { useEmojisQuery } from '@utils/queryHooks/emojis'
|
import { useEmojisQuery } from '@utils/queryHooks/emojis'
|
||||||
|
import { getInstanceFrequentEmojis } from '@utils/slices/instancesSlice'
|
||||||
import { chunk, forEach, groupBy, sortBy } from 'lodash'
|
import { chunk, forEach, groupBy, sortBy } from 'lodash'
|
||||||
import React, {
|
import React, {
|
||||||
Dispatch,
|
Dispatch,
|
||||||
@ -11,11 +12,16 @@ import React, {
|
|||||||
useEffect,
|
useEffect,
|
||||||
useReducer
|
useReducer
|
||||||
} from 'react'
|
} from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import FastImage from 'react-native-fast-image'
|
import FastImage from 'react-native-fast-image'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
import EmojisContext, { emojisReducer } from './Emojis/helpers/EmojisContext'
|
import EmojisContext, { emojisReducer } from './Emojis/helpers/EmojisContext'
|
||||||
|
|
||||||
const prefetchEmojis = (
|
const prefetchEmojis = (
|
||||||
sortedEmojis: { title: string; data: Mastodon.Emoji[][] }[],
|
sortedEmojis: {
|
||||||
|
title: string
|
||||||
|
data: Pick<Mastodon.Emoji, 'shortcode' | 'url' | 'static_url'>[][]
|
||||||
|
}[],
|
||||||
reduceMotionEnabled: boolean
|
reduceMotionEnabled: boolean
|
||||||
) => {
|
) => {
|
||||||
const prefetches: { uri: string }[] = []
|
const prefetches: { uri: string }[] = []
|
||||||
@ -101,14 +107,28 @@ const ComponentEmojis: React.FC<Props> = ({
|
|||||||
[value, selectionRange.current?.start, selectionRange.current?.end]
|
[value, selectionRange.current?.start, selectionRange.current?.end]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const { t } = useTranslation()
|
||||||
const { data } = useEmojisQuery({ options: { enabled } })
|
const { data } = useEmojisQuery({ options: { enabled } })
|
||||||
|
const frequentEmojis = useSelector(getInstanceFrequentEmojis, () => true)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data && data.length) {
|
if (data && data.length) {
|
||||||
let sortedEmojis: { title: string; data: Mastodon.Emoji[][] }[] = []
|
let sortedEmojis: {
|
||||||
|
title: string
|
||||||
|
data: Pick<Mastodon.Emoji, 'shortcode' | 'url' | 'static_url'>[][]
|
||||||
|
}[] = []
|
||||||
forEach(
|
forEach(
|
||||||
groupBy(sortBy(data, ['category', 'shortcode']), 'category'),
|
groupBy(sortBy(data, ['category', 'shortcode']), 'category'),
|
||||||
(value, key) => sortedEmojis.push({ title: key, data: chunk(value, 5) })
|
(value, key) => sortedEmojis.push({ title: key, data: chunk(value, 5) })
|
||||||
)
|
)
|
||||||
|
if (frequentEmojis.length) {
|
||||||
|
sortedEmojis.unshift({
|
||||||
|
title: t('componentEmojis:frequentUsed'),
|
||||||
|
data: chunk(
|
||||||
|
frequentEmojis.map(e => e.emoji),
|
||||||
|
5
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
emojisDispatch({
|
emojisDispatch({
|
||||||
type: 'load',
|
type: 'load',
|
||||||
payload: sortedEmojis
|
payload: sortedEmojis
|
||||||
|
@ -7,7 +7,7 @@ import EmojisContext from './helpers/EmojisContext'
|
|||||||
|
|
||||||
const EmojisButton = React.memo(
|
const EmojisButton = React.memo(
|
||||||
() => {
|
() => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { emojisState, emojisDispatch } = useContext(EmojisContext)
|
const { emojisState, emojisDispatch } = useContext(EmojisContext)
|
||||||
|
|
||||||
return emojisState.enabled ? (
|
return emojisState.enabled ? (
|
||||||
@ -30,8 +30,8 @@ const EmojisButton = React.memo(
|
|||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={
|
color={
|
||||||
emojisState.emojis && emojisState.emojis.length
|
emojisState.emojis && emojisState.emojis.length
|
||||||
? theme.primaryDefault
|
? colors.primaryDefault
|
||||||
: theme.disabled
|
: colors.disabled
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
||||||
|
import { countInstanceEmoji } from '@utils/slices/instancesSlice'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import layoutAnimation from '@utils/styles/layoutAnimation'
|
import layoutAnimation from '@utils/styles/layoutAnimation'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
@ -14,20 +15,22 @@ import {
|
|||||||
View
|
View
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import FastImage from 'react-native-fast-image'
|
import FastImage from 'react-native-fast-image'
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
import validUrl from 'valid-url'
|
import validUrl from 'valid-url'
|
||||||
import EmojisContext from './helpers/EmojisContext'
|
import EmojisContext from './helpers/EmojisContext'
|
||||||
|
|
||||||
const EmojisList = React.memo(
|
const EmojisList = React.memo(
|
||||||
() => {
|
() => {
|
||||||
|
const dispatch = useDispatch()
|
||||||
const { reduceMotionEnabled } = useAccessibility()
|
const { reduceMotionEnabled } = useAccessibility()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const { emojisState, emojisDispatch } = useContext(EmojisContext)
|
const { emojisState, emojisDispatch } = useContext(EmojisContext)
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const listHeader = useCallback(
|
const listHeader = useCallback(
|
||||||
({ section: { title } }) => (
|
({ section: { title } }) => (
|
||||||
<Text style={[styles.group, { color: theme.secondary }]}>{title}</Text>
|
<Text style={[styles.group, { color: colors.secondary }]}>{title}</Text>
|
||||||
),
|
),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
@ -42,12 +45,13 @@ const EmojisList = React.memo(
|
|||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
key={emoji.shortcode}
|
key={emoji.shortcode}
|
||||||
onPress={() =>
|
onPress={() => {
|
||||||
emojisDispatch({
|
emojisDispatch({
|
||||||
type: 'shortcode',
|
type: 'shortcode',
|
||||||
payload: `:${emoji.shortcode}:`
|
payload: `:${emoji.shortcode}:`
|
||||||
})
|
})
|
||||||
}
|
dispatch(countInstanceEmoji(emoji))
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<FastImage
|
<FastImage
|
||||||
accessibilityLabel={t(
|
accessibilityLabel={t(
|
||||||
|
@ -3,7 +3,10 @@ import { createContext, Dispatch } from 'react'
|
|||||||
export type EmojisState = {
|
export type EmojisState = {
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
active: boolean
|
active: boolean
|
||||||
emojis: { title: string; data: Mastodon.Emoji[][] }[]
|
emojis: {
|
||||||
|
title: string
|
||||||
|
data: Pick<Mastodon.Emoji, 'shortcode' | 'url' | 'static_url'>[][]
|
||||||
|
}[]
|
||||||
shortcode: Mastodon.Emoji['shortcode'] | null
|
shortcode: Mastodon.Emoji['shortcode'] | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React, { useCallback, useMemo, useState } from 'react'
|
import React, { useCallback, useMemo, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
@ -23,7 +24,7 @@ export interface Props {
|
|||||||
accessibilityHint?: AccessibilityProps['accessibilityHint']
|
accessibilityHint?: AccessibilityProps['accessibilityHint']
|
||||||
|
|
||||||
hidden?: boolean
|
hidden?: boolean
|
||||||
uri: { preview?: string; original?: string; remote?: string }
|
uri: { preview?: string; original?: string; remote?: string; static?: string }
|
||||||
blurhash?: string
|
blurhash?: string
|
||||||
dimension?: { width: number; height: number }
|
dimension?: { width: number; height: number }
|
||||||
onPress?: () => void
|
onPress?: () => void
|
||||||
@ -51,7 +52,8 @@ const GracefullyImage = React.memo(
|
|||||||
imageStyle,
|
imageStyle,
|
||||||
setImageDimensions
|
setImageDimensions
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { theme } = useTheme()
|
const { reduceMotionEnabled } = useAccessibility()
|
||||||
|
const { colors } = useTheme()
|
||||||
const [originalFailed, setOriginalFailed] = useState(false)
|
const [originalFailed, setOriginalFailed] = useState(false)
|
||||||
const [imageLoaded, setImageLoaded] = useState(false)
|
const [imageLoaded, setImageLoaded] = useState(false)
|
||||||
|
|
||||||
@ -59,7 +61,9 @@ const GracefullyImage = React.memo(
|
|||||||
if (originalFailed) {
|
if (originalFailed) {
|
||||||
return { uri: uri.remote || undefined }
|
return { uri: uri.remote || undefined }
|
||||||
} else {
|
} else {
|
||||||
return { uri: uri.original }
|
return {
|
||||||
|
uri: reduceMotionEnabled && uri.static ? uri.static : uri.original
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [originalFailed])
|
}, [originalFailed])
|
||||||
|
|
||||||
@ -85,7 +89,7 @@ const GracefullyImage = React.memo(
|
|||||||
source={{ uri: uri.preview }}
|
source={{ uri: uri.preview }}
|
||||||
style={[
|
style={[
|
||||||
styles.placeholder,
|
styles.placeholder,
|
||||||
{ backgroundColor: theme.shimmerDefault }
|
{ backgroundColor: colors.shimmerDefault }
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
) : null,
|
) : null,
|
||||||
@ -118,7 +122,7 @@ const GracefullyImage = React.memo(
|
|||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.placeholder,
|
styles.placeholder,
|
||||||
{ backgroundColor: theme.shimmerDefault }
|
{ backgroundColor: colors.shimmerDefault }
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -135,7 +139,7 @@ const GracefullyImage = React.memo(
|
|||||||
: { accessibilityRole: 'image' })}
|
: { accessibilityRole: 'image' })}
|
||||||
accessibilityLabel={accessibilityLabel}
|
accessibilityLabel={accessibilityLabel}
|
||||||
accessibilityHint={accessibilityHint}
|
accessibilityHint={accessibilityHint}
|
||||||
style={[style, dimension, { backgroundColor: theme.shimmerDefault }]}
|
style={[style, dimension, { backgroundColor: colors.shimmerDefault }]}
|
||||||
{...(onPress
|
{...(onPress
|
||||||
? hidden
|
? hidden
|
||||||
? { disabled: true }
|
? { disabled: true }
|
||||||
|
@ -17,10 +17,9 @@ const ComponentHashtag: React.FC<Props> = ({
|
|||||||
onPress: customOnPress,
|
onPress: customOnPress,
|
||||||
origin
|
origin
|
||||||
}) => {
|
}) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const navigation = useNavigation<
|
const navigation =
|
||||||
StackNavigationProp<Nav.TabLocalStackParamList>
|
useNavigation<StackNavigationProp<Nav.TabLocalStackParamList>>()
|
||||||
>()
|
|
||||||
|
|
||||||
const onPress = useCallback(() => {
|
const onPress = useCallback(() => {
|
||||||
analytics('search_account_press', { page: origin })
|
analytics('search_account_press', { page: origin })
|
||||||
@ -33,7 +32,7 @@ const ComponentHashtag: React.FC<Props> = ({
|
|||||||
style={styles.itemDefault}
|
style={styles.itemDefault}
|
||||||
onPress={customOnPress || onPress}
|
onPress={customOnPress || onPress}
|
||||||
>
|
>
|
||||||
<Text style={[styles.itemHashtag, { color: theme.primaryDefault }]}>
|
<Text style={[styles.itemHashtag, { color: colors.primaryDefault }]}>
|
||||||
#{hashtag.name}
|
#{hashtag.name}
|
||||||
</Text>
|
</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
@ -11,13 +11,13 @@ export interface Props {
|
|||||||
// Used for Android mostly
|
// Used for Android mostly
|
||||||
const HeaderCenter = React.memo(
|
const HeaderCenter = React.memo(
|
||||||
({ content, inverted = false }: Props) => {
|
({ content, inverted = false }: Props) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
style={[
|
style={[
|
||||||
styles.text,
|
styles.text,
|
||||||
{ color: inverted ? theme.primaryOverlay : theme.primaryDefault }
|
{ color: inverted ? colors.primaryOverlay : colors.primaryDefault }
|
||||||
]}
|
]}
|
||||||
children={content}
|
children={content}
|
||||||
/>
|
/>
|
||||||
|
@ -20,14 +20,14 @@ const HeaderLeft: React.FC<Props> = ({
|
|||||||
background = false,
|
background = false,
|
||||||
onPress
|
onPress
|
||||||
}) => {
|
}) => {
|
||||||
const { theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
|
|
||||||
const children = useMemo(() => {
|
const children = useMemo(() => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'icon':
|
case 'icon':
|
||||||
return (
|
return (
|
||||||
<Icon
|
<Icon
|
||||||
color={theme.primaryDefault}
|
color={colors.primaryDefault}
|
||||||
name={content || 'ChevronLeft'}
|
name={content || 'ChevronLeft'}
|
||||||
size={StyleConstants.Spacing.M * 1.25}
|
size={StyleConstants.Spacing.M * 1.25}
|
||||||
/>
|
/>
|
||||||
@ -35,7 +35,7 @@ const HeaderLeft: React.FC<Props> = ({
|
|||||||
case 'text':
|
case 'text':
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
style={[styles.text, { color: theme.primaryDefault }]}
|
style={[styles.text, { color: colors.primaryDefault }]}
|
||||||
children={content}
|
children={content}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -50,7 +50,7 @@ const HeaderLeft: React.FC<Props> = ({
|
|||||||
styles.base,
|
styles.base,
|
||||||
{
|
{
|
||||||
backgroundColor: background
|
backgroundColor: background
|
||||||
? theme.backgroundOverlayDefault
|
? colors.backgroundOverlayDefault
|
||||||
: undefined,
|
: undefined,
|
||||||
minHeight: 44,
|
minHeight: 44,
|
||||||
minWidth: 44,
|
minWidth: 44,
|
||||||
|
@ -41,14 +41,14 @@ const HeaderRight: React.FC<Props> = ({
|
|||||||
disabled,
|
disabled,
|
||||||
onPress
|
onPress
|
||||||
}) => {
|
}) => {
|
||||||
const { theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
|
|
||||||
const loadingSpinkit = useMemo(
|
const loadingSpinkit = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<View style={{ position: 'absolute' }}>
|
<View style={{ position: 'absolute' }}>
|
||||||
<Flow
|
<Flow
|
||||||
size={StyleConstants.Font.Size.M * 1.25}
|
size={StyleConstants.Font.Size.M * 1.25}
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
),
|
),
|
||||||
@ -64,7 +64,7 @@ const HeaderRight: React.FC<Props> = ({
|
|||||||
name={content}
|
name={content}
|
||||||
style={{ opacity: loading ? 0 : 1 }}
|
style={{ opacity: loading ? 0 : 1 }}
|
||||||
size={StyleConstants.Spacing.M * 1.25}
|
size={StyleConstants.Spacing.M * 1.25}
|
||||||
color={disabled ? theme.secondary : theme.primaryDefault}
|
color={disabled ? colors.secondary : colors.primaryDefault}
|
||||||
/>
|
/>
|
||||||
{loading && loadingSpinkit}
|
{loading && loadingSpinkit}
|
||||||
</>
|
</>
|
||||||
@ -76,7 +76,7 @@ const HeaderRight: React.FC<Props> = ({
|
|||||||
style={[
|
style={[
|
||||||
styles.text,
|
styles.text,
|
||||||
{
|
{
|
||||||
color: disabled ? theme.secondary : theme.primaryDefault,
|
color: disabled ? colors.secondary : colors.primaryDefault,
|
||||||
opacity: loading ? 0 : 1
|
opacity: loading ? 0 : 1
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
@ -101,7 +101,7 @@ const HeaderRight: React.FC<Props> = ({
|
|||||||
styles.base,
|
styles.base,
|
||||||
{
|
{
|
||||||
backgroundColor: background
|
backgroundColor: background
|
||||||
? theme.backgroundOverlayDefault
|
? colors.backgroundOverlayDefault
|
||||||
: undefined,
|
: undefined,
|
||||||
minHeight: 44,
|
minHeight: 44,
|
||||||
minWidth: 44,
|
minWidth: 44,
|
||||||
|
@ -57,7 +57,7 @@ const Input: React.FC<Props> = ({
|
|||||||
setValue,
|
setValue,
|
||||||
options
|
options
|
||||||
}) => {
|
}) => {
|
||||||
const { mode, theme } = useTheme()
|
const { colors, mode } = useTheme()
|
||||||
|
|
||||||
const animateTitle = useAnimatedStyle(() => {
|
const animateTitle = useAnimatedStyle(() => {
|
||||||
if (value) {
|
if (value) {
|
||||||
@ -66,7 +66,7 @@ const Input: React.FC<Props> = ({
|
|||||||
paddingHorizontal: withTiming(StyleConstants.Spacing.XS),
|
paddingHorizontal: withTiming(StyleConstants.Spacing.XS),
|
||||||
left: withTiming(StyleConstants.Spacing.S),
|
left: withTiming(StyleConstants.Spacing.S),
|
||||||
top: withTiming(-(StyleConstants.Font.Size.S / 2) - 2),
|
top: withTiming(-(StyleConstants.Font.Size.S / 2) - 2),
|
||||||
backgroundColor: withTiming(theme.backgroundDefault)
|
backgroundColor: withTiming(colors.backgroundDefault)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
@ -74,7 +74,7 @@ const Input: React.FC<Props> = ({
|
|||||||
paddingHorizontal: withTiming(0),
|
paddingHorizontal: withTiming(0),
|
||||||
left: withTiming(StyleConstants.Spacing.S),
|
left: withTiming(StyleConstants.Spacing.S),
|
||||||
top: withTiming(StyleConstants.Spacing.S + 1),
|
top: withTiming(StyleConstants.Spacing.S + 1),
|
||||||
backgroundColor: withTiming(theme.backgroundDefaultTransparent)
|
backgroundColor: withTiming(colors.backgroundDefaultTransparent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [mode, value])
|
}, [mode, value])
|
||||||
@ -109,7 +109,7 @@ const Input: React.FC<Props> = ({
|
|||||||
style={[
|
style={[
|
||||||
styles.base,
|
styles.base,
|
||||||
{
|
{
|
||||||
borderColor: theme.border,
|
borderColor: colors.border,
|
||||||
flexDirection: multiline ? 'column' : 'row',
|
flexDirection: multiline ? 'column' : 'row',
|
||||||
alignItems: 'stretch'
|
alignItems: 'stretch'
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ const Input: React.FC<Props> = ({
|
|||||||
style={[
|
style={[
|
||||||
styles.textInput,
|
styles.textInput,
|
||||||
{
|
{
|
||||||
color: theme.primaryDefault,
|
color: colors.primaryDefault,
|
||||||
minHeight:
|
minHeight:
|
||||||
Platform.OS === 'ios' && multiline
|
Platform.OS === 'ios' && multiline
|
||||||
? StyleConstants.Font.LineHeight.M * 5
|
? StyleConstants.Font.LineHeight.M * 5
|
||||||
@ -149,14 +149,14 @@ const Input: React.FC<Props> = ({
|
|||||||
</EmojisContext.Consumer>
|
</EmojisContext.Consumer>
|
||||||
{title ? (
|
{title ? (
|
||||||
<Animated.Text
|
<Animated.Text
|
||||||
style={[styles.title, animateTitle, { color: theme.secondary }]}
|
style={[styles.title, animateTitle, { color: colors.secondary }]}
|
||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
</Animated.Text>
|
</Animated.Text>
|
||||||
) : null}
|
) : null}
|
||||||
<View style={{ flexDirection: 'row', alignSelf: 'flex-end' }}>
|
<View style={{ flexDirection: 'row', alignSelf: 'flex-end' }}>
|
||||||
{options?.maxLength && value?.length ? (
|
{options?.maxLength && value?.length ? (
|
||||||
<Text style={[styles.maxLength, { color: theme.secondary }]}>
|
<Text style={[styles.maxLength, { color: colors.secondary }]}>
|
||||||
{value?.length} / {options.maxLength}
|
{value?.length} / {options.maxLength}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -39,7 +39,7 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
goBack = false
|
goBack = false
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation('componentInstance')
|
const { t } = useTranslation('componentInstance')
|
||||||
const { mode, theme } = useTheme()
|
const { colors, mode } = useTheme()
|
||||||
const { screenReaderEnabled } = useAccessibility()
|
const { screenReaderEnabled } = useAccessibility()
|
||||||
|
|
||||||
const instances = useSelector(getInstances, () => true)
|
const instances = useSelector(getInstances, () => true)
|
||||||
@ -149,10 +149,10 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
style={[
|
style={[
|
||||||
styles.prefix,
|
styles.prefix,
|
||||||
{
|
{
|
||||||
color: theme.primaryDefault,
|
color: colors.primaryDefault,
|
||||||
borderBottomColor: instanceQuery.isError
|
borderBottomColor: instanceQuery.isError
|
||||||
? theme.red
|
? colors.red
|
||||||
: theme.border
|
: colors.border
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
editable={false}
|
editable={false}
|
||||||
@ -162,10 +162,10 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
style={[
|
style={[
|
||||||
styles.textInput,
|
styles.textInput,
|
||||||
{
|
{
|
||||||
color: theme.primaryDefault,
|
color: colors.primaryDefault,
|
||||||
borderBottomColor: instanceQuery.isError
|
borderBottomColor: instanceQuery.isError
|
||||||
? theme.red
|
? colors.red
|
||||||
: theme.border
|
: colors.border
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
onChangeText={onChangeText}
|
onChangeText={onChangeText}
|
||||||
@ -175,7 +175,7 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
textContentType='URL'
|
textContentType='URL'
|
||||||
onSubmitEditing={onSubmitEditing}
|
onSubmitEditing={onSubmitEditing}
|
||||||
placeholder={' ' + t('server.textInput.placeholder')}
|
placeholder={' ' + t('server.textInput.placeholder')}
|
||||||
placeholderTextColor={theme.secondary}
|
placeholderTextColor={colors.secondary}
|
||||||
returnKeyType='go'
|
returnKeyType='go'
|
||||||
keyboardAppearance={mode}
|
keyboardAppearance={mode}
|
||||||
{...(scrollViewRef && {
|
{...(scrollViewRef && {
|
||||||
@ -234,11 +234,11 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
<Icon
|
<Icon
|
||||||
name='Lock'
|
name='Lock'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
style={styles.disclaimerIcon}
|
style={styles.disclaimerIcon}
|
||||||
/>
|
/>
|
||||||
<Text
|
<Text
|
||||||
style={[styles.disclaimerText, { color: theme.secondary }]}
|
style={[styles.disclaimerText, { color: colors.secondary }]}
|
||||||
accessibilityRole='link'
|
accessibilityRole='link'
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (screenReaderEnabled) {
|
if (screenReaderEnabled) {
|
||||||
@ -252,7 +252,7 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
{t('server.disclaimer.base')}
|
{t('server.disclaimer.base')}
|
||||||
<Text
|
<Text
|
||||||
accessible
|
accessible
|
||||||
style={{ color: theme.blue }}
|
style={{ color: colors.blue }}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
analytics('view_privacy')
|
analytics('view_privacy')
|
||||||
WebBrowser.openBrowserAsync(
|
WebBrowser.openBrowserAsync(
|
||||||
|
@ -13,15 +13,15 @@ export interface Props {
|
|||||||
|
|
||||||
const InstanceInfo = React.memo(
|
const InstanceInfo = React.memo(
|
||||||
({ style, header, content, potentialWidth }: Props) => {
|
({ style, header, content, potentialWidth }: Props) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.base, style]} accessible>
|
<View style={[styles.base, style]} accessible>
|
||||||
<Text style={[styles.header, { color: theme.primaryDefault }]}>
|
<Text style={[styles.header, { color: colors.primaryDefault }]}>
|
||||||
{header}
|
{header}
|
||||||
</Text>
|
</Text>
|
||||||
{content ? (
|
{content ? (
|
||||||
<Text style={[styles.content, { color: theme.primaryDefault }]}>
|
<Text style={[styles.content, { color: colors.primaryDefault }]}>
|
||||||
{content}
|
{content}
|
||||||
</Text>
|
</Text>
|
||||||
) : (
|
) : (
|
||||||
@ -32,7 +32,7 @@ const InstanceInfo = React.memo(
|
|||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
height={StyleConstants.Font.LineHeight.M}
|
height={StyleConstants.Font.LineHeight.M}
|
||||||
color={theme.shimmerDefault}
|
color={colors.shimmerDefault}
|
||||||
noMargin
|
noMargin
|
||||||
style={{ borderRadius: 0 }}
|
style={{ borderRadius: 0 }}
|
||||||
/>
|
/>
|
||||||
|
@ -8,11 +8,11 @@ export interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MenuHeader: React.FC<Props> = ({ heading }) => {
|
const MenuHeader: React.FC<Props> = ({ heading }) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.base}>
|
<View style={styles.base}>
|
||||||
<Text style={[styles.text, { color: theme.secondary }]}>{heading}</Text>
|
<Text style={[styles.text, { color: colors.secondary }]}>{heading}</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
loading = false,
|
loading = false,
|
||||||
onPress
|
onPress
|
||||||
}) => {
|
}) => {
|
||||||
const { theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
const { screenReaderEnabled } = useAccessibility()
|
const { screenReaderEnabled } = useAccessibility()
|
||||||
|
|
||||||
const loadingSpinkit = useMemo(
|
const loadingSpinkit = useMemo(
|
||||||
@ -51,7 +51,7 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
<View style={{ position: 'absolute' }}>
|
<View style={{ position: 'absolute' }}>
|
||||||
<Flow
|
<Flow
|
||||||
size={StyleConstants.Font.Size.M * 1.25}
|
size={StyleConstants.Font.Size.M * 1.25}
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
),
|
),
|
||||||
@ -83,7 +83,7 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
<Icon
|
<Icon
|
||||||
name={iconFront}
|
name={iconFront}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme[iconFrontColor]}
|
color={colors[iconFrontColor]}
|
||||||
style={styles.iconFront}
|
style={styles.iconFront}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -92,7 +92,7 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
style={{
|
style={{
|
||||||
width: 8,
|
width: 8,
|
||||||
height: 8,
|
height: 8,
|
||||||
backgroundColor: theme.red,
|
backgroundColor: colors.red,
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
marginRight: StyleConstants.Spacing.S
|
marginRight: StyleConstants.Spacing.S
|
||||||
}}
|
}}
|
||||||
@ -100,7 +100,7 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
) : null}
|
) : null}
|
||||||
<View style={styles.main}>
|
<View style={styles.main}>
|
||||||
<Text
|
<Text
|
||||||
style={[styles.title, { color: theme.primaryDefault }]}
|
style={[styles.title, { color: colors.primaryDefault }]}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
@ -116,7 +116,7 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
style={[
|
style={[
|
||||||
styles.content,
|
styles.content,
|
||||||
{
|
{
|
||||||
color: theme.secondary,
|
color: colors.secondary,
|
||||||
opacity: !iconBack && loading ? 0 : 1
|
opacity: !iconBack && loading ? 0 : 1
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
@ -133,7 +133,7 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
value={switchValue}
|
value={switchValue}
|
||||||
onValueChange={switchOnValueChange}
|
onValueChange={switchOnValueChange}
|
||||||
disabled={switchDisabled}
|
disabled={switchDisabled}
|
||||||
trackColor={{ true: theme.blue, false: theme.disabled }}
|
trackColor={{ true: colors.blue, false: colors.disabled }}
|
||||||
style={{ opacity: loading ? 0 : 1 }}
|
style={{ opacity: loading ? 0 : 1 }}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
@ -141,7 +141,7 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
<Icon
|
<Icon
|
||||||
name={iconBack}
|
name={iconBack}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme[iconBackColor]}
|
color={colors[iconBackColor]}
|
||||||
style={[styles.iconBack, { opacity: loading ? 0 : 1 }]}
|
style={[styles.iconBack, { opacity: loading ? 0 : 1 }]}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
@ -150,7 +150,7 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
{description ? (
|
{description ? (
|
||||||
<Text style={[styles.description, { color: theme.secondary }]}>
|
<Text style={[styles.description, { color: colors.secondary }]}>
|
||||||
{description}
|
{description}
|
||||||
</Text>
|
</Text>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Icon from '@components/Icon'
|
import Icon from '@components/Icon'
|
||||||
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 { getTheme } from '@utils/styles/themes'
|
import { getColors, Theme } from '@utils/styles/themes'
|
||||||
import React, { RefObject } from 'react'
|
import React, { RefObject } from 'react'
|
||||||
import { AccessibilityInfo } from 'react-native'
|
import { AccessibilityInfo } from 'react-native'
|
||||||
import FlashMessage, {
|
import FlashMessage, {
|
||||||
@ -17,7 +17,7 @@ const displayMessage = ({
|
|||||||
message,
|
message,
|
||||||
description,
|
description,
|
||||||
onPress,
|
onPress,
|
||||||
mode,
|
theme,
|
||||||
type
|
type
|
||||||
}:
|
}:
|
||||||
| {
|
| {
|
||||||
@ -27,7 +27,7 @@ const displayMessage = ({
|
|||||||
message: string
|
message: string
|
||||||
description?: string
|
description?: string
|
||||||
onPress?: () => void
|
onPress?: () => void
|
||||||
mode?: undefined
|
theme?: undefined
|
||||||
type?: undefined
|
type?: undefined
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
@ -37,7 +37,7 @@ const displayMessage = ({
|
|||||||
message: string
|
message: string
|
||||||
description?: string
|
description?: string
|
||||||
onPress?: () => void
|
onPress?: () => void
|
||||||
mode: 'light' | 'dark'
|
theme: Theme
|
||||||
type: 'success' | 'error' | 'warning'
|
type: 'success' | 'error' | 'warning'
|
||||||
}) => {
|
}) => {
|
||||||
AccessibilityInfo.announceForAccessibility(message + '.' + description)
|
AccessibilityInfo.announceForAccessibility(message + '.' + description)
|
||||||
@ -64,14 +64,14 @@ const displayMessage = ({
|
|||||||
message,
|
message,
|
||||||
description,
|
description,
|
||||||
onPress,
|
onPress,
|
||||||
...(mode &&
|
...(theme &&
|
||||||
type && {
|
type && {
|
||||||
renderFlashMessageIcon: () => {
|
renderFlashMessageIcon: () => {
|
||||||
return (
|
return (
|
||||||
<Icon
|
<Icon
|
||||||
name={iconMapping[type]}
|
name={iconMapping[type]}
|
||||||
size={StyleConstants.Font.LineHeight.M}
|
size={StyleConstants.Font.LineHeight.M}
|
||||||
color={getTheme(mode)[colorMapping[type]]}
|
color={getColors(theme)[colorMapping[type]]}
|
||||||
style={{ marginRight: StyleConstants.Spacing.S }}
|
style={{ marginRight: StyleConstants.Spacing.S }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -85,14 +85,14 @@ const displayMessage = ({
|
|||||||
message,
|
message,
|
||||||
description,
|
description,
|
||||||
onPress,
|
onPress,
|
||||||
...(mode &&
|
...(theme &&
|
||||||
type && {
|
type && {
|
||||||
renderFlashMessageIcon: () => {
|
renderFlashMessageIcon: () => {
|
||||||
return (
|
return (
|
||||||
<Icon
|
<Icon
|
||||||
name={iconMapping[type]}
|
name={iconMapping[type]}
|
||||||
size={StyleConstants.Font.LineHeight.M}
|
size={StyleConstants.Font.LineHeight.M}
|
||||||
color={getTheme(mode)[colorMapping[type]]}
|
color={getColors(theme)[colorMapping[type]]}
|
||||||
style={{ marginRight: StyleConstants.Spacing.S }}
|
style={{ marginRight: StyleConstants.Spacing.S }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -111,7 +111,7 @@ const removeMessage = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Message = React.forwardRef<FlashMessage>((_, ref) => {
|
const Message = React.forwardRef<FlashMessage>((_, ref) => {
|
||||||
const { mode, theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FlashMessage
|
<FlashMessage
|
||||||
@ -120,19 +120,19 @@ const Message = React.forwardRef<FlashMessage>((_, ref) => {
|
|||||||
position='top'
|
position='top'
|
||||||
floating
|
floating
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: theme.backgroundDefault,
|
backgroundColor: colors.backgroundDefault,
|
||||||
shadowColor: theme.primaryDefault,
|
shadowColor: colors.primaryDefault,
|
||||||
shadowOffset: { width: 0, height: 0 },
|
shadowOffset: { width: 0, height: 0 },
|
||||||
shadowOpacity: mode === 'light' ? 0.16 : 0.24,
|
shadowOpacity: theme === 'light' ? 0.16 : 0.24,
|
||||||
shadowRadius: 4
|
shadowRadius: 4
|
||||||
}}
|
}}
|
||||||
titleStyle={{
|
titleStyle={{
|
||||||
color: theme.primaryDefault,
|
color: colors.primaryDefault,
|
||||||
...StyleConstants.FontStyle.M,
|
...StyleConstants.FontStyle.M,
|
||||||
fontWeight: StyleConstants.Font.Weight.Bold
|
fontWeight: StyleConstants.Font.Weight.Bold
|
||||||
}}
|
}}
|
||||||
textStyle={{
|
textStyle={{
|
||||||
color: theme.primaryDefault,
|
color: colors.primaryDefault,
|
||||||
...StyleConstants.FontStyle.S
|
...StyleConstants.FontStyle.S
|
||||||
}}
|
}}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -39,11 +39,11 @@ const ParseEmojis = React.memo(
|
|||||||
adaptiveSize ? adaptiveFontsize : 0
|
adaptiveSize ? adaptiveFontsize : 0
|
||||||
)
|
)
|
||||||
|
|
||||||
const { mode, theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
const styles = useMemo(() => {
|
const styles = useMemo(() => {
|
||||||
return StyleSheet.create({
|
return StyleSheet.create({
|
||||||
text: {
|
text: {
|
||||||
color: theme.primaryDefault,
|
color: colors.primaryDefault,
|
||||||
fontSize: adaptedFontsize,
|
fontSize: adaptedFontsize,
|
||||||
lineHeight: adaptedLineheight,
|
lineHeight: adaptedLineheight,
|
||||||
...(fontBold && { fontWeight: StyleConstants.Font.Weight.Bold })
|
...(fontBold && { fontWeight: StyleConstants.Font.Weight.Bold })
|
||||||
@ -54,7 +54,7 @@ const ParseEmojis = React.memo(
|
|||||||
transform: [{ translateY: -2 }]
|
transform: [{ translateY: -2 }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [mode, adaptiveFontsize])
|
}, [theme, adaptiveFontsize])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text style={styles.text}>
|
<Text style={styles.text}>
|
||||||
|
@ -18,7 +18,7 @@ import { useSelector } from 'react-redux'
|
|||||||
// Prevent going to the same hashtag multiple times
|
// Prevent going to the same hashtag multiple times
|
||||||
const renderNode = ({
|
const renderNode = ({
|
||||||
routeParams,
|
routeParams,
|
||||||
theme,
|
colors,
|
||||||
node,
|
node,
|
||||||
index,
|
index,
|
||||||
adaptedFontsize,
|
adaptedFontsize,
|
||||||
@ -30,7 +30,7 @@ const renderNode = ({
|
|||||||
disableDetails
|
disableDetails
|
||||||
}: {
|
}: {
|
||||||
routeParams?: any
|
routeParams?: any
|
||||||
theme: any
|
colors: any
|
||||||
node: any
|
node: any
|
||||||
index: number
|
index: number
|
||||||
adaptedFontsize: number
|
adaptedFontsize: number
|
||||||
@ -56,7 +56,7 @@ const renderNode = ({
|
|||||||
accessible
|
accessible
|
||||||
key={index}
|
key={index}
|
||||||
style={{
|
style={{
|
||||||
color: theme.blue,
|
color: colors.blue,
|
||||||
fontSize: adaptedFontsize,
|
fontSize: adaptedFontsize,
|
||||||
lineHeight: adaptedLineheight
|
lineHeight: adaptedLineheight
|
||||||
}}
|
}}
|
||||||
@ -84,7 +84,8 @@ const renderNode = ({
|
|||||||
<Text
|
<Text
|
||||||
key={index}
|
key={index}
|
||||||
style={{
|
style={{
|
||||||
color: accountIndex !== -1 ? theme.blue : theme.primaryDefault,
|
color:
|
||||||
|
accountIndex !== -1 ? colors.blue : colors.primaryDefault,
|
||||||
fontSize: adaptedFontsize,
|
fontSize: adaptedFontsize,
|
||||||
lineHeight: adaptedLineheight
|
lineHeight: adaptedLineheight
|
||||||
}}
|
}}
|
||||||
@ -114,7 +115,7 @@ const renderNode = ({
|
|||||||
<Text
|
<Text
|
||||||
key={index}
|
key={index}
|
||||||
style={{
|
style={{
|
||||||
color: theme.blue,
|
color: colors.blue,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
fontSize: adaptedFontsize,
|
fontSize: adaptedFontsize,
|
||||||
lineHeight: adaptedLineheight
|
lineHeight: adaptedLineheight
|
||||||
@ -132,7 +133,7 @@ const renderNode = ({
|
|||||||
(showFullLink ? href : domain[1])}
|
(showFullLink ? href : domain[1])}
|
||||||
{!shouldBeTag ? (
|
{!shouldBeTag ? (
|
||||||
<Icon
|
<Icon
|
||||||
color={theme.blue}
|
color={colors.blue}
|
||||||
name='ExternalLink'
|
name='ExternalLink'
|
||||||
size={adaptedFontsize}
|
size={adaptedFontsize}
|
||||||
style={{
|
style={{
|
||||||
@ -192,11 +193,10 @@ const ParseHTML = React.memo(
|
|||||||
adaptiveSize ? adaptiveFontsize : 0
|
adaptiveSize ? adaptiveFontsize : 0
|
||||||
)
|
)
|
||||||
|
|
||||||
const navigation = useNavigation<
|
const navigation =
|
||||||
StackNavigationProp<Nav.TabLocalStackParamList>
|
useNavigation<StackNavigationProp<Nav.TabLocalStackParamList>>()
|
||||||
>()
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const { mode, theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
const { t, i18n } = useTranslation('componentParse')
|
const { t, i18n } = useTranslation('componentParse')
|
||||||
if (!expandHint) {
|
if (!expandHint) {
|
||||||
expandHint = t('HTML.defaultHint')
|
expandHint = t('HTML.defaultHint')
|
||||||
@ -206,7 +206,7 @@ const ParseHTML = React.memo(
|
|||||||
(node, index) =>
|
(node, index) =>
|
||||||
renderNode({
|
renderNode({
|
||||||
routeParams: route.params,
|
routeParams: route.params,
|
||||||
theme,
|
colors,
|
||||||
node,
|
node,
|
||||||
index,
|
index,
|
||||||
adaptedFontsize,
|
adaptedFontsize,
|
||||||
@ -271,14 +271,14 @@ const ParseHTML = React.memo(
|
|||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
marginTop: expanded ? 0 : -adaptedLineheight,
|
marginTop: expanded ? 0 : -adaptedLineheight,
|
||||||
minHeight: 44,
|
minHeight: 44,
|
||||||
backgroundColor: theme.backgroundDefault
|
backgroundColor: colors.backgroundDefault
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
...StyleConstants.FontStyle.S,
|
...StyleConstants.FontStyle.S,
|
||||||
color: theme.primaryDefault
|
color: colors.primaryDefault
|
||||||
}}
|
}}
|
||||||
children={t(`HTML.expanded.${expanded.toString()}`, {
|
children={t(`HTML.expanded.${expanded.toString()}`, {
|
||||||
hint: expandHint
|
hint: expandHint
|
||||||
@ -289,7 +289,7 @@ const ParseHTML = React.memo(
|
|||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[mode, i18n.language]
|
[theme, i18n.language]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -19,7 +19,7 @@ export interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const RelationshipIncoming: React.FC<Props> = ({ id }) => {
|
const RelationshipIncoming: React.FC<Props> = ({ id }) => {
|
||||||
const { mode } = useTheme()
|
const { theme } = useTheme()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const queryKeyRelationship: QueryKeyRelationship = ['Relationship', { id }]
|
const queryKeyRelationship: QueryKeyRelationship = ['Relationship', { id }]
|
||||||
@ -40,7 +40,7 @@ const RelationshipIncoming: React.FC<Props> = ({ id }) => {
|
|||||||
haptics('Error')
|
haptics('Error')
|
||||||
displayMessage({
|
displayMessage({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
mode,
|
theme,
|
||||||
message: t('common:message.error.message', {
|
message: t('common:message.error.message', {
|
||||||
function: t(`relationship:${type}.function`)
|
function: t(`relationship:${type}.function`)
|
||||||
}),
|
}),
|
||||||
|
@ -19,7 +19,7 @@ export interface Props {
|
|||||||
|
|
||||||
const RelationshipOutgoing = React.memo(
|
const RelationshipOutgoing = React.memo(
|
||||||
({ id }: Props) => {
|
({ id }: Props) => {
|
||||||
const { mode } = useTheme()
|
const { theme } = useTheme()
|
||||||
const { t } = useTranslation('componentRelationship')
|
const { t } = useTranslation('componentRelationship')
|
||||||
|
|
||||||
const query = useRelationshipQuery({ id })
|
const query = useRelationshipQuery({ id })
|
||||||
@ -40,7 +40,7 @@ const RelationshipOutgoing = React.memo(
|
|||||||
},
|
},
|
||||||
onError: (err: any, { payload: { action } }) => {
|
onError: (err: any, { payload: { action } }) => {
|
||||||
displayMessage({
|
displayMessage({
|
||||||
mode,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: t('common:message.error.message', {
|
message: t('common:message.error.message', {
|
||||||
function: t(`${action}.function`)
|
function: t(`${action}.function`)
|
||||||
|
@ -10,13 +10,13 @@ export interface Props {
|
|||||||
|
|
||||||
const ComponentSeparator = React.memo(
|
const ComponentSeparator = React.memo(
|
||||||
({ extraMarginLeft = 0, extraMarginRight = 0 }: Props) => {
|
({ extraMarginLeft = 0, extraMarginRight = 0 }: Props) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: theme.backgroundDefault,
|
backgroundColor: colors.backgroundDefault,
|
||||||
borderTopColor: theme.border,
|
borderTopColor: colors.border,
|
||||||
borderTopWidth: StyleSheet.hairlineWidth,
|
borderTopWidth: StyleSheet.hairlineWidth,
|
||||||
marginLeft:
|
marginLeft:
|
||||||
StyleConstants.Spacing.Global.PagePadding + extraMarginLeft,
|
StyleConstants.Spacing.Global.PagePadding + extraMarginLeft,
|
||||||
|
@ -48,7 +48,7 @@ const Timeline: React.FC<Props> = ({
|
|||||||
lookback,
|
lookback,
|
||||||
customProps
|
customProps
|
||||||
}) => {
|
}) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
@ -118,8 +118,8 @@ const Timeline: React.FC<Props> = ({
|
|||||||
refreshControl: (
|
refreshControl: (
|
||||||
<RefreshControl
|
<RefreshControl
|
||||||
enabled
|
enabled
|
||||||
colors={[theme.primaryDefault]}
|
colors={[colors.primaryDefault]}
|
||||||
progressBackgroundColor={theme.backgroundDefault}
|
progressBackgroundColor={colors.backgroundDefault}
|
||||||
refreshing={isFetching || isLoading}
|
refreshing={isFetching || isLoading}
|
||||||
onRefresh={() => refetch()}
|
onRefresh={() => refetch()}
|
||||||
/>
|
/>
|
||||||
|
@ -32,7 +32,7 @@ const Avatars: React.FC<{ accounts: Mastodon.Account[] }> = ({ accounts }) => {
|
|||||||
{accounts.slice(0, 4).map(account => (
|
{accounts.slice(0, 4).map(account => (
|
||||||
<GracefullyImage
|
<GracefullyImage
|
||||||
key={account.id}
|
key={account.id}
|
||||||
uri={{ original: account.avatar_static }}
|
uri={{ original: account.avatar, static: account.avatar_static }}
|
||||||
dimension={{
|
dimension={{
|
||||||
width: StyleConstants.Avatar.M,
|
width: StyleConstants.Avatar.M,
|
||||||
height:
|
height:
|
||||||
@ -62,7 +62,7 @@ const TimelineConversation: React.FC<Props> = ({
|
|||||||
getInstanceAccount,
|
getInstanceAccount,
|
||||||
(prev, next) => prev?.id === next?.id
|
(prev, next) => prev?.id === next?.id
|
||||||
)
|
)
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const fireMutation = useCallback(() => {
|
const fireMutation = useCallback(() => {
|
||||||
@ -77,9 +77,8 @@ const TimelineConversation: React.FC<Props> = ({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const navigation = useNavigation<
|
const navigation =
|
||||||
StackNavigationProp<Nav.TabLocalStackParamList>
|
useNavigation<StackNavigationProp<Nav.TabLocalStackParamList>>()
|
||||||
>()
|
|
||||||
const onPress = useCallback(() => {
|
const onPress = useCallback(() => {
|
||||||
analytics('timeline_conversation_press')
|
analytics('timeline_conversation_press')
|
||||||
if (conversation.last_status) {
|
if (conversation.last_status) {
|
||||||
@ -95,10 +94,10 @@ const TimelineConversation: React.FC<Props> = ({
|
|||||||
<Pressable
|
<Pressable
|
||||||
style={[
|
style={[
|
||||||
styles.base,
|
styles.base,
|
||||||
{ backgroundColor: theme.backgroundDefault },
|
{ backgroundColor: colors.backgroundDefault },
|
||||||
conversation.unread && {
|
conversation.unread && {
|
||||||
borderLeftWidth: StyleConstants.Spacing.XS,
|
borderLeftWidth: StyleConstants.Spacing.XS,
|
||||||
borderLeftColor: theme.blue,
|
borderLeftColor: colors.blue,
|
||||||
paddingLeft:
|
paddingLeft:
|
||||||
StyleConstants.Spacing.Global.PagePadding -
|
StyleConstants.Spacing.Global.PagePadding -
|
||||||
StyleConstants.Spacing.XS
|
StyleConstants.Spacing.XS
|
||||||
|
@ -42,11 +42,10 @@ const TimelineDefault: React.FC<Props> = ({
|
|||||||
disableDetails = false,
|
disableDetails = false,
|
||||||
disableOnPress = false
|
disableOnPress = false
|
||||||
}) => {
|
}) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const instanceAccount = useSelector(getInstanceAccount, () => true)
|
const instanceAccount = useSelector(getInstanceAccount, () => true)
|
||||||
const navigation = useNavigation<
|
const navigation =
|
||||||
StackNavigationProp<Nav.TabLocalStackParamList>
|
useNavigation<StackNavigationProp<Nav.TabLocalStackParamList>>()
|
||||||
>()
|
|
||||||
|
|
||||||
const actualStatus = item.reblog ? item.reblog : item
|
const actualStatus = item.reblog ? item.reblog : item
|
||||||
|
|
||||||
@ -78,7 +77,7 @@ const TimelineDefault: React.FC<Props> = ({
|
|||||||
style={[
|
style={[
|
||||||
styles.statusView,
|
styles.statusView,
|
||||||
{
|
{
|
||||||
backgroundColor: theme.backgroundDefault,
|
backgroundColor: colors.backgroundDefault,
|
||||||
paddingBottom:
|
paddingBottom:
|
||||||
disableDetails && disableOnPress
|
disableDetails && disableOnPress
|
||||||
? StyleConstants.Spacing.Global.PagePadding
|
? StyleConstants.Spacing.Global.PagePadding
|
||||||
|
@ -20,14 +20,17 @@ const TimelineEmpty = React.memo(
|
|||||||
options: { notifyOnChangeProps: ['status'] }
|
options: { notifyOnChangeProps: ['status'] }
|
||||||
})
|
})
|
||||||
|
|
||||||
const { mode, theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
const { t, i18n } = useTranslation('componentTimeline')
|
const { t, i18n } = useTranslation('componentTimeline')
|
||||||
|
|
||||||
const children = useMemo(() => {
|
const children = useMemo(() => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'loading':
|
case 'loading':
|
||||||
return (
|
return (
|
||||||
<Circle size={StyleConstants.Font.Size.L} color={theme.secondary} />
|
<Circle
|
||||||
|
size={StyleConstants.Font.Size.L}
|
||||||
|
color={colors.secondary}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
case 'error':
|
case 'error':
|
||||||
return (
|
return (
|
||||||
@ -35,9 +38,9 @@ const TimelineEmpty = React.memo(
|
|||||||
<Icon
|
<Icon
|
||||||
name='Frown'
|
name='Frown'
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme.primaryDefault}
|
color={colors.primaryDefault}
|
||||||
/>
|
/>
|
||||||
<Text style={[styles.error, { color: theme.primaryDefault }]}>
|
<Text style={[styles.error, { color: colors.primaryDefault }]}>
|
||||||
{t('empty.error.message')}
|
{t('empty.error.message')}
|
||||||
</Text>
|
</Text>
|
||||||
<Button
|
<Button
|
||||||
@ -56,18 +59,18 @@ const TimelineEmpty = React.memo(
|
|||||||
<Icon
|
<Icon
|
||||||
name='Smartphone'
|
name='Smartphone'
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme.primaryDefault}
|
color={colors.primaryDefault}
|
||||||
/>
|
/>
|
||||||
<Text style={[styles.error, { color: theme.primaryDefault }]}>
|
<Text style={[styles.error, { color: colors.primaryDefault }]}>
|
||||||
{t('empty.success.message')}
|
{t('empty.success.message')}
|
||||||
</Text>
|
</Text>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}, [mode, i18n.language, status])
|
}, [theme, i18n.language, status])
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[styles.base, { backgroundColor: theme.backgroundDefault }]}
|
style={[styles.base, { backgroundColor: colors.backgroundDefault }]}
|
||||||
children={children}
|
children={children}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -24,21 +24,21 @@ const TimelineFooter = React.memo(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.base}>
|
<View style={styles.base}>
|
||||||
{!disableInfinity && hasNextPage ? (
|
{!disableInfinity && hasNextPage ? (
|
||||||
<Circle size={StyleConstants.Font.Size.L} color={theme.secondary} />
|
<Circle size={StyleConstants.Font.Size.L} color={colors.secondary} />
|
||||||
) : (
|
) : (
|
||||||
<Text style={[styles.text, { color: theme.secondary }]}>
|
<Text style={[styles.text, { color: colors.secondary }]}>
|
||||||
<Trans
|
<Trans
|
||||||
i18nKey='componentTimeline:end.message'
|
i18nKey='componentTimeline:end.message'
|
||||||
components={[
|
components={[
|
||||||
<Icon
|
<Icon
|
||||||
name='Coffee'
|
name='Coffee'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
/>
|
/>
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
@ -7,12 +7,14 @@ import { StyleSheet, Text, View } from 'react-native'
|
|||||||
const TimelineLookback = React.memo(
|
const TimelineLookback = React.memo(
|
||||||
() => {
|
() => {
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.base, { backgroundColor: theme.backgroundDefault }]}>
|
<View
|
||||||
|
style={[styles.base, { backgroundColor: colors.backgroundDefault }]}
|
||||||
|
>
|
||||||
<Text
|
<Text
|
||||||
style={[StyleConstants.FontStyle.S, { color: theme.primaryDefault }]}
|
style={[StyleConstants.FontStyle.S, { color: colors.primaryDefault }]}
|
||||||
>
|
>
|
||||||
{t('lookback.message')}
|
{t('lookback.message')}
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -38,14 +38,13 @@ const TimelineNotifications: React.FC<Props> = ({
|
|||||||
return <TimelineFiltered />
|
return <TimelineFiltered />
|
||||||
}
|
}
|
||||||
|
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const instanceAccount = useSelector(
|
const instanceAccount = useSelector(
|
||||||
getInstanceAccount,
|
getInstanceAccount,
|
||||||
(prev, next) => prev?.id === next?.id
|
(prev, next) => prev?.id === next?.id
|
||||||
)
|
)
|
||||||
const navigation = useNavigation<
|
const navigation =
|
||||||
StackNavigationProp<Nav.TabLocalStackParamList>
|
useNavigation<StackNavigationProp<Nav.TabLocalStackParamList>>()
|
||||||
>()
|
|
||||||
|
|
||||||
const actualAccount = notification.status
|
const actualAccount = notification.status
|
||||||
? notification.status.account
|
? notification.status.account
|
||||||
@ -65,7 +64,7 @@ const TimelineNotifications: React.FC<Props> = ({
|
|||||||
style={[
|
style={[
|
||||||
styles.notificationView,
|
styles.notificationView,
|
||||||
{
|
{
|
||||||
backgroundColor: theme.backgroundDefault,
|
backgroundColor: colors.backgroundDefault,
|
||||||
paddingBottom: notification.status
|
paddingBottom: notification.status
|
||||||
? 0
|
? 0
|
||||||
: StyleConstants.Spacing.Global.PagePadding
|
: StyleConstants.Spacing.Global.PagePadding
|
||||||
@ -148,8 +147,10 @@ const TimelineNotifications: React.FC<Props> = ({
|
|||||||
status={notification.status}
|
status={notification.status}
|
||||||
highlighted={highlighted}
|
highlighted={highlighted}
|
||||||
accts={uniqBy(
|
accts={uniqBy(
|
||||||
([notification.status.account] as Mastodon.Account[] &
|
(
|
||||||
Mastodon.Mention[])
|
[notification.status.account] as Mastodon.Account[] &
|
||||||
|
Mastodon.Mention[]
|
||||||
|
)
|
||||||
.concat(notification.status.mentions)
|
.concat(notification.status.mentions)
|
||||||
.filter(d => d?.id !== instanceAccount?.id),
|
.filter(d => d?.id !== instanceAccount?.id),
|
||||||
d => d?.id
|
d => d?.id
|
||||||
|
@ -101,7 +101,7 @@ const TimelineRefresh: React.FC<Props> = ({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const clearFirstPage = () => {
|
const clearFirstPage = () => {
|
||||||
@ -254,13 +254,16 @@ const TimelineRefresh: React.FC<Props> = ({
|
|||||||
<View style={styles.base}>
|
<View style={styles.base}>
|
||||||
{isFetching ? (
|
{isFetching ? (
|
||||||
<View style={styles.container2}>
|
<View style={styles.container2}>
|
||||||
<Circle size={StyleConstants.Font.Size.L} color={theme.secondary} />
|
<Circle
|
||||||
|
size={StyleConstants.Font.Size.L}
|
||||||
|
color={colors.secondary}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<View style={styles.container1}>
|
<View style={styles.container1}>
|
||||||
<Text
|
<Text
|
||||||
style={[styles.explanation, { color: theme.primaryDefault }]}
|
style={[styles.explanation, { color: colors.primaryDefault }]}
|
||||||
onLayout={onLayout}
|
onLayout={onLayout}
|
||||||
children={t('refresh.fetchPreviousPage')}
|
children={t('refresh.fetchPreviousPage')}
|
||||||
/>
|
/>
|
||||||
@ -277,14 +280,14 @@ const TimelineRefresh: React.FC<Props> = ({
|
|||||||
<Icon
|
<Icon
|
||||||
name='ArrowLeft'
|
name='ArrowLeft'
|
||||||
size={StyleConstants.Font.Size.M}
|
size={StyleConstants.Font.Size.M}
|
||||||
color={theme.primaryDefault}
|
color={colors.primaryDefault}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.container2}>
|
<View style={styles.container2}>
|
||||||
<Text
|
<Text
|
||||||
style={[styles.explanation, { color: theme.primaryDefault }]}
|
style={[styles.explanation, { color: colors.primaryDefault }]}
|
||||||
onLayout={onLayout}
|
onLayout={onLayout}
|
||||||
children={t('refresh.refetch')}
|
children={t('refresh.refetch')}
|
||||||
/>
|
/>
|
||||||
|
@ -18,12 +18,11 @@ export interface Props {
|
|||||||
const TimelineActioned = React.memo(
|
const TimelineActioned = React.memo(
|
||||||
({ account, action, notification = false }: Props) => {
|
({ account, action, notification = false }: Props) => {
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const navigation = useNavigation<
|
const navigation =
|
||||||
StackNavigationProp<Nav.TabLocalStackParamList>
|
useNavigation<StackNavigationProp<Nav.TabLocalStackParamList>>()
|
||||||
>()
|
|
||||||
const name = account.display_name || account.username
|
const name = account.display_name || account.username
|
||||||
const iconColor = theme.primaryDefault
|
const iconColor = colors.primaryDefault
|
||||||
|
|
||||||
const content = (content: string) => (
|
const content = (content: string) => (
|
||||||
<ParseEmojis content={content} emojis={account.emojis} size='S' />
|
<ParseEmojis content={content} emojis={account.emojis} size='S' />
|
||||||
|
@ -33,8 +33,8 @@ const TimelineActions: React.FC<Props> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { mode, theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
const iconColor = theme.secondary
|
const iconColor = colors.secondary
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const mutation = useTimelineMutation({
|
const mutation = useTimelineMutation({
|
||||||
@ -83,7 +83,7 @@ const TimelineActions: React.FC<Props> = ({
|
|||||||
onError: (err: any, params, oldData) => {
|
onError: (err: any, params, oldData) => {
|
||||||
const correctParam = params as MutationVarsTimelineUpdateStatusProperty
|
const correctParam = params as MutationVarsTimelineUpdateStatusProperty
|
||||||
displayMessage({
|
displayMessage({
|
||||||
mode,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: t('common:message.error.message', {
|
message: t('common:message.error.message', {
|
||||||
function: t(
|
function: t(
|
||||||
@ -185,7 +185,7 @@ const TimelineActions: React.FC<Props> = ({
|
|||||||
{status.replies_count > 0 ? (
|
{status.replies_count > 0 ? (
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
color: theme.secondary,
|
color: colors.secondary,
|
||||||
fontSize: StyleConstants.Font.Size.M,
|
fontSize: StyleConstants.Font.Size.M,
|
||||||
marginLeft: StyleConstants.Spacing.XS
|
marginLeft: StyleConstants.Spacing.XS
|
||||||
}}
|
}}
|
||||||
@ -198,14 +198,14 @@ const TimelineActions: React.FC<Props> = ({
|
|||||||
[status.replies_count]
|
[status.replies_count]
|
||||||
)
|
)
|
||||||
const childrenReblog = useMemo(() => {
|
const childrenReblog = useMemo(() => {
|
||||||
const color = (state: boolean) => (state ? theme.green : theme.secondary)
|
const color = (state: boolean) => (state ? colors.green : colors.secondary)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Icon
|
<Icon
|
||||||
name='Repeat'
|
name='Repeat'
|
||||||
color={
|
color={
|
||||||
status.visibility === 'private' || status.visibility === 'direct'
|
status.visibility === 'private' || status.visibility === 'direct'
|
||||||
? theme.disabled
|
? colors.disabled
|
||||||
: color(status.reblogged)
|
: color(status.reblogged)
|
||||||
}
|
}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
@ -225,7 +225,7 @@ const TimelineActions: React.FC<Props> = ({
|
|||||||
)
|
)
|
||||||
}, [status.reblogged, status.reblogs_count])
|
}, [status.reblogged, status.reblogs_count])
|
||||||
const childrenFavourite = useMemo(() => {
|
const childrenFavourite = useMemo(() => {
|
||||||
const color = (state: boolean) => (state ? theme.red : theme.secondary)
|
const color = (state: boolean) => (state ? colors.red : colors.secondary)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Icon
|
<Icon
|
||||||
@ -249,7 +249,7 @@ const TimelineActions: React.FC<Props> = ({
|
|||||||
)
|
)
|
||||||
}, [status.favourited, status.favourites_count])
|
}, [status.favourited, status.favourites_count])
|
||||||
const childrenBookmark = useMemo(() => {
|
const childrenBookmark = useMemo(() => {
|
||||||
const color = (state: boolean) => (state ? theme.yellow : theme.secondary)
|
const color = (state: boolean) => (state ? colors.yellow : colors.secondary)
|
||||||
return (
|
return (
|
||||||
<Icon
|
<Icon
|
||||||
name='Bookmark'
|
name='Bookmark'
|
||||||
|
@ -19,10 +19,9 @@ const TimelineActionsUsers = React.memo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const navigation = useNavigation<
|
const navigation =
|
||||||
StackNavigationProp<Nav.TabLocalStackParamList>
|
useNavigation<StackNavigationProp<Nav.TabLocalStackParamList>>()
|
||||||
>()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.base}>
|
<View style={styles.base}>
|
||||||
@ -38,7 +37,7 @@ const TimelineActionsUsers = React.memo(
|
|||||||
'shared.actionsUsers.reblogged_by.accessibilityHint'
|
'shared.actionsUsers.reblogged_by.accessibilityHint'
|
||||||
)}
|
)}
|
||||||
accessibilityRole='button'
|
accessibilityRole='button'
|
||||||
style={[styles.text, { color: theme.blue }]}
|
style={[styles.text, { color: colors.blue }]}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
analytics('timeline_shared_actionsusers_press_boosted', {
|
analytics('timeline_shared_actionsusers_press_boosted', {
|
||||||
count: status.reblogs_count
|
count: status.reblogs_count
|
||||||
@ -68,7 +67,7 @@ const TimelineActionsUsers = React.memo(
|
|||||||
'shared.actionsUsers.favourited_by.accessibilityHint'
|
'shared.actionsUsers.favourited_by.accessibilityHint'
|
||||||
)}
|
)}
|
||||||
accessibilityRole='button'
|
accessibilityRole='button'
|
||||||
style={[styles.text, { color: theme.blue }]}
|
style={[styles.text, { color: colors.blue }]}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
analytics('timeline_shared_actionsusers_press_boosted', {
|
analytics('timeline_shared_actionsusers_press_boosted', {
|
||||||
count: status.favourites_count
|
count: status.favourites_count
|
||||||
|
@ -23,7 +23,7 @@ const AttachmentAudio: React.FC<Props> = ({
|
|||||||
sensitiveShown,
|
sensitiveShown,
|
||||||
audio
|
audio
|
||||||
}) => {
|
}) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const [audioPlayer, setAudioPlayer] = useState<Audio.Sound>()
|
const [audioPlayer, setAudioPlayer] = useState<Audio.Sound>()
|
||||||
const [audioPlaying, setAudioPlaying] = useState(false)
|
const [audioPlaying, setAudioPlaying] = useState(false)
|
||||||
@ -56,7 +56,7 @@ const AttachmentAudio: React.FC<Props> = ({
|
|||||||
style={[
|
style={[
|
||||||
styles.base,
|
styles.base,
|
||||||
{
|
{
|
||||||
backgroundColor: theme.disabled,
|
backgroundColor: colors.disabled,
|
||||||
aspectRatio: attachmentAspectRatio({ total, index })
|
aspectRatio: attachmentAspectRatio({ total, index })
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
@ -102,7 +102,7 @@ const AttachmentAudio: React.FC<Props> = ({
|
|||||||
alignSelf: 'flex-end',
|
alignSelf: 'flex-end',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: StyleConstants.Spacing.M + StyleConstants.Spacing.S * 2,
|
height: StyleConstants.Spacing.M + StyleConstants.Spacing.S * 2,
|
||||||
backgroundColor: theme.backgroundOverlayInvert,
|
backgroundColor: colors.backgroundOverlayInvert,
|
||||||
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding,
|
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding,
|
||||||
borderRadius: 100,
|
borderRadius: 100,
|
||||||
opacity: sensitiveShown ? 0.35 : undefined
|
opacity: sensitiveShown ? 0.35 : undefined
|
||||||
@ -112,8 +112,8 @@ const AttachmentAudio: React.FC<Props> = ({
|
|||||||
minimumValue={0}
|
minimumValue={0}
|
||||||
maximumValue={audio.meta.original.duration * 1000}
|
maximumValue={audio.meta.original.duration * 1000}
|
||||||
value={audioPosition}
|
value={audioPosition}
|
||||||
minimumTrackTintColor={theme.secondary}
|
minimumTrackTintColor={colors.secondary}
|
||||||
maximumTrackTintColor={theme.disabled}
|
maximumTrackTintColor={colors.disabled}
|
||||||
// onSlidingStart={() => {
|
// onSlidingStart={() => {
|
||||||
// audioPlayer?.pauseAsync()
|
// audioPlayer?.pauseAsync()
|
||||||
// setAudioPlaying(false)
|
// setAudioPlaying(false)
|
||||||
@ -123,7 +123,7 @@ const AttachmentAudio: React.FC<Props> = ({
|
|||||||
// }}
|
// }}
|
||||||
enabled={false} // Bug in above sliding actions
|
enabled={false} // Bug in above sliding actions
|
||||||
thumbSize={StyleConstants.Spacing.M}
|
thumbSize={StyleConstants.Spacing.M}
|
||||||
thumbTintColor={theme.primaryOverlay}
|
thumbTintColor={colors.primaryOverlay}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -28,7 +28,16 @@ const AttachmentImage = React.memo(
|
|||||||
uri={{ original: image.preview_url, remote: image.remote_url }}
|
uri={{ original: image.preview_url, remote: image.remote_url }}
|
||||||
blurhash={image.blurhash}
|
blurhash={image.blurhash}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
style={[{ aspectRatio: attachmentAspectRatio({ total, index }) }]}
|
style={{
|
||||||
|
aspectRatio:
|
||||||
|
total > 1 ||
|
||||||
|
!image.meta?.original?.width ||
|
||||||
|
!image.meta?.original?.height
|
||||||
|
? attachmentAspectRatio({ total, index })
|
||||||
|
: image.meta.original.height / image.meta.original.width > 2
|
||||||
|
? 0.5
|
||||||
|
: image.meta.original.width / image.meta.original.height
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
@ -23,7 +23,7 @@ const AttachmentUnsupported: React.FC<Props> = ({
|
|||||||
attachment
|
attachment
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
@ -49,8 +49,8 @@ const AttachmentUnsupported: React.FC<Props> = ({
|
|||||||
styles.text,
|
styles.text,
|
||||||
{
|
{
|
||||||
color: attachment.blurhash
|
color: attachment.blurhash
|
||||||
? theme.backgroundDefault
|
? colors.backgroundDefault
|
||||||
: theme.primaryDefault
|
: colors.primaryDefault
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
|
@ -16,9 +16,8 @@ export interface Props {
|
|||||||
const TimelineAvatar = React.memo(
|
const TimelineAvatar = React.memo(
|
||||||
({ queryKey, account, highlighted }: Props) => {
|
({ queryKey, account, highlighted }: Props) => {
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const navigation = useNavigation<
|
const navigation =
|
||||||
StackNavigationProp<Nav.TabLocalStackParamList>
|
useNavigation<StackNavigationProp<Nav.TabLocalStackParamList>>()
|
||||||
>()
|
|
||||||
// Need to fix go back root
|
// Need to fix go back root
|
||||||
const onPress = useCallback(() => {
|
const onPress = useCallback(() => {
|
||||||
analytics('timeline_shared_avatar_press', {
|
analytics('timeline_shared_avatar_press', {
|
||||||
@ -38,7 +37,7 @@ const TimelineAvatar = React.memo(
|
|||||||
})
|
})
|
||||||
})}
|
})}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
uri={{ original: account.avatar_static }}
|
uri={{ original: account.avatar, static: account.avatar_static }}
|
||||||
dimension={{
|
dimension={{
|
||||||
width: StyleConstants.Avatar.M,
|
width: StyleConstants.Avatar.M,
|
||||||
height: StyleConstants.Avatar.M
|
height: StyleConstants.Avatar.M
|
||||||
|
@ -13,14 +13,14 @@ export interface Props {
|
|||||||
|
|
||||||
const TimelineCard = React.memo(
|
const TimelineCard = React.memo(
|
||||||
({ card }: Props) => {
|
({ card }: Props) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
accessible
|
accessible
|
||||||
accessibilityRole='link'
|
accessibilityRole='link'
|
||||||
style={[styles.card, { borderColor: theme.border }]}
|
style={[styles.card, { borderColor: colors.border }]}
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
analytics('timeline_shared_card_press')
|
analytics('timeline_shared_card_press')
|
||||||
await openLink(card.url, navigation)
|
await openLink(card.url, navigation)
|
||||||
@ -38,7 +38,7 @@ const TimelineCard = React.memo(
|
|||||||
<View style={styles.right}>
|
<View style={styles.right}>
|
||||||
<Text
|
<Text
|
||||||
numberOfLines={2}
|
numberOfLines={2}
|
||||||
style={[styles.rightTitle, { color: theme.primaryDefault }]}
|
style={[styles.rightTitle, { color: colors.primaryDefault }]}
|
||||||
testID='title'
|
testID='title'
|
||||||
>
|
>
|
||||||
{card.title}
|
{card.title}
|
||||||
@ -46,7 +46,10 @@ const TimelineCard = React.memo(
|
|||||||
{card.description ? (
|
{card.description ? (
|
||||||
<Text
|
<Text
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={[styles.rightDescription, { color: theme.primaryDefault }]}
|
style={[
|
||||||
|
styles.rightDescription,
|
||||||
|
{ color: colors.primaryDefault }
|
||||||
|
]}
|
||||||
testID='description'
|
testID='description'
|
||||||
>
|
>
|
||||||
{card.description}
|
{card.description}
|
||||||
@ -54,7 +57,7 @@ const TimelineCard = React.memo(
|
|||||||
) : null}
|
) : null}
|
||||||
<Text
|
<Text
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={[styles.rightLink, { color: theme.secondary }]}
|
style={[styles.rightLink, { color: colors.secondary }]}
|
||||||
>
|
>
|
||||||
{card.url}
|
{card.url}
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -10,15 +10,15 @@ import { Text, View } from 'react-native'
|
|||||||
|
|
||||||
const TimelineFiltered = React.memo(
|
const TimelineFiltered = React.memo(
|
||||||
() => {
|
() => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ backgroundColor: theme.backgroundDefault }}>
|
<View style={{ backgroundColor: colors.backgroundDefault }}>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
...StyleConstants.FontStyle.S,
|
...StyleConstants.FontStyle.S,
|
||||||
color: theme.secondary,
|
color: colors.secondary,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
paddingVertical: StyleConstants.Spacing.S,
|
paddingVertical: StyleConstants.Spacing.S,
|
||||||
paddingLeft: StyleConstants.Avatar.M + StyleConstants.Spacing.S
|
paddingLeft: StyleConstants.Avatar.M + StyleConstants.Spacing.S
|
||||||
@ -46,7 +46,7 @@ export const shouldFilter = ({
|
|||||||
let shouldFilter = false
|
let shouldFilter = false
|
||||||
if (!ownAccount) {
|
if (!ownAccount) {
|
||||||
const parser = new htmlparser2.Parser({
|
const parser = new htmlparser2.Parser({
|
||||||
ontext (text: string) {
|
ontext: (text: string) => {
|
||||||
const checkFilter = (filter: Mastodon.Filter) => {
|
const checkFilter = (filter: Mastodon.Filter) => {
|
||||||
const escapedPhrase = filter.phrase.replace(
|
const escapedPhrase = filter.phrase.replace(
|
||||||
/[.*+?^${}()|[\]\\]/g,
|
/[.*+?^${}()|[\]\\]/g,
|
||||||
@ -54,7 +54,7 @@ export const shouldFilter = ({
|
|||||||
) // $& means the whole matched string
|
) // $& means the whole matched string
|
||||||
switch (filter.whole_word) {
|
switch (filter.whole_word) {
|
||||||
case true:
|
case true:
|
||||||
if (new RegExp('\\b' + escapedPhrase + '\\b').test(text)) {
|
if (new RegExp('\\B' + escapedPhrase + '\\B').test(text)) {
|
||||||
shouldFilter = true
|
shouldFilter = true
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
@ -13,7 +13,7 @@ export interface Props {
|
|||||||
const TimelineFullConversation = React.memo(
|
const TimelineFullConversation = React.memo(
|
||||||
({ queryKey, status }: Props) => {
|
({ queryKey, status }: Props) => {
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return queryKey &&
|
return queryKey &&
|
||||||
queryKey[1].page !== 'Toot' &&
|
queryKey[1].page !== 'Toot' &&
|
||||||
@ -25,7 +25,7 @@ const TimelineFullConversation = React.memo(
|
|||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
...StyleConstants.FontStyle.S,
|
...StyleConstants.FontStyle.S,
|
||||||
color: theme.blue,
|
color: colors.blue,
|
||||||
marginTop: StyleConstants.Spacing.S
|
marginTop: StyleConstants.Spacing.S
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -18,12 +18,12 @@ import HeaderSharedMuted from './HeaderShared/Muted'
|
|||||||
const Names = React.memo(
|
const Names = React.memo(
|
||||||
({ accounts }: { accounts: Mastodon.Account[] }) => {
|
({ accounts }: { accounts: Mastodon.Account[] }) => {
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
style={[styles.namesLeading, { color: theme.secondary }]}
|
style={[styles.namesLeading, { color: colors.secondary }]}
|
||||||
>
|
>
|
||||||
<Text>{t('shared.header.conversation.withAccounts')}</Text>
|
<Text>{t('shared.header.conversation.withAccounts')}</Text>
|
||||||
{accounts.map((account, index) => (
|
{accounts.map((account, index) => (
|
||||||
@ -49,7 +49,7 @@ export interface Props {
|
|||||||
|
|
||||||
const HeaderConversation = React.memo(
|
const HeaderConversation = React.memo(
|
||||||
({ queryKey, conversation }: Props) => {
|
({ queryKey, conversation }: Props) => {
|
||||||
const { mode } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
@ -57,7 +57,7 @@ const HeaderConversation = React.memo(
|
|||||||
onMutate: true,
|
onMutate: true,
|
||||||
onError: (err: any, _, oldData) => {
|
onError: (err: any, _, oldData) => {
|
||||||
displayMessage({
|
displayMessage({
|
||||||
mode,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: t('common:message.error.message', {
|
message: t('common:message.error.message', {
|
||||||
function: t(`shared.header.conversation.delete.function`)
|
function: t(`shared.header.conversation.delete.function`)
|
||||||
@ -74,8 +74,6 @@ const HeaderConversation = React.memo(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { theme } = useTheme()
|
|
||||||
|
|
||||||
const actionOnPress = useCallback(() => {
|
const actionOnPress = useCallback(() => {
|
||||||
analytics('timeline_conversation_delete_press')
|
analytics('timeline_conversation_delete_press')
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
@ -90,7 +88,7 @@ const HeaderConversation = React.memo(
|
|||||||
() => (
|
() => (
|
||||||
<Icon
|
<Icon
|
||||||
name='Trash'
|
name='Trash'
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
@ -22,7 +22,7 @@ const TimelineHeaderDefault = React.memo(
|
|||||||
({ queryKey, rootQueryKey, status }: Props) => {
|
({ queryKey, rootQueryKey, status }: Props) => {
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.base}>
|
<View style={styles.base}>
|
||||||
@ -52,7 +52,7 @@ const TimelineHeaderDefault = React.memo(
|
|||||||
children={
|
children={
|
||||||
<Icon
|
<Icon
|
||||||
name='MoreHorizontal'
|
name='MoreHorizontal'
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ export interface Props {
|
|||||||
const TimelineHeaderNotification = React.memo(
|
const TimelineHeaderNotification = React.memo(
|
||||||
({ queryKey, notification }: Props) => {
|
({ queryKey, notification }: Props) => {
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const actions = useMemo(() => {
|
const actions = useMemo(() => {
|
||||||
switch (notification.type) {
|
switch (notification.type) {
|
||||||
@ -52,7 +52,7 @@ const TimelineHeaderNotification = React.memo(
|
|||||||
children={
|
children={
|
||||||
<Icon
|
<Icon
|
||||||
name='MoreHorizontal'
|
name='MoreHorizontal'
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ export interface Props {
|
|||||||
const HeaderSharedAccount = React.memo(
|
const HeaderSharedAccount = React.memo(
|
||||||
({ account, withoutName = false }: Props) => {
|
({ account, withoutName = false }: Props) => {
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.base}>
|
<View style={styles.base}>
|
||||||
@ -36,7 +36,7 @@ const HeaderSharedAccount = React.memo(
|
|||||||
accessibilityHint={t(
|
accessibilityHint={t(
|
||||||
'shared.header.shared.account.account.accessibilityHint'
|
'shared.header.shared.account.account.accessibilityHint'
|
||||||
)}
|
)}
|
||||||
style={[styles.acct, { color: theme.secondary }]}
|
style={[styles.acct, { color: colors.secondary }]}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
>
|
>
|
||||||
@{account.acct}
|
@{account.acct}
|
||||||
|
@ -12,7 +12,7 @@ export interface Props {
|
|||||||
|
|
||||||
const HeaderSharedApplication = React.memo(
|
const HeaderSharedApplication = React.memo(
|
||||||
({ application }: Props) => {
|
({ application }: Props) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
|
|
||||||
return application && application.name !== 'Web' ? (
|
return application && application.name !== 'Web' ? (
|
||||||
@ -24,7 +24,7 @@ const HeaderSharedApplication = React.memo(
|
|||||||
})
|
})
|
||||||
application.website && (await openLink(application.website))
|
application.website && (await openLink(application.website))
|
||||||
}}
|
}}
|
||||||
style={[styles.application, { color: theme.secondary }]}
|
style={[styles.application, { color: colors.secondary }]}
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
>
|
>
|
||||||
{t('shared.header.shared.application', {
|
{t('shared.header.shared.application', {
|
||||||
|
@ -10,10 +10,10 @@ export interface Props {
|
|||||||
|
|
||||||
const HeaderSharedCreated = React.memo(
|
const HeaderSharedCreated = React.memo(
|
||||||
({ created_at }: Props) => {
|
({ created_at }: Props) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text style={[styles.created_at, { color: theme.secondary }]}>
|
<Text style={[styles.created_at, { color: colors.secondary }]}>
|
||||||
<RelativeTime date={created_at} />
|
<RelativeTime date={created_at} />
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
|
@ -12,14 +12,14 @@ export interface Props {
|
|||||||
const HeaderSharedMuted = React.memo(
|
const HeaderSharedMuted = React.memo(
|
||||||
({ muted }: Props) => {
|
({ muted }: Props) => {
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return muted ? (
|
return muted ? (
|
||||||
<Icon
|
<Icon
|
||||||
accessibilityLabel={t('shared.header.shared.muted.accessibilityLabel')}
|
accessibilityLabel={t('shared.header.shared.muted.accessibilityLabel')}
|
||||||
name='VolumeX'
|
name='VolumeX'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
style={styles.visibility}
|
style={styles.visibility}
|
||||||
/>
|
/>
|
||||||
) : null
|
) : null
|
||||||
|
@ -12,7 +12,7 @@ export interface Props {
|
|||||||
const HeaderSharedVisibility = React.memo(
|
const HeaderSharedVisibility = React.memo(
|
||||||
({ visibility }: Props) => {
|
({ visibility }: Props) => {
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
switch (visibility) {
|
switch (visibility) {
|
||||||
case 'private':
|
case 'private':
|
||||||
@ -23,7 +23,7 @@ const HeaderSharedVisibility = React.memo(
|
|||||||
)}
|
)}
|
||||||
name='Lock'
|
name='Lock'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
style={styles.visibility}
|
style={styles.visibility}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -35,7 +35,7 @@ const HeaderSharedVisibility = React.memo(
|
|||||||
)}
|
)}
|
||||||
name='Mail'
|
name='Mail'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
style={styles.visibility}
|
style={styles.visibility}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -36,7 +36,7 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
reblog,
|
reblog,
|
||||||
sameAccount
|
sameAccount
|
||||||
}) => {
|
}) => {
|
||||||
const { mode, theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
const { t, i18n } = useTranslation('componentTimeline')
|
const { t, i18n } = useTranslation('componentTimeline')
|
||||||
|
|
||||||
const [allOptions, setAllOptions] = useState(
|
const [allOptions, setAllOptions] = useState(
|
||||||
@ -53,7 +53,7 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
haptics('Success')
|
haptics('Success')
|
||||||
switch (theParams.payload.property) {
|
switch (theParams.payload.property) {
|
||||||
case 'poll':
|
case 'poll':
|
||||||
theParams.payload.data = (body as unknown) as Mastodon.Poll
|
theParams.payload.data = body as unknown as Mastodon.Poll
|
||||||
updateStatusProperty(theParams)
|
updateStatusProperty(theParams)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
onError: (err: any, params) => {
|
onError: (err: any, params) => {
|
||||||
const theParams = params as MutationVarsTimelineUpdateStatusProperty
|
const theParams = params as MutationVarsTimelineUpdateStatusProperty
|
||||||
displayMessage({
|
displayMessage({
|
||||||
mode,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: t('common:message.error.message', {
|
message: t('common:message.error.message', {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -136,7 +136,7 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
mode,
|
theme,
|
||||||
i18n.language,
|
i18n.language,
|
||||||
poll.expired,
|
poll.expired,
|
||||||
poll.voted,
|
poll.voted,
|
||||||
@ -147,14 +147,14 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
const pollExpiration = useMemo(() => {
|
const pollExpiration = useMemo(() => {
|
||||||
if (poll.expired) {
|
if (poll.expired) {
|
||||||
return (
|
return (
|
||||||
<Text style={[styles.expiration, { color: theme.secondary }]}>
|
<Text style={[styles.expiration, { color: colors.secondary }]}>
|
||||||
{t('shared.poll.meta.expiration.expired')}
|
{t('shared.poll.meta.expiration.expired')}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
if (poll.expires_at) {
|
if (poll.expires_at) {
|
||||||
return (
|
return (
|
||||||
<Text style={[styles.expiration, { color: theme.secondary }]}>
|
<Text style={[styles.expiration, { color: colors.secondary }]}>
|
||||||
<Trans
|
<Trans
|
||||||
i18nKey='componentTimeline:shared.poll.meta.expiration.until'
|
i18nKey='componentTimeline:shared.poll.meta.expiration.until'
|
||||||
components={[<RelativeTime date={poll.expires_at} />]}
|
components={[<RelativeTime date={poll.expires_at} />]}
|
||||||
@ -163,7 +163,7 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [mode, i18n.language, poll.expired, poll.expires_at])
|
}, [theme, i18n.language, poll.expired, poll.expires_at])
|
||||||
|
|
||||||
const isSelected = useCallback(
|
const isSelected = useCallback(
|
||||||
(index: number): string =>
|
(index: number): string =>
|
||||||
@ -174,8 +174,10 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const pollBodyDisallow = useMemo(() => {
|
const pollBodyDisallow = useMemo(() => {
|
||||||
const maxValue = maxBy(poll.options, option => option.votes_count)
|
const maxValue = maxBy(
|
||||||
?.votes_count
|
poll.options,
|
||||||
|
option => option.votes_count
|
||||||
|
)?.votes_count
|
||||||
return poll.options.map((option, index) => (
|
return poll.options.map((option, index) => (
|
||||||
<View key={index} style={styles.optionContainer}>
|
<View key={index} style={styles.optionContainer}>
|
||||||
<View style={styles.optionContent}>
|
<View style={styles.optionContent}>
|
||||||
@ -188,14 +190,14 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
}
|
}
|
||||||
size={StyleConstants.Font.Size.M}
|
size={StyleConstants.Font.Size.M}
|
||||||
color={
|
color={
|
||||||
poll.own_votes?.includes(index) ? theme.blue : theme.disabled
|
poll.own_votes?.includes(index) ? colors.blue : colors.disabled
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Text style={styles.optionText}>
|
<Text style={styles.optionText}>
|
||||||
<ParseEmojis content={option.title} emojis={poll.emojis} />
|
<ParseEmojis content={option.title} emojis={poll.emojis} />
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
style={[styles.optionPercentage, { color: theme.primaryDefault }]}
|
style={[styles.optionPercentage, { color: colors.primaryDefault }]}
|
||||||
>
|
>
|
||||||
{poll.votes_count
|
{poll.votes_count
|
||||||
? Math.round(
|
? Math.round(
|
||||||
@ -217,13 +219,13 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
100
|
100
|
||||||
)}%`,
|
)}%`,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
option.votes_count === maxValue ? theme.blue : theme.disabled
|
option.votes_count === maxValue ? colors.blue : colors.disabled
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
))
|
))
|
||||||
}, [mode, poll.options])
|
}, [theme, poll.options])
|
||||||
const pollBodyAllow = useMemo(() => {
|
const pollBodyAllow = useMemo(() => {
|
||||||
return poll.options.map((option, index) => (
|
return poll.options.map((option, index) => (
|
||||||
<Pressable
|
<Pressable
|
||||||
@ -256,7 +258,7 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
style={styles.optionSelection}
|
style={styles.optionSelection}
|
||||||
name={isSelected(index)}
|
name={isSelected(index)}
|
||||||
size={StyleConstants.Font.Size.M}
|
size={StyleConstants.Font.Size.M}
|
||||||
color={theme.primaryDefault}
|
color={colors.primaryDefault}
|
||||||
/>
|
/>
|
||||||
<Text style={styles.optionText}>
|
<Text style={styles.optionText}>
|
||||||
<ParseEmojis content={option.title} emojis={poll.emojis} />
|
<ParseEmojis content={option.title} emojis={poll.emojis} />
|
||||||
@ -264,19 +266,19 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
</View>
|
</View>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
))
|
))
|
||||||
}, [mode, allOptions])
|
}, [theme, allOptions])
|
||||||
|
|
||||||
const pollVoteCounts = useMemo(() => {
|
const pollVoteCounts = useMemo(() => {
|
||||||
if (poll.voters_count !== null) {
|
if (poll.voters_count !== null) {
|
||||||
return (
|
return (
|
||||||
<Text style={[styles.votes, { color: theme.secondary }]}>
|
<Text style={[styles.votes, { color: colors.secondary }]}>
|
||||||
{t('shared.poll.meta.count.voters', { count: poll.voters_count })}
|
{t('shared.poll.meta.count.voters', { count: poll.voters_count })}
|
||||||
{' • '}
|
{' • '}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
} else if (poll.votes_count !== null) {
|
} else if (poll.votes_count !== null) {
|
||||||
return (
|
return (
|
||||||
<Text style={[styles.votes, { color: theme.secondary }]}>
|
<Text style={[styles.votes, { color: colors.secondary }]}>
|
||||||
{t('shared.poll.meta.count.votes', { count: poll.votes_count })}
|
{t('shared.poll.meta.count.votes', { count: poll.votes_count })}
|
||||||
{' • '}
|
{' • '}
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -26,7 +26,7 @@ const TimelineTranslate = React.memo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const tootLanguage = status.language.slice(0, 2)
|
const tootLanguage = status.language.slice(0, 2)
|
||||||
|
|
||||||
@ -82,10 +82,10 @@ const TimelineTranslate = React.memo(
|
|||||||
...StyleConstants.FontStyle.M,
|
...StyleConstants.FontStyle.M,
|
||||||
color:
|
color:
|
||||||
isLoading || isSuccess
|
isLoading || isSuccess
|
||||||
? theme.secondary
|
? colors.secondary
|
||||||
: isError
|
: isError
|
||||||
? theme.red
|
? colors.red
|
||||||
: theme.blue
|
: colors.blue
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isError
|
{isError
|
||||||
@ -109,7 +109,7 @@ const TimelineTranslate = React.memo(
|
|||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Circle
|
<Circle
|
||||||
size={StyleConstants.Font.Size.M}
|
size={StyleConstants.Font.Size.M}
|
||||||
color={theme.disabled}
|
color={colors.disabled}
|
||||||
style={{ marginLeft: StyleConstants.Spacing.S }}
|
style={{ marginLeft: StyleConstants.Spacing.S }}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -8,6 +8,7 @@ export default {
|
|||||||
screenImageViewer: require('./screens/imageViewer'),
|
screenImageViewer: require('./screens/imageViewer'),
|
||||||
screenTabs: require('./screens/tabs'),
|
screenTabs: require('./screens/tabs'),
|
||||||
|
|
||||||
|
componentEmojis: require('./components/emojis'),
|
||||||
componentInstance: require('./components/instance'),
|
componentInstance: require('./components/instance'),
|
||||||
componentMediaSelector: require('./components/mediaSelector'),
|
componentMediaSelector: require('./components/mediaSelector'),
|
||||||
componentParse: require('./components/parse'),
|
componentParse: require('./components/parse'),
|
||||||
|
3
src/i18n/en/components/emojis.json
Normal file
3
src/i18n/en/components/emojis.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"frequentUsed": "Frequent used"
|
||||||
|
}
|
@ -232,6 +232,14 @@
|
|||||||
"cancel": "$t(common:buttons.cancel)"
|
"cancel": "$t(common:buttons.cancel)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"darkTheme": {
|
||||||
|
"heading": "Dark theme",
|
||||||
|
"options": {
|
||||||
|
"lighter": "Lighter",
|
||||||
|
"darker": "Darker",
|
||||||
|
"cancel": "$t(common:buttons.cancel)"
|
||||||
|
}
|
||||||
|
},
|
||||||
"browser": {
|
"browser": {
|
||||||
"heading": "Opening Link",
|
"heading": "Opening Link",
|
||||||
"options": {
|
"options": {
|
||||||
@ -240,6 +248,9 @@
|
|||||||
"cancel": "$t(common:buttons.cancel)"
|
"cancel": "$t(common:buttons.cancel)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"feedback": {
|
||||||
|
"heading": "Feature Requests"
|
||||||
|
},
|
||||||
"support": {
|
"support": {
|
||||||
"heading": "Support tooot"
|
"heading": "Support tooot"
|
||||||
},
|
},
|
||||||
|
@ -8,6 +8,7 @@ export default {
|
|||||||
screenImageViewer: require('./screens/imageViewer'),
|
screenImageViewer: require('./screens/imageViewer'),
|
||||||
screenTabs: require('./screens/tabs'),
|
screenTabs: require('./screens/tabs'),
|
||||||
|
|
||||||
|
componentEmojis: require('./components/emojis'),
|
||||||
componentInstance: require('./components/instance'),
|
componentInstance: require('./components/instance'),
|
||||||
componentMediaSelector: require('./components/mediaSelector'),
|
componentMediaSelector: require('./components/mediaSelector'),
|
||||||
componentParse: require('./components/parse'),
|
componentParse: require('./components/parse'),
|
||||||
|
1
src/i18n/ko/components/emojis.json
Normal file
1
src/i18n/ko/components/emojis.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
@ -8,6 +8,7 @@ export default {
|
|||||||
screenImageViewer: require('./screens/imageViewer'),
|
screenImageViewer: require('./screens/imageViewer'),
|
||||||
screenTabs: require('./screens/tabs'),
|
screenTabs: require('./screens/tabs'),
|
||||||
|
|
||||||
|
componentEmojis: require('./components/emojis'),
|
||||||
componentInstance: require('./components/instance'),
|
componentInstance: require('./components/instance'),
|
||||||
componentMediaSelector: require('./components/mediaSelector'),
|
componentMediaSelector: require('./components/mediaSelector'),
|
||||||
componentParse: require('./components/parse'),
|
componentParse: require('./components/parse'),
|
||||||
|
1
src/i18n/vi/components/emojis.json
Normal file
1
src/i18n/vi/components/emojis.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"HTML": {
|
"HTML": {
|
||||||
"expanded": {
|
"expanded": {
|
||||||
"true": "Thu gọn {{hint}}",
|
"true": "Cuộn {{hint}}",
|
||||||
"false": "Mở rộng {{hint}}"
|
"false": "Mở {{hint}}"
|
||||||
},
|
},
|
||||||
"defaultHint": "Tút"
|
"defaultHint": "Tút"
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"strings": {
|
"strings": {
|
||||||
"prefixAgo": "",
|
"prefixAgo": "",
|
||||||
"prefixFromNow": "",
|
"prefixFromNow": "",
|
||||||
"suffixAgo": "trước",
|
"suffixAgo": " trước",
|
||||||
"suffixFromNow": "",
|
"suffixFromNow": "",
|
||||||
"seconds": "%d giây",
|
"seconds": "%d giây",
|
||||||
"minute": "một phút",
|
"minute": "một phút",
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
"follow_request": "{{name}} yêu cầu theo dõi bạn",
|
"follow_request": "{{name}} yêu cầu theo dõi bạn",
|
||||||
"poll": "Cuộc bình chọn đã kết thúc",
|
"poll": "Cuộc bình chọn đã kết thúc",
|
||||||
"reblog": {
|
"reblog": {
|
||||||
"default": "{{name}} đã chia sẻ",
|
"default": "{{name}} chia sẻ",
|
||||||
"notification": "{{name}} chia sẻ tút của bạn"
|
"notification": "{{name}} chia sẻ tút của bạn"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -62,7 +62,7 @@
|
|||||||
},
|
},
|
||||||
"attachment": {
|
"attachment": {
|
||||||
"sensitive": {
|
"sensitive": {
|
||||||
"button": "Hiện nội dung nhạy cảm"
|
"button": "NSFW"
|
||||||
},
|
},
|
||||||
"unsupported": {
|
"unsupported": {
|
||||||
"text": "Không hỗ trợ định dạng",
|
"text": "Không hỗ trợ định dạng",
|
||||||
@ -74,14 +74,16 @@
|
|||||||
"accessibilityHint": "Đến trang cá nhân {{name}}"
|
"accessibilityHint": "Đến trang cá nhân {{name}}"
|
||||||
},
|
},
|
||||||
"content": {
|
"content": {
|
||||||
"expandHint": "nội dung bị ẩn"
|
"expandHint": "nội dung ẩn"
|
||||||
},
|
},
|
||||||
"filtered": "Đã lọc",
|
"filtered": "Đã lọc",
|
||||||
"fullConversation": "Xem thêm",
|
"fullConversation": "Xem thêm",
|
||||||
"translate": {
|
"translate": {
|
||||||
"default": "Dịch",
|
"default": "Dịch",
|
||||||
"succeed": "Dịch bằng {{provider}} từ {{source}}",
|
"succeed": "Dịch bằng {{provider}} từ {{source}}",
|
||||||
"failed": "Không thể dịch!"
|
"failed": "Không thể dịch!",
|
||||||
|
"source_not_supported": "không hỗ trợ ngôn ngữ tút",
|
||||||
|
"target_not_supported": "Ngôn ngữ đích không hỗ trợ"
|
||||||
},
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"shared": {
|
"shared": {
|
||||||
@ -93,7 +95,7 @@
|
|||||||
"accessibilityHint": "Tài khoản"
|
"accessibilityHint": "Tài khoản"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"application": "Đăng bằng {{application}}",
|
"application": "via {{application}}",
|
||||||
"muted": {
|
"muted": {
|
||||||
"accessibilityLabel": "Đã ẩn tút"
|
"accessibilityLabel": "Đã ẩn tút"
|
||||||
},
|
},
|
||||||
@ -107,7 +109,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"conversation": {
|
"conversation": {
|
||||||
"withAccounts": "Với",
|
"withAccounts": "Với ",
|
||||||
"delete": {
|
"delete": {
|
||||||
"function": "Xóa nhắn riêng"
|
"function": "Xóa nhắn riêng"
|
||||||
}
|
}
|
||||||
@ -146,16 +148,16 @@
|
|||||||
},
|
},
|
||||||
"share": {
|
"share": {
|
||||||
"status": {
|
"status": {
|
||||||
"heading": "Tút",
|
"heading": "Chia sẻ",
|
||||||
"button": "Chia sẻ URL tút"
|
"button": "Chia sẻ URL tút"
|
||||||
},
|
},
|
||||||
"account": {
|
"account": {
|
||||||
"heading": "Chia sẻ người dùng",
|
"heading": "Chia sẻ",
|
||||||
"button": "Chia sẻ URL người dùng này"
|
"button": "Chia sẻ URL người dùng này"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"heading": "Về tút",
|
"heading": "Đối với tút",
|
||||||
"delete": {
|
"delete": {
|
||||||
"function": "Xóa tút",
|
"function": "Xóa tút",
|
||||||
"button": "Xóa tút này"
|
"button": "Xóa tút này"
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"cancel": "$t(common:buttons.cancel)"
|
"cancel": "$t(common:buttons.cancel)"
|
||||||
},
|
},
|
||||||
"notificationsFilter": {
|
"notificationsFilter": {
|
||||||
"heading": "Hiện những dạng thông báo",
|
"heading": "Những kiểu thông báo cho phép",
|
||||||
"content": {
|
"content": {
|
||||||
"follow": "$t(screenTabs:me.push.follow.heading)",
|
"follow": "$t(screenTabs:me.push.follow.heading)",
|
||||||
"favourite": "$t(screenTabs:me.push.favourite.heading)",
|
"favourite": "$t(screenTabs:me.push.favourite.heading)",
|
||||||
|
@ -13,10 +13,10 @@
|
|||||||
},
|
},
|
||||||
"right": {
|
"right": {
|
||||||
"button": {
|
"button": {
|
||||||
"default": "Tút",
|
"default": "Đăng",
|
||||||
"conversation": "Tin nhắn",
|
"conversation": "Tin nhắn",
|
||||||
"reply": "Lượt trả lời",
|
"reply": "Trả lời",
|
||||||
"edit": "Tút"
|
"edit": "Sửa"
|
||||||
},
|
},
|
||||||
"alert": {
|
"alert": {
|
||||||
"default": {
|
"default": {
|
||||||
@ -63,7 +63,7 @@
|
|||||||
"option": {
|
"option": {
|
||||||
"placeholder": {
|
"placeholder": {
|
||||||
"accessibilityLabel": "Tùy chọn bình chọn {{index}}",
|
"accessibilityLabel": "Tùy chọn bình chọn {{index}}",
|
||||||
"single": "Chỉ được chọn một",
|
"single": "Lựa chọn",
|
||||||
"multiple": "Nhiều lựa chọn"
|
"multiple": "Nhiều lựa chọn"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -117,7 +117,7 @@
|
|||||||
},
|
},
|
||||||
"visibility": {
|
"visibility": {
|
||||||
"accessibilityLabel": "Tút thuộc dạng {{visibility}}",
|
"accessibilityLabel": "Tút thuộc dạng {{visibility}}",
|
||||||
"title": "Dạng tút",
|
"title": "Kiểu tút",
|
||||||
"options": {
|
"options": {
|
||||||
"public": "Công khai",
|
"public": "Công khai",
|
||||||
"unlisted": "Hạn chế",
|
"unlisted": "Hạn chế",
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
"name": "Thông báo đẩy"
|
"name": "Thông báo đẩy"
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"name": "Trang cá nhân"
|
"name": "Cài đặt cá nhân"
|
||||||
},
|
},
|
||||||
"profileName": {
|
"profileName": {
|
||||||
"name": "Tên hiển thị mới"
|
"name": "Tên hiển thị mới"
|
||||||
@ -65,7 +65,7 @@
|
|||||||
"name": "Metadata"
|
"name": "Metadata"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"name": "Cài đặt App"
|
"name": "Thiết lập"
|
||||||
},
|
},
|
||||||
"switch": {
|
"switch": {
|
||||||
"name": "Chuyển đổi tài khoản"
|
"name": "Chuyển đổi tài khoản"
|
||||||
@ -102,22 +102,22 @@
|
|||||||
},
|
},
|
||||||
"avatar": {
|
"avatar": {
|
||||||
"title": "Ảnh đại diện",
|
"title": "Ảnh đại diện",
|
||||||
"description": "Sẽ tự động chuyển còn 400x400px"
|
"description": "Tự động nén xuống 400x400px"
|
||||||
},
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"title": "Ảnh bìa",
|
"title": "Ảnh bìa",
|
||||||
"description": "Sẽ tự động chuyển còn 1500x1500px"
|
"description": "Tự động nén xuống 1500x500px"
|
||||||
},
|
},
|
||||||
"note": {
|
"note": {
|
||||||
"title": "Mô tả"
|
"title": "Mô tả"
|
||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"title": "Metadata",
|
"title": "Metadata",
|
||||||
"total": "{{count}} trường",
|
"total": "{{count}} mục",
|
||||||
"total_plural": "{{count}} trường"
|
"total_plural": "{{count}} mục"
|
||||||
},
|
},
|
||||||
"visibility": {
|
"visibility": {
|
||||||
"title": "Dạng tút",
|
"title": "Kiểu tút mặc định",
|
||||||
"options": {
|
"options": {
|
||||||
"public": "Công khai",
|
"public": "Công khai",
|
||||||
"unlisted": "Hạn chế",
|
"unlisted": "Hạn chế",
|
||||||
@ -126,19 +126,19 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sensitive": {
|
"sensitive": {
|
||||||
"title": "Đăng nội dung nhạy cảm"
|
"title": "Đây là tài khoản NSFW"
|
||||||
},
|
},
|
||||||
"lock": {
|
"lock": {
|
||||||
"title": "Đây là tài khoản riêng tư",
|
"title": "Đây là tài khoản riêng tư",
|
||||||
"description": "Tự bạn sẽ phê duyệt người theo dõi"
|
"description": "Tự bạn sẽ phê duyệt người theo dõi"
|
||||||
},
|
},
|
||||||
"bot": {
|
"bot": {
|
||||||
"title": "Tài khoản bot",
|
"title": "Đây là tài khoản Bot",
|
||||||
"description": "Tài khoản này tự động thực hiện các hành động và không được quản lý bởi người thật"
|
"description": "Tài khoản này tự động thực hiện các hành động và không được quản lý bởi người thật"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"group": "Nhóm {{index}}",
|
"group": "Mục {{index}}",
|
||||||
"label": "Nhãn",
|
"label": "Nhãn",
|
||||||
"content": "Nội dung"
|
"content": "Nội dung"
|
||||||
}
|
}
|
||||||
@ -150,11 +150,11 @@
|
|||||||
"settings": "Bật trong cài đặt"
|
"settings": "Bật trong cài đặt"
|
||||||
},
|
},
|
||||||
"global": {
|
"global": {
|
||||||
"heading": "Bật khi {{acct}}",
|
"heading": "Bật cho {{acct}}",
|
||||||
"description": "Thông báo được truyền qua máy chủ tooot"
|
"description": "Thông báo được truyền qua máy chủ tooot"
|
||||||
},
|
},
|
||||||
"decode": {
|
"decode": {
|
||||||
"heading": "Chi tiết thông báo",
|
"heading": "Hiện chi tiết thông báo",
|
||||||
"description": "Theo mặc định, thông báo truyền qua máy chủ tooot sẽ được mã hóa, nhưng bạn cũng có thể chọn không mã hóa. Máy chủ của chúng tôi luôn công khai mã nguồn và không lưu lại bất cứ gì."
|
"description": "Theo mặc định, thông báo truyền qua máy chủ tooot sẽ được mã hóa, nhưng bạn cũng có thể chọn không mã hóa. Máy chủ của chúng tôi luôn công khai mã nguồn và không lưu lại bất cứ gì."
|
||||||
},
|
},
|
||||||
"default": {
|
"default": {
|
||||||
@ -232,6 +232,14 @@
|
|||||||
"cancel": "$t(common:buttons.cancel)"
|
"cancel": "$t(common:buttons.cancel)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"darkTheme": {
|
||||||
|
"heading": "Độ tối",
|
||||||
|
"options": {
|
||||||
|
"lighter": "Thấp",
|
||||||
|
"darker": "Vừa",
|
||||||
|
"cancel": "$t(common:buttons.cancel)"
|
||||||
|
}
|
||||||
|
},
|
||||||
"browser": {
|
"browser": {
|
||||||
"heading": "Mở liên kết",
|
"heading": "Mở liên kết",
|
||||||
"options": {
|
"options": {
|
||||||
@ -240,6 +248,9 @@
|
|||||||
"cancel": "$t(common:buttons.cancel)"
|
"cancel": "$t(common:buttons.cancel)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"feedback": {
|
||||||
|
"heading": "Yêu cầu tính năng"
|
||||||
|
},
|
||||||
"support": {
|
"support": {
|
||||||
"heading": "Ủng hộ tooot"
|
"heading": "Ủng hộ tooot"
|
||||||
},
|
},
|
||||||
@ -250,13 +261,13 @@
|
|||||||
"heading": "Liên hệ tooot"
|
"heading": "Liên hệ tooot"
|
||||||
},
|
},
|
||||||
"analytics": {
|
"analytics": {
|
||||||
"heading": "Đóng góp ý kiến",
|
"heading": "Thu thập dữ liệu",
|
||||||
"description": "Chỉ thu thập thông tin không liên quan người dùng"
|
"description": "Giúp cải thiện chất lượng app"
|
||||||
},
|
},
|
||||||
"version": "Phiên bản {{version}}"
|
"version": "Phiên bản {{version}}"
|
||||||
},
|
},
|
||||||
"switch": {
|
"switch": {
|
||||||
"existing": "Chọn từ màn hình đăng nhập",
|
"existing": "Đã đăng nhập trước đó",
|
||||||
"new": "Đăng nhập máy chủ"
|
"new": "Đăng nhập máy chủ"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -279,15 +290,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"attachments": {
|
"attachments": {
|
||||||
"name": "<0 /><1>'s media</1>"
|
"name": "Bộ sưu tập của <1></1>"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"header": {
|
"header": {
|
||||||
"prefix": "Đang tìm...",
|
"prefix": "Tìm kiếm",
|
||||||
"placeholder": "về..."
|
"placeholder": "tất cả mọi thứ"
|
||||||
},
|
},
|
||||||
"empty": {
|
"empty": {
|
||||||
"general": "Nhập từ khóa <bold>$t(screenTabs:shared.search.sections.accounts)</bold>、<bold>$t(screenTabs:shared.search.sections.hashtags)</bold> hoặc<bold>$t(screenTabs:shared.search.sections.statuses)</bold>",
|
"general": "Tìm <bold>$t(screenTabs:shared.search.sections.accounts)</bold>, <bold>$t(screenTabs:shared.search.sections.hashtags)</bold> hoặc <bold>$t(screenTabs:shared.search.sections.statuses)</bold><bold>",
|
||||||
"advanced": {
|
"advanced": {
|
||||||
"header": "Tìm kiếm nâng cao",
|
"header": "Tìm kiếm nâng cao",
|
||||||
"example": {
|
"example": {
|
||||||
@ -310,12 +321,12 @@
|
|||||||
},
|
},
|
||||||
"users": {
|
"users": {
|
||||||
"accounts": {
|
"accounts": {
|
||||||
"following": "Đang theo dõi {{count}}",
|
"following": "{{count}} theo dõi",
|
||||||
"followers": "{{count}} người theo dõi"
|
"followers": "{{count}} người theo dõi"
|
||||||
},
|
},
|
||||||
"statuses": {
|
"statuses": {
|
||||||
"reblogged_by": "{{count}} người chia sẻ",
|
"reblogged_by": "{{count}} chia sẻ",
|
||||||
"favourited_by": "{{count}} người thích"
|
"favourited_by": "{{count}} thích"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ export default {
|
|||||||
screenImageViewer: require('./screens/imageViewer'),
|
screenImageViewer: require('./screens/imageViewer'),
|
||||||
screenTabs: require('./screens/tabs'),
|
screenTabs: require('./screens/tabs'),
|
||||||
|
|
||||||
|
componentEmojis: require('./components/emojis'),
|
||||||
componentInstance: require('./components/instance'),
|
componentInstance: require('./components/instance'),
|
||||||
componentMediaSelector: require('./components/mediaSelector'),
|
componentMediaSelector: require('./components/mediaSelector'),
|
||||||
componentParse: require('./components/parse'),
|
componentParse: require('./components/parse'),
|
||||||
|
3
src/i18n/zh-Hans/components/emojis.json
Normal file
3
src/i18n/zh-Hans/components/emojis.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"frequentUsed": "常用"
|
||||||
|
}
|
@ -232,6 +232,14 @@
|
|||||||
"cancel": "$t(common:buttons.cancel)"
|
"cancel": "$t(common:buttons.cancel)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"darkTheme": {
|
||||||
|
"heading": "深色主题",
|
||||||
|
"options": {
|
||||||
|
"lighter": "暗淡",
|
||||||
|
"darker": "暗黑",
|
||||||
|
"cancel": "$t(common:buttons.cancel)"
|
||||||
|
}
|
||||||
|
},
|
||||||
"browser": {
|
"browser": {
|
||||||
"heading": "外部链接",
|
"heading": "外部链接",
|
||||||
"options": {
|
"options": {
|
||||||
@ -240,6 +248,9 @@
|
|||||||
"cancel": "$t(common:buttons.cancel)"
|
"cancel": "$t(common:buttons.cancel)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"feedback": {
|
||||||
|
"heading": "功能建议"
|
||||||
|
},
|
||||||
"support": {
|
"support": {
|
||||||
"heading": "赞助 tooot 开发"
|
"heading": "赞助 tooot 开发"
|
||||||
},
|
},
|
||||||
|
@ -68,7 +68,7 @@ const ScreenActions = React.memo(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
|
|
||||||
const DEFAULT_VALUE = 350
|
const DEFAULT_VALUE = 350
|
||||||
@ -189,7 +189,7 @@ const ScreenActions = React.memo(
|
|||||||
<Animated.View
|
<Animated.View
|
||||||
style={[
|
style={[
|
||||||
styles.overlay,
|
styles.overlay,
|
||||||
{ backgroundColor: theme.backgroundOverlayInvert }
|
{ backgroundColor: colors.backgroundOverlayInvert }
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<PanGestureHandler onGestureEvent={onGestureEvent}>
|
<PanGestureHandler onGestureEvent={onGestureEvent}>
|
||||||
@ -198,7 +198,7 @@ const ScreenActions = React.memo(
|
|||||||
styles.container,
|
styles.container,
|
||||||
styleTop,
|
styleTop,
|
||||||
{
|
{
|
||||||
backgroundColor: theme.backgroundDefault,
|
backgroundColor: colors.backgroundDefault,
|
||||||
paddingBottom: insets.bottom || StyleConstants.Spacing.L
|
paddingBottom: insets.bottom || StyleConstants.Spacing.L
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
@ -206,7 +206,7 @@ const ScreenActions = React.memo(
|
|||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.handle,
|
styles.handle,
|
||||||
{ backgroundColor: theme.primaryOverlay }
|
{ backgroundColor: colors.primaryOverlay }
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
{actions}
|
{actions}
|
||||||
|
@ -24,7 +24,7 @@ const ActionsAccount: React.FC<Props> = ({
|
|||||||
account,
|
account,
|
||||||
dismiss
|
dismiss
|
||||||
}) => {
|
}) => {
|
||||||
const { mode } = useTheme()
|
const { theme } = useTheme()
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
@ -32,7 +32,7 @@ const ActionsAccount: React.FC<Props> = ({
|
|||||||
onSuccess: (_, params) => {
|
onSuccess: (_, params) => {
|
||||||
const theParams = params as MutationVarsTimelineUpdateAccountProperty
|
const theParams = params as MutationVarsTimelineUpdateAccountProperty
|
||||||
displayMessage({
|
displayMessage({
|
||||||
mode,
|
theme,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: t('common:message.success.message', {
|
message: t('common:message.success.message', {
|
||||||
function: t(
|
function: t(
|
||||||
@ -47,7 +47,7 @@ const ActionsAccount: React.FC<Props> = ({
|
|||||||
onError: (err: any, params) => {
|
onError: (err: any, params) => {
|
||||||
const theParams = params as MutationVarsTimelineUpdateAccountProperty
|
const theParams = params as MutationVarsTimelineUpdateAccountProperty
|
||||||
displayMessage({
|
displayMessage({
|
||||||
mode,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: t('common:message.error.message', {
|
message: t('common:message.error.message', {
|
||||||
function: t(
|
function: t(
|
||||||
|
@ -26,13 +26,13 @@ const ActionsDomain: React.FC<Props> = ({
|
|||||||
domain,
|
domain,
|
||||||
dismiss
|
dismiss
|
||||||
}) => {
|
}) => {
|
||||||
const { mode } = useTheme()
|
const { theme } = useTheme()
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const mutation = useTimelineMutation({
|
const mutation = useTimelineMutation({
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
displayMessage({
|
displayMessage({
|
||||||
mode,
|
theme,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: t('common:message.success.message', {
|
message: t('common:message.success.message', {
|
||||||
function: t(`shared.header.actions.domain.block.function`)
|
function: t(`shared.header.actions.domain.block.function`)
|
||||||
|
@ -30,7 +30,7 @@ const ActionsStatus: React.FC<Props> = ({
|
|||||||
status,
|
status,
|
||||||
dismiss
|
dismiss
|
||||||
}) => {
|
}) => {
|
||||||
const { mode } = useTheme()
|
const { theme } = useTheme()
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { t } = useTranslation('componentTimeline')
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
@ -42,7 +42,7 @@ const ActionsStatus: React.FC<Props> = ({
|
|||||||
? (params as MutationVarsTimelineUpdateStatusProperty).payload.property
|
? (params as MutationVarsTimelineUpdateStatusProperty).payload.property
|
||||||
: 'delete'
|
: 'delete'
|
||||||
displayMessage({
|
displayMessage({
|
||||||
mode,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: t('common:message.error.message', {
|
message: t('common:message.error.message', {
|
||||||
function: t(`shared.header.actions.status.${theFunction}.function`)
|
function: t(`shared.header.actions.status.${theFunction}.function`)
|
||||||
|
@ -36,7 +36,7 @@ const ScreenAnnouncements: React.FC<
|
|||||||
navigation
|
navigation
|
||||||
}) => {
|
}) => {
|
||||||
const { reduceMotionEnabled } = useAccessibility()
|
const { reduceMotionEnabled } = useAccessibility()
|
||||||
const { mode, theme } = useTheme()
|
const { colors, mode } = useTheme()
|
||||||
const [index, setIndex] = useState(0)
|
const [index, setIndex] = useState(0)
|
||||||
const { t } = useTranslation('screenAnnouncements')
|
const { t } = useTranslation('screenAnnouncements')
|
||||||
|
|
||||||
@ -73,12 +73,12 @@ const ScreenAnnouncements: React.FC<
|
|||||||
style={[
|
style={[
|
||||||
styles.announcement,
|
styles.announcement,
|
||||||
{
|
{
|
||||||
borderColor: theme.primaryDefault,
|
borderColor: colors.primaryDefault,
|
||||||
backgroundColor: theme.backgroundDefault
|
backgroundColor: colors.backgroundDefault
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Text style={[styles.published, { color: theme.secondary }]}>
|
<Text style={[styles.published, { color: colors.secondary }]}>
|
||||||
<Trans
|
<Trans
|
||||||
i18nKey='screenAnnouncements:content.published'
|
i18nKey='screenAnnouncements:content.published'
|
||||||
components={[<RelativeTime date={item.published_at} />]}
|
components={[<RelativeTime date={item.published_at} />]}
|
||||||
@ -103,11 +103,11 @@ const ScreenAnnouncements: React.FC<
|
|||||||
styles.reaction,
|
styles.reaction,
|
||||||
{
|
{
|
||||||
borderColor: reaction.me
|
borderColor: reaction.me
|
||||||
? theme.disabled
|
? colors.disabled
|
||||||
: theme.primaryDefault,
|
: colors.primaryDefault,
|
||||||
backgroundColor: reaction.me
|
backgroundColor: reaction.me
|
||||||
? theme.disabled
|
? colors.disabled
|
||||||
: theme.backgroundDefault
|
: colors.backgroundDefault
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
@ -138,7 +138,7 @@ const ScreenAnnouncements: React.FC<
|
|||||||
<Text
|
<Text
|
||||||
style={[
|
style={[
|
||||||
styles.reactionCount,
|
styles.reactionCount,
|
||||||
{ color: theme.primaryDefault }
|
{ color: colors.primaryDefault }
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{reaction.count}
|
{reaction.count}
|
||||||
@ -147,13 +147,13 @@ const ScreenAnnouncements: React.FC<
|
|||||||
</Pressable>
|
</Pressable>
|
||||||
))}
|
))}
|
||||||
{/* <Pressable
|
{/* <Pressable
|
||||||
style={[styles.reaction, { borderColor: theme.primaryDefault }]}
|
style={[styles.reaction, { borderColor: colors.primaryDefault }]}
|
||||||
onPress={() => invisibleTextInputRef.current?.focus()}
|
onPress={() => invisibleTextInputRef.current?.focus()}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
name='Plus'
|
name='Plus'
|
||||||
size={StyleConstants.Font.Size.M}
|
size={StyleConstants.Font.Size.M}
|
||||||
color={theme.primaryDefault}
|
color={colors.primaryDefault}
|
||||||
/>
|
/>
|
||||||
</Pressable> */}
|
</Pressable> */}
|
||||||
</View>
|
</View>
|
||||||
@ -177,7 +177,7 @@ const ScreenAnnouncements: React.FC<
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
),
|
),
|
||||||
[theme]
|
[mode]
|
||||||
)
|
)
|
||||||
|
|
||||||
const onMomentumScrollEnd = useCallback(
|
const onMomentumScrollEnd = useCallback(
|
||||||
@ -201,7 +201,7 @@ const ScreenAnnouncements: React.FC<
|
|||||||
alignItems: 'center'
|
alignItems: 'center'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Circle size={StyleConstants.Font.Size.L} color={theme.secondary} />
|
<Circle size={StyleConstants.Font.Size.L} color={colors.secondary} />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}, [])
|
}, [])
|
||||||
@ -211,7 +211,7 @@ const ScreenAnnouncements: React.FC<
|
|||||||
blurType={mode}
|
blurType={mode}
|
||||||
blurAmount={20}
|
blurAmount={20}
|
||||||
style={styles.base}
|
style={styles.base}
|
||||||
reducedTransparencyFallbackColor={theme.backgroundDefault}
|
reducedTransparencyFallbackColor={colors.backgroundDefault}
|
||||||
>
|
>
|
||||||
<SafeAreaView style={styles.base}>
|
<SafeAreaView style={styles.base}>
|
||||||
<FlatList
|
<FlatList
|
||||||
@ -232,9 +232,9 @@ const ScreenAnnouncements: React.FC<
|
|||||||
style={[
|
style={[
|
||||||
styles.indicator,
|
styles.indicator,
|
||||||
{
|
{
|
||||||
borderColor: theme.primaryDefault,
|
borderColor: colors.primaryDefault,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
i === index ? theme.primaryDefault : undefined,
|
i === index ? colors.primaryDefault : undefined,
|
||||||
marginLeft:
|
marginLeft:
|
||||||
i === query.data.length ? 0 : StyleConstants.Spacing.S
|
i === query.data.length ? 0 : StyleConstants.Spacing.S
|
||||||
}
|
}
|
||||||
@ -248,7 +248,7 @@ const ScreenAnnouncements: React.FC<
|
|||||||
</BlurView>
|
</BlurView>
|
||||||
) : (
|
) : (
|
||||||
<SafeAreaView
|
<SafeAreaView
|
||||||
style={[styles.base, { backgroundColor: theme.backgroundDefault }]}
|
style={[styles.base, { backgroundColor: colors.backgroundDefault }]}
|
||||||
>
|
>
|
||||||
<FlatList
|
<FlatList
|
||||||
horizontal
|
horizontal
|
||||||
@ -268,9 +268,9 @@ const ScreenAnnouncements: React.FC<
|
|||||||
style={[
|
style={[
|
||||||
styles.indicator,
|
styles.indicator,
|
||||||
{
|
{
|
||||||
borderColor: theme.primaryDefault,
|
borderColor: colors.primaryDefault,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
i === index ? theme.primaryDefault : undefined,
|
i === index ? colors.primaryDefault : undefined,
|
||||||
marginLeft:
|
marginLeft:
|
||||||
i === query.data.length ? 0 : StyleConstants.Spacing.S
|
i === query.data.length ? 0 : StyleConstants.Spacing.S
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
|
|||||||
navigation
|
navigation
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation('screenCompose')
|
const { t } = useTranslation('screenCompose')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
const [hasKeyboard, setHasKeyboard] = useState(false)
|
const [hasKeyboard, setHasKeyboard] = useState(false)
|
||||||
@ -373,7 +373,7 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
|
|||||||
component={ComposeRoot}
|
component={ComposeRoot}
|
||||||
options={{
|
options={{
|
||||||
title: headerContent,
|
title: headerContent,
|
||||||
titleStyle: {
|
headerTitleStyle: {
|
||||||
fontWeight:
|
fontWeight:
|
||||||
totalTextCount > maxTootChars
|
totalTextCount > maxTootChars
|
||||||
? StyleConstants.Font.Weight.Bold
|
? StyleConstants.Font.Weight.Bold
|
||||||
@ -381,7 +381,7 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
|
|||||||
fontSize: StyleConstants.Font.Size.M
|
fontSize: StyleConstants.Font.Size.M
|
||||||
},
|
},
|
||||||
headerTintColor:
|
headerTintColor:
|
||||||
totalTextCount > maxTootChars ? theme.red : theme.secondary,
|
totalTextCount > maxTootChars ? colors.red : colors.secondary,
|
||||||
headerLeft,
|
headerLeft,
|
||||||
headerRight
|
headerRight
|
||||||
}}
|
}}
|
||||||
|
@ -37,7 +37,7 @@ const ComposeDraftsListRoot: React.FC<Props> = ({ timestamp }) => {
|
|||||||
const { t } = useTranslation('screenCompose')
|
const { t } = useTranslation('screenCompose')
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const { mode, theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
const instanceDrafts = useSelector(getInstanceDrafts)?.filter(
|
const instanceDrafts = useSelector(getInstanceDrafts)?.filter(
|
||||||
draft => draft.timestamp !== timestamp
|
draft => draft.timestamp !== timestamp
|
||||||
)
|
)
|
||||||
@ -56,7 +56,7 @@ const ComposeDraftsListRoot: React.FC<Props> = ({ timestamp }) => {
|
|||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
accessibilityHint={t('content.draftsList.content.accessibilityHint')}
|
accessibilityHint={t('content.draftsList.content.accessibilityHint')}
|
||||||
style={[styles.draft, { backgroundColor: theme.backgroundDefault }]}
|
style={[styles.draft, { backgroundColor: colors.backgroundDefault }]}
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
setCheckingAttachments(true)
|
setCheckingAttachments(true)
|
||||||
let tempDraft = item
|
let tempDraft = item
|
||||||
@ -104,7 +104,7 @@ const ComposeDraftsListRoot: React.FC<Props> = ({ timestamp }) => {
|
|||||||
<HeaderSharedCreated created_at={item.timestamp} />
|
<HeaderSharedCreated created_at={item.timestamp} />
|
||||||
<Text
|
<Text
|
||||||
numberOfLines={2}
|
numberOfLines={2}
|
||||||
style={[styles.text, { color: theme.primaryDefault }]}
|
style={[styles.text, { color: colors.primaryDefault }]}
|
||||||
>
|
>
|
||||||
{item.text ||
|
{item.text ||
|
||||||
item.spoiler ||
|
item.spoiler ||
|
||||||
@ -132,12 +132,12 @@ const ComposeDraftsListRoot: React.FC<Props> = ({ timestamp }) => {
|
|||||||
</Pressable>
|
</Pressable>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[mode]
|
[theme]
|
||||||
)
|
)
|
||||||
const renderHiddenItem = useCallback(
|
const renderHiddenItem = useCallback(
|
||||||
({ item }) => (
|
({ item }) => (
|
||||||
<View
|
<View
|
||||||
style={[styles.hiddenBase, { backgroundColor: theme.red }]}
|
style={[styles.hiddenBase, { backgroundColor: colors.red }]}
|
||||||
children={
|
children={
|
||||||
<Pressable
|
<Pressable
|
||||||
style={styles.action}
|
style={styles.action}
|
||||||
@ -146,14 +146,14 @@ const ComposeDraftsListRoot: React.FC<Props> = ({ timestamp }) => {
|
|||||||
<Icon
|
<Icon
|
||||||
name='Trash'
|
name='Trash'
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme.primaryOverlay}
|
color={colors.primaryOverlay}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[mode]
|
[theme]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -184,14 +184,14 @@ const ComposeDraftsListRoot: React.FC<Props> = ({ timestamp }) => {
|
|||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.modal,
|
styles.modal,
|
||||||
{ backgroundColor: theme.backgroundOverlayInvert }
|
{ backgroundColor: colors.backgroundOverlayInvert }
|
||||||
]}
|
]}
|
||||||
children={
|
children={
|
||||||
<Text
|
<Text
|
||||||
children='检查附件在服务器的状态…'
|
children='检查附件在服务器的状态…'
|
||||||
style={{
|
style={{
|
||||||
...StyleConstants.FontStyle.M,
|
...StyleConstants.FontStyle.M,
|
||||||
color: theme.primaryOverlay
|
color: colors.primaryOverlay
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ export interface Props {
|
|||||||
|
|
||||||
const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
|
const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
|
||||||
const { t } = useTranslation('screenCompose')
|
const { t } = useTranslation('screenCompose')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { screenReaderEnabled } = useAccessibility()
|
const { screenReaderEnabled } = useAccessibility()
|
||||||
|
|
||||||
const { composeState, composeDispatch } = useContext(ComposeContext)
|
const { composeState, composeDispatch } = useContext(ComposeContext)
|
||||||
@ -146,16 +146,21 @@ const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
|
|||||||
<G>
|
<G>
|
||||||
<Path
|
<Path
|
||||||
d='M1000,0 L1000,1000 L0,1000 L0,0 L1000,0 Z M500,475 C486.192881,475 475,486.192881 475,500 C475,513.807119 486.192881,525 500,525 C513.807119,525 525,513.807119 525,500 C525,486.192881 513.807119,475 500,475 Z'
|
d='M1000,0 L1000,1000 L0,1000 L0,0 L1000,0 Z M500,475 C486.192881,475 475,486.192881 475,500 C475,513.807119 486.192881,525 500,525 C513.807119,525 525,513.807119 525,500 C525,486.192881 513.807119,475 500,475 Z'
|
||||||
fill={theme.backgroundOverlayInvert}
|
fill={colors.backgroundOverlayInvert}
|
||||||
/>
|
/>
|
||||||
<Circle
|
<Circle
|
||||||
stroke={theme.primaryOverlay}
|
stroke={colors.primaryOverlay}
|
||||||
stroke-width='2'
|
stroke-width='2'
|
||||||
cx='500'
|
cx='500'
|
||||||
cy='500'
|
cy='500'
|
||||||
r='24'
|
r='24'
|
||||||
/>
|
/>
|
||||||
<Circle fill={theme.primaryOverlay} cx='500' cy='500' r='2' />
|
<Circle
|
||||||
|
fill={colors.primaryOverlay}
|
||||||
|
cx='500'
|
||||||
|
cy='500'
|
||||||
|
r='2'
|
||||||
|
/>
|
||||||
</G>
|
</G>
|
||||||
</G>
|
</G>
|
||||||
</Svg>
|
</Svg>
|
||||||
@ -163,7 +168,7 @@ const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
|
|||||||
</PanGestureHandler>
|
</PanGestureHandler>
|
||||||
</View>
|
</View>
|
||||||
{screenReaderEnabled ? null : (
|
{screenReaderEnabled ? null : (
|
||||||
<Text style={[styles.imageFocusText, { color: theme.primaryDefault }]}>
|
<Text style={[styles.imageFocusText, { color: colors.primaryDefault }]}>
|
||||||
{t('content.editAttachment.content.imageFocus')}
|
{t('content.editAttachment.content.imageFocus')}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
@ -13,7 +13,7 @@ export interface Props {
|
|||||||
|
|
||||||
const ComposeEditAttachmentRoot: React.FC<Props> = ({ index }) => {
|
const ComposeEditAttachmentRoot: React.FC<Props> = ({ index }) => {
|
||||||
const { t } = useTranslation('screenCompose')
|
const { t } = useTranslation('screenCompose')
|
||||||
const { mode, theme } = useTheme()
|
const { colors, mode } = useTheme()
|
||||||
const { composeState, composeDispatch } = useContext(ComposeContext)
|
const { composeState, composeDispatch } = useContext(ComposeContext)
|
||||||
const theAttachment = composeState.attachments.uploads[index].remote!
|
const theAttachment = composeState.attachments.uploads[index].remote!
|
||||||
|
|
||||||
@ -61,13 +61,15 @@ const ComposeEditAttachmentRoot: React.FC<Props> = ({ index }) => {
|
|||||||
<ScrollView ref={scrollViewRef}>
|
<ScrollView ref={scrollViewRef}>
|
||||||
{mediaDisplay}
|
{mediaDisplay}
|
||||||
<View style={styles.altTextContainer}>
|
<View style={styles.altTextContainer}>
|
||||||
<Text style={[styles.altTextInputHeading, { color: theme.primaryDefault }]}>
|
<Text
|
||||||
|
style={[styles.altTextInputHeading, { color: colors.primaryDefault }]}
|
||||||
|
>
|
||||||
{t('content.editAttachment.content.altText.heading')}
|
{t('content.editAttachment.content.altText.heading')}
|
||||||
</Text>
|
</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
style={[
|
style={[
|
||||||
styles.altTextInput,
|
styles.altTextInput,
|
||||||
{ borderColor: theme.border, color: theme.primaryDefault }
|
{ borderColor: colors.border, color: colors.primaryDefault }
|
||||||
]}
|
]}
|
||||||
onFocus={() => scrollViewRef.current?.scrollToEnd()}
|
onFocus={() => scrollViewRef.current?.scrollToEnd()}
|
||||||
autoCapitalize='none'
|
autoCapitalize='none'
|
||||||
@ -76,12 +78,12 @@ const ComposeEditAttachmentRoot: React.FC<Props> = ({ index }) => {
|
|||||||
multiline
|
multiline
|
||||||
onChangeText={onChangeText}
|
onChangeText={onChangeText}
|
||||||
placeholder={t('content.editAttachment.content.altText.placeholder')}
|
placeholder={t('content.editAttachment.content.altText.placeholder')}
|
||||||
placeholderTextColor={theme.secondary}
|
placeholderTextColor={colors.secondary}
|
||||||
scrollEnabled
|
scrollEnabled
|
||||||
value={theAttachment.description}
|
value={theAttachment.description}
|
||||||
keyboardAppearance={mode}
|
keyboardAppearance={mode}
|
||||||
/>
|
/>
|
||||||
<Text style={[styles.altTextLength, { color: theme.secondary }]}>
|
<Text style={[styles.altTextLength, { color: colors.secondary }]}>
|
||||||
{theAttachment.description?.length || 0} / 1500
|
{theAttachment.description?.length || 0} / 1500
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
@ -6,7 +6,7 @@ import ComposeContext from './utils/createContext'
|
|||||||
const ComposePosting = React.memo(
|
const ComposePosting = React.memo(
|
||||||
() => {
|
() => {
|
||||||
const { composeState } = useContext(ComposeContext)
|
const { composeState } = useContext(ComposeContext)
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
@ -14,7 +14,9 @@ const ComposePosting = React.memo(
|
|||||||
animationType='fade'
|
animationType='fade'
|
||||||
visible={composeState.posting}
|
visible={composeState.posting}
|
||||||
children={
|
children={
|
||||||
<View style={{ flex: 1, backgroundColor: theme.backgroundOverlayInvert }} />
|
<View
|
||||||
|
style={{ flex: 1, backgroundColor: colors.backgroundOverlayInvert }}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -30,7 +30,11 @@ import FastImage from 'react-native-fast-image'
|
|||||||
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
||||||
import { ComposeState } from './utils/types'
|
import { ComposeState } from './utils/types'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { getInstanceConfigurationStatusCharsURL } from '@utils/slices/instancesSlice'
|
import {
|
||||||
|
getInstanceConfigurationStatusCharsURL,
|
||||||
|
getInstanceFrequentEmojis
|
||||||
|
} from '@utils/slices/instancesSlice'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
const prefetchEmojis = (
|
const prefetchEmojis = (
|
||||||
sortedEmojis: NonNullable<ComposeState['emoji']['emojis']>,
|
sortedEmojis: NonNullable<ComposeState['emoji']['emojis']>,
|
||||||
@ -61,7 +65,7 @@ export let instanceConfigurationStatusCharsURL = 23
|
|||||||
const ComposeRoot = React.memo(
|
const ComposeRoot = React.memo(
|
||||||
() => {
|
() => {
|
||||||
const { reduceMotionEnabled } = useAccessibility()
|
const { reduceMotionEnabled } = useAccessibility()
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
instanceConfigurationStatusCharsURL = useSelector(
|
instanceConfigurationStatusCharsURL = useSelector(
|
||||||
getInstanceConfigurationStatusCharsURL,
|
getInstanceConfigurationStatusCharsURL,
|
||||||
@ -99,15 +103,29 @@ const ComposeRoot = React.memo(
|
|||||||
}
|
}
|
||||||
}, [composeState.tag])
|
}, [composeState.tag])
|
||||||
|
|
||||||
|
const { t } = useTranslation()
|
||||||
const { data: emojisData } = useEmojisQuery({})
|
const { data: emojisData } = useEmojisQuery({})
|
||||||
|
const frequentEmojis = useSelector(getInstanceFrequentEmojis, () => true)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (emojisData && emojisData.length) {
|
if (emojisData && emojisData.length) {
|
||||||
let sortedEmojis: { title: string; data: Mastodon.Emoji[][] }[] = []
|
const sortedEmojis: {
|
||||||
|
title: string
|
||||||
|
data: Pick<Mastodon.Emoji, 'shortcode' | 'url' | 'static_url'>[][]
|
||||||
|
}[] = []
|
||||||
forEach(
|
forEach(
|
||||||
groupBy(sortBy(emojisData, ['category', 'shortcode']), 'category'),
|
groupBy(sortBy(emojisData, ['category', 'shortcode']), 'category'),
|
||||||
(value, key) =>
|
(value, key) =>
|
||||||
sortedEmojis.push({ title: key, data: chunk(value, 5) })
|
sortedEmojis.push({ title: key, data: chunk(value, 5) })
|
||||||
)
|
)
|
||||||
|
if (frequentEmojis.length) {
|
||||||
|
sortedEmojis.unshift({
|
||||||
|
title: t('componentEmojis:frequentUsed'),
|
||||||
|
data: chunk(
|
||||||
|
frequentEmojis.map(e => e.emoji),
|
||||||
|
5
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
composeDispatch({
|
composeDispatch({
|
||||||
type: 'emoji',
|
type: 'emoji',
|
||||||
payload: { ...composeState.emoji, emojis: sortedEmojis }
|
payload: { ...composeState.emoji, emojis: sortedEmojis }
|
||||||
@ -122,7 +140,7 @@ const ComposeRoot = React.memo(
|
|||||||
<View key='listEmpty' style={styles.loading}>
|
<View key='listEmpty' style={styles.loading}>
|
||||||
<Circle
|
<Circle
|
||||||
size={StyleConstants.Font.Size.M * 1.25}
|
size={StyleConstants.Font.Size.M * 1.25}
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
@ -16,19 +16,19 @@ const ComposeActions: React.FC = () => {
|
|||||||
const { showActionSheetWithOptions } = useActionSheet()
|
const { showActionSheetWithOptions } = useActionSheet()
|
||||||
const { composeState, composeDispatch } = useContext(ComposeContext)
|
const { composeState, composeDispatch } = useContext(ComposeContext)
|
||||||
const { t } = useTranslation('screenCompose')
|
const { t } = useTranslation('screenCompose')
|
||||||
const { theme } = useTheme()
|
const { colors, mode } = useTheme()
|
||||||
const instanceConfigurationStatusMaxAttachments = useSelector(
|
const instanceConfigurationStatusMaxAttachments = useSelector(
|
||||||
getInstanceConfigurationStatusMaxAttachments,
|
getInstanceConfigurationStatusMaxAttachments,
|
||||||
() => true
|
() => true
|
||||||
)
|
)
|
||||||
|
|
||||||
const attachmentColor = useMemo(() => {
|
const attachmentColor = useMemo(() => {
|
||||||
if (composeState.poll.active) return theme.disabled
|
if (composeState.poll.active) return colors.disabled
|
||||||
|
|
||||||
if (composeState.attachments.uploads.length) {
|
if (composeState.attachments.uploads.length) {
|
||||||
return theme.primaryDefault
|
return colors.primaryDefault
|
||||||
} else {
|
} else {
|
||||||
return theme.secondary
|
return colors.secondary
|
||||||
}
|
}
|
||||||
}, [composeState.poll.active, composeState.attachments.uploads])
|
}, [composeState.poll.active, composeState.attachments.uploads])
|
||||||
const attachmentOnPress = useCallback(async () => {
|
const attachmentOnPress = useCallback(async () => {
|
||||||
@ -49,12 +49,12 @@ const ComposeActions: React.FC = () => {
|
|||||||
}, [composeState.poll.active, composeState.attachments.uploads])
|
}, [composeState.poll.active, composeState.attachments.uploads])
|
||||||
|
|
||||||
const pollColor = useMemo(() => {
|
const pollColor = useMemo(() => {
|
||||||
if (composeState.attachments.uploads.length) return theme.disabled
|
if (composeState.attachments.uploads.length) return colors.disabled
|
||||||
|
|
||||||
if (composeState.poll.active) {
|
if (composeState.poll.active) {
|
||||||
return theme.primaryDefault
|
return colors.primaryDefault
|
||||||
} else {
|
} else {
|
||||||
return theme.secondary
|
return colors.secondary
|
||||||
}
|
}
|
||||||
}, [composeState.poll.active, composeState.attachments.uploads])
|
}, [composeState.poll.active, composeState.attachments.uploads])
|
||||||
const pollOnPress = useCallback(() => {
|
const pollOnPress = useCallback(() => {
|
||||||
@ -97,7 +97,8 @@ const ComposeActions: React.FC = () => {
|
|||||||
t('content.root.actions.visibility.options.direct'),
|
t('content.root.actions.visibility.options.direct'),
|
||||||
t('content.root.actions.visibility.options.cancel')
|
t('content.root.actions.visibility.options.cancel')
|
||||||
],
|
],
|
||||||
cancelButtonIndex: 4
|
cancelButtonIndex: 4,
|
||||||
|
userInterfaceStyle: mode
|
||||||
},
|
},
|
||||||
buttonIndex => {
|
buttonIndex => {
|
||||||
switch (buttonIndex) {
|
switch (buttonIndex) {
|
||||||
@ -150,12 +151,12 @@ const ComposeActions: React.FC = () => {
|
|||||||
}, [composeState.spoiler.active, composeState.textInputFocus])
|
}, [composeState.spoiler.active, composeState.textInputFocus])
|
||||||
|
|
||||||
const emojiColor = useMemo(() => {
|
const emojiColor = useMemo(() => {
|
||||||
if (!composeState.emoji.emojis) return theme.disabled
|
if (!composeState.emoji.emojis) return colors.disabled
|
||||||
|
|
||||||
if (composeState.emoji.active) {
|
if (composeState.emoji.active) {
|
||||||
return theme.primaryDefault
|
return colors.primaryDefault
|
||||||
} else {
|
} else {
|
||||||
return theme.secondary
|
return colors.secondary
|
||||||
}
|
}
|
||||||
}, [composeState.emoji.active, composeState.emoji.emojis])
|
}, [composeState.emoji.active, composeState.emoji.emojis])
|
||||||
const emojiOnPress = useCallback(() => {
|
const emojiOnPress = useCallback(() => {
|
||||||
@ -177,8 +178,8 @@ const ComposeActions: React.FC = () => {
|
|||||||
style={[
|
style={[
|
||||||
styles.additions,
|
styles.additions,
|
||||||
{
|
{
|
||||||
backgroundColor: theme.backgroundDefault,
|
backgroundColor: colors.backgroundDefault,
|
||||||
borderTopColor: theme.border
|
borderTopColor: colors.border
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
@ -223,7 +224,7 @@ const ComposeActions: React.FC = () => {
|
|||||||
name={visibilityIcon}
|
name={visibilityIcon}
|
||||||
size={24}
|
size={24}
|
||||||
color={
|
color={
|
||||||
composeState.visibilityLock ? theme.disabled : theme.secondary
|
composeState.visibilityLock ? colors.disabled : colors.secondary
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
@ -242,8 +243,8 @@ const ComposeActions: React.FC = () => {
|
|||||||
size={24}
|
size={24}
|
||||||
color={
|
color={
|
||||||
composeState.spoiler.active
|
composeState.spoiler.active
|
||||||
? theme.primaryDefault
|
? colors.primaryDefault
|
||||||
: theme.secondary
|
: colors.secondary
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
|
|||||||
const { showActionSheetWithOptions } = useActionSheet()
|
const { showActionSheetWithOptions } = useActionSheet()
|
||||||
const { composeState, composeDispatch } = useContext(ComposeContext)
|
const { composeState, composeDispatch } = useContext(ComposeContext)
|
||||||
const { t } = useTranslation('screenCompose')
|
const { t } = useTranslation('screenCompose')
|
||||||
const { theme } = useTheme()
|
const { colors, mode } = useTheme()
|
||||||
const navigation = useNavigation<any>()
|
const navigation = useNavigation<any>()
|
||||||
|
|
||||||
const flatListRef = useRef<FlatList>(null)
|
const flatListRef = useRef<FlatList>(null)
|
||||||
@ -135,8 +135,8 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
|
|||||||
style={[
|
style={[
|
||||||
styles.duration,
|
styles.duration,
|
||||||
{
|
{
|
||||||
color: theme.backgroundDefault,
|
color: colors.backgroundDefault,
|
||||||
backgroundColor: theme.backgroundOverlayInvert
|
backgroundColor: colors.backgroundOverlayInvert
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
@ -147,12 +147,12 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
|
|||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.uploading,
|
styles.uploading,
|
||||||
{ backgroundColor: theme.backgroundOverlayInvert }
|
{ backgroundColor: colors.backgroundOverlayInvert }
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Circle
|
<Circle
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme.primaryOverlay}
|
color={colors.primaryOverlay}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
@ -213,7 +213,7 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
|
|||||||
styles.container,
|
styles.container,
|
||||||
{
|
{
|
||||||
width: DEFAULT_HEIGHT,
|
width: DEFAULT_HEIGHT,
|
||||||
backgroundColor: theme.backgroundOverlayInvert
|
backgroundColor: colors.backgroundOverlayInvert
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
@ -255,9 +255,9 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
|
|||||||
<Icon
|
<Icon
|
||||||
name={composeState.attachments.sensitive ? 'CheckCircle' : 'Circle'}
|
name={composeState.attachments.sensitive ? 'CheckCircle' : 'Circle'}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme.primaryDefault}
|
color={colors.primaryDefault}
|
||||||
/>
|
/>
|
||||||
<Text style={[styles.sensitiveText, { color: theme.primaryDefault }]}>
|
<Text style={[styles.sensitiveText, { color: colors.primaryDefault }]}>
|
||||||
{t('content.root.footer.attachments.sensitive')}
|
{t('content.root.footer.attachments.sensitive')}
|
||||||
</Text>
|
</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import haptics from '@components/haptics'
|
import haptics from '@components/haptics'
|
||||||
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
||||||
|
import { countInstanceEmoji } from '@utils/slices/instancesSlice'
|
||||||
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, { RefObject, useCallback, useContext, useEffect } from 'react'
|
import React, { RefObject, useCallback, useContext, useEffect } from 'react'
|
||||||
@ -14,6 +15,7 @@ import {
|
|||||||
View
|
View
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import FastImage from 'react-native-fast-image'
|
import FastImage from 'react-native-fast-image'
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
import validUrl from 'valid-url'
|
import validUrl from 'valid-url'
|
||||||
import updateText from '../../updateText'
|
import updateText from '../../updateText'
|
||||||
import ComposeContext from '../../utils/createContext'
|
import ComposeContext from '../../utils/createContext'
|
||||||
@ -25,8 +27,9 @@ export interface Props {
|
|||||||
const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
|
const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
|
||||||
const { composeState, composeDispatch } = useContext(ComposeContext)
|
const { composeState, composeDispatch } = useContext(ComposeContext)
|
||||||
const { reduceMotionEnabled } = useAccessibility()
|
const { reduceMotionEnabled } = useAccessibility()
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const tagEmojis = findNodeHandle(accessibleRefEmojis.current)
|
const tagEmojis = findNodeHandle(accessibleRefEmojis.current)
|
||||||
@ -37,7 +40,7 @@ const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
|
|||||||
|
|
||||||
const listHeader = useCallback(
|
const listHeader = useCallback(
|
||||||
({ section: { title } }) => (
|
({ section: { title } }) => (
|
||||||
<Text style={[styles.group, { color: theme.secondary }]}>{title}</Text>
|
<Text style={[styles.group, { color: colors.secondary }]}>{title}</Text>
|
||||||
),
|
),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
@ -53,13 +56,14 @@ const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
|
|||||||
<Pressable
|
<Pressable
|
||||||
key={emoji.shortcode}
|
key={emoji.shortcode}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
|
haptics('Light')
|
||||||
updateText({
|
updateText({
|
||||||
composeState,
|
composeState,
|
||||||
composeDispatch,
|
composeDispatch,
|
||||||
newText: `:${emoji.shortcode}:`,
|
newText: `:${emoji.shortcode}:`,
|
||||||
type: 'emoji'
|
type: 'emoji'
|
||||||
})
|
})
|
||||||
haptics('Light')
|
dispatch(countInstanceEmoji(emoji))
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FastImage
|
<FastImage
|
||||||
|
@ -21,7 +21,7 @@ const ComposePoll: React.FC = () => {
|
|||||||
composeDispatch
|
composeDispatch
|
||||||
} = useContext(ComposeContext)
|
} = useContext(ComposeContext)
|
||||||
const { t } = useTranslation('screenCompose')
|
const { t } = useTranslation('screenCompose')
|
||||||
const { mode, theme } = useTheme()
|
const { colors, mode } = useTheme()
|
||||||
|
|
||||||
const instanceConfigurationPoll = useSelector(
|
const instanceConfigurationPoll = useSelector(
|
||||||
getInstanceConfigurationPoll,
|
getInstanceConfigurationPoll,
|
||||||
@ -39,7 +39,7 @@ const ComposePoll: React.FC = () => {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.base, { borderColor: theme.border }]}>
|
<View style={[styles.base, { borderColor: colors.border }]}>
|
||||||
<View style={styles.options}>
|
<View style={styles.options}>
|
||||||
{[...Array(total)].map((e, i) => {
|
{[...Array(total)].map((e, i) => {
|
||||||
const restOptions = Object.keys(options).filter(
|
const restOptions = Object.keys(options).filter(
|
||||||
@ -57,7 +57,7 @@ const ComposePoll: React.FC = () => {
|
|||||||
<Icon
|
<Icon
|
||||||
name={multiple ? 'Square' : 'Circle'}
|
name={multiple ? 'Square' : 'Circle'}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme.secondary}
|
color={colors.secondary}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
accessibilityLabel={t(
|
accessibilityLabel={t(
|
||||||
@ -69,8 +69,8 @@ const ComposePoll: React.FC = () => {
|
|||||||
style={[
|
style={[
|
||||||
styles.textInput,
|
styles.textInput,
|
||||||
{
|
{
|
||||||
borderColor: theme.border,
|
borderColor: colors.border,
|
||||||
color: hasConflict ? theme.red : theme.primaryDefault
|
color: hasConflict ? colors.red : colors.primaryDefault
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
placeholder={
|
placeholder={
|
||||||
@ -78,7 +78,7 @@ const ComposePoll: React.FC = () => {
|
|||||||
? t('content.root.footer.poll.option.placeholder.multiple')
|
? t('content.root.footer.poll.option.placeholder.multiple')
|
||||||
: t('content.root.footer.poll.option.placeholder.single')
|
: t('content.root.footer.poll.option.placeholder.single')
|
||||||
}
|
}
|
||||||
placeholderTextColor={theme.disabled}
|
placeholderTextColor={colors.disabled}
|
||||||
maxLength={MAX_CHARS_PER_OPTION}
|
maxLength={MAX_CHARS_PER_OPTION}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
value={options[i]}
|
value={options[i]}
|
||||||
@ -168,7 +168,8 @@ const ComposePoll: React.FC = () => {
|
|||||||
t('content.root.footer.poll.multiple.options.multiple'),
|
t('content.root.footer.poll.multiple.options.multiple'),
|
||||||
t('content.root.footer.poll.multiple.options.cancel')
|
t('content.root.footer.poll.multiple.options.cancel')
|
||||||
],
|
],
|
||||||
cancelButtonIndex: 2
|
cancelButtonIndex: 2,
|
||||||
|
userInterfaceStyle: mode
|
||||||
},
|
},
|
||||||
index => {
|
index => {
|
||||||
if (index && index < 2) {
|
if (index && index < 2) {
|
||||||
@ -211,7 +212,8 @@ const ComposePoll: React.FC = () => {
|
|||||||
),
|
),
|
||||||
t('content.root.footer.poll.expiration.options.cancel')
|
t('content.root.footer.poll.expiration.options.cancel')
|
||||||
],
|
],
|
||||||
cancelButtonIndex: expirations.length
|
cancelButtonIndex: expirations.length,
|
||||||
|
userInterfaceStyle: mode
|
||||||
},
|
},
|
||||||
index => {
|
index => {
|
||||||
if (index && index < expirations.length) {
|
if (index && index < expirations.length) {
|
||||||
|
@ -8,10 +8,10 @@ const ComposeReply: React.FC = () => {
|
|||||||
const {
|
const {
|
||||||
composeState: { replyToStatus }
|
composeState: { replyToStatus }
|
||||||
} = useContext(ComposeContext)
|
} = useContext(ComposeContext)
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={[styles.base, { borderTopColor: theme.border }]}>
|
<View style={[styles.base, { borderTopColor: colors.border }]}>
|
||||||
<TimelineDefault item={replyToStatus!} disableDetails disableOnPress />
|
<TimelineDefault item={replyToStatus!} disableDetails disableOnPress />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
@ -12,7 +12,7 @@ import { useSelector } from 'react-redux'
|
|||||||
const ComposePostingAs = React.memo(
|
const ComposePostingAs = React.memo(
|
||||||
() => {
|
() => {
|
||||||
const { t } = useTranslation('screenCompose')
|
const { t } = useTranslation('screenCompose')
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const instanceAccount = useSelector(
|
const instanceAccount = useSelector(
|
||||||
getInstanceAccount,
|
getInstanceAccount,
|
||||||
@ -21,7 +21,7 @@ const ComposePostingAs = React.memo(
|
|||||||
const instanceUri = useSelector(getInstanceUri)
|
const instanceUri = useSelector(getInstanceUri)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text style={[styles.text, { color: theme.secondary }]}>
|
<Text style={[styles.text, { color: colors.secondary }]}>
|
||||||
{t('content.root.header.postingAs', {
|
{t('content.root.header.postingAs', {
|
||||||
acct: instanceAccount?.acct,
|
acct: instanceAccount?.acct,
|
||||||
domain: instanceUri
|
domain: instanceUri
|
||||||
|
@ -9,7 +9,7 @@ import ComposeContext from '../../utils/createContext'
|
|||||||
const ComposeSpoilerInput: React.FC = () => {
|
const ComposeSpoilerInput: React.FC = () => {
|
||||||
const { composeState, composeDispatch } = useContext(ComposeContext)
|
const { composeState, composeDispatch } = useContext(ComposeContext)
|
||||||
const { t } = useTranslation('screenCompose')
|
const { t } = useTranslation('screenCompose')
|
||||||
const { mode, theme } = useTheme()
|
const { colors, mode } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TextInput
|
<TextInput
|
||||||
@ -17,8 +17,8 @@ const ComposeSpoilerInput: React.FC = () => {
|
|||||||
style={[
|
style={[
|
||||||
styles.spoilerInput,
|
styles.spoilerInput,
|
||||||
{
|
{
|
||||||
color: theme.primaryDefault,
|
color: colors.primaryDefault,
|
||||||
borderBottomColor: theme.border
|
borderBottomColor: colors.border
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
autoCapitalize='none'
|
autoCapitalize='none'
|
||||||
@ -27,7 +27,7 @@ const ComposeSpoilerInput: React.FC = () => {
|
|||||||
enablesReturnKeyAutomatically
|
enablesReturnKeyAutomatically
|
||||||
multiline
|
multiline
|
||||||
placeholder={t('content.root.header.spoilerInput.placeholder')}
|
placeholder={t('content.root.header.spoilerInput.placeholder')}
|
||||||
placeholderTextColor={theme.secondary}
|
placeholderTextColor={colors.secondary}
|
||||||
onChangeText={content =>
|
onChangeText={content =>
|
||||||
formatText({
|
formatText({
|
||||||
textInput: 'spoiler',
|
textInput: 'spoiler',
|
||||||
|
@ -9,7 +9,7 @@ import ComposeContext from '../../utils/createContext'
|
|||||||
const ComposeTextInput: React.FC = () => {
|
const ComposeTextInput: React.FC = () => {
|
||||||
const { composeState, composeDispatch } = useContext(ComposeContext)
|
const { composeState, composeDispatch } = useContext(ComposeContext)
|
||||||
const { t } = useTranslation('screenCompose')
|
const { t } = useTranslation('screenCompose')
|
||||||
const { mode, theme } = useTheme()
|
const { colors, mode } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TextInput
|
<TextInput
|
||||||
@ -17,15 +17,15 @@ const ComposeTextInput: React.FC = () => {
|
|||||||
style={[
|
style={[
|
||||||
styles.textInput,
|
styles.textInput,
|
||||||
{
|
{
|
||||||
color: theme.primaryDefault,
|
color: colors.primaryDefault,
|
||||||
borderBottomColor: theme.border
|
borderBottomColor: colors.border
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
autoFocus
|
autoFocus
|
||||||
enablesReturnKeyAutomatically
|
enablesReturnKeyAutomatically
|
||||||
multiline
|
multiline
|
||||||
placeholder={t('content.root.header.textInput.placeholder')}
|
placeholder={t('content.root.header.textInput.placeholder')}
|
||||||
placeholderTextColor={theme.secondary}
|
placeholderTextColor={colors.secondary}
|
||||||
onChangeText={content =>
|
onChangeText={content =>
|
||||||
formatText({
|
formatText({
|
||||||
textInput: 'text',
|
textInput: 'text',
|
||||||
|
@ -16,9 +16,9 @@ export interface Params {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TagText = ({ text }: { text: string }) => {
|
const TagText = ({ text }: { text: string }) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
return <Text style={{ color: theme.blue }}>{text}</Text>
|
return <Text style={{ color: colors.blue }}>{text}</Text>
|
||||||
}
|
}
|
||||||
|
|
||||||
const debouncedSuggestions = debounce(
|
const debouncedSuggestions = debounce(
|
||||||
|
7
src/screens/Compose/utils/types.d.ts
vendored
7
src/screens/Compose/utils/types.d.ts
vendored
@ -40,7 +40,12 @@ export type ComposeState = {
|
|||||||
}
|
}
|
||||||
emoji: {
|
emoji: {
|
||||||
active: boolean
|
active: boolean
|
||||||
emojis: { title: string; data: Mastodon.Emoji[][] }[] | undefined
|
emojis:
|
||||||
|
| {
|
||||||
|
title: string
|
||||||
|
data: Pick<Mastodon.Emoji, 'shortcode' | 'url' | 'static_url'>[][]
|
||||||
|
}[]
|
||||||
|
| undefined
|
||||||
}
|
}
|
||||||
poll: {
|
poll: {
|
||||||
active: boolean
|
active: boolean
|
||||||
|
@ -2,6 +2,7 @@ import haptics from '@components/haptics'
|
|||||||
import { displayMessage } from '@components/Message'
|
import { displayMessage } from '@components/Message'
|
||||||
import CameraRoll from '@react-native-community/cameraroll'
|
import CameraRoll from '@react-native-community/cameraroll'
|
||||||
import { RootStackParamList } from '@utils/navigation/navigators'
|
import { RootStackParamList } from '@utils/navigation/navigators'
|
||||||
|
import { Theme } from '@utils/styles/themes'
|
||||||
import * as FileSystem from 'expo-file-system'
|
import * as FileSystem from 'expo-file-system'
|
||||||
import i18next from 'i18next'
|
import i18next from 'i18next'
|
||||||
import { RefObject } from 'react'
|
import { RefObject } from 'react'
|
||||||
@ -10,17 +11,17 @@ import FlashMessage from 'react-native-flash-message'
|
|||||||
|
|
||||||
type CommonProps = {
|
type CommonProps = {
|
||||||
messageRef: RefObject<FlashMessage>
|
messageRef: RefObject<FlashMessage>
|
||||||
mode: 'light' | 'dark'
|
theme: Theme
|
||||||
image: RootStackParamList['Screen-ImagesViewer']['imageUrls'][0]
|
image: RootStackParamList['Screen-ImagesViewer']['imageUrls'][0]
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveIos = async ({ messageRef, mode, image }: CommonProps) => {
|
const saveIos = async ({ messageRef, theme, image }: CommonProps) => {
|
||||||
CameraRoll.save(image.url)
|
CameraRoll.save(image.url)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
haptics('Success')
|
haptics('Success')
|
||||||
displayMessage({
|
displayMessage({
|
||||||
ref: messageRef,
|
ref: messageRef,
|
||||||
mode,
|
theme,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: i18next.t('screenImageViewer:content.save.succeed')
|
message: i18next.t('screenImageViewer:content.save.succeed')
|
||||||
})
|
})
|
||||||
@ -32,7 +33,7 @@ const saveIos = async ({ messageRef, mode, image }: CommonProps) => {
|
|||||||
haptics('Success')
|
haptics('Success')
|
||||||
displayMessage({
|
displayMessage({
|
||||||
ref: messageRef,
|
ref: messageRef,
|
||||||
mode,
|
theme,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: i18next.t('screenImageViewer:content.save.succeed')
|
message: i18next.t('screenImageViewer:content.save.succeed')
|
||||||
})
|
})
|
||||||
@ -41,7 +42,7 @@ const saveIos = async ({ messageRef, mode, image }: CommonProps) => {
|
|||||||
haptics('Error')
|
haptics('Error')
|
||||||
displayMessage({
|
displayMessage({
|
||||||
ref: messageRef,
|
ref: messageRef,
|
||||||
mode,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: i18next.t('screenImageViewer:content.save.failed')
|
message: i18next.t('screenImageViewer:content.save.failed')
|
||||||
})
|
})
|
||||||
@ -50,7 +51,7 @@ const saveIos = async ({ messageRef, mode, image }: CommonProps) => {
|
|||||||
haptics('Error')
|
haptics('Error')
|
||||||
displayMessage({
|
displayMessage({
|
||||||
ref: messageRef,
|
ref: messageRef,
|
||||||
mode,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: i18next.t('screenImageViewer:content.save.failed')
|
message: i18next.t('screenImageViewer:content.save.failed')
|
||||||
})
|
})
|
||||||
@ -58,7 +59,7 @@ const saveIos = async ({ messageRef, mode, image }: CommonProps) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveAndroid = async ({ messageRef, mode, image }: CommonProps) => {
|
const saveAndroid = async ({ messageRef, theme, image }: CommonProps) => {
|
||||||
const fileUri: string = `${FileSystem.documentDirectory}${image.id}.jpg`
|
const fileUri: string = `${FileSystem.documentDirectory}${image.id}.jpg`
|
||||||
const downloadedFile: FileSystem.FileSystemDownloadResult =
|
const downloadedFile: FileSystem.FileSystemDownloadResult =
|
||||||
await FileSystem.downloadAsync(image.url, fileUri)
|
await FileSystem.downloadAsync(image.url, fileUri)
|
||||||
@ -67,7 +68,7 @@ const saveAndroid = async ({ messageRef, mode, image }: CommonProps) => {
|
|||||||
haptics('Error')
|
haptics('Error')
|
||||||
displayMessage({
|
displayMessage({
|
||||||
ref: messageRef,
|
ref: messageRef,
|
||||||
mode,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: i18next.t('screenImageViewer:content.save.failed')
|
message: i18next.t('screenImageViewer:content.save.failed')
|
||||||
})
|
})
|
||||||
@ -83,7 +84,7 @@ const saveAndroid = async ({ messageRef, mode, image }: CommonProps) => {
|
|||||||
haptics('Error')
|
haptics('Error')
|
||||||
displayMessage({
|
displayMessage({
|
||||||
ref: messageRef,
|
ref: messageRef,
|
||||||
mode,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: i18next.t('screenImageViewer:content.save.failed')
|
message: i18next.t('screenImageViewer:content.save.failed')
|
||||||
})
|
})
|
||||||
@ -96,7 +97,7 @@ const saveAndroid = async ({ messageRef, mode, image }: CommonProps) => {
|
|||||||
haptics('Success')
|
haptics('Success')
|
||||||
displayMessage({
|
displayMessage({
|
||||||
ref: messageRef,
|
ref: messageRef,
|
||||||
mode,
|
theme,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: i18next.t('screenImageViewer:content.save.succeed')
|
message: i18next.t('screenImageViewer:content.save.succeed')
|
||||||
})
|
})
|
||||||
@ -105,7 +106,7 @@ const saveAndroid = async ({ messageRef, mode, image }: CommonProps) => {
|
|||||||
haptics('Error')
|
haptics('Error')
|
||||||
displayMessage({
|
displayMessage({
|
||||||
ref: messageRef,
|
ref: messageRef,
|
||||||
mode,
|
theme,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: i18next.t('screenImageViewer:content.save.failed')
|
message: i18next.t('screenImageViewer:content.save.failed')
|
||||||
})
|
})
|
||||||
|
@ -35,7 +35,7 @@ const HeaderComponent = React.memo(
|
|||||||
imageUrls: RootStackParamList['Screen-ImagesViewer']['imageUrls']
|
imageUrls: RootStackParamList['Screen-ImagesViewer']['imageUrls']
|
||||||
}) => {
|
}) => {
|
||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
const { mode } = useTheme()
|
const { mode, theme } = useTheme()
|
||||||
const { t } = useTranslation('screenImageViewer')
|
const { t } = useTranslation('screenImageViewer')
|
||||||
const { showActionSheetWithOptions } = useActionSheet()
|
const { showActionSheetWithOptions } = useActionSheet()
|
||||||
|
|
||||||
@ -48,13 +48,14 @@ const HeaderComponent = React.memo(
|
|||||||
t('content.options.share'),
|
t('content.options.share'),
|
||||||
t('content.options.cancel')
|
t('content.options.cancel')
|
||||||
],
|
],
|
||||||
cancelButtonIndex: 2
|
cancelButtonIndex: 2,
|
||||||
|
userInterfaceStyle: mode
|
||||||
},
|
},
|
||||||
async buttonIndex => {
|
async buttonIndex => {
|
||||||
switch (buttonIndex) {
|
switch (buttonIndex) {
|
||||||
case 0:
|
case 0:
|
||||||
analytics('imageviewer_more_save_press')
|
analytics('imageviewer_more_save_press')
|
||||||
saveImage({ messageRef, mode, image: imageUrls[currentIndex] })
|
saveImage({ messageRef, theme, image: imageUrls[currentIndex] })
|
||||||
break
|
break
|
||||||
case 1:
|
case 1:
|
||||||
analytics('imageviewer_more_share_press')
|
analytics('imageviewer_more_share_press')
|
||||||
@ -117,7 +118,7 @@ const ScreenImagesViewer = ({
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const { mode } = useTheme()
|
const { theme } = useTheme()
|
||||||
|
|
||||||
const initialIndex = imageUrls.findIndex(image => image.id === id)
|
const initialIndex = imageUrls.findIndex(image => image.id === id)
|
||||||
const [currentIndex, setCurrentIndex] = useState(initialIndex)
|
const [currentIndex, setCurrentIndex] = useState(initialIndex)
|
||||||
@ -132,7 +133,7 @@ const ScreenImagesViewer = ({
|
|||||||
imageIndex={initialIndex}
|
imageIndex={initialIndex}
|
||||||
onImageIndexChange={index => setCurrentIndex(index)}
|
onImageIndexChange={index => setCurrentIndex(index)}
|
||||||
onRequestClose={() => navigation.goBack()}
|
onRequestClose={() => navigation.goBack()}
|
||||||
onLongPress={image => saveImage({ messageRef, mode, image })}
|
onLongPress={image => saveImage({ messageRef, theme, image })}
|
||||||
HeaderComponent={() => (
|
HeaderComponent={() => (
|
||||||
<HeaderComponent
|
<HeaderComponent
|
||||||
messageRef={messageRef}
|
messageRef={messageRef}
|
||||||
|
@ -31,7 +31,7 @@ const Tab = createBottomTabNavigator<ScreenTabsStackParamList>()
|
|||||||
|
|
||||||
const ScreenTabs = React.memo(
|
const ScreenTabs = React.memo(
|
||||||
({ navigation }: RootStackScreenProps<'Screen-Tabs'>) => {
|
({ navigation }: RootStackScreenProps<'Screen-Tabs'>) => {
|
||||||
const { theme } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const instanceActive = useSelector(getInstanceActive)
|
const instanceActive = useSelector(getInstanceActive)
|
||||||
const instanceAccount = useSelector(
|
const instanceAccount = useSelector(
|
||||||
@ -42,8 +42,8 @@ const ScreenTabs = React.memo(
|
|||||||
const screenOptions = useCallback(
|
const screenOptions = useCallback(
|
||||||
({ route }): BottomTabNavigationOptions => ({
|
({ route }): BottomTabNavigationOptions => ({
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
tabBarActiveTintColor: theme.primaryDefault,
|
tabBarActiveTintColor: colors.primaryDefault,
|
||||||
tabBarInactiveTintColor: theme.secondary,
|
tabBarInactiveTintColor: colors.secondary,
|
||||||
tabBarShowLabel: false,
|
tabBarShowLabel: false,
|
||||||
...(Platform.OS === 'android' && { tabBarHideOnKeyboard: true }),
|
...(Platform.OS === 'android' && { tabBarHideOnKeyboard: true }),
|
||||||
tabBarStyle: { display: instanceActive !== -1 ? 'flex' : 'none' },
|
tabBarStyle: { display: instanceActive !== -1 ? 'flex' : 'none' },
|
||||||
@ -78,7 +78,7 @@ const ScreenTabs = React.memo(
|
|||||||
borderRadius: size,
|
borderRadius: size,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
borderWidth: focused ? 2 : 0,
|
borderWidth: focused ? 2 : 0,
|
||||||
borderColor: focused ? theme.secondary : color
|
borderColor: focused ? colors.secondary : color
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -23,16 +23,18 @@ const prepareFields = (
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const TabMeProfileFields: React.FC<TabMeProfileStackScreenProps<
|
const TabMeProfileFields: React.FC<
|
||||||
'Tab-Me-Profile-Fields'
|
TabMeProfileStackScreenProps<'Tab-Me-Profile-Fields'> & {
|
||||||
> & { messageRef: RefObject<FlashMessage> }> = ({
|
messageRef: RefObject<FlashMessage>
|
||||||
|
}
|
||||||
|
> = ({
|
||||||
messageRef,
|
messageRef,
|
||||||
route: {
|
route: {
|
||||||
params: { fields }
|
params: { fields }
|
||||||
},
|
},
|
||||||
navigation
|
navigation
|
||||||
}) => {
|
}) => {
|
||||||
const { mode, theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
const { t, i18n } = useTranslation('screenTabs')
|
const { t, i18n } = useTranslation('screenTabs')
|
||||||
const { mutateAsync, status } = useProfileMutation()
|
const { mutateAsync, status } = useProfileMutation()
|
||||||
|
|
||||||
@ -77,7 +79,7 @@ const TabMeProfileFields: React.FC<TabMeProfileStackScreenProps<
|
|||||||
content='Save'
|
content='Save'
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
mode,
|
theme,
|
||||||
messageRef,
|
messageRef,
|
||||||
message: {
|
message: {
|
||||||
text: 'me.profile.root.note.title',
|
text: 'me.profile.root.note.title',
|
||||||
@ -95,14 +97,14 @@ const TabMeProfileFields: React.FC<TabMeProfileStackScreenProps<
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}, [mode, i18n.language, dirty, status, newFields])
|
}, [theme, i18n.language, dirty, status, newFields])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView style={styles.base} keyboardShouldPersistTaps='always'>
|
<ScrollView style={styles.base} keyboardShouldPersistTaps='always'>
|
||||||
<View style={{ marginBottom: StyleConstants.Spacing.L * 2 }}>
|
<View style={{ marginBottom: StyleConstants.Spacing.L * 2 }}>
|
||||||
{Array.from(Array(4).keys()).map(index => (
|
{Array.from(Array(4).keys()).map(index => (
|
||||||
<View key={index} style={styles.group}>
|
<View key={index} style={styles.group}>
|
||||||
<Text style={[styles.headline, { color: theme.primaryDefault }]}>
|
<Text style={[styles.headline, { color: colors.primaryDefault }]}>
|
||||||
{t('me.profile.fields.group', { index: index + 1 })}
|
{t('me.profile.fields.group', { index: index + 1 })}
|
||||||
</Text>
|
</Text>
|
||||||
<Input
|
<Input
|
||||||
|
@ -21,7 +21,7 @@ const TabMeProfileName: React.FC<
|
|||||||
},
|
},
|
||||||
navigation
|
navigation
|
||||||
}) => {
|
}) => {
|
||||||
const { mode } = useTheme()
|
const { theme } = useTheme()
|
||||||
const { t, i18n } = useTranslation('screenTabs')
|
const { t, i18n } = useTranslation('screenTabs')
|
||||||
const { mutateAsync, status } = useProfileMutation()
|
const { mutateAsync, status } = useProfileMutation()
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ const TabMeProfileName: React.FC<
|
|||||||
content='Save'
|
content='Save'
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
mode,
|
theme,
|
||||||
messageRef,
|
messageRef,
|
||||||
message: {
|
message: {
|
||||||
text: 'me.profile.root.name.title',
|
text: 'me.profile.root.name.title',
|
||||||
@ -82,7 +82,7 @@ const TabMeProfileName: React.FC<
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}, [mode, i18n.language, dirty, status, displayName])
|
}, [theme, i18n.language, dirty, status, displayName])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView style={styles.base} keyboardShouldPersistTaps='always'>
|
<ScrollView style={styles.base} keyboardShouldPersistTaps='always'>
|
||||||
|
@ -10,16 +10,18 @@ import { Alert, StyleSheet, View } from 'react-native'
|
|||||||
import FlashMessage from 'react-native-flash-message'
|
import FlashMessage from 'react-native-flash-message'
|
||||||
import { ScrollView } from 'react-native-gesture-handler'
|
import { ScrollView } from 'react-native-gesture-handler'
|
||||||
|
|
||||||
const TabMeProfileNote: React.FC<TabMeProfileStackScreenProps<
|
const TabMeProfileNote: React.FC<
|
||||||
'Tab-Me-Profile-Note'
|
TabMeProfileStackScreenProps<'Tab-Me-Profile-Note'> & {
|
||||||
> & { messageRef: RefObject<FlashMessage> }> = ({
|
messageRef: RefObject<FlashMessage>
|
||||||
|
}
|
||||||
|
> = ({
|
||||||
messageRef,
|
messageRef,
|
||||||
route: {
|
route: {
|
||||||
params: { note }
|
params: { note }
|
||||||
},
|
},
|
||||||
navigation
|
navigation
|
||||||
}) => {
|
}) => {
|
||||||
const { mode } = useTheme()
|
const { theme } = useTheme()
|
||||||
const { t, i18n } = useTranslation('screenTabs')
|
const { t, i18n } = useTranslation('screenTabs')
|
||||||
const { mutateAsync, status } = useProfileMutation()
|
const { mutateAsync, status } = useProfileMutation()
|
||||||
|
|
||||||
@ -64,7 +66,7 @@ const TabMeProfileNote: React.FC<TabMeProfileStackScreenProps<
|
|||||||
content='Save'
|
content='Save'
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
mode,
|
theme,
|
||||||
messageRef,
|
messageRef,
|
||||||
message: {
|
message: {
|
||||||
text: 'me.profile.root.note.title',
|
text: 'me.profile.root.note.title',
|
||||||
@ -80,7 +82,7 @@ const TabMeProfileNote: React.FC<TabMeProfileStackScreenProps<
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}, [mode, i18n.language, dirty, status, newNote])
|
}, [theme, i18n.language, dirty, status, newNote])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView style={styles.base} keyboardShouldPersistTaps='always'>
|
<ScrollView style={styles.base} keyboardShouldPersistTaps='always'>
|
||||||
|
@ -12,10 +12,12 @@ import { ScrollView } from 'react-native-gesture-handler'
|
|||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
import ProfileAvatarHeader from './Root/AvatarHeader'
|
import ProfileAvatarHeader from './Root/AvatarHeader'
|
||||||
|
|
||||||
const TabMeProfileRoot: React.FC<TabMeProfileStackScreenProps<
|
const TabMeProfileRoot: React.FC<
|
||||||
'Tab-Me-Profile-Root'
|
TabMeProfileStackScreenProps<'Tab-Me-Profile-Root'> & {
|
||||||
> & { messageRef: RefObject<FlashMessage> }> = ({ messageRef, navigation }) => {
|
messageRef: RefObject<FlashMessage>
|
||||||
const { mode } = useTheme()
|
}
|
||||||
|
> = ({ messageRef, navigation }) => {
|
||||||
|
const { mode, theme } = useTheme()
|
||||||
const { t } = useTranslation('screenTabs')
|
const { t } = useTranslation('screenTabs')
|
||||||
|
|
||||||
const { showActionSheetWithOptions } = useActionSheet()
|
const { showActionSheetWithOptions } = useActionSheet()
|
||||||
@ -34,7 +36,8 @@ const TabMeProfileRoot: React.FC<TabMeProfileStackScreenProps<
|
|||||||
t('me.profile.root.visibility.options.private'),
|
t('me.profile.root.visibility.options.private'),
|
||||||
t('me.profile.root.visibility.options.cancel')
|
t('me.profile.root.visibility.options.cancel')
|
||||||
],
|
],
|
||||||
cancelButtonIndex: 3
|
cancelButtonIndex: 3,
|
||||||
|
userInterfaceStyle: mode
|
||||||
},
|
},
|
||||||
async buttonIndex => {
|
async buttonIndex => {
|
||||||
switch (buttonIndex) {
|
switch (buttonIndex) {
|
||||||
@ -54,7 +57,7 @@ const TabMeProfileRoot: React.FC<TabMeProfileStackScreenProps<
|
|||||||
new: indexVisibilityMapping[buttonIndex]
|
new: indexVisibilityMapping[buttonIndex]
|
||||||
})
|
})
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
mode,
|
theme,
|
||||||
messageRef,
|
messageRef,
|
||||||
message: {
|
message: {
|
||||||
text: 'me.profile.root.visibility.title',
|
text: 'me.profile.root.visibility.title',
|
||||||
@ -69,7 +72,7 @@ const TabMeProfileRoot: React.FC<TabMeProfileStackScreenProps<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}, [data?.source.privacy])
|
}, [theme, data?.source.privacy])
|
||||||
|
|
||||||
const onPressSensitive = useCallback(() => {
|
const onPressSensitive = useCallback(() => {
|
||||||
analytics('me_profile_sensitive', {
|
analytics('me_profile_sensitive', {
|
||||||
@ -77,7 +80,7 @@ const TabMeProfileRoot: React.FC<TabMeProfileStackScreenProps<
|
|||||||
new: data?.source.sensitive === undefined ? true : !data.source.sensitive
|
new: data?.source.sensitive === undefined ? true : !data.source.sensitive
|
||||||
})
|
})
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
mode,
|
theme,
|
||||||
messageRef,
|
messageRef,
|
||||||
message: {
|
message: {
|
||||||
text: 'me.profile.root.sensitive.title',
|
text: 'me.profile.root.sensitive.title',
|
||||||
@ -95,7 +98,7 @@ const TabMeProfileRoot: React.FC<TabMeProfileStackScreenProps<
|
|||||||
new: data?.locked === undefined ? true : !data.locked
|
new: data?.locked === undefined ? true : !data.locked
|
||||||
})
|
})
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
mode,
|
theme,
|
||||||
messageRef,
|
messageRef,
|
||||||
message: {
|
message: {
|
||||||
text: 'me.profile.root.lock.title',
|
text: 'me.profile.root.lock.title',
|
||||||
@ -105,7 +108,7 @@ const TabMeProfileRoot: React.FC<TabMeProfileStackScreenProps<
|
|||||||
type: 'locked',
|
type: 'locked',
|
||||||
data: data?.locked === undefined ? true : !data.locked
|
data: data?.locked === undefined ? true : !data.locked
|
||||||
})
|
})
|
||||||
}, [data?.locked])
|
}, [theme, data?.locked])
|
||||||
|
|
||||||
const onPressBot = useCallback(() => {
|
const onPressBot = useCallback(() => {
|
||||||
analytics('me_profile_bot', {
|
analytics('me_profile_bot', {
|
||||||
@ -113,7 +116,7 @@ const TabMeProfileRoot: React.FC<TabMeProfileStackScreenProps<
|
|||||||
new: data?.bot === undefined ? true : !data.bot
|
new: data?.bot === undefined ? true : !data.bot
|
||||||
})
|
})
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
mode,
|
theme,
|
||||||
messageRef,
|
messageRef,
|
||||||
message: {
|
message: {
|
||||||
text: 'me.profile.root.bot.title',
|
text: 'me.profile.root.bot.title',
|
||||||
@ -123,7 +126,7 @@ const TabMeProfileRoot: React.FC<TabMeProfileStackScreenProps<
|
|||||||
type: 'bot',
|
type: 'bot',
|
||||||
data: data?.bot === undefined ? true : !data.bot
|
data: data?.bot === undefined ? true : !data.bot
|
||||||
})
|
})
|
||||||
}, [data?.bot])
|
}, [theme, data?.bot])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
|
@ -14,7 +14,7 @@ export interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ProfileAvatarHeader: React.FC<Props> = ({ type, messageRef }) => {
|
const ProfileAvatarHeader: React.FC<Props> = ({ type, messageRef }) => {
|
||||||
const { mode } = useTheme()
|
const { theme } = useTheme()
|
||||||
const { t } = useTranslation('screenTabs')
|
const { t } = useTranslation('screenTabs')
|
||||||
|
|
||||||
const { showActionSheetWithOptions } = useActionSheet()
|
const { showActionSheetWithOptions } = useActionSheet()
|
||||||
@ -35,7 +35,7 @@ const ProfileAvatarHeader: React.FC<Props> = ({ type, messageRef }) => {
|
|||||||
resize: { width: 400, height: 400 }
|
resize: { width: 400, height: 400 }
|
||||||
})
|
})
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
mode,
|
theme,
|
||||||
messageRef,
|
messageRef,
|
||||||
message: {
|
message: {
|
||||||
text: `me.profile.root.${type}.title`,
|
text: `me.profile.root.${type}.title`,
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user