Skip to content

Commit 102e5f7

Browse files
committed
Allow user access to Sentry Event IDs or Aggregate ID
1 parent 28c2392 commit 102e5f7

4 files changed

Lines changed: 78 additions & 23 deletions

File tree

src/components/cards/ErrorCard.tsx

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Clipboard from '@react-native-clipboard/clipboard'
12
import * as React from 'react'
23

34
import { useHandler } from '../../hooks/useHandler'
@@ -6,7 +7,7 @@ import { useSelector } from '../../types/reactRedux'
67
import { normalizeError } from '../../util/normalizeError'
78
import { trackError } from '../../util/tracking'
89
import { RawTextModal } from '../modals/RawTextModal'
9-
import { Airship } from '../services/AirshipInstance'
10+
import { Airship, showToast } from '../services/AirshipInstance'
1011
import { AlertCardUi4 } from './AlertCard'
1112

1213
/**
@@ -36,51 +37,92 @@ export const ErrorCard: React.FC<Props> = props => {
3637
const { error } = props
3738

3839
const isDevMode = useSelector(state => state.ui.settings.developerModeOn)
39-
const [reportSent, setReportSent] = React.useState(false)
40+
const [errorIdentifier, setErrorIdentifier] = React.useState<
41+
{ eventId: string } | { aggregateId: string }
42+
>()
43+
44+
// Reset error identifier when error changes
45+
React.useEffect(() => {
46+
setErrorIdentifier(undefined)
47+
}, [error])
4048

4149
const handleReportError = useHandler((): void => {
4250
if (error != null) {
43-
trackError(error, 'AlertDropdown_Report', {
51+
const errorIdentifier = trackError(error, 'AlertDropdown_Report', {
4452
userReportedError: true
4553
})
46-
setReportSent(true)
54+
setErrorIdentifier(errorIdentifier)
55+
}
56+
})
57+
58+
const handleCopyEventId = useHandler((): void => {
59+
if (errorIdentifier != null) {
60+
const id =
61+
'eventId' in errorIdentifier
62+
? errorIdentifier.eventId
63+
: errorIdentifier.aggregateId
64+
Clipboard.setString(id)
65+
showToast(lstrings.fragment_error_report_id_copied)
4766
}
4867
})
4968

69+
const handleShowError = useHandler(async (): Promise<void> => {
70+
await Airship.show(bridge => (
71+
<RawTextModal bridge={bridge} body={normalizeError(error).toString()} />
72+
))
73+
})
74+
5075
// Happy path
5176
if (error instanceof I18nError) {
5277
return (
5378
<AlertCardUi4 type="error" title={error.title} body={error.message} />
5479
)
5580
}
5681

82+
const reportSent = errorIdentifier != null
83+
84+
const isAggregateError =
85+
errorIdentifier != null && 'aggregateId' in errorIdentifier
86+
const copyLabel = isAggregateError
87+
? lstrings.fragment_copy_aggregate_id
88+
: lstrings.fragment_copy_event_id
89+
5790
const buttonProps =
5891
isDevMode || __DEV__
5992
? {
60-
label: 'Show Error',
61-
onPress: async () => {
62-
await Airship.show(bridge => (
63-
<RawTextModal
64-
bridge={bridge}
65-
body={normalizeError(error).toString()}
66-
/>
67-
))
68-
}
93+
label: lstrings.string_show_error,
94+
onPress: handleShowError
95+
}
96+
: reportSent
97+
? {
98+
label: copyLabel,
99+
onPress: handleCopyEventId
69100
}
70101
: {
71-
label: reportSent
72-
? lstrings.string_report_sent
73-
: lstrings.string_report_error,
74-
disabled: reportSent,
102+
label: lstrings.string_report_error,
75103
onPress: handleReportError
76104
}
77105

106+
const idLabel =
107+
errorIdentifier != null && 'eventId' in errorIdentifier
108+
? lstrings.fragment_event_id
109+
: lstrings.fragment_aggregate_id
110+
const idValue =
111+
errorIdentifier != null
112+
? 'eventId' in errorIdentifier
113+
? errorIdentifier.eventId
114+
: errorIdentifier.aggregateId
115+
: ''
116+
const bodyText = reportSent
117+
? `${lstrings.string_report_sent}\n\n${idLabel}: ${idValue}`
118+
: lstrings.error_generic_message
119+
78120
// Unhappy path
79121
return (
80122
<AlertCardUi4
81123
type="error"
82124
title={lstrings.error_unexpected_title}
83-
body={lstrings.error_generic_message}
125+
body={bodyText}
84126
button={buttonProps}
85127
/>
86128
)

src/locales/en_US.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ const strings = {
220220
fragment_request_address_uri_copied:
221221
'Request address URI copied to clipboard',
222222
fragment_copied: 'Successfully copied to clipboard',
223+
fragment_aggregate_id: 'Aggregate ID',
224+
fragment_copy_aggregate_id: 'Copy Aggregate ID',
225+
fragment_copy_event_id: 'Copy Event ID',
226+
fragment_event_id: 'Event ID',
227+
fragment_error_report_id_copied: 'Error report ID copied',
223228
request_minimum_notification_title: 'Minimum Balance Required',
224229
request_xrp_minimum_notification_body_1xrp:
225230
'Ripple (XRP) wallets require a 1 XRP minimum balance. You must deposit at least 1 XRP to this address before this wallet will show a balance or transactions. 1 XRP will be unspendable for the lifetime of this wallet address.',
@@ -1407,7 +1412,8 @@ const strings = {
14071412
string_max_cap: 'MAX',
14081413
string_warning: 'Warning', // Generic string. Same with wc_smartcontract_warning_title
14091414
string_report_error: 'Report Error',
1410-
string_report_sent: 'Report sent.',
1415+
string_report_sent: 'The report has been sent successfully.',
1416+
string_show_error: 'Show Error',
14111417
string_best_rate_badge_text: 'Best\nRate',
14121418

14131419
step_prefix_s: 'Step %s:',

src/locales/strings/enUS.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@
134134
"fragment_request_subtitle": "Receive",
135135
"fragment_request_address_uri_copied": "Request address URI copied to clipboard",
136136
"fragment_copied": "Successfully copied to clipboard",
137+
"fragment_aggregate_id": "Aggregate ID",
138+
"fragment_copy_aggregate_id": "Copy Aggregate ID",
139+
"fragment_copy_event_id": "Copy Event ID",
140+
"fragment_event_id": "Event ID",
141+
"fragment_error_report_id_copied": "Error report ID copied",
137142
"request_minimum_notification_title": "Minimum Balance Required",
138143
"request_xrp_minimum_notification_body_1xrp": "Ripple (XRP) wallets require a 1 XRP minimum balance. You must deposit at least 1 XRP to this address before this wallet will show a balance or transactions. 1 XRP will be unspendable for the lifetime of this wallet address.",
139144
"request_xrp_minimum_notification_alert_body_1xrp": "This wallet will always require a 1 XRP minimum",
@@ -1111,7 +1116,8 @@
11111116
"string_max_cap": "MAX",
11121117
"string_warning": "Warning",
11131118
"string_report_error": "Report Error",
1114-
"string_report_sent": "Report sent.",
1119+
"string_report_sent": "The report has been sent successfully.",
1120+
"string_show_error": "Show Error",
11151121
"string_best_rate_badge_text": "Best\nRate",
11161122
"step_prefix_s": "Step %s:",
11171123
"scan_as_in_scan_barcode": "Scan",

src/util/tracking.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ export function trackError(
190190
error: unknown,
191191
nameTag?: string,
192192
metadata?: Record<string, any>
193-
): void {
193+
): { eventId: string } | { aggregateId: string } {
194194
const err = normalizeError(error)
195195

196196
if (err instanceof AggregateErrorFix) {
@@ -202,10 +202,10 @@ export function trackError(
202202
trackError(e, nameTag, metadata)
203203
})
204204
})
205-
return
205+
return { aggregateId }
206206
}
207207

208-
captureException(err, scope => {
208+
const eventId = captureException(err, scope => {
209209
scope.setTag('event.name', nameTag)
210210
if (metadata != null) {
211211
const context: Record<string, unknown> = {}
@@ -214,6 +214,7 @@ export function trackError(
214214
}
215215
return scope
216216
})
217+
return { eventId }
217218
}
218219

219220
/**

0 commit comments

Comments
 (0)