mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
@ -3,9 +3,6 @@ export ENVIRONMENT="development"
|
|||||||
export SENTRY_ORGANIZATION=""
|
export SENTRY_ORGANIZATION=""
|
||||||
export SENTRY_PROJECT=""
|
export SENTRY_PROJECT=""
|
||||||
export SENTRY_AUTH_TOKEN=""
|
export SENTRY_AUTH_TOKEN=""
|
||||||
export SENTRY_DSN=""
|
|
||||||
|
|
||||||
export TOOOT_PUSH_KEY_PUBLIC=""
|
|
||||||
|
|
||||||
# Fastlane start
|
# Fastlane start
|
||||||
export LC_ALL=""
|
export LC_ALL=""
|
||||||
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -43,8 +43,6 @@ jobs:
|
|||||||
SENTRY_ORGANIZATION: ${{ secrets.SENTRY_ORGANIZATION }}
|
SENTRY_ORGANIZATION: ${{ secrets.SENTRY_ORGANIZATION }}
|
||||||
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
|
||||||
TOOOT_PUSH_KEY_PUBLIC: ${{ secrets.TOOOT_PUSH_KEY_PUBLIC }}
|
|
||||||
FASTLANE_USER: ${{ secrets.FASTLANE_USER }}
|
FASTLANE_USER: ${{ secrets.FASTLANE_USER }}
|
||||||
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
|
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
|
||||||
MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }}
|
MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }}
|
||||||
|
@ -12,10 +12,6 @@ export default (): ExpoConfig => ({
|
|||||||
version: toootVersion,
|
version: toootVersion,
|
||||||
privacy: 'hidden',
|
privacy: 'hidden',
|
||||||
assetBundlePatterns: ['assets/*'],
|
assetBundlePatterns: ['assets/*'],
|
||||||
extra: {
|
|
||||||
sentryDSN: process.env.SENTRY_DSN,
|
|
||||||
toootPushKeyPublic: process.env.TOOOT_PUSH_KEY_PUBLIC
|
|
||||||
},
|
|
||||||
hooks: {
|
hooks: {
|
||||||
postPublish: [
|
postPublish: [
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"native": "220508",
|
"native": "220508",
|
||||||
"major": 4,
|
"major": 4,
|
||||||
"minor": 0,
|
"minor": 0,
|
||||||
"patch": 0,
|
"patch": 1,
|
||||||
"expo": "45.0.0"
|
"expo": "45.0.0"
|
||||||
},
|
},
|
||||||
"description": "tooot app for Mastodon",
|
"description": "tooot app for Mastodon",
|
||||||
|
@ -54,7 +54,6 @@ import { enableFreeze } from 'react-native-screens'
|
|||||||
import { QueryClientProvider } from 'react-query'
|
import { QueryClientProvider } from 'react-query'
|
||||||
import { Provider } from 'react-redux'
|
import { Provider } from 'react-redux'
|
||||||
import { PersistGate } from 'redux-persist/integration/react'
|
import { PersistGate } from 'redux-persist/integration/react'
|
||||||
import { IntlProvider } from 'react-intl'
|
|
||||||
|
|
||||||
Platform.select({
|
Platform.select({
|
||||||
android: LogBox.ignoreLogs(['Setting a timer for a long period of time'])
|
android: LogBox.ignoreLogs(['Setting a timer for a long period of time'])
|
||||||
@ -132,9 +131,7 @@ const App: React.FC = () => {
|
|||||||
<ActionSheetProvider>
|
<ActionSheetProvider>
|
||||||
<AccessibilityManager>
|
<AccessibilityManager>
|
||||||
<ThemeManager>
|
<ThemeManager>
|
||||||
<IntlProvider locale={language}>
|
<Screens localCorrupt={localCorrupt} />
|
||||||
<Screens localCorrupt={localCorrupt} />
|
|
||||||
</IntlProvider>
|
|
||||||
</ThemeManager>
|
</ThemeManager>
|
||||||
</AccessibilityManager>
|
</AccessibilityManager>
|
||||||
</ActionSheetProvider>
|
</ActionSheetProvider>
|
||||||
|
@ -26,6 +26,7 @@ import * as Linking from 'expo-linking'
|
|||||||
import { addScreenshotListener } from 'expo-screen-capture'
|
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 { IntlProvider } from 'react-intl'
|
||||||
import { Alert, Platform, StatusBar } from 'react-native'
|
import { Alert, Platform, StatusBar } from 'react-native'
|
||||||
import ShareMenu from 'react-native-share-menu'
|
import ShareMenu from 'react-native-share-menu'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
@ -39,7 +40,7 @@ export interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
||||||
const { t } = useTranslation('screens')
|
const { i18n, t } = useTranslation('screens')
|
||||||
const dispatch = useAppDispatch()
|
const dispatch = useAppDispatch()
|
||||||
const instanceActive = useSelector(getInstanceActive)
|
const instanceActive = useSelector(getInstanceActive)
|
||||||
const { colors, theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
@ -320,7 +321,7 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<IntlProvider locale={i18n.language}>
|
||||||
<StatusBar backgroundColor={colors.backgroundDefault} />
|
<StatusBar backgroundColor={colors.backgroundDefault} />
|
||||||
<NavigationContainer
|
<NavigationContainer
|
||||||
ref={navigationRef}
|
ref={navigationRef}
|
||||||
@ -381,7 +382,7 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
|
|||||||
|
|
||||||
<Message />
|
<Message />
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
</>
|
</IntlProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +156,7 @@ const TimelineDefault = React.memo(
|
|||||||
rootQueryKey={rootQueryKey}
|
rootQueryKey={rootQueryKey}
|
||||||
highlighted={highlighted}
|
highlighted={highlighted}
|
||||||
status={actualStatus}
|
status={actualStatus}
|
||||||
|
ownAccount={ownAccount}
|
||||||
accts={uniqBy(
|
accts={uniqBy(
|
||||||
(
|
(
|
||||||
[actualStatus.account] as Mastodon.Account[] &
|
[actualStatus.account] as Mastodon.Account[] &
|
||||||
|
@ -22,6 +22,7 @@ export interface Props {
|
|||||||
rootQueryKey?: QueryKeyTimeline
|
rootQueryKey?: QueryKeyTimeline
|
||||||
highlighted: boolean
|
highlighted: boolean
|
||||||
status: Mastodon.Status
|
status: Mastodon.Status
|
||||||
|
ownAccount?: boolean
|
||||||
accts: Mastodon.Account['acct'][] // When replying to conversations
|
accts: Mastodon.Account['acct'][] // When replying to conversations
|
||||||
reblog: boolean
|
reblog: boolean
|
||||||
}
|
}
|
||||||
@ -31,6 +32,7 @@ const TimelineActions: React.FC<Props> = ({
|
|||||||
rootQueryKey,
|
rootQueryKey,
|
||||||
highlighted,
|
highlighted,
|
||||||
status,
|
status,
|
||||||
|
ownAccount = false,
|
||||||
accts,
|
accts,
|
||||||
reblog
|
reblog
|
||||||
}) => {
|
}) => {
|
||||||
@ -207,7 +209,8 @@ const TimelineActions: React.FC<Props> = ({
|
|||||||
<Icon
|
<Icon
|
||||||
name='Repeat'
|
name='Repeat'
|
||||||
color={
|
color={
|
||||||
status.visibility === 'direct'
|
status.visibility === 'direct' ||
|
||||||
|
(status.visibility === 'private' && !ownAccount)
|
||||||
? colors.disabled
|
? colors.disabled
|
||||||
: color(status.reblogged)
|
: color(status.reblogged)
|
||||||
}
|
}
|
||||||
@ -216,7 +219,10 @@ const TimelineActions: React.FC<Props> = ({
|
|||||||
{status.reblogs_count > 0 ? (
|
{status.reblogs_count > 0 ? (
|
||||||
<CustomText
|
<CustomText
|
||||||
style={{
|
style={{
|
||||||
color: color(status.reblogged),
|
color:
|
||||||
|
status.visibility === 'private' && !ownAccount
|
||||||
|
? colors.disabled
|
||||||
|
: color(status.reblogged),
|
||||||
fontSize: StyleConstants.Font.Size.M,
|
fontSize: StyleConstants.Font.Size.M,
|
||||||
marginLeft: StyleConstants.Spacing.XS
|
marginLeft: StyleConstants.Spacing.XS
|
||||||
}}
|
}}
|
||||||
@ -297,7 +303,10 @@ const TimelineActions: React.FC<Props> = ({
|
|||||||
style={styles.action}
|
style={styles.action}
|
||||||
onPress={onPressReblog}
|
onPress={onPressReblog}
|
||||||
children={childrenReblog}
|
children={childrenReblog}
|
||||||
disabled={status.visibility === 'direct'}
|
disabled={
|
||||||
|
status.visibility === 'direct' ||
|
||||||
|
(status.visibility === 'private' && !ownAccount)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Pressable
|
<Pressable
|
||||||
|
@ -4,7 +4,7 @@ import { StyleConstants } from '@utils/styles/constants'
|
|||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { FormattedDate, FormattedRelativeTime, FormattedTime } from 'react-intl'
|
import { FormattedDate, FormattedRelativeTime } from 'react-intl'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
created_at: Mastodon.Status['created_at'] | number
|
created_at: Mastodon.Status['created_at'] | number
|
||||||
|
@ -101,7 +101,7 @@
|
|||||||
"accessibilityHint": "用户帐户名"
|
"accessibilityHint": "用户帐户名"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"application": "发自于 {{application}}",
|
"application": "发自{{application}}",
|
||||||
"edited": {
|
"edited": {
|
||||||
"accessibilityLabel": "嘟文已编辑"
|
"accessibilityLabel": "嘟文已编辑"
|
||||||
},
|
},
|
||||||
@ -113,7 +113,7 @@
|
|||||||
"accessibilityLabel": "此嘟文是私信"
|
"accessibilityLabel": "此嘟文是私信"
|
||||||
},
|
},
|
||||||
"private": {
|
"private": {
|
||||||
"accessibilityLabel": "此嘟文仅关注着可见"
|
"accessibilityLabel": "此嘟文仅关注者可见"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -184,13 +184,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deleteEdit": {
|
"deleteEdit": {
|
||||||
"function": "删除嘟文",
|
"function": "删除并重新编辑",
|
||||||
"button": "删除此条嘟文",
|
"button": "删除并重新编辑此条嘟文",
|
||||||
"alert": {
|
"alert": {
|
||||||
"title": "确认删除嘟文?",
|
"title": "确认删除嘟文?",
|
||||||
"message": "确定要删除这条嘟文并重新编辑它吗?所有相关的转嘟和喜欢都会被清除,回复将会失去关联。",
|
"message": "确定要删除这条嘟文并重新编辑它吗?所有相关的转嘟和喜欢都会被清除,回复将会失去关联。",
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"confirm": "确认删除",
|
"confirm": "删除并重新编辑",
|
||||||
"cancel": "$t(common:buttons.cancel)"
|
"cancel": "$t(common:buttons.cancel)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ const TabMePush: React.FC = () => {
|
|||||||
} else {
|
} else {
|
||||||
Notifications.getExpoPushTokenAsync({
|
Notifications.getExpoPushTokenAsync({
|
||||||
experienceId: '@xmflsct/tooot',
|
experienceId: '@xmflsct/tooot',
|
||||||
applicationId: 'com.xmflsct.tooot.app'
|
applicationId: 'com.xmflsct.app.tooot'
|
||||||
})
|
})
|
||||||
.then(data => setPushAvailable(!!data))
|
.then(data => setPushAvailable(!!data))
|
||||||
.catch(() => setPushAvailable(false))
|
.catch(() => setPushAvailable(false))
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import { isDevelopment } from '@utils/checkEnvironment'
|
import { isRelease } from '@utils/checkEnvironment'
|
||||||
import Constants from 'expo-constants'
|
|
||||||
import * as Sentry from 'sentry-expo'
|
import * as Sentry from 'sentry-expo'
|
||||||
import log from './log'
|
import log from './log'
|
||||||
|
|
||||||
const sentry = () => {
|
const sentry = () => {
|
||||||
log('log', 'Sentry', 'initializing')
|
log('log', 'Sentry', 'initializing')
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: Constants.manifest?.extra?.sentryDSN,
|
dsn: 'https://53348b60ff844d52886e90251b3a5f41@o917354.ingest.sentry.io/6410576',
|
||||||
enableInExpoDevelopment: false,
|
enableInExpoDevelopment: true,
|
||||||
debug: isDevelopment
|
debug: !isRelease
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ const pushUseConnect = ({ t, instances }: Params) => {
|
|||||||
: (
|
: (
|
||||||
await Notifications.getExpoPushTokenAsync({
|
await Notifications.getExpoPushTokenAsync({
|
||||||
experienceId: '@xmflsct/tooot',
|
experienceId: '@xmflsct/tooot',
|
||||||
applicationId: 'com.xmflsct.tooot.app'
|
applicationId: 'com.xmflsct.app.tooot'
|
||||||
})
|
})
|
||||||
).data
|
).data
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ import apiTooot, { TOOOT_API_DOMAIN } from '@api/tooot'
|
|||||||
import i18n from '@root/i18n/i18n'
|
import i18n from '@root/i18n/i18n'
|
||||||
import { RootState } from '@root/store'
|
import { RootState } from '@root/store'
|
||||||
import { getInstance, Instance } from '@utils/slices/instancesSlice'
|
import { getInstance, Instance } from '@utils/slices/instancesSlice'
|
||||||
import Constants from 'expo-constants'
|
|
||||||
import * as Notifications from 'expo-notifications'
|
import * as Notifications from 'expo-notifications'
|
||||||
import * as Random from 'expo-random'
|
import * as Random from 'expo-random'
|
||||||
import { Platform } from 'react-native'
|
import { Platform } from 'react-native'
|
||||||
@ -57,7 +56,7 @@ const pushRegister = async (
|
|||||||
formData.append('subscription[endpoint]', endpoint)
|
formData.append('subscription[endpoint]', endpoint)
|
||||||
formData.append(
|
formData.append(
|
||||||
'subscription[keys][p256dh]',
|
'subscription[keys][p256dh]',
|
||||||
Constants.manifest?.extra?.toootPushKeyPublic
|
'BMn2PLpZrMefG981elzG6SB1EY9gU7QZwmtZ/a/J2vUeWG+zXgeskMPwHh4T/bxsD4l7/8QT94F57CbZqYRRfJo='
|
||||||
)
|
)
|
||||||
formData.append('subscription[keys][auth]', auth)
|
formData.append('subscription[keys][auth]', auth)
|
||||||
Object.keys(alerts).map(key =>
|
Object.keys(alerts).map(key =>
|
||||||
|
@ -18,7 +18,7 @@ export const updateInstancePush = createAsyncThunk(
|
|||||||
: (
|
: (
|
||||||
await Notifications.getExpoPushTokenAsync({
|
await Notifications.getExpoPushTokenAsync({
|
||||||
experienceId: '@xmflsct/tooot',
|
experienceId: '@xmflsct/tooot',
|
||||||
applicationId: 'com.xmflsct.tooot.app'
|
applicationId: 'com.xmflsct.app.tooot'
|
||||||
})
|
})
|
||||||
).data
|
).data
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ export const updateInstancePushDecode = createAsyncThunk(
|
|||||||
: (
|
: (
|
||||||
await Notifications.getExpoPushTokenAsync({
|
await Notifications.getExpoPushTokenAsync({
|
||||||
experienceId: '@xmflsct/tooot',
|
experienceId: '@xmflsct/tooot',
|
||||||
applicationId: 'com.xmflsct.tooot.app'
|
applicationId: 'com.xmflsct.app.tooot'
|
||||||
})
|
})
|
||||||
).data
|
).data
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user