tracePreferences.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import * as Sentry from '@sentry/react';
  2. import {traceReducerExhaustiveActionCheck} from 'sentry/views/performance/newTraceDetails/traceState';
  3. type TraceLayoutPreferences = 'drawer left' | 'drawer bottom' | 'drawer right';
  4. type TracePreferencesAction =
  5. | {payload: TraceLayoutPreferences; type: 'set layout'}
  6. | {
  7. payload: number;
  8. type: 'set drawer dimension';
  9. }
  10. | {payload: number; type: 'set list width'}
  11. | {payload: boolean; type: 'minimize drawer'};
  12. type TraceDrawerPreferences = {
  13. layoutOptions: TraceLayoutPreferences[];
  14. minimized: boolean;
  15. sizes: {
  16. [key in TraceLayoutPreferences]: number;
  17. };
  18. };
  19. export type TracePreferencesState = {
  20. drawer: TraceDrawerPreferences;
  21. layout: TraceLayoutPreferences;
  22. list: {
  23. width: number;
  24. };
  25. };
  26. export const TRACE_DRAWER_DEFAULT_SIZES: TraceDrawerPreferences['sizes'] = {
  27. 'drawer left': 0.33,
  28. 'drawer right': 0.33,
  29. 'drawer bottom': 0.5,
  30. };
  31. export const DEFAULT_TRACE_VIEW_PREFERENCES: TracePreferencesState = {
  32. drawer: {
  33. minimized: false,
  34. sizes: {
  35. 'drawer left': 0.33,
  36. 'drawer right': 0.33,
  37. 'drawer bottom': 0.5,
  38. },
  39. layoutOptions: ['drawer left', 'drawer right', 'drawer bottom'],
  40. },
  41. layout: 'drawer right',
  42. list: {
  43. width: 0.5,
  44. },
  45. };
  46. export function storeTraceViewPreferences(
  47. key: string,
  48. state: TracePreferencesState
  49. ): void {
  50. // Make sure we dont fire this during a render phase
  51. window.requestAnimationFrame(() => {
  52. try {
  53. localStorage.setItem(key, JSON.stringify(state));
  54. } catch (e) {
  55. Sentry.captureException(e);
  56. }
  57. });
  58. }
  59. function isInt(value: any): value is number {
  60. return typeof value === 'number' && !isNaN(value);
  61. }
  62. export function loadTraceViewPreferences(key: string): TracePreferencesState | null {
  63. const stored = localStorage.getItem(key);
  64. if (stored) {
  65. try {
  66. const parsed = JSON.parse(stored);
  67. // We need a more robust way to validate the stored preferences.
  68. // Since we dont have a schema validation lib, just do it manually for now.
  69. if (
  70. parsed?.drawer &&
  71. typeof parsed.drawer.minimized === 'boolean' &&
  72. Array.isArray(parsed.drawer.layoutOptions) &&
  73. parsed.drawer.sizes &&
  74. isInt(parsed.drawer.sizes['drawer left']) &&
  75. isInt(parsed.drawer.sizes['drawer right']) &&
  76. isInt(parsed.drawer.sizes['drawer bottom']) &&
  77. parsed.layout &&
  78. typeof parsed.layout === 'string' &&
  79. parsed.list &&
  80. isInt(parsed.list.width)
  81. ) {
  82. return parsed;
  83. }
  84. } catch (e) {
  85. Sentry.captureException(e);
  86. }
  87. }
  88. return null;
  89. }
  90. export function tracePreferencesReducer(
  91. state: TracePreferencesState,
  92. action: TracePreferencesAction
  93. ): TracePreferencesState {
  94. switch (action.type) {
  95. case 'minimize drawer':
  96. return {...state, drawer: {...state.drawer, minimized: action.payload}};
  97. case 'set layout':
  98. return {
  99. ...state,
  100. layout: action.payload,
  101. drawer: {...state.drawer, minimized: false},
  102. };
  103. case 'set drawer dimension':
  104. return {
  105. ...state,
  106. drawer: {
  107. ...state.drawer,
  108. sizes: {
  109. ...state.drawer.sizes,
  110. [state.layout]:
  111. action.payload < 0 ? 0 : action.payload > 1 ? 1 : action.payload,
  112. },
  113. },
  114. };
  115. case 'set list width':
  116. return {
  117. ...state,
  118. list: {
  119. width: action.payload < 0 ? 0 : action.payload > 1 ? 1 : action.payload,
  120. },
  121. };
  122. default:
  123. traceReducerExhaustiveActionCheck(action);
  124. return state;
  125. }
  126. }