mirror of https://github.com/tooot-app/app
commit
6dad65631f
|
@ -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",
|
||||||
|
|
17
src/App.tsx
17
src/App.tsx
|
@ -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
|
||||||
|
|
|
@ -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]}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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) => (
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
"accessibilityHint": "用户帐户名"
|
"accessibilityHint": "用户帐户名"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"application": "发自{{application}}",
|
"application": "发自 {{application}}",
|
||||||
"edited": {
|
"edited": {
|
||||||
"accessibilityLabel": "嘟文已编辑"
|
"accessibilityLabel": "嘟文已编辑"
|
||||||
},
|
},
|
||||||
|
|
|
@ -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, [
|
||||||
|
|
|
@ -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 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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()
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue