diff --git a/package.json b/package.json
index caf787f8..df67c3a9 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"native": "220508",
"major": 4,
"minor": 0,
- "patch": 1,
+ "patch": 2,
"expo": "45.0.0"
},
"description": "tooot app for Mastodon",
diff --git a/src/App.tsx b/src/App.tsx
index c0032d71..bdf6569a 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -54,6 +54,7 @@ import { enableFreeze } from 'react-native-screens'
import { QueryClientProvider } from 'react-query'
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/integration/react'
+import * as Sentry from 'sentry-expo'
Platform.select({
android: LogBox.ignoreLogs(['Setting a timer for a long period of time'])
@@ -128,13 +129,15 @@ const App: React.FC = () => {
}
return (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
)
} else {
return null
diff --git a/src/Screens.tsx b/src/Screens.tsx
index 53d27938..805129ff 100644
--- a/src/Screens.tsx
+++ b/src/Screens.tsx
@@ -322,7 +322,11 @@ const Screens: React.FC = ({ localCorrupt }) => {
return (
-
+
({
})
})
.catch(error => {
- // if (sentry && Math.random() < 0.01) {
- // Sentry.Native.setExtras({
- // API: 'general',
- // ...(error.response && { response: error.response }),
- // ...(error.request && { request: error.request })
- // })
- // Sentry.Native.captureException(error)
- // }
-
- if (error.response) {
+ if (error?.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.error(
@@ -80,7 +71,7 @@ const apiGeneral = async ({
status: error.response.status,
message: error.response.data.error
})
- } else if (error.request) {
+ } else if (error?.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
@@ -94,7 +85,7 @@ const apiGeneral = async ({
console.error(
ctx.bold(' API general '),
ctx.bold('internal'),
- error.message,
+ error?.message,
url
)
return Promise.reject()
diff --git a/src/api/instance.ts b/src/api/instance.ts
index 73975956..86d9a367 100644
--- a/src/api/instance.ts
+++ b/src/api/instance.ts
@@ -100,16 +100,7 @@ const apiInstance = async ({
})
})
.catch(error => {
- // if (Math.random() < 0.001) {
- // Sentry.Native.setExtras({
- // API: 'instance',
- // ...(error.response && { response: error.response }),
- // ...(error.request && { request: error.request })
- // })
- // Sentry.Native.captureException(error)
- // }
-
- if (error.response) {
+ if (error?.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.error(
@@ -122,7 +113,7 @@ const apiInstance = async ({
status: error.response.status,
message: error.response.data.error
})
- } else if (error.request) {
+ } else if (error?.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
@@ -132,7 +123,7 @@ const apiInstance = async ({
console.error(
ctx.bold(' API instance '),
ctx.bold('internal'),
- error.message,
+ error?.message,
url
)
return Promise.reject()
diff --git a/src/api/tooot.ts b/src/api/tooot.ts
index 6e7b9ba3..db5c86af 100644
--- a/src/api/tooot.ts
+++ b/src/api/tooot.ts
@@ -66,16 +66,16 @@ const apiTooot = async ({
})
})
.catch(error => {
- if (sentry && Math.random() < 0.01) {
+ if (sentry && Math.random() < 0.1) {
Sentry.Native.setExtras({
API: 'tooot',
- ...(error.response && { response: error.response }),
- ...(error.request && { request: error.request })
+ ...(error?.response && { response: error.response }),
+ ...(error?.request && { request: error.request })
})
Sentry.Native.captureException(error)
}
- if (error.response) {
+ if (error?.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.error(
@@ -88,7 +88,7 @@ const apiTooot = async ({
status: error.response.status,
message: error.response.data.error
})
- } else if (error.request) {
+ } else if (error?.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
@@ -102,7 +102,7 @@ const apiTooot = async ({
console.error(
ctx.bold(' API tooot '),
ctx.bold('internal'),
- error.message,
+ error?.message,
url
)
return Promise.reject()
diff --git a/src/components/Timeline/Shared/Actioned.tsx b/src/components/Timeline/Shared/Actioned.tsx
index 47b59a9f..9b600d2f 100644
--- a/src/components/Timeline/Shared/Actioned.tsx
+++ b/src/components/Timeline/Shared/Actioned.tsx
@@ -22,7 +22,7 @@ const TimelineActioned = React.memo(
const { colors } = useTheme()
const navigation =
useNavigation>()
- const name = account.display_name || account.username
+ const name = account?.display_name || account.username
const iconColor = colors.primaryDefault
const content = (content: string) => (
diff --git a/src/i18n/zh-Hans/components/timeline.json b/src/i18n/zh-Hans/components/timeline.json
index 60a57594..642bff69 100644
--- a/src/i18n/zh-Hans/components/timeline.json
+++ b/src/i18n/zh-Hans/components/timeline.json
@@ -101,7 +101,7 @@
"accessibilityHint": "用户帐户名"
}
},
- "application": "发自{{application}}",
+ "application": "发自 {{application}}",
"edited": {
"accessibilityLabel": "嘟文已编辑"
},
diff --git a/src/screens/Compose.tsx b/src/screens/Compose.tsx
index 712e31db..a848b695 100644
--- a/src/screens/Compose.tsx
+++ b/src/screens/Compose.tsx
@@ -354,7 +354,7 @@ const ScreenCompose: React.FC> = ({
navigation.goBack()
})
.catch(error => {
- if (error.removeReply) {
+ if (error?.removeReply) {
Alert.alert(
t('heading.right.alert.removeReply.title'),
t('heading.right.alert.removeReply.description'),
@@ -377,7 +377,12 @@ const ScreenCompose: React.FC> = ({
]
)
} else {
- Sentry.Native.captureMessage('Compose posting', error)
+ Sentry.Native.captureMessage('Compose posting', {
+ contexts: {
+ errorObject: error,
+ errorString: error.toString()
+ }
+ })
haptics('Error')
composeDispatch({ type: 'posting', payload: false })
Alert.alert(t('heading.right.alert.default.title'), undefined, [
diff --git a/src/screens/Tabs/Me/Root/Settings.tsx b/src/screens/Tabs/Me/Root/Settings.tsx
index 5e08d0f5..d7687db4 100644
--- a/src/screens/Tabs/Me/Root/Settings.tsx
+++ b/src/screens/Tabs/Me/Root/Settings.tsx
@@ -28,7 +28,8 @@ const Settings: React.FC = () => {
onPress={() =>
WebBrowser.openAuthSessionAsync(
`https://${url}/settings/preferences`,
- ''
+ 'tooot://tooot',
+ { dismissButtonStyle: 'done', readerMode: false }
)
}
/>
diff --git a/src/screens/Tabs/Me/Settings/Tooot.tsx b/src/screens/Tabs/Me/Settings/Tooot.tsx
index d1ff4f87..e1c7087a 100644
--- a/src/screens/Tabs/Me/Settings/Tooot.tsx
+++ b/src/screens/Tabs/Me/Settings/Tooot.tsx
@@ -64,8 +64,8 @@ const SettingsTooot: React.FC = () => {
iconBack='ChevronRight'
onPress={() => {
analytics('settings_review_press')
- StoreReview.isAvailableAsync().then(() =>
- StoreReview.requestReview()
+ StoreReview?.isAvailableAsync().then(() =>
+ StoreReview?.requestReview()
)
}}
/>
diff --git a/src/screens/Tabs/Shared/Toot.tsx b/src/screens/Tabs/Shared/Toot.tsx
index fb1f4d1d..63a6a6ea 100644
--- a/src/screens/Tabs/Shared/Toot.tsx
+++ b/src/screens/Tabs/Shared/Toot.tsx
@@ -35,7 +35,7 @@ const TabSharedToot: React.FC> = ({
result.data.pages.flatMap(d => [...d.body])
: []
// Auto go back when toot page is empty
- if (flattenData.length === 0) {
+ if (flattenData.length < 1) {
navigation.goBack()
return
}
@@ -46,13 +46,14 @@ const TabSharedToot: React.FC> = ({
if (pointer < 1) return
try {
setTimeout(() => {
- console.log('scrolling')
flRef.current?.scrollToIndex({
index: pointer,
viewOffset: 100
})
}, 500)
- } catch {}
+ } catch (error) {
+ return
+ }
}
}
})
diff --git a/src/startup/netInfo.ts b/src/startup/netInfo.ts
index 55a7fc68..21188668 100644
--- a/src/startup/netInfo.ts
+++ b/src/startup/netInfo.ts
@@ -41,10 +41,10 @@ const netInfo = async (): Promise<{
}).then(res => res.body)
} catch (error: any) {
log('error', 'netInfo', 'local credential check failed')
- if (error.status && error.status == 401) {
+ if (error?.status && error.status == 401) {
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')
diff --git a/src/startup/sentry.ts b/src/startup/sentry.ts
index 507516ca..7d398c66 100644
--- a/src/startup/sentry.ts
+++ b/src/startup/sentry.ts
@@ -6,8 +6,9 @@ const sentry = () => {
log('log', 'Sentry', 'initializing')
Sentry.init({
dsn: 'https://53348b60ff844d52886e90251b3a5f41@o917354.ingest.sentry.io/6410576',
- enableInExpoDevelopment: true,
- debug: !isRelease
+ enableInExpoDevelopment: false,
+ debug: !isRelease,
+ autoSessionTracking: true
})
}
diff --git a/src/utils/push/useConnect.ts b/src/utils/push/useConnect.ts
index 79f04f43..84174ea4 100644
--- a/src/utils/push/useConnect.ts
+++ b/src/utils/push/useConnect.ts
@@ -35,7 +35,7 @@ const pushUseConnect = ({ t, instances }: Params) => {
url: `push/connect/${expoToken}`,
sentry: true
}).catch(error => {
- if (error.status == 404) {
+ if (error?.status == 404) {
displayMessage({
theme,
type: 'error',
diff --git a/src/utils/slices/contextsSlice.ts b/src/utils/slices/contextsSlice.ts
index 65d7c2e1..b957f65c 100644
--- a/src/utils/slices/contextsSlice.ts
+++ b/src/utils/slices/contextsSlice.ts
@@ -41,7 +41,9 @@ const contextsSlice = createSlice({
if (Updates.releaseChannel.includes('release')) {
state.storeReview.current = state.storeReview.current + action.payload
if (state.storeReview.current === state.storeReview.context) {
- StoreReview.isAvailableAsync().then(() => StoreReview.requestReview())
+ StoreReview?.isAvailableAsync().then(() =>
+ StoreReview.requestReview()
+ )
}
}
},
diff --git a/src/utils/slices/instancesSlice.ts b/src/utils/slices/instancesSlice.ts
index 605c036a..85210dff 100644
--- a/src/utils/slices/instancesSlice.ts
+++ b/src/utils/slices/instancesSlice.ts
@@ -306,6 +306,7 @@ const instancesSlice = createSlice({
// Check if frequently used emojis still exist
.addCase(checkEmojis.fulfilled, (state, action) => {
+ if (!action.payload || !action.payload.length) return
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].frequentEmojis = state.instances[
activeIndex