mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
Merge branch 'main' into candidate
This commit is contained in:
@ -306,7 +306,7 @@ PODS:
|
|||||||
- React-Core
|
- React-Core
|
||||||
- react-native-language-detection (0.2.2):
|
- react-native-language-detection (0.2.2):
|
||||||
- React
|
- React
|
||||||
- react-native-menu (0.7.2):
|
- react-native-menu (0.7.3):
|
||||||
- React
|
- React
|
||||||
- react-native-mmkv (2.5.1):
|
- react-native-mmkv (2.5.1):
|
||||||
- MMKV (>= 1.2.13)
|
- MMKV (>= 1.2.13)
|
||||||
@ -748,7 +748,7 @@ SPEC CHECKSUMS:
|
|||||||
react-native-image-picker: 60f4246eb5bb7187fc15638a8c1f13abd3820695
|
react-native-image-picker: 60f4246eb5bb7187fc15638a8c1f13abd3820695
|
||||||
react-native-ios-context-menu: b170594b4448c0cd10c79e13432216bac99de1ac
|
react-native-ios-context-menu: b170594b4448c0cd10c79e13432216bac99de1ac
|
||||||
react-native-language-detection: f414937fa715108ab50a6269a3de0bcb95e4ceb0
|
react-native-language-detection: f414937fa715108ab50a6269a3de0bcb95e4ceb0
|
||||||
react-native-menu: 8e172cfcf0e42e92f028e7781eddf84d430cae24
|
react-native-menu: 9d7d6f819cc7fa14a15cf86888c53f3240d86f1b
|
||||||
react-native-mmkv: 69b9c003f10afdd01addf7c6ee784ce42ee2eff3
|
react-native-mmkv: 69b9c003f10afdd01addf7c6ee784ce42ee2eff3
|
||||||
react-native-netinfo: 2517ad504b3d303e90d7a431b0fcaef76d207983
|
react-native-netinfo: 2517ad504b3d303e90d7a431b0fcaef76d207983
|
||||||
react-native-pager-view: 54bed894cecebe28cede54c01038d9d1e122de43
|
react-native-pager-view: 54bed894cecebe28cede54c01038d9d1e122de43
|
||||||
|
@ -86,5 +86,7 @@
|
|||||||
<string>Automatic</string>
|
<string>Automatic</string>
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<false/>
|
<false/>
|
||||||
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -90,7 +90,6 @@
|
|||||||
"react-native-tab-view": "^3.3.4",
|
"react-native-tab-view": "^3.3.4",
|
||||||
"react-redux": "^8.0.5",
|
"react-redux": "^8.0.5",
|
||||||
"rn-placeholder": "^3.0.3",
|
"rn-placeholder": "^3.0.3",
|
||||||
"rtl-detect": "^1.0.4",
|
|
||||||
"valid-url": "^1.0.9",
|
"valid-url": "^1.0.9",
|
||||||
"zeego": "^1.0.2"
|
"zeego": "^1.0.2"
|
||||||
},
|
},
|
||||||
|
@ -15,7 +15,7 @@ interface Props {
|
|||||||
const AccountButton: React.FC<Props> = ({ account, selected = false, additionalActions }) => {
|
const AccountButton: React.FC<Props> = ({ account, selected = false, additionalActions }) => {
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
const accountDetails = getAccountDetails(
|
const accountDetails = getAccountDetails(
|
||||||
['auth.account.acct', 'auth.domain', 'auth.account.id'],
|
['auth.domain', 'auth.account.acct', 'auth.account.domain', 'auth.account.id'],
|
||||||
account
|
account
|
||||||
)
|
)
|
||||||
if (!accountDetails) return null
|
if (!accountDetails) return null
|
||||||
@ -28,7 +28,7 @@ const AccountButton: React.FC<Props> = ({ account, selected = false, additionalA
|
|||||||
marginBottom: StyleConstants.Spacing.M,
|
marginBottom: StyleConstants.Spacing.M,
|
||||||
marginRight: StyleConstants.Spacing.M
|
marginRight: StyleConstants.Spacing.M
|
||||||
}}
|
}}
|
||||||
content={`@${accountDetails['auth.account.acct']}@${accountDetails['auth.domain']}${
|
content={`@${accountDetails['auth.account.acct']}@${accountDetails['auth.account.domain']}${
|
||||||
selected ? ' ✓' : ''
|
selected ? ' ✓' : ''
|
||||||
}`}
|
}`}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
|
@ -123,6 +123,8 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
'auth.domain': domain,
|
'auth.domain': domain,
|
||||||
'auth.account.id': id,
|
'auth.account.id': id,
|
||||||
'auth.account.acct': acct,
|
'auth.account.acct': acct,
|
||||||
|
// @ts-ignore
|
||||||
|
'auth.account.domain': instanceQuery.data?.domain || instanceQuery.data?.uri,
|
||||||
'auth.account.avatar_static': avatar_static,
|
'auth.account.avatar_static': avatar_static,
|
||||||
version: instanceQuery.data?.version || '0',
|
version: instanceQuery.data?.version || '0',
|
||||||
preferences: undefined,
|
preferences: undefined,
|
||||||
@ -190,7 +192,7 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
const processUpdate = useCallback(() => {
|
const processUpdate = useCallback(() => {
|
||||||
if (domain) {
|
if (domain) {
|
||||||
const accounts = getGlobalStorage.object('accounts')
|
const accounts = getGlobalStorage.object('accounts')
|
||||||
if (accounts && accounts.filter(account => account.startsWith(`${domain}/`)).length) {
|
if (accounts?.filter(account => account.startsWith(`${domain}/`)).length) {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
t('componentInstance:update.alert.title'),
|
t('componentInstance:update.alert.title'),
|
||||||
t('componentInstance:update.alert.message'),
|
t('componentInstance:update.alert.message'),
|
||||||
|
@ -3,10 +3,10 @@ import CustomText from '@components/Text'
|
|||||||
import { usePreferencesQuery } from '@utils/queryHooks/preferences'
|
import { usePreferencesQuery } from '@utils/queryHooks/preferences'
|
||||||
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 i18next from 'i18next'
|
||||||
import React, { useContext } from 'react'
|
import React, { useContext } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Platform, View } from 'react-native'
|
import { Platform, View } from 'react-native'
|
||||||
import { isRtlLang } from 'rtl-detect'
|
|
||||||
import StatusContext from './Context'
|
import StatusContext from './Context'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
@ -23,6 +23,11 @@ const TimelineContent: React.FC<Props> = ({ notificationOwnToot = false, setSpoi
|
|||||||
|
|
||||||
const { data: preferences } = usePreferencesQuery()
|
const { data: preferences } = usePreferencesQuery()
|
||||||
|
|
||||||
|
const isRTLiOSTextStyles =
|
||||||
|
Platform.OS === 'ios' && status.language && i18next.dir(status.language) === 'rtl'
|
||||||
|
? ({ writingDirection: 'rtl' } as { writingDirection: 'rtl' })
|
||||||
|
: undefined
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
{status.spoiler_text?.length ? (
|
{status.spoiler_text?.length ? (
|
||||||
@ -37,11 +42,7 @@ const TimelineContent: React.FC<Props> = ({ notificationOwnToot = false, setSpoi
|
|||||||
numberOfLines={999}
|
numberOfLines={999}
|
||||||
highlighted={highlighted}
|
highlighted={highlighted}
|
||||||
disableDetails={disableDetails}
|
disableDetails={disableDetails}
|
||||||
textStyles={
|
textStyles={isRTLiOSTextStyles}
|
||||||
Platform.OS === 'ios' && status.language && isRtlLang(status.language)
|
|
||||||
? { writingDirection: 'rtl' }
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
{inThread ? (
|
{inThread ? (
|
||||||
<CustomText
|
<CustomText
|
||||||
@ -73,11 +74,7 @@ const TimelineContent: React.FC<Props> = ({ notificationOwnToot = false, setSpoi
|
|||||||
setSpoilerExpanded={setSpoilerExpanded}
|
setSpoilerExpanded={setSpoilerExpanded}
|
||||||
highlighted={highlighted}
|
highlighted={highlighted}
|
||||||
disableDetails={disableDetails}
|
disableDetails={disableDetails}
|
||||||
textStyles={
|
textStyles={isRTLiOSTextStyles}
|
||||||
Platform.OS === 'ios' && status.language && isRtlLang(status.language)
|
|
||||||
? { writingDirection: 'rtl' }
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
@ -90,11 +87,7 @@ const TimelineContent: React.FC<Props> = ({ notificationOwnToot = false, setSpoi
|
|||||||
tags={status.tags}
|
tags={status.tags}
|
||||||
numberOfLines={highlighted || inThread ? 999 : notificationOwnToot ? 2 : undefined}
|
numberOfLines={highlighted || inThread ? 999 : notificationOwnToot ? 2 : undefined}
|
||||||
disableDetails={disableDetails}
|
disableDetails={disableDetails}
|
||||||
textStyles={
|
textStyles={isRTLiOSTextStyles}
|
||||||
Platform.OS === 'ios' && status.language && isRtlLang(status.language)
|
|
||||||
? { writingDirection: 'rtl' }
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
@ -115,7 +115,7 @@
|
|||||||
"accessibilityHint": "User's account"
|
"accessibilityHint": "User's account"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"application": "Via {{application}}",
|
"application": "via {{application}}",
|
||||||
"edited": {
|
"edited": {
|
||||||
"accessibilityLabel": "Toot edited"
|
"accessibilityLabel": "Toot edited"
|
||||||
},
|
},
|
||||||
|
@ -23,7 +23,7 @@ const ComposePostingAs = () => {
|
|||||||
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
|
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
|
||||||
{t('content.root.header.postingAs', {
|
{t('content.root.header.postingAs', {
|
||||||
acct: getAccountStorage.string('auth.account.acct'),
|
acct: getAccountStorage.string('auth.account.acct'),
|
||||||
domain: getAccountStorage.string('auth.domain')
|
domain: getAccountStorage.string('auth.account.domain')
|
||||||
})}
|
})}
|
||||||
</CustomText>
|
</CustomText>
|
||||||
</View>
|
</View>
|
||||||
|
@ -53,7 +53,6 @@ const TabMeFollowedTags: React.FC<TabMeStackScreenProps<'Tab-Me-FollowedTags'>>
|
|||||||
renderItem={({ item }) => (
|
renderItem={({ item }) => (
|
||||||
<ComponentHashtag
|
<ComponentHashtag
|
||||||
hashtag={item}
|
hashtag={item}
|
||||||
onPress={() => {}}
|
|
||||||
children={
|
children={
|
||||||
<Button
|
<Button
|
||||||
type='text'
|
type='text'
|
||||||
|
@ -29,8 +29,9 @@ const TabMePush: React.FC = () => {
|
|||||||
const [expoToken] = useGlobalStorage.string('app.expo_token')
|
const [expoToken] = useGlobalStorage.string('app.expo_token')
|
||||||
const [push] = useAccountStorage.object('push')
|
const [push] = useAccountStorage.object('push')
|
||||||
const [domain] = useAccountStorage.string('auth.domain')
|
const [domain] = useAccountStorage.string('auth.domain')
|
||||||
const [accountId] = useAccountStorage.string('auth.account.id')
|
|
||||||
const [accountAcct] = useAccountStorage.string('auth.account.acct')
|
const [accountAcct] = useAccountStorage.string('auth.account.acct')
|
||||||
|
const [accountDomain] = useAccountStorage.string('auth.account.domain')
|
||||||
|
const [accountId] = useAccountStorage.string('auth.account.id')
|
||||||
|
|
||||||
const appsQuery = useAppsQuery()
|
const appsQuery = useAppsQuery()
|
||||||
|
|
||||||
@ -65,7 +66,7 @@ const TabMePush: React.FC = () => {
|
|||||||
|
|
||||||
const alerts = () =>
|
const alerts = () =>
|
||||||
push?.alerts
|
push?.alerts
|
||||||
? PUSH_DEFAULT.map(alert => (
|
? PUSH_DEFAULT().map(alert => (
|
||||||
<MenuRow
|
<MenuRow
|
||||||
key={alert}
|
key={alert}
|
||||||
title={t(`me.push.${alert}.heading`)}
|
title={t(`me.push.${alert}.heading`)}
|
||||||
@ -93,7 +94,7 @@ const TabMePush: React.FC = () => {
|
|||||||
const profileQuery = useProfileQuery()
|
const profileQuery = useProfileQuery()
|
||||||
const adminAlerts = () =>
|
const adminAlerts = () =>
|
||||||
profileQuery.data?.role?.permissions
|
profileQuery.data?.role?.permissions
|
||||||
? PUSH_ADMIN.map(({ type }) => (
|
? PUSH_ADMIN().map(({ type }) => (
|
||||||
<MenuRow
|
<MenuRow
|
||||||
key={type}
|
key={type}
|
||||||
title={t(`me.push.${type}.heading`)}
|
title={t(`me.push.${type}.heading`)}
|
||||||
@ -119,7 +120,7 @@ const TabMePush: React.FC = () => {
|
|||||||
: null
|
: null
|
||||||
|
|
||||||
const pushPath = `${expoToken}/${domain}/${accountId}`
|
const pushPath = `${expoToken}/${domain}/${accountId}`
|
||||||
const accountFull = `@${accountAcct}@${domain}`
|
const accountFull = `@${accountAcct}@${accountDomain}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
@ -152,7 +153,7 @@ const TabMePush: React.FC = () => {
|
|||||||
) : null}
|
) : null}
|
||||||
<MenuContainer>
|
<MenuContainer>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
title={t('me.push.global.heading', { acct: `@${accountAcct}@${domain}` })}
|
title={t('me.push.global.heading', { acct: `@${accountAcct}@${accountDomain}` })}
|
||||||
description={t('me.push.global.description')}
|
description={t('me.push.global.description')}
|
||||||
switchDisabled={!pushEnabled}
|
switchDisabled={!pushEnabled}
|
||||||
switchValue={pushEnabled === false ? false : push?.global}
|
switchValue={pushEnabled === false ? false : push?.global}
|
||||||
|
@ -38,7 +38,7 @@ const SettingsApp: React.FC = () => {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
LOCALES[
|
LOCALES[
|
||||||
Platform.OS === 'ios'
|
Platform.OS === 'ios'
|
||||||
? Localization.locale.toLowerCase().replace(new RegExp(/.*-.*(-.*)/, 'i'), '')
|
? Localization.locale.replace(new RegExp(/.*-.*(-.*)/, 'i'), '')
|
||||||
: i18n.language.toLowerCase()
|
: i18n.language.toLowerCase()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import Button from '@components/Button'
|
|||||||
import { MenuContainer, MenuRow } from '@components/Menu'
|
import { MenuContainer, MenuRow } from '@components/Menu'
|
||||||
import { displayMessage } from '@components/Message'
|
import { displayMessage } from '@components/Message'
|
||||||
import { useActionSheet } from '@expo/react-native-action-sheet'
|
import { useActionSheet } from '@expo/react-native-action-sheet'
|
||||||
|
import { useNavigation } from '@react-navigation/native'
|
||||||
import { androidActionSheetStyles } from '@utils/helpers/androidActionSheetStyles'
|
import { androidActionSheetStyles } from '@utils/helpers/androidActionSheetStyles'
|
||||||
import { storage } from '@utils/storage'
|
import { storage } from '@utils/storage'
|
||||||
import { getGlobalStorage, useGlobalStorage } from '@utils/storage/actions'
|
import { getGlobalStorage, useGlobalStorage } from '@utils/storage/actions'
|
||||||
@ -11,6 +12,7 @@ import React from 'react'
|
|||||||
import { MMKV } from 'react-native-mmkv'
|
import { MMKV } from 'react-native-mmkv'
|
||||||
|
|
||||||
const SettingsDev: React.FC = () => {
|
const SettingsDev: React.FC = () => {
|
||||||
|
const navigation = useNavigation()
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { showActionSheetWithOptions } = useActionSheet()
|
const { showActionSheetWithOptions } = useActionSheet()
|
||||||
|
|
||||||
@ -54,16 +56,17 @@ const SettingsDev: React.FC = () => {
|
|||||||
destructive
|
destructive
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
const accounts = getGlobalStorage.object('accounts')
|
const accounts = getGlobalStorage.object('accounts')
|
||||||
if (!accounts) return
|
storage.account = undefined
|
||||||
|
if (accounts) {
|
||||||
for (const account of accounts) {
|
for (const account of accounts) {
|
||||||
console.log('Clearing', account)
|
console.log('Clearing', account)
|
||||||
const temp = new MMKV({ id: account })
|
const temp = new MMKV({ id: account })
|
||||||
temp.clearAll()
|
temp.clearAll()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Clearing', 'global')
|
console.log('Clearing', 'global')
|
||||||
storage.global.clearAll()
|
storage.global.clearAll()
|
||||||
|
navigation.goBack()
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
|
@ -88,11 +88,11 @@ const TabMeSettingsFontsize: React.FC<TabMeStackScreenProps<'Tab-Me-Settings-Fon
|
|||||||
marginBottom: StyleConstants.Spacing.M,
|
marginBottom: StyleConstants.Spacing.M,
|
||||||
fontSize: adaptiveScale(StyleConstants.Font.Size.M, size),
|
fontSize: adaptiveScale(StyleConstants.Font.Size.M, size),
|
||||||
lineHeight: adaptiveScale(StyleConstants.Font.LineHeight.M, size),
|
lineHeight: adaptiveScale(StyleConstants.Font.LineHeight.M, size),
|
||||||
color: fontSize === size ? colors.primaryDefault : colors.secondary,
|
color: (fontSize || 0) === size ? colors.primaryDefault : colors.secondary,
|
||||||
borderWidth: StyleSheet.hairlineWidth,
|
borderWidth: StyleSheet.hairlineWidth,
|
||||||
borderColor: colors.border
|
borderColor: colors.border
|
||||||
}}
|
}}
|
||||||
fontWeight={fontSize === size ? 'Bold' : undefined}
|
fontWeight={(fontSize || 0) === size ? 'Bold' : undefined}
|
||||||
>
|
>
|
||||||
{t(`me.fontSize.sizes.${mapFontsizeToName(size)}`)}
|
{t(`me.fontSize.sizes.${mapFontsizeToName(size)}`)}
|
||||||
</CustomText>
|
</CustomText>
|
||||||
@ -107,10 +107,10 @@ const TabMeSettingsFontsize: React.FC<TabMeStackScreenProps<'Tab-Me-Settings-Fon
|
|||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (fontSize && fontSize > -1) {
|
if ((fontSize || 0) > -1) {
|
||||||
haptics('Light')
|
haptics('Light')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
setFontSize(fontSize - 1)
|
setFontSize((fontSize || 0) - 1)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
type='icon'
|
type='icon'
|
||||||
@ -121,10 +121,10 @@ const TabMeSettingsFontsize: React.FC<TabMeStackScreenProps<'Tab-Me-Settings-Fon
|
|||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (fontSize && fontSize < 3) {
|
if ((fontSize || 0) < 3) {
|
||||||
haptics('Light')
|
haptics('Light')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
setFontSize(fontSize + 1)
|
setFontSize((fontSize || 0) + 1)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
type='icon'
|
type='icon'
|
||||||
|
@ -66,7 +66,7 @@ const TabNotificationsFilters: React.FC<
|
|||||||
return (
|
return (
|
||||||
<ScrollView style={{ flex: 1 }}>
|
<ScrollView style={{ flex: 1 }}>
|
||||||
<MenuContainer>
|
<MenuContainer>
|
||||||
{PUSH_DEFAULT.map((type, index) => (
|
{PUSH_DEFAULT().map((type, index) => (
|
||||||
<MenuRow
|
<MenuRow
|
||||||
key={index}
|
key={index}
|
||||||
title={t(`screenTabs:me.push.${type}.heading`)}
|
title={t(`screenTabs:me.push.${type}.heading`)}
|
||||||
@ -74,7 +74,9 @@ const TabNotificationsFilters: React.FC<
|
|||||||
switchOnValueChange={() => setFilters({ ...filters, [type]: !filters[type] })}
|
switchOnValueChange={() => setFilters({ ...filters, [type]: !filters[type] })}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
{PUSH_ADMIN.map(({ type }) => (
|
</MenuContainer>
|
||||||
|
<MenuContainer>
|
||||||
|
{PUSH_ADMIN().map(({ type }) => (
|
||||||
<MenuRow
|
<MenuRow
|
||||||
key={type}
|
key={type}
|
||||||
title={t(`screenTabs:me.push.${type}.heading`)}
|
title={t(`screenTabs:me.push.${type}.heading`)}
|
||||||
|
@ -19,7 +19,7 @@ const AccountInformationAccount: React.FC<Props> = ({ account, myInfo }) => {
|
|||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
|
|
||||||
const [acct] = useAccountStorage.string('auth.account.acct')
|
const [acct] = useAccountStorage.string('auth.account.acct')
|
||||||
const domain = getAccountStorage.string('auth.domain')
|
const domain = getAccountStorage.string('auth.account.domain')
|
||||||
|
|
||||||
const { data: relationship } = useRelationshipQuery({
|
const { data: relationship } = useRelationshipQuery({
|
||||||
id: account?.id || '',
|
id: account?.id || '',
|
||||||
|
@ -74,7 +74,7 @@ const TabSharedReport: React.FC<TabSharedStackScreenProps<'Tab-Shared-Report'>>
|
|||||||
}, [isReporting, comment, forward, categories, rules])
|
}, [isReporting, comment, forward, categories, rules])
|
||||||
|
|
||||||
const localInstance = account?.acct.includes('@')
|
const localInstance = account?.acct.includes('@')
|
||||||
? account?.acct.includes(`@${getAccountStorage.string('auth.domain')}`)
|
? account?.acct.includes(`@${getAccountStorage.string('auth.account.domain')}`)
|
||||||
: true
|
: true
|
||||||
|
|
||||||
const rulesQuery = useRulesQuery()
|
const rulesQuery = useRulesQuery()
|
||||||
|
@ -91,13 +91,7 @@ const SearchEmpty: React.FC<Props> = ({ isFetching, inputRef, setSearchTerm }) =
|
|||||||
return (
|
return (
|
||||||
<React.Fragment key={index}>
|
<React.Fragment key={index}>
|
||||||
{index !== 0 ? <ComponentSeparator /> : null}
|
{index !== 0 ? <ComponentSeparator /> : null}
|
||||||
<ComponentHashtag
|
<ComponentHashtag hashtag={hashtag} />
|
||||||
hashtag={hashtag}
|
|
||||||
onPress={() => {
|
|
||||||
inputRef.current?.setNativeProps({ text: `#${hashtag.name}` })
|
|
||||||
setSearchTerm(`#${hashtag.name}`)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
@ -10,43 +10,39 @@ import { QueryKeyProfile } from '@utils/queryHooks/profile'
|
|||||||
import { getAccountDetails, getGlobalStorage } from '@utils/storage/actions'
|
import { getAccountDetails, getGlobalStorage } from '@utils/storage/actions'
|
||||||
import * as Notifications from 'expo-notifications'
|
import * as Notifications from 'expo-notifications'
|
||||||
|
|
||||||
export const PUSH_DEFAULT = [
|
export const PUSH_DEFAULT = () =>
|
||||||
'follow',
|
['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'poll', 'update', 'status'].filter(
|
||||||
'follow_request',
|
type => {
|
||||||
'favourite',
|
switch (type) {
|
||||||
'reblog',
|
case 'status':
|
||||||
'mention',
|
return featureCheck('notification_type_status')
|
||||||
'poll',
|
case 'update':
|
||||||
'update',
|
return featureCheck('notification_type_update')
|
||||||
'status'
|
default:
|
||||||
].filter(type => {
|
return true
|
||||||
switch (type) {
|
}
|
||||||
case 'status':
|
}
|
||||||
return featureCheck('notification_type_status')
|
) as ['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'poll', 'update', 'status']
|
||||||
case 'update':
|
|
||||||
return featureCheck('notification_type_update')
|
|
||||||
default:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}) as ['follow', 'follow_request', 'favourite', 'reblog', 'mention', 'poll', 'update', 'status']
|
|
||||||
|
|
||||||
export const PUSH_ADMIN = [
|
export const PUSH_ADMIN = () =>
|
||||||
{ type: 'admin.sign_up', permission: PERMISSION_MANAGE_USERS },
|
[
|
||||||
{ type: 'admin.report', permission: PERMISSION_MANAGE_REPORTS }
|
{ type: 'admin.sign_up', permission: PERMISSION_MANAGE_USERS },
|
||||||
].filter(({ type, permission }) => {
|
{ type: 'admin.report', permission: PERMISSION_MANAGE_REPORTS }
|
||||||
const queryKeyProfile: QueryKeyProfile = ['Profile']
|
].filter(({ type, permission }) => {
|
||||||
const permissions = queryClient.getQueryData<Mastodon.Account>(queryKeyProfile)?.role?.permissions
|
const queryKeyProfile: QueryKeyProfile = ['Profile']
|
||||||
switch (type) {
|
const permissions =
|
||||||
case 'admin.sign_up':
|
queryClient.getQueryData<Mastodon.Account>(queryKeyProfile)?.role?.permissions
|
||||||
return (
|
switch (type) {
|
||||||
featureCheck('notification_type_admin_signup') && checkPermission(permission, permissions)
|
case 'admin.sign_up':
|
||||||
)
|
return (
|
||||||
case 'admin.report':
|
featureCheck('notification_type_admin_signup') && checkPermission(permission, permissions)
|
||||||
return (
|
)
|
||||||
featureCheck('notification_type_admin_report') && checkPermission(permission, permissions)
|
case 'admin.report':
|
||||||
)
|
return (
|
||||||
}
|
featureCheck('notification_type_admin_report') && checkPermission(permission, permissions)
|
||||||
}) as { type: 'admin.sign_up' | 'admin.report'; permission: number }[]
|
)
|
||||||
|
}
|
||||||
|
}) as { type: 'admin.sign_up' | 'admin.report'; permission: number }[]
|
||||||
|
|
||||||
export const setChannels = async (reset: boolean | undefined = false, specificAccount?: string) => {
|
export const setChannels = async (reset: boolean | undefined = false, specificAccount?: string) => {
|
||||||
const account = specificAccount || getGlobalStorage.string('account.active')
|
const account = specificAccount || getGlobalStorage.string('account.active')
|
||||||
@ -76,18 +72,18 @@ export const setChannels = async (reset: boolean | undefined = false, specificAc
|
|||||||
|
|
||||||
if (!accountDetails.push.decode) {
|
if (!accountDetails.push.decode) {
|
||||||
await setChannel('default')
|
await setChannel('default')
|
||||||
for (const push of PUSH_DEFAULT) {
|
for (const push of PUSH_DEFAULT()) {
|
||||||
await deleteChannel(push)
|
await deleteChannel(push)
|
||||||
}
|
}
|
||||||
for (const { type } of PUSH_ADMIN) {
|
for (const { type } of PUSH_ADMIN()) {
|
||||||
await deleteChannel(type)
|
await deleteChannel(type)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await deleteChannel('default')
|
await deleteChannel('default')
|
||||||
for (const push of PUSH_DEFAULT) {
|
for (const push of PUSH_DEFAULT()) {
|
||||||
await setChannel(push)
|
await setChannel(push)
|
||||||
}
|
}
|
||||||
for (const { type } of PUSH_ADMIN) {
|
for (const { type } of PUSH_ADMIN()) {
|
||||||
await setChannel(type)
|
await setChannel(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,11 @@ const useProfileQuery = (
|
|||||||
options: UseQueryOptions<AccountWithSource, AxiosError>
|
options: UseQueryOptions<AccountWithSource, AxiosError>
|
||||||
} | void
|
} | void
|
||||||
) => {
|
) => {
|
||||||
return useQuery(queryKey, queryFunctionProfile, params?.options)
|
return useQuery(queryKey, queryFunctionProfile, {
|
||||||
|
...params?.options,
|
||||||
|
staleTime: Infinity,
|
||||||
|
cacheTime: Infinity
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type MutationVarsProfileBase =
|
type MutationVarsProfileBase =
|
||||||
|
@ -18,9 +18,10 @@ export type AccountV0 = {
|
|||||||
'auth.clientId': string
|
'auth.clientId': string
|
||||||
'auth.clientSecret': string
|
'auth.clientSecret': string
|
||||||
'auth.token': string
|
'auth.token': string
|
||||||
'auth.domain': string
|
'auth.domain': string // used for API
|
||||||
'auth.account.id': string
|
'auth.account.id': string
|
||||||
'auth.account.acct': string
|
'auth.account.acct': string
|
||||||
|
'auth.account.domain': string // used for username
|
||||||
'auth.account.avatar_static': string
|
'auth.account.avatar_static': string
|
||||||
version: string
|
version: string
|
||||||
// number
|
// number
|
||||||
|
@ -24,10 +24,16 @@ export const getGlobalStorage = {
|
|||||||
storage.global.getBoolean(key) as NonNullable<StorageGlobal[T]> extends boolean
|
storage.global.getBoolean(key) as NonNullable<StorageGlobal[T]> extends boolean
|
||||||
? StorageGlobal[T]
|
? StorageGlobal[T]
|
||||||
: never,
|
: never,
|
||||||
object: <T extends keyof StorageGlobal>(key: T) =>
|
object: <T extends keyof StorageGlobal>(key: T) => {
|
||||||
JSON.parse(storage.global.getString(key) || '') as NonNullable<StorageGlobal[T]> extends object
|
const value = storage.global.getString(key)
|
||||||
? StorageGlobal[T]
|
if (value?.length) {
|
||||||
: never
|
return JSON.parse(value) as NonNullable<StorageGlobal[T]> extends object
|
||||||
|
? StorageGlobal[T]
|
||||||
|
: never
|
||||||
|
} else {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export const useGlobalStorage = {
|
export const useGlobalStorage = {
|
||||||
string: <T extends keyof StorageGlobal>(key: T) =>
|
string: <T extends keyof StorageGlobal>(key: T) =>
|
||||||
@ -84,7 +90,7 @@ export const getAccountStorage = {
|
|||||||
: never,
|
: never,
|
||||||
object: <T extends keyof StorageAccount>(key: T) => {
|
object: <T extends keyof StorageAccount>(key: T) => {
|
||||||
const value = storage.account?.getString(key)
|
const value = storage.account?.getString(key)
|
||||||
if (value) {
|
if (value?.length) {
|
||||||
return JSON.parse(value) as NonNullable<StorageAccount[T]> extends object
|
return JSON.parse(value) as NonNullable<StorageAccount[T]> extends object
|
||||||
? StorageAccount[T]
|
? StorageAccount[T]
|
||||||
: never
|
: never
|
||||||
@ -166,8 +172,9 @@ export const getAccountDetails = <T extends Array<keyof StorageAccount>>(
|
|||||||
case 'auth.clientSecret':
|
case 'auth.clientSecret':
|
||||||
case 'auth.token':
|
case 'auth.token':
|
||||||
case 'auth.domain':
|
case 'auth.domain':
|
||||||
case 'auth.account.id':
|
|
||||||
case 'auth.account.acct':
|
case 'auth.account.acct':
|
||||||
|
case 'auth.account.domain':
|
||||||
|
case 'auth.account.id':
|
||||||
case 'auth.account.avatar_static':
|
case 'auth.account.avatar_static':
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
result[key] = temp.getString(key)
|
result[key] = temp.getString(key)
|
||||||
@ -180,9 +187,12 @@ export const getAccountDetails = <T extends Array<keyof StorageAccount>>(
|
|||||||
case 'drafts':
|
case 'drafts':
|
||||||
case 'emojis_frequent':
|
case 'emojis_frequent':
|
||||||
const value = temp.getString(key)
|
const value = temp.getString(key)
|
||||||
if (value) {
|
if (value?.length) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
result[key] = JSON.parse(value)
|
result[key] = JSON.parse(value)
|
||||||
|
} else {
|
||||||
|
// @ts-ignore
|
||||||
|
result[key] = undefined
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -67,16 +67,17 @@ export async function migrateFromAsyncStorage(): Promise<void> {
|
|||||||
const accounts: string[] = []
|
const accounts: string[] = []
|
||||||
|
|
||||||
for (const instance of JSON.parse(storeInstances.instances)) {
|
for (const instance of JSON.parse(storeInstances.instances)) {
|
||||||
const account = `${instance.uri}/${instance.account.id}`
|
const account = `${instance.url}/${instance.account.id}`
|
||||||
|
|
||||||
const temp = new MMKV({ id: account })
|
const temp = new MMKV({ id: account })
|
||||||
temp.set('auth.clientId', instance.appData.clientId)
|
temp.set('auth.clientId', instance.appData.clientId)
|
||||||
temp.set('auth.clientSecret', instance.appData.clientSecret)
|
temp.set('auth.clientSecret', instance.appData.clientSecret)
|
||||||
temp.set('auth.token', instance.token)
|
temp.set('auth.token', instance.token)
|
||||||
temp.set('auth.domain', instance.uri)
|
temp.set('auth.domain', instance.url)
|
||||||
|
|
||||||
temp.set('auth.account.id', instance.account.id)
|
|
||||||
temp.set('auth.account.acct', instance.account.acct)
|
temp.set('auth.account.acct', instance.account.acct)
|
||||||
|
temp.set('auth.account.domain', instance.uri)
|
||||||
|
temp.set('auth.account.id', instance.account.id)
|
||||||
temp.set('auth.account.avatar_static', instance.account.avatarStatic)
|
temp.set('auth.account.avatar_static', instance.account.avatarStatic)
|
||||||
|
|
||||||
if (instance.account.preferences) {
|
if (instance.account.preferences) {
|
||||||
|
@ -10232,7 +10232,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"rtl-detect@npm:^1.0.2, rtl-detect@npm:^1.0.4":
|
"rtl-detect@npm:^1.0.2":
|
||||||
version: 1.0.4
|
version: 1.0.4
|
||||||
resolution: "rtl-detect@npm:1.0.4"
|
resolution: "rtl-detect@npm:1.0.4"
|
||||||
checksum: d562535baa0db62f57f0a1d4676297bff72fd6b94e88f0f0900d5c3e810ab512c5c4cadffd3e05fbe8d9c74310c919afa3ea8c1001c244e5555e8eef12d02d6f
|
checksum: d562535baa0db62f57f0a1d4676297bff72fd6b94e88f0f0900d5c3e810ab512c5c4cadffd3e05fbe8d9c74310c919afa3ea8c1001c244e5555e8eef12d02d6f
|
||||||
@ -11304,7 +11304,6 @@ __metadata:
|
|||||||
react-native-tab-view: ^3.3.4
|
react-native-tab-view: ^3.3.4
|
||||||
react-redux: ^8.0.5
|
react-redux: ^8.0.5
|
||||||
rn-placeholder: ^3.0.3
|
rn-placeholder: ^3.0.3
|
||||||
rtl-detect: ^1.0.4
|
|
||||||
typescript: ^4.9.4
|
typescript: ^4.9.4
|
||||||
valid-url: ^1.0.9
|
valid-url: ^1.0.9
|
||||||
zeego: ^1.0.2
|
zeego: ^1.0.2
|
||||||
|
Reference in New Issue
Block a user