@@ -14,6 +14,7 @@ import type {PlatformKey, Project} from 'sentry/types/project';
14
14
import { trackAnalytics } from 'sentry/utils/analytics' ;
15
15
import { isMobilePlatform , isNativePlatform } from 'sentry/utils/platform' ;
16
16
import useApi from 'sentry/utils/useApi' ;
17
+ import { useLocalStorageState } from 'sentry/utils/useLocalStorageState' ;
17
18
import useOrganization from 'sentry/utils/useOrganization' ;
18
19
import { InterimSection } from 'sentry/views/issueDetails/streamline/interimSection' ;
19
20
import { useHasStreamlinedUI } from 'sentry/views/issueDetails/utils' ;
@@ -32,12 +33,14 @@ export const displayOptions = {
32
33
} ;
33
34
34
35
type State = {
35
- display : Array < keyof typeof displayOptions > ;
36
36
fullStackTrace : boolean ;
37
37
sortBy : keyof typeof sortByOptions ;
38
38
} ;
39
39
40
- type ChildProps = Omit < State , 'sortBy' > & { recentFirst : boolean } ;
40
+ type ChildProps = Omit < State , 'sortBy' > & {
41
+ display : Array < keyof typeof displayOptions > ;
42
+ recentFirst : boolean ;
43
+ } ;
41
44
42
45
type Props = {
43
46
children : ( childProps : ChildProps ) => React . ReactNode ;
@@ -87,9 +90,13 @@ export function TraceEventDataSection({
87
90
const [ state , setState ] = useState < State > ( {
88
91
sortBy : recentFirst ? 'recent-first' : 'recent-last' ,
89
92
fullStackTrace : ! hasAppOnlyFrames ? true : fullStackTrace ,
90
- display : [ ] ,
91
93
} ) ;
92
94
95
+ const [ display , setDisplay ] = useLocalStorageState < Array < keyof typeof displayOptions > > (
96
+ `issue-details-stracktrace-display-${ organization . slug } -${ projectSlug } ` ,
97
+ [ ]
98
+ ) ;
99
+
93
100
const isMobile = isMobilePlatform ( platform ) ;
94
101
95
102
const handleFilterFramesChange = useCallback (
@@ -144,7 +151,7 @@ export function TraceEventDataSection({
144
151
is_mobile : isMobile ,
145
152
checked : true ,
146
153
} ) ;
147
- } else if ( state . display . includes ( 'raw-stack-trace' ) ) {
154
+ } else if ( display . includes ( 'raw-stack-trace' ) ) {
148
155
trackAnalytics ( 'stack-trace.display_option_raw_stack_trace_clicked' , {
149
156
organization,
150
157
project_slug : projectSlug ,
@@ -162,7 +169,7 @@ export function TraceEventDataSection({
162
169
is_mobile : isMobile ,
163
170
checked : true ,
164
171
} ) ;
165
- } else if ( state . display . includes ( 'absolute-addresses' ) ) {
172
+ } else if ( display . includes ( 'absolute-addresses' ) ) {
166
173
trackAnalytics ( 'stack-trace.display_option_absolute_addresses_clicked' , {
167
174
organization,
168
175
project_slug : projectSlug ,
@@ -180,7 +187,7 @@ export function TraceEventDataSection({
180
187
is_mobile : isMobile ,
181
188
checked : true ,
182
189
} ) ;
183
- } else if ( state . display . includes ( 'absolute-file-paths' ) ) {
190
+ } else if ( display . includes ( 'absolute-file-paths' ) ) {
184
191
trackAnalytics ( 'stack-trace.display_option_absolute_file_paths_clicked' , {
185
192
organization,
186
193
project_slug : projectSlug ,
@@ -203,7 +210,7 @@ export function TraceEventDataSection({
203
210
checked : true ,
204
211
}
205
212
) ;
206
- } else if ( state . display . includes ( 'minified' ) ) {
213
+ } else if ( display . includes ( 'minified' ) ) {
207
214
trackAnalytics (
208
215
platform . startsWith ( 'javascript' )
209
216
? 'stack-trace.display_option_minified_clicked'
@@ -226,7 +233,7 @@ export function TraceEventDataSection({
226
233
is_mobile : isMobile ,
227
234
checked : true ,
228
235
} ) ;
229
- } else if ( state . display . includes ( 'verbose-function-names' ) ) {
236
+ } else if ( display . includes ( 'verbose-function-names' ) ) {
230
237
trackAnalytics ( 'stack-trace.display_option_verbose_function_names_clicked' , {
231
238
organization,
232
239
project_slug : projectSlug ,
@@ -236,9 +243,9 @@ export function TraceEventDataSection({
236
243
} ) ;
237
244
}
238
245
239
- setState ( currentState => ( { ... currentState , display : vals } ) ) ;
246
+ setDisplay ( vals ) ;
240
247
} ,
241
- [ organization , platform , projectSlug , isMobile , state ]
248
+ [ organization , platform , projectSlug , isMobile , display , setDisplay ]
242
249
) ;
243
250
244
251
function getDisplayOptions ( ) : {
@@ -257,8 +264,8 @@ export function TraceEventDataSection({
257
264
{
258
265
label : displayOptions [ 'absolute-addresses' ] ,
259
266
value : 'absolute-addresses' ,
260
- disabled : state . display . includes ( 'raw-stack-trace' ) || ! hasAbsoluteAddresses ,
261
- tooltip : state . display . includes ( 'raw-stack-trace' )
267
+ disabled : display . includes ( 'raw-stack-trace' ) || ! hasAbsoluteAddresses ,
268
+ tooltip : display . includes ( 'raw-stack-trace' )
262
269
? t ( 'Not available on raw stack trace' )
263
270
: ! hasAbsoluteAddresses
264
271
? t ( 'Absolute addresses not available' )
@@ -267,8 +274,8 @@ export function TraceEventDataSection({
267
274
{
268
275
label : displayOptions [ 'absolute-file-paths' ] ,
269
276
value : 'absolute-file-paths' ,
270
- disabled : state . display . includes ( 'raw-stack-trace' ) || ! hasAbsoluteFilePaths ,
271
- tooltip : state . display . includes ( 'raw-stack-trace' )
277
+ disabled : display . includes ( 'raw-stack-trace' ) || ! hasAbsoluteFilePaths ,
278
+ tooltip : display . includes ( 'raw-stack-trace' )
272
279
? t ( 'Not available on raw stack trace' )
273
280
: ! hasAbsoluteFilePaths
274
281
? t ( 'Absolute file paths not available' )
@@ -287,8 +294,8 @@ export function TraceEventDataSection({
287
294
{
288
295
label : displayOptions [ 'verbose-function-names' ] ,
289
296
value : 'verbose-function-names' ,
290
- disabled : state . display . includes ( 'raw-stack-trace' ) || ! hasVerboseFunctionNames ,
291
- tooltip : state . display . includes ( 'raw-stack-trace' )
297
+ disabled : display . includes ( 'raw-stack-trace' ) || ! hasVerboseFunctionNames ,
298
+ tooltip : display . includes ( 'raw-stack-trace' )
292
299
? t ( 'Not available on raw stack trace' )
293
300
: ! hasVerboseFunctionNames
294
301
? t ( 'Verbose function names not available' )
@@ -337,26 +344,31 @@ export function TraceEventDataSection({
337
344
}
338
345
339
346
const nativePlatform = isNativePlatform ( platform ) ;
340
- const minified = state . display . includes ( 'minified' ) ;
347
+ const minified = display . includes ( 'minified' ) ;
341
348
342
349
// Apple crash report endpoint
343
350
const appleCrashEndpoint = `/projects/${ organization . slug } /${ projectSlug } /events/${ eventId } /apple-crash-report?minified=${ minified } ` ;
344
351
const rawStackTraceDownloadLink = `${ api . baseUrl } ${ appleCrashEndpoint } &download=1` ;
345
352
346
353
const sortByTooltip = ! hasNewestFirst
347
354
? t ( 'Not available on stack trace with single frame' )
348
- : state . display . includes ( 'raw-stack-trace' )
355
+ : display . includes ( 'raw-stack-trace' )
349
356
? t ( 'Not available on raw stack trace' )
350
357
: undefined ;
351
358
352
359
const childProps = {
353
360
recentFirst : state . sortBy === 'recent-first' ,
354
- display : state . display ,
361
+ display,
355
362
fullStackTrace : state . fullStackTrace ,
356
363
} ;
357
364
358
365
const SectionComponent = isNestedSection ? InlineThreadSection : InterimSection ;
359
366
367
+ const optionsToShow = getDisplayOptions ( ) ;
368
+ const displayValues = display . filter ( value =>
369
+ optionsToShow . some ( opt => opt . value === value && ! opt . disabled )
370
+ ) ;
371
+
360
372
return (
361
373
< SectionComponent
362
374
type = { type }
@@ -365,7 +377,7 @@ export function TraceEventDataSection({
365
377
actions = {
366
378
! stackTraceNotFound && (
367
379
< ButtonBar gap = { 1 } >
368
- { ! state . display . includes ( 'raw-stack-trace' ) && (
380
+ { ! display . includes ( 'raw-stack-trace' ) && (
369
381
< Tooltip
370
382
title = { t ( 'Only full version available' ) }
371
383
disabled = { hasAppOnlyFrames }
@@ -385,7 +397,7 @@ export function TraceEventDataSection({
385
397
</ SegmentedControl >
386
398
</ Tooltip >
387
399
) }
388
- { state . display . includes ( 'raw-stack-trace' ) && nativePlatform && (
400
+ { display . includes ( 'raw-stack-trace' ) && nativePlatform && (
389
401
< LinkButton
390
402
size = "xs"
391
403
href = { rawStackTraceDownloadLink }
@@ -429,9 +441,9 @@ export function TraceEventDataSection({
429
441
multiple
430
442
triggerLabel = ""
431
443
position = "bottom-end"
432
- value = { state . display }
444
+ value = { displayValues }
433
445
onChange = { opts => handleDisplayChange ( opts . map ( opt => opt . value ) ) }
434
- options = { [ { label : t ( 'Display' ) , options : getDisplayOptions ( ) } ] }
446
+ options = { [ { label : t ( 'Display' ) , options : optionsToShow } ] }
435
447
/>
436
448
</ ButtonBar >
437
449
)
0 commit comments