Compare commits

...

10 Commits

Author SHA1 Message Date
xmflsct 6dad65631f
Merge pull request #300 from tooot-app/main
Release v4.0.2
2022-05-18 00:27:47 +02:00
xmflsct 0479e2fc9f
Merge pull request #297 from tooot-app/l10n_main
New Crowdin updates
2022-05-18 00:11:49 +02:00
Zhiyuan Zheng 4dcc561cbf Update error tracing 2022-05-18 00:11:31 +02:00
Zhiyuan Zheng 051dc7be8c Update Screens.tsx
https://github.com/tooot-app/app/issues/298
2022-05-18 00:11:02 +02:00
Zhiyuan Zheng 8a1ccdb305 Update instancesSlice.ts 2022-05-17 23:26:29 +02:00
Zhiyuan Zheng 02360c443f Make error object as optional 2022-05-17 23:18:49 +02:00
Zhiyuan Zheng 4b3b222582 Some Android phones do not have StoreReview? 2022-05-17 23:14:23 +02:00
Zhiyuan Zheng 5d615174cb Fix possible undefined 2022-05-17 23:12:43 +02:00
Zhiyuan Zheng 94e9e023e3 Fix account setting cannot be opened 2022-05-17 23:10:25 +02:00
xmflsct f7e8d90f1a New translations timeline.json (Chinese Simplified) 2022-05-17 03:40:36 +02:00
17 changed files with 55 additions and 55 deletions

View File

@ -4,7 +4,7 @@
"native": "220508", "native": "220508",
"major": 4, "major": 4,
"minor": 0, "minor": 0,
"patch": 1, "patch": 2,
"expo": "45.0.0" "expo": "45.0.0"
}, },
"description": "tooot app for Mastodon", "description": "tooot app for Mastodon",

View File

@ -54,6 +54,7 @@ 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 * as Sentry from 'sentry-expo'
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'])
@ -128,13 +129,15 @@ const App: React.FC = () => {
} }
return ( return (
<ActionSheetProvider> <Sentry.Native.TouchEventBoundary>
<AccessibilityManager> <ActionSheetProvider>
<ThemeManager> <AccessibilityManager>
<Screens localCorrupt={localCorrupt} /> <ThemeManager>
</ThemeManager> <Screens localCorrupt={localCorrupt} />
</AccessibilityManager> </ThemeManager>
</ActionSheetProvider> </AccessibilityManager>
</ActionSheetProvider>
</Sentry.Native.TouchEventBoundary>
) )
} else { } else {
return null return null

View File

@ -322,7 +322,11 @@ const Screens: React.FC<Props> = ({ localCorrupt }) => {
return ( return (
<IntlProvider locale={i18n.language}> <IntlProvider locale={i18n.language}>
<StatusBar backgroundColor={colors.backgroundDefault} /> <StatusBar
{...(Platform.OS === 'ios' && {
backgroundColor: colors.backgroundDefault
})}
/>
<NavigationContainer <NavigationContainer
ref={navigationRef} ref={navigationRef}
theme={themes[theme]} theme={themes[theme]}

View File

@ -58,16 +58,7 @@ const apiGeneral = async <T = unknown>({
}) })
}) })
.catch(error => { .catch(error => {
// if (sentry && Math.random() < 0.01) { if (error?.response) {
// Sentry.Native.setExtras({
// API: 'general',
// ...(error.response && { response: error.response }),
// ...(error.request && { request: error.request })
// })
// Sentry.Native.captureException(error)
// }
if (error.response) {
// The request was made and the server responded with a status code // The request was made and the server responded with a status code
// that falls out of the range of 2xx // that falls out of the range of 2xx
console.error( console.error(
@ -80,7 +71,7 @@ const apiGeneral = async <T = unknown>({
status: error.response.status, status: error.response.status,
message: error.response.data.error message: error.response.data.error
}) })
} else if (error.request) { } else if (error?.request) {
// The request was made but no response was received // The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js // http.ClientRequest in node.js
@ -94,7 +85,7 @@ const apiGeneral = async <T = unknown>({
console.error( console.error(
ctx.bold(' API general '), ctx.bold(' API general '),
ctx.bold('internal'), ctx.bold('internal'),
error.message, error?.message,
url url
) )
return Promise.reject() return Promise.reject()

View File

@ -100,16 +100,7 @@ const apiInstance = async <T = unknown>({
}) })
}) })
.catch(error => { .catch(error => {
// if (Math.random() < 0.001) { if (error?.response) {
// Sentry.Native.setExtras({
// API: 'instance',
// ...(error.response && { response: error.response }),
// ...(error.request && { request: error.request })
// })
// Sentry.Native.captureException(error)
// }
if (error.response) {
// The request was made and the server responded with a status code // The request was made and the server responded with a status code
// that falls out of the range of 2xx // that falls out of the range of 2xx
console.error( console.error(
@ -122,7 +113,7 @@ const apiInstance = async <T = unknown>({
status: error.response.status, status: error.response.status,
message: error.response.data.error message: error.response.data.error
}) })
} else if (error.request) { } else if (error?.request) {
// The request was made but no response was received // The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js // http.ClientRequest in node.js
@ -132,7 +123,7 @@ const apiInstance = async <T = unknown>({
console.error( console.error(
ctx.bold(' API instance '), ctx.bold(' API instance '),
ctx.bold('internal'), ctx.bold('internal'),
error.message, error?.message,
url url
) )
return Promise.reject() return Promise.reject()

View File

@ -66,16 +66,16 @@ const apiTooot = async <T = unknown>({
}) })
}) })
.catch(error => { .catch(error => {
if (sentry && Math.random() < 0.01) { if (sentry && Math.random() < 0.1) {
Sentry.Native.setExtras({ Sentry.Native.setExtras({
API: 'tooot', API: 'tooot',
...(error.response && { response: error.response }), ...(error?.response && { response: error.response }),
...(error.request && { request: error.request }) ...(error?.request && { request: error.request })
}) })
Sentry.Native.captureException(error) Sentry.Native.captureException(error)
} }
if (error.response) { if (error?.response) {
// The request was made and the server responded with a status code // The request was made and the server responded with a status code
// that falls out of the range of 2xx // that falls out of the range of 2xx
console.error( console.error(
@ -88,7 +88,7 @@ const apiTooot = async <T = unknown>({
status: error.response.status, status: error.response.status,
message: error.response.data.error message: error.response.data.error
}) })
} else if (error.request) { } else if (error?.request) {
// The request was made but no response was received // The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js // http.ClientRequest in node.js
@ -102,7 +102,7 @@ const apiTooot = async <T = unknown>({
console.error( console.error(
ctx.bold(' API tooot '), ctx.bold(' API tooot '),
ctx.bold('internal'), ctx.bold('internal'),
error.message, error?.message,
url url
) )
return Promise.reject() return Promise.reject()

View File

@ -22,7 +22,7 @@ const TimelineActioned = React.memo(
const { colors } = useTheme() const { colors } = useTheme()
const navigation = const navigation =
useNavigation<StackNavigationProp<TabLocalStackParamList>>() useNavigation<StackNavigationProp<TabLocalStackParamList>>()
const name = account.display_name || account.username const name = account?.display_name || account.username
const iconColor = colors.primaryDefault const iconColor = colors.primaryDefault
const content = (content: string) => ( const content = (content: string) => (

View File

@ -101,7 +101,7 @@
"accessibilityHint": "用户帐户名" "accessibilityHint": "用户帐户名"
} }
}, },
"application": "发自{{application}}", "application": "发自 {{application}}",
"edited": { "edited": {
"accessibilityLabel": "嘟文已编辑" "accessibilityLabel": "嘟文已编辑"
}, },

View File

@ -354,7 +354,7 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
navigation.goBack() navigation.goBack()
}) })
.catch(error => { .catch(error => {
if (error.removeReply) { if (error?.removeReply) {
Alert.alert( Alert.alert(
t('heading.right.alert.removeReply.title'), t('heading.right.alert.removeReply.title'),
t('heading.right.alert.removeReply.description'), t('heading.right.alert.removeReply.description'),
@ -377,7 +377,12 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
] ]
) )
} else { } else {
Sentry.Native.captureMessage('Compose posting', error) Sentry.Native.captureMessage('Compose posting', {
contexts: {
errorObject: error,
errorString: error.toString()
}
})
haptics('Error') haptics('Error')
composeDispatch({ type: 'posting', payload: false }) composeDispatch({ type: 'posting', payload: false })
Alert.alert(t('heading.right.alert.default.title'), undefined, [ Alert.alert(t('heading.right.alert.default.title'), undefined, [

View File

@ -28,7 +28,8 @@ const Settings: React.FC = () => {
onPress={() => onPress={() =>
WebBrowser.openAuthSessionAsync( WebBrowser.openAuthSessionAsync(
`https://${url}/settings/preferences`, `https://${url}/settings/preferences`,
'' 'tooot://tooot',
{ dismissButtonStyle: 'done', readerMode: false }
) )
} }
/> />

View File

@ -64,8 +64,8 @@ const SettingsTooot: React.FC = () => {
iconBack='ChevronRight' iconBack='ChevronRight'
onPress={() => { onPress={() => {
analytics('settings_review_press') analytics('settings_review_press')
StoreReview.isAvailableAsync().then(() => StoreReview?.isAvailableAsync().then(() =>
StoreReview.requestReview() StoreReview?.requestReview()
) )
}} }}
/> />

View File

@ -35,7 +35,7 @@ const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
result.data.pages.flatMap(d => [...d.body]) result.data.pages.flatMap(d => [...d.body])
: [] : []
// Auto go back when toot page is empty // Auto go back when toot page is empty
if (flattenData.length === 0) { if (flattenData.length < 1) {
navigation.goBack() navigation.goBack()
return return
} }
@ -46,13 +46,14 @@ const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
if (pointer < 1) return if (pointer < 1) return
try { try {
setTimeout(() => { setTimeout(() => {
console.log('scrolling')
flRef.current?.scrollToIndex({ flRef.current?.scrollToIndex({
index: pointer, index: pointer,
viewOffset: 100 viewOffset: 100
}) })
}, 500) }, 500)
} catch {} } catch (error) {
return
}
} }
} }
}) })

View File

@ -41,10 +41,10 @@ const netInfo = async (): Promise<{
}).then(res => res.body) }).then(res => res.body)
} catch (error: any) { } catch (error: any) {
log('error', 'netInfo', 'local credential check failed') log('error', 'netInfo', 'local credential check failed')
if (error.status && error.status == 401) { if (error?.status && error.status == 401) {
store.dispatch(removeInstance(instance)) store.dispatch(removeInstance(instance))
} }
return Promise.resolve({ corrupted: error.data.error }) return Promise.resolve({ corrupted: error.data?.error })
} }
log('log', 'netInfo', 'local credential check passed') log('log', 'netInfo', 'local credential check passed')

View File

@ -6,8 +6,9 @@ const sentry = () => {
log('log', 'Sentry', 'initializing') log('log', 'Sentry', 'initializing')
Sentry.init({ Sentry.init({
dsn: 'https://53348b60ff844d52886e90251b3a5f41@o917354.ingest.sentry.io/6410576', dsn: 'https://53348b60ff844d52886e90251b3a5f41@o917354.ingest.sentry.io/6410576',
enableInExpoDevelopment: true, enableInExpoDevelopment: false,
debug: !isRelease debug: !isRelease,
autoSessionTracking: true
}) })
} }

View File

@ -35,7 +35,7 @@ const pushUseConnect = ({ t, instances }: Params) => {
url: `push/connect/${expoToken}`, url: `push/connect/${expoToken}`,
sentry: true sentry: true
}).catch(error => { }).catch(error => {
if (error.status == 404) { if (error?.status == 404) {
displayMessage({ displayMessage({
theme, theme,
type: 'error', type: 'error',

View File

@ -41,7 +41,9 @@ const contextsSlice = createSlice({
if (Updates.releaseChannel.includes('release')) { if (Updates.releaseChannel.includes('release')) {
state.storeReview.current = state.storeReview.current + action.payload state.storeReview.current = state.storeReview.current + action.payload
if (state.storeReview.current === state.storeReview.context) { if (state.storeReview.current === state.storeReview.context) {
StoreReview.isAvailableAsync().then(() => StoreReview.requestReview()) StoreReview?.isAvailableAsync().then(() =>
StoreReview.requestReview()
)
} }
} }
}, },

View File

@ -306,6 +306,7 @@ const instancesSlice = createSlice({
// Check if frequently used emojis still exist // Check if frequently used emojis still exist
.addCase(checkEmojis.fulfilled, (state, action) => { .addCase(checkEmojis.fulfilled, (state, action) => {
if (!action.payload || !action.payload.length) return
const activeIndex = findInstanceActive(state.instances) const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].frequentEmojis = state.instances[ state.instances[activeIndex].frequentEmojis = state.instances[
activeIndex activeIndex