Merge pull request #486 from tooot-app/main

Release v4.6.3
This commit is contained in:
xmflsct 2022-11-22 22:47:20 +01:00 committed by GitHub
commit 354050c4ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 275 additions and 309 deletions

View File

@ -108,29 +108,6 @@ private_lane :build_android do
end
end
desc "Build Android apk"
private_lane :build_android_apk do
sh("echo #{ENV["ANDROID_KEYSTORE"]} | base64 -d | tee #{File.expand_path('..', Dir.pwd)}/android/tooot.jks >/dev/null", log: false)
prepare_playstore_android
build_android_app(
task: 'assemble',
build_type: 'release',
project_dir: "./android",
print_command: true,
print_command_output: true,
properties: {
"android.injected.signing.store.file" => "#{File.expand_path('..', Dir.pwd)}/android/tooot.jks",
"android.injected.signing.store.password" => ENV["ANDROID_KEYSTORE_PASSWORD"],
"android.injected.signing.key.alias" => ENV["ANDROID_KEYSTORE_ALIAS"],
"android.injected.signing.key.password" => ENV["ANDROID_KEYSTORE_KEY_PASSWORD"],
}
)
sh "mv #{lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]} #{File.expand_path('..', Dir.pwd)}/tooot-#{GITHUB_RELEASE}.apk"
end
lane :ios do
cocoapods(clean_install: true, podfile: "./ios/Podfile")
build_ios
@ -144,15 +121,13 @@ end
lane :release do
if ENVIRONMENT == 'release'
build_android_apk
set_github_release(
repository_name: GITHUB_REPO,
name: GITHUB_RELEASE,
tag_name: GITHUB_RELEASE,
description: "No changelog provided",
commitish: git_branch,
is_prerelease: false,
upload_assets: ["#{File.expand_path('..', Dir.pwd)}/tooot-#{GITHUB_RELEASE}.apk"]
is_prerelease: false
)
end
rocket

View File

@ -23,7 +23,7 @@ PODS:
- ExpoModulesCore
- EXNotifications (0.17.0):
- ExpoModulesCore
- Expo (47.0.6):
- Expo (47.0.7):
- ExpoModulesCore
- ExpoCrypto (12.0.0):
- ExpoModulesCore
@ -419,7 +419,7 @@ PODS:
- React-Core
- react-native-netinfo (9.3.6):
- React-Core
- react-native-pager-view (6.1.0):
- react-native-pager-view (6.1.1):
- React-Core
- react-native-paste-input (0.5.1):
- React-Core
@ -830,7 +830,7 @@ SPEC CHECKSUMS:
EXFirebaseCore: d0d88cb904e893af07f809ab08c0892489bc6956
EXFont: 319606bfe48c33b5b5063fb0994afdc496befe80
EXNotifications: babce2a87b7922051354fcfe7a74dd279b7e272a
Expo: a581e979539bae3e49cd02d9dee2432947383d3b
Expo: a37d568e9ae87645b74ed597dd0f0fd89e2daf2d
ExpoCrypto: 51e7662c7f5bfeab25b7909b8a5d545ec15d4877
ExpoHaptics: 5a56d30a87ea213dd00b09566dc4b441a4dff97f
ExpoKeepAwake: 69b59d0a8d2b24de9f82759c39b3821fec030318
@ -884,7 +884,7 @@ SPEC CHECKSUMS:
react-native-language-detection: 0e43195ad014974f1b7a31b64820eff34a243f2d
react-native-live-text-image-view: 483bacfdba464162b8cf176bba555364f18b584c
react-native-netinfo: f80db8cac2151405633324cb645c60af098ee461
react-native-pager-view: 7abf89f9834d9a4021b2fb6a5ef2abff570b46fb
react-native-pager-view: 3c66c4e2f3ab423643d07b2c7041f8ac48395f72
react-native-paste-input: 183ad7dc224e192719616f4258dde5b548627d08
react-native-safe-area-context: 99b24a0c5acd0d5dcac2b1a7f18c49ea317be99a
react-native-segmented-control: 65df6cd0619b780b3843d574a72d4c7cec396097

View File

@ -1,6 +1,6 @@
{
"name": "tooot",
"version": "4.6.2",
"version": "4.6.3",
"description": "tooot for Mastodon",
"author": "xmflsct <me@xmflsct.com>",
"license": "GPL-3.0-or-later",
@ -33,15 +33,15 @@
"@react-native-community/blur": "^4.3.0",
"@react-native-community/netinfo": "9.3.6",
"@react-native-community/segmented-control": "^2.2.2",
"@react-navigation/bottom-tabs": "^6.4.0",
"@react-navigation/native": "^6.0.13",
"@react-navigation/native-stack": "^6.9.1",
"@react-navigation/stack": "^6.3.4",
"@react-navigation/bottom-tabs": "^6.4.1",
"@react-navigation/native": "^6.0.14",
"@react-navigation/native-stack": "^6.9.2",
"@react-navigation/stack": "^6.3.5",
"@reduxjs/toolkit": "^1.9.0",
"@sentry/react-native": "4.8.0",
"@sharcoux/slider": "^6.0.3",
"axios": "^0.27.2",
"expo": "^47.0.6",
"expo": "^47.0.7",
"expo-auth-session": "^3.7.2",
"expo-av": "^13.0.1",
"expo-constants": "^14.0.2",
@ -80,7 +80,7 @@
"react-native-image-picker": "^4.10.1",
"react-native-language-detection": "^0.1.0",
"react-native-live-text-image-view": "^0.4.0",
"react-native-pager-view": "^6.1.0",
"react-native-pager-view": "^6.1.1",
"react-native-reanimated": "^2.13.0",
"react-native-reanimated-zoom": "^0.3.3",
"react-native-safe-area-context": "^4.4.1",

View File

@ -131,6 +131,9 @@ const contextMenuAccount = ({ actions, type, queryKey, rootQueryKey, id: account
}
return (index: number) => {
if (typeof index !== 'number' || !actions[index]) {
return // For Android
}
if (actions[index].id === 'account-mute') {
analytics('timeline_shared_headeractions_account_mute_press', {
page: queryKey && queryKey[1].page

View File

@ -1,9 +1,6 @@
import analytics from '@components/analytics'
import { displayMessage } from '@components/Message'
import {
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import { QueryKeyTimeline, useTimelineMutation } from '@utils/queryHooks/timeline'
import { getInstanceUrl } from '@utils/slices/instancesSlice'
import { useTheme } from '@utils/styles/ThemeManager'
import { useTranslation } from 'react-i18next'
@ -19,12 +16,7 @@ export interface Props {
rootQueryKey?: QueryKeyTimeline
}
const contextMenuInstance = ({
actions,
status,
queryKey,
rootQueryKey
}: Props) => {
const contextMenuInstance = ({ actions, status, queryKey, rootQueryKey }: Props) => {
const { t } = useTranslation('componentContextMenu')
const { theme } = useTheme()
@ -72,10 +64,12 @@ const contextMenuInstance = ({
}
return (index: number) => {
if (typeof index !== 'number' || !actions[index]) {
return // For Android
}
if (
actions[index].id === 'instance-block' ||
(actions[index].id === 'instance' &&
actions[index].actions?.[0].id === 'instance-block')
(actions[index].id === 'instance' && actions[index].actions?.[0].id === 'instance-block')
) {
analytics('timeline_shared_headeractions_domain_block_press', {
page: queryKey[1].page

View File

@ -25,7 +25,8 @@ const contextMenuShare = ({ copiableContent, actions, type, url }: Props) => {
title: t(`share.${type}.action`),
systemIcon: 'square.and.arrow.up'
})
Platform.OS !== 'android' && type === 'status' &&
Platform.OS !== 'android' &&
type === 'status' &&
actions.push({
id: 'copy',
title: t(`copy.action`),
@ -34,6 +35,9 @@ const contextMenuShare = ({ copiableContent, actions, type, url }: Props) => {
})
return (index: number) => {
if (typeof index !== 'number' || !actions[index]) {
return // For Android
}
if (actions[index].id === 'copy') {
analytics('timeline_shared_headeractions_copy_press')
Clipboard.setString(copiableContent?.current.content || '')

View File

@ -9,10 +9,7 @@ import {
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import {
checkInstanceFeature,
getInstanceAccount
} from '@utils/slices/instancesSlice'
import { checkInstanceFeature, getInstanceAccount } from '@utils/slices/instancesSlice'
import { useTheme } from '@utils/styles/ThemeManager'
import { useTranslation } from 'react-i18next'
import { Alert } from 'react-native'
@ -27,16 +24,8 @@ export interface Props {
rootQueryKey?: QueryKeyTimeline
}
const contextMenuStatus = ({
actions,
status,
queryKey,
rootQueryKey
}: Props) => {
const navigation =
useNavigation<
NativeStackNavigationProp<RootStackParamList, 'Screen-Tabs'>
>()
const contextMenuStatus = ({ actions, status, queryKey, rootQueryKey }: Props) => {
const navigation = useNavigation<NativeStackNavigationProp<RootStackParamList, 'Screen-Tabs'>>()
const { theme } = useTheme()
const { t } = useTranslation('componentContextMenu')
@ -44,8 +33,7 @@ const contextMenuStatus = ({
const mutation = useTimelineMutation({
onMutate: true,
onError: (err: any, params, oldData) => {
const theFunction = (params as MutationVarsTimelineUpdateStatusProperty)
.payload
const theFunction = (params as MutationVarsTimelineUpdateStatusProperty).payload
? (params as MutationVarsTimelineUpdateStatusProperty).payload.property
: 'delete'
displayMessage({
@ -59,17 +47,14 @@ const contextMenuStatus = ({
err.data &&
err.data.error &&
typeof err.data.error === 'string' && {
description: err.data.error
})
description: err.data.error
})
})
queryClient.setQueryData(queryKey, oldData)
}
})
const instanceAccount = useSelector(
getInstanceAccount,
(prev, next) => prev.id === next.id
)
const instanceAccount = useSelector(getInstanceAccount, (prev, next) => prev.id === next.id)
const ownAccount = instanceAccount?.id === status?.account?.id
if (ownAccount) {
@ -118,83 +103,75 @@ const contextMenuStatus = ({
}
return async (index: number) => {
if (typeof index !== 'number' || !actions[index]) {
return // For Android
}
if (actions[index].id === 'status-delete') {
analytics('timeline_shared_headeractions_status_delete_press', {
page: queryKey && queryKey[1].page
})
Alert.alert(
t('status.delete.alert.title'),
t('status.delete.alert.message'),
[
{
text: t('status.delete.alert.buttons.confirm'),
style: 'destructive',
onPress: async () => {
analytics('timeline_shared_headeractions_status_delete_confirm', {
page: queryKey && queryKey[1].page
})
mutation.mutate({
type: 'deleteItem',
source: 'statuses',
queryKey,
rootQueryKey,
id: status.id
})
}
},
{
text: t('common:buttons.cancel')
Alert.alert(t('status.delete.alert.title'), t('status.delete.alert.message'), [
{
text: t('status.delete.alert.buttons.confirm'),
style: 'destructive',
onPress: async () => {
analytics('timeline_shared_headeractions_status_delete_confirm', {
page: queryKey && queryKey[1].page
})
mutation.mutate({
type: 'deleteItem',
source: 'statuses',
queryKey,
rootQueryKey,
id: status.id
})
}
]
)
},
{
text: t('common:buttons.cancel')
}
])
}
if (actions[index].id === 'status-delete-edit') {
analytics('timeline_shared_headeractions_status_deleteedit_press', {
page: queryKey && queryKey[1].page
})
Alert.alert(
t('status.deleteEdit.alert.title'),
t('status.deleteEdit.alert.message'),
[
{
text: t('status.deleteEdit.alert.buttons.confirm'),
style: 'destructive',
onPress: async () => {
analytics(
'timeline_shared_headeractions_status_deleteedit_confirm',
{
page: queryKey && queryKey[1].page
}
)
let replyToStatus: Mastodon.Status | undefined = undefined
if (status.in_reply_to_id) {
replyToStatus = await apiInstance<Mastodon.Status>({
method: 'get',
url: `statuses/${status.in_reply_to_id}`
}).then(res => res.body)
}
mutation
.mutateAsync({
type: 'deleteItem',
source: 'statuses',
queryKey,
id: status.id
})
.then(res => {
navigation.navigate('Screen-Compose', {
type: 'deleteEdit',
incomingStatus: res.body as Mastodon.Status,
...(replyToStatus && { replyToStatus }),
queryKey
})
})
Alert.alert(t('status.deleteEdit.alert.title'), t('status.deleteEdit.alert.message'), [
{
text: t('status.deleteEdit.alert.buttons.confirm'),
style: 'destructive',
onPress: async () => {
analytics('timeline_shared_headeractions_status_deleteedit_confirm', {
page: queryKey && queryKey[1].page
})
let replyToStatus: Mastodon.Status | undefined = undefined
if (status.in_reply_to_id) {
replyToStatus = await apiInstance<Mastodon.Status>({
method: 'get',
url: `statuses/${status.in_reply_to_id}`
}).then(res => res.body)
}
},
{
text: t('common:buttons.cancel')
mutation
.mutateAsync({
type: 'deleteItem',
source: 'statuses',
queryKey,
id: status.id
})
.then(res => {
navigation.navigate('Screen-Compose', {
type: 'deleteEdit',
incomingStatus: res.body as Mastodon.Status,
...(replyToStatus && { replyToStatus }),
queryKey
})
})
}
]
)
},
{
text: t('common:buttons.cancel')
}
])
}
if (actions[index].id === 'status-mute') {
analytics('timeline_shared_headeractions_status_mute_press', {

View File

@ -157,15 +157,6 @@ const TimelineDefault: React.FC<Props> = ({
return disableOnPress ? (
<View style={mainStyle}>{main()}</View>
) : Platform.OS === 'android' ? (
<Pressable
accessible={highlighted ? false : true}
style={mainStyle}
onPress={onPress}
onLongPress={() => {}}
>
{main()}
</Pressable>
) : (
<TimelineContextMenu
copiableContent={copiableContent}

View File

@ -64,7 +64,7 @@ const AttachmentVideo: React.FC<Props> = ({
}, [])
const _handleAppStateChange = async (nextAppState: AppStateStatus) => {
if (appState.current.match(/active/) && nextAppState.match(/inactive/)) {
await videoPlayer.current?.stopAsync()
// await videoPlayer.current?.stopAsync()
} else if (gifv && appState.current.match(/background/) && nextAppState.match(/active/)) {
await videoPlayer.current?.setIsMutedAsync(true)
await videoPlayer.current?.playAsync()

View File

@ -3,13 +3,14 @@ import contextMenuInstance from '@components/ContextMenu/instance'
import contextMenuShare from '@components/ContextMenu/share'
import contextMenuStatus from '@components/ContextMenu/status'
import Icon from '@components/Icon'
import { useActionSheet } from '@expo/react-native-action-sheet'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, View } from 'react-native'
import ContextMenu, { ContextMenuAction } from 'react-native-context-menu-view'
import { ContextMenuAction } from 'react-native-context-menu-view'
import HeaderSharedAccount from './HeaderShared/Account'
import HeaderSharedApplication from './HeaderShared/Application'
import HeaderSharedCreated from './HeaderShared/Created'
@ -55,6 +56,8 @@ const TimelineHeaderDefault = ({ queryKey, status, highlighted }: Props) => {
queryKey
})
const { showActionSheetWithOptions } = useActionSheet()
return (
<View style={{ flex: 1, flexDirection: 'row' }}>
<View style={{ flex: 7 }}>
@ -82,25 +85,26 @@ const TimelineHeaderDefault = ({ queryKey, status, highlighted }: Props) => {
<Pressable
accessibilityHint={t('accessibilityHint')}
style={{ flex: 1, flexBasis: StyleConstants.Font.Size.L }}
onLongPress={() => null}
>
<ContextMenu
style={{ flex: 1, alignItems: 'center' }}
dropdownMenuMode
actions={actions}
onPress={({ nativeEvent: { index } }) => {
for (const on of [shareOnPress, statusOnPress, accountOnPress, instanceOnPress]) {
on && on(index)
onPress={() =>
showActionSheetWithOptions(
{
options: actions.map(action => action.title),
cancelButtonIndex: 999,
destructiveButtonIndex: actions
.map((action, index) => (action.destructive ? index : 999))
.filter(num => num !== 999)
},
index => {
if (index !== undefined) {
for (const on of [shareOnPress, statusOnPress, accountOnPress, instanceOnPress]) {
on && on(index)
}
}
}
}}
children={
<Icon
name='MoreHorizontal'
color={colors.secondary}
size={StyleConstants.Font.Size.L}
/>
}
/>
)
}
>
<Icon name='MoreHorizontal' color={colors.secondary} size={StyleConstants.Font.Size.L} />
</Pressable>
) : null}
</View>

View File

@ -4,12 +4,13 @@ import contextMenuShare from '@components/ContextMenu/share'
import contextMenuStatus from '@components/ContextMenu/status'
import Icon from '@components/Icon'
import { RelationshipIncoming, RelationshipOutgoing } from '@components/Relationship'
import { useActionSheet } from '@expo/react-native-action-sheet'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useMemo } from 'react'
import { Pressable, View } from 'react-native'
import ContextMenu, { ContextMenuAction } from 'react-native-context-menu-view'
import { ContextMenuAction } from 'react-native-context-menu-view'
import HeaderSharedAccount from './HeaderShared/Account'
import HeaderSharedApplication from './HeaderShared/Application'
import HeaderSharedCreated from './HeaderShared/Created'
@ -57,6 +58,8 @@ const TimelineHeaderNotification = ({ queryKey, notification }: Props) => {
queryKey
})
const { showActionSheetWithOptions } = useActionSheet()
const actions = useMemo(() => {
switch (notification.type) {
case 'follow':
@ -68,29 +71,34 @@ const TimelineHeaderNotification = ({ queryKey, notification }: Props) => {
return (
<Pressable
style={{ flex: 1, flexBasis: StyleConstants.Font.Size.L }}
onLongPress={() => null}
children={
<ContextMenu
style={{ flex: 1, alignItems: 'center' }}
dropdownMenuMode
actions={contextMenuActions}
onPress={({ nativeEvent: { index } }) => {
for (const on of [
shareOnPress,
statusOnPress,
accountOnPress,
instanceOnPress
]) {
on && on(index)
onPress={() =>
showActionSheetWithOptions(
{
options: contextMenuActions.map(action => action.title),
cancelButtonIndex: 999,
destructiveButtonIndex: contextMenuActions
.map((action, index) => (action.destructive ? index : 999))
.filter(num => num !== 999)
},
index => {
if (index !== undefined) {
for (const on of [
shareOnPress,
statusOnPress,
accountOnPress,
instanceOnPress
]) {
on && on(index)
}
}
}}
children={
<Icon
name='MoreHorizontal'
color={colors.secondary}
size={StyleConstants.Font.Size.L}
/>
}
)
}
children={
<Icon
name='MoreHorizontal'
color={colors.secondary}
size={StyleConstants.Font.Size.L}
/>
}
/>

View File

@ -26,7 +26,6 @@ const HeaderSharedApplication = React.memo(
application.website && (await openLink(application.website))
}}
style={{
flex: 1,
marginLeft: StyleConstants.Spacing.S,
color: colors.secondary
}}

View File

@ -36,7 +36,7 @@
"action": "Tröt teilen"
},
"account": {
"action": "User verlinken"
"action": "Link zum Profil teilen"
}
},
"status": {
@ -55,17 +55,17 @@
}
},
"deleteEdit": {
"action": "Tröt und Boost entfernen",
"action": "Tröt neu entwerfen",
"alert": {
"title": "Löschen und Boost bestätigen?",
"message": "Alle Boosts und Favoriten inklusive der Antworten werden gelöscht.",
"title": "Beitrag wirklich entfernen?",
"message": "Alle Boosts und Likes inklusive der Antworten werden gelöscht.",
"buttons": {
"confirm": "Bestätigen"
}
}
},
"mute": {
"action_false": "Diesen Tröt sowie die Antworten stummschalten",
"action_false": "Diskussion stummschalten",
"action_true": "Tröt und Antworten nicht mehr stummschalten"
},
"pin": {

View File

@ -11,7 +11,7 @@
"domains": "Domains"
},
"disclaimer": {
"base": "Der Login erfolgt über den Browser, so dass Ihre Kontoinformationen für die Toot-App nicht sichtbar sind."
"base": "Der Login erfolgt über den Browser, sodass deine Kontoinformationen für die App nicht sichtbar sind."
},
"terms": {
"base": "Mit dem Login stimmst du der <0>Datenschutzrichtlinie</0> und den <1>Nutzungsbedingungen</1> zu."

View File

@ -47,7 +47,7 @@
},
"favourited": {
"accessibilityLabel": "Favorit",
"function": "Sternen"
"function": "Liken"
},
"bookmarked": {
"accessibilityLabel": "Lesezeichen hinzufügen",
@ -67,7 +67,7 @@
},
"history": {
"accessibilityLabel": "Dieser Tröt wurde {{count}} mal bearbeitet",
"accessibilityHint": "Für den vollständigen Verlauf auswählen",
"accessibilityHint": "Bearbeitungsverlauf anzeigen",
"text_one": "{{count}} Bearbeitung",
"text_other": "{{count}} mal bearbeitet"
}

View File

@ -12,7 +12,7 @@
"reblog": "$t(screenTabs:me.push.reblog.heading)",
"mention": "$t(screenTabs:me.push.mention.heading)",
"poll": "$t(screenTabs:me.push.poll.heading)",
"status": "Toot eines abonnierten Nutzers",
"status": "Tt eines abonnierten Nutzers",
"update": "Boost wurde bearbeitet"
}
}

View File

@ -125,7 +125,7 @@
"options": {
"public": "Öffentlich",
"unlisted": "Ungelistet",
"private": "Nur für Folgende",
"private": "Nur für Follower",
"cancel": "$t(common:buttons.cancel)"
}
},

View File

@ -312,7 +312,7 @@
},
"hashtag": {
"follow": "フォロー",
"unfollow": "フォローをやめる"
"unfollow": "フォロー解除"
},
"history": {
"name": "編集履歴"

View File

@ -39,7 +39,7 @@
"header": {
"postingAs": "Skriver som @{{acct}}@{{domain}}",
"spoilerInput": {
"placeholder": "Spoilervarningsmeddelande"
"placeholder": "Innehållsvarning"
},
"textInput": {
"placeholder": "Vad tänker du på",
@ -71,8 +71,8 @@
"option": {
"placeholder": {
"accessibilityLabel": "Omröstningsalternativ {{index}}",
"single": "Enval",
"multiple": "Flera val"
"single": "Alternativ",
"multiple": "Alternativ"
}
},
"quantity": {
@ -89,7 +89,7 @@
"heading": "Typ av val",
"options": {
"single": "Enval",
"multiple": "Flera val",
"multiple": "Flerval",
"cancel": "$t(common:buttons.cancel)"
}
},
@ -135,7 +135,7 @@
}
},
"spoiler": {
"accessibilityLabel": "Spoiler"
"accessibilityLabel": "Innehållsvarning"
},
"emoji": {
"accessibilityLabel": "Lägg till emoji",

View File

@ -78,7 +78,7 @@
}
},
"fontSize": {
"demo": "<p>Det här är ett demoinlägg😊. Du kan välja mellan flera alternativ nedan.<br /><br />Denna inställning påverkar endast huvudinnehållet i inlägg men inte andra teckenstorlekar.</p>",
"demo": "<p>Det här är ett demoinlägg 😊. Du kan välja mellan flera alternativ ovan.<br /><br />Denna inställning påverkar endast huvudinnehållet i inlägg men inte andra teckenstorlekar.</p>",
"sizes": {
"S": "S",
"M": "M - Standard",
@ -252,7 +252,7 @@
}
},
"browser": {
"heading": "Öppnar länk",
"heading": "Öppna länk",
"options": {
"internal": "Inuti appen",
"external": "Använd systemets webbläsare",
@ -320,7 +320,7 @@
"search": {
"header": {
"prefix": "Söker",
"placeholder": "r..."
"placeholder": "efter..."
},
"empty": {
"general": "Ange sökord för att söka efter <bold>$t(screenTabs:shared.search.sections.accounts)</bold>, <bold>$t(screenTabs:shared.search.sections.hashtags)</bold> eller <bold>$t(screenTabs:shared.search.sections.statuses)</bold>",

View File

@ -4,7 +4,7 @@ import { AnyAction, configureStore, Reducer } from '@reduxjs/toolkit'
import contextsMigration from '@utils/migrations/contexts/migration'
import instancesMigration from '@utils/migrations/instances/migration'
import settingsMigration from '@utils/migrations/settings/migration'
import appSlice from '@utils/slices/appSlice'
import appSlice, { AppState } from '@utils/slices/appSlice'
import contextsSlice, { ContextsState } from '@utils/slices/contextsSlice'
import instancesSlice, { InstancesState } from '@utils/slices/instancesSlice'
import settingsSlice, { SettingsState } from '@utils/slices/settingsSlice'
@ -26,6 +26,13 @@ const secureStorage = createSecureStore()
const prefix = 'tooot'
const appPersistConfig = {
key: 'app',
prefix,
storage: AsyncStorage,
version: 0
}
const contextsPersistConfig = {
key: 'contexts',
prefix,
@ -55,19 +62,19 @@ const settingsPersistConfig = {
const store = configureStore({
reducer: {
app: persistReducer(appPersistConfig, appSlice) as Reducer<AppState, AnyAction>,
contexts: persistReducer(contextsPersistConfig, contextsSlice) as Reducer<
ContextsState,
AnyAction
>,
instances: persistReducer(
instancesPersistConfig,
instancesSlice
) as Reducer<InstancesState, AnyAction>,
instances: persistReducer(instancesPersistConfig, instancesSlice) as Reducer<
InstancesState,
AnyAction
>,
settings: persistReducer(settingsPersistConfig, settingsSlice) as Reducer<
SettingsState,
AnyAction
>,
app: appSlice
>
},
middleware: getDefaultMiddleware =>
getDefaultMiddleware({

View File

@ -0,0 +1,4 @@
export type AppV0 = {
expoToken?: string
versionUpdate: boolean
}

View File

@ -33,53 +33,55 @@ const pushUseConnect = ({ t, instances }: Params) => {
method: 'get',
url: `push/connect/${expoToken}`,
sentry: true
}).catch(error => {
Sentry.setExtras({
API: 'tooot',
...(error?.response && { response: error.response }),
...(error?.request && { request: error.request })
})
Sentry.captureException(error)
Notifications.setBadgeCountAsync(0)
if (error?.status == 404) {
displayMessage({
theme,
type: 'error',
duration: 'long',
message: t('pushError.message'),
description: t('pushError.description'),
onPress: () => {
navigationRef.navigate('Screen-Tabs', {
screen: 'Tab-Me',
params: {
screen: 'Tab-Me-Root'
}
})
navigationRef.navigate('Screen-Tabs', {
screen: 'Tab-Me',
params: {
screen: 'Tab-Me-Settings'
}
})
}
})
dispatch(disableAllPushes())
instances.forEach(instance => {
if (instance.push.global.value) {
apiGeneral<{}>({
method: 'delete',
domain: instance.url,
url: 'api/v1/push/subscription',
headers: {
Authorization: `Bearer ${instance.token}`
}
}).catch(() => console.log('error!!!'))
}
})
}
})
.then(() => Notifications.setBadgeCountAsync(0))
.catch(error => {
Sentry.setExtras({
API: 'tooot',
...(error?.response && { response: error.response }),
...(error?.request && { request: error.request })
})
Sentry.captureException(error)
Notifications.setBadgeCountAsync(0)
if (error?.status == 404) {
displayMessage({
theme,
type: 'error',
duration: 'long',
message: t('pushError.message'),
description: t('pushError.description'),
onPress: () => {
navigationRef.navigate('Screen-Tabs', {
screen: 'Tab-Me',
params: {
screen: 'Tab-Me-Root'
}
})
navigationRef.navigate('Screen-Tabs', {
screen: 'Tab-Me',
params: {
screen: 'Tab-Me-Settings'
}
})
}
})
dispatch(disableAllPushes())
instances.forEach(instance => {
if (instance.push.global.value) {
apiGeneral<{}>({
method: 'delete',
domain: instance.url,
url: 'api/v1/push/subscription',
headers: {
Authorization: `Bearer ${instance.token}`
}
}).catch(() => console.log('error!!!'))
}
})
}
})
}
const pushEnabled = instances.filter(instance => instance.push.global.value)
@ -89,7 +91,6 @@ const pushUseConnect = ({ t, instances }: Params) => {
if (expoToken && pushEnabled.length && state === 'active') {
Notifications.getBadgeCountAsync().then(count => {
if (count > 0) {
Notifications.setBadgeCountAsync(0)
connect()
}
})
@ -102,7 +103,6 @@ const pushUseConnect = ({ t, instances }: Params) => {
}, [expoToken, pushEnabled.length])
return useEffect(() => {
Notifications.setBadgeCountAsync(0)
if (expoToken && pushEnabled.length) {
connect()
}

View File

@ -1141,13 +1141,13 @@
mv "~2"
safe-json-stringify "~1"
"@expo/cli@0.4.9":
version "0.4.9"
resolved "https://registry.yarnpkg.com/@expo/cli/-/cli-0.4.9.tgz#24a2714b11a918b588138220c79b4ec9b553adba"
integrity sha512-/9ljfK4eMWXb97XWSJgxcSWpuKXABHFd7Q8Kswp24B2Y5w4MIyaEPhSErIJYTq/FJH7p98Ti1zhk/PhBL0vVTw==
"@expo/cli@0.4.10":
version "0.4.10"
resolved "https://registry.yarnpkg.com/@expo/cli/-/cli-0.4.10.tgz#e965b97888c83cecdaddbb8dca3d5827643a0f36"
integrity sha512-c8NJOVa5b8g9CYj8ahdaN21cVE2wPwUaFrtTE0kLeRR5ASy8reWLFEOcstEtt6eufdcN/uGgBWQ0FLovgLZuzw==
dependencies:
"@babel/runtime" "^7.14.0"
"@expo/code-signing-certificates" "^0.0.2"
"@expo/code-signing-certificates" "0.0.5"
"@expo/config" "~7.0.2"
"@expo/config-plugins" "~5.0.3"
"@expo/dev-server" "0.1.123"
@ -1208,10 +1208,10 @@
uuid "^3.4.0"
wrap-ansi "^7.0.0"
"@expo/code-signing-certificates@^0.0.2":
version "0.0.2"
resolved "https://registry.yarnpkg.com/@expo/code-signing-certificates/-/code-signing-certificates-0.0.2.tgz#65cd615800e6724b54831c966dd1a90145017246"
integrity sha512-vnPHFjwOqxQ1VLztktY+fYCfwvLzjqpzKn09rchcQE7Sdf0wtW5fFtIZBEFOOY5wasp8tXSnp627zrAwazPHzg==
"@expo/code-signing-certificates@0.0.5":
version "0.0.5"
resolved "https://registry.yarnpkg.com/@expo/code-signing-certificates/-/code-signing-certificates-0.0.5.tgz#a693ff684fb20c4725dade4b88a6a9f96b02496c"
integrity sha512-BNhXkY1bblxKZpltzAx98G2Egj9g1Q+JRcvR7E99DOj862FTCX+ZPsAUtPTr7aHxwtrL7+fL3r0JSmM9kBm+Bw==
dependencies:
node-forge "^1.2.1"
nullthrows "^1.1.1"
@ -2139,19 +2139,19 @@
resolved "https://registry.yarnpkg.com/@react-native/polyfills/-/polyfills-2.0.0.tgz#4c40b74655c83982c8cf47530ee7dc13d957b6aa"
integrity sha512-K0aGNn1TjalKj+65D7ycc1//H9roAQ51GJVk5ZJQFb2teECGmzd86bYDC0aYdbRf7gtovescq4Zt6FR0tgXiHQ==
"@react-navigation/bottom-tabs@^6.4.0":
version "6.4.0"
resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-6.4.0.tgz#63743874648f92adedf37186cb7cedcd47826ee9"
integrity sha512-90CapiXjiWudbCiki9e6fOr/CECQRguIxv5OD7IBfbAMGX5GGiJpX8aqiHAz2DxpAz31v4JZcUr945+lFhXBfA==
"@react-navigation/bottom-tabs@^6.4.1":
version "6.4.1"
resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-6.4.1.tgz#54e469077f7c9f3750e6727ec8f298d5497b6ae5"
integrity sha512-b12o0aVe+A9bUVP31kQLVcZ5l4Inm/7XhpSS5FvwhoI9L2iwofK1tt98uEQd79NIAklfui+IqRqr2X6XKkygbA==
dependencies:
"@react-navigation/elements" "^1.3.6"
"@react-navigation/elements" "^1.3.7"
color "^4.2.3"
warn-once "^0.1.0"
"@react-navigation/core@^6.4.0":
version "6.4.0"
resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.0.tgz#c44d33a8d8ef010a102c7f831fc8add772678509"
integrity sha512-tpc0Ak/DiHfU3LlYaRmIY7vI4sM/Ru0xCet6runLUh9aABf4wiLgxyFJ5BtoWq6xFF8ymYEA/KWtDhetQ24YiA==
"@react-navigation/core@^6.4.1":
version "6.4.1"
resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.1.tgz#2d290cadc23992e914c45b5712efa30e5f37587f"
integrity sha512-M1rTS+qaw84ZItvObwFTjuvXfrJRnXL2uJJeiDVwSvu7/30Wp6bkL3/MfLUEA6I4CzJhL74iRSfCKSVe7kVhlw==
dependencies:
"@react-navigation/routers" "^6.1.3"
escape-string-regexp "^4.0.0"
@ -2160,25 +2160,25 @@
react-is "^16.13.0"
use-latest-callback "^0.1.5"
"@react-navigation/elements@^1.3.6":
version "1.3.6"
resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.6.tgz#fa700318528db93f05144b1be4b691b9c1dd1abe"
integrity sha512-pNJ8R9JMga6SXOw6wGVN0tjmE6vegwPmJBL45SEMX2fqTfAk2ykDnlJHodRpHpAgsv0DaI8qX76z3A+aqKSU0w==
"@react-navigation/elements@^1.3.7":
version "1.3.7"
resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.7.tgz#40d80a7f34d645b605289da10bc4b6c3a7667215"
integrity sha512-OZg2N/dd2tl6qkfrWvmUjFsYsbEyHEv4NbZSBuT+CR+d1pzmexN2IeVmi4cEMoR7U7GwhFcHRevF36yBsjU/dw==
"@react-navigation/native-stack@^6.9.1":
version "6.9.1"
resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.1.tgz#6013300e4cd0b33e242aa18593e4dff7db2ab3d1"
integrity sha512-aOuJP97ge6NRz8wH6sDKfLTfdygGmraYh0apKrrVbGvMnflbPX4kpjQiAQcUPUpMeas0betH/Su8QubNL8HEkg==
"@react-navigation/native-stack@^6.9.2":
version "6.9.2"
resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.2.tgz#8c861a59a2a86aaf25f0f33a990958edc36ddac4"
integrity sha512-W5CYX+mYVyOYUgWoN15O34Pv/JieX2/pU09yh+kacxPHPEm4gYTQM/OIHACOov5T2WyiNSU6iIHjfzQ6e7M9zw==
dependencies:
"@react-navigation/elements" "^1.3.6"
"@react-navigation/elements" "^1.3.7"
warn-once "^0.1.0"
"@react-navigation/native@^6.0.13":
version "6.0.13"
resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.0.13.tgz#ec504120e193ea6a7f24ffa765a1338be5a3160a"
integrity sha512-CwaJcAGbhv3p3ECablxBkw8QBCGDWXqVRwQ4QbelajNW623m3sNTC9dOF6kjp8au6Rg9B5e0KmeuY0xWbPk79A==
"@react-navigation/native@^6.0.14":
version "6.0.14"
resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.0.14.tgz#3ce3a4176ac7dc5495241d56a28db18449baf754"
integrity sha512-Z95bJrRkZerBJq6Qc/xjA/kibPpB+UvPeMWS1CBhRF8FaX1483UdHqPqSbW879tPwjP2R4XfoA4dtoEHswrOjA==
dependencies:
"@react-navigation/core" "^6.4.0"
"@react-navigation/core" "^6.4.1"
escape-string-regexp "^4.0.0"
fast-deep-equal "^3.1.3"
nanoid "^3.1.23"
@ -2190,12 +2190,12 @@
dependencies:
nanoid "^3.1.23"
"@react-navigation/stack@^6.3.4":
version "6.3.4"
resolved "https://registry.yarnpkg.com/@react-navigation/stack/-/stack-6.3.4.tgz#c3b7a479aea609c0de609f91be7b2539dbae37c2"
integrity sha512-f4vQcbaDPSFHF1i6CnEYbA0Bnk5jRGMoCIs2/Tq0HwsUI62Mui1q5vvIlRDIi5QomJoHzhfTBp9IzMQ/sUQJlg==
"@react-navigation/stack@^6.3.5":
version "6.3.5"
resolved "https://registry.yarnpkg.com/@react-navigation/stack/-/stack-6.3.5.tgz#c616ef78cbaa55938da993d871d9fc41801d41f4"
integrity sha512-G706Ow+8fhiLT5Cf48566YsjboU5h5ll9nva90xX3br7V6x0JMoGMvXjvbORZyzLuUytQO3mf0T3nVUuO52vZQ==
dependencies:
"@react-navigation/elements" "^1.3.6"
"@react-navigation/elements" "^1.3.7"
color "^4.2.3"
warn-once "^0.1.0"
@ -5728,13 +5728,13 @@ expo-web-browser@~12.0.0:
dependencies:
compare-urls "^2.0.0"
expo@^47.0.6:
version "47.0.6"
resolved "https://registry.yarnpkg.com/expo/-/expo-47.0.6.tgz#4436bf0f667b6282f9189e987ddf67cd64807140"
integrity sha512-XFcTnkOWEbc5mbrpdgIkPq3Heuem+8OErdjnWshwiDtaCdqK0EKToJtE2ufhCxb/RzfeJ5k07mpk+8CRRayi4w==
expo@^47.0.7:
version "47.0.7"
resolved "https://registry.yarnpkg.com/expo/-/expo-47.0.7.tgz#4fe95529c6b1e6d8026a164847ce1048f6dc5ccd"
integrity sha512-uHTxvPdD4K7W277tXVAdFmgjSZ0Hg+0g5bnez0jXyXQINa+0CTtGmulgFehBOrbrUZBqwosN0K8TsrxADwcXZQ==
dependencies:
"@babel/runtime" "^7.14.0"
"@expo/cli" "0.4.9"
"@expo/cli" "0.4.10"
"@expo/config" "7.0.3"
"@expo/config-plugins" "5.0.4"
"@expo/vector-icons" "^13.0.0"
@ -10507,10 +10507,10 @@ react-native-live-text-image-view@^0.4.0:
resolved "https://registry.yarnpkg.com/react-native-live-text-image-view/-/react-native-live-text-image-view-0.4.0.tgz#d23d5850788609fd1448533213fc6c453c584761"
integrity sha512-PhVFE0YogSLrTlnHIxUWL80CrmbDvxk1JvLx4UHiRHRwLda4dV/e/9Q+Pyh7Vq7qwAPE6vGoN6sjbXNaj4WCew==
react-native-pager-view@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.1.0.tgz#6cb13fb6f2db8836c89ee8261b07603e97527ceb"
integrity sha512-wBtc77l+lWRDS1FlpeO+rE0iG/ecRtVhHrERMkm7CACQvhB+ty8NL2zlAzOCCbS83DZrIdtWuPu9VqziKHzJPw==
react-native-pager-view@^6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.1.1.tgz#e396b0c78d74931a92d1c9bf28c450eb356b904d"
integrity sha512-4WqR0YWBjaUtc3iPVk8w6wsTsMq+r0plNiXdqPXOiUdQIhxKfsP1iqb6hRzdeJKOo8UH7RCP6zI7dxdFEAXzrw==
react-native-reanimated-zoom@^0.3.3:
version "0.3.3"