From f9029f078173a0a662fdbdfead5232ead99fc896 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Thu, 30 Jan 2025 11:51:25 -0500 Subject: [PATCH 1/2] Add prev/next buttons in the assembly view. --- locales/en-US/app.ftl | 8 ++ src/actions/profile-view.ts | 9 ++ .../app/AssemblyViewNativeSymbolNavigator.tsx | 116 ++++++++++++++++++ src/components/app/BottomBox.css | 21 +++- src/components/app/BottomBox.tsx | 2 + src/reducers/url-state.ts | 6 + src/selectors/url-state.ts | 6 + src/test/components/BottomBox.test.tsx | 53 +++++++- src/types/actions.ts | 4 + 9 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 src/components/app/AssemblyViewNativeSymbolNavigator.tsx diff --git a/locales/en-US/app.ftl b/locales/en-US/app.ftl index 8139f27e05..ab040c7ef1 100644 --- a/locales/en-US/app.ftl +++ b/locales/en-US/app.ftl @@ -1307,6 +1307,14 @@ AssemblyView--show-button = AssemblyView--hide-button = .title = Hide the assembly view +# The "◀" button above the assembly view. +AssemblyView--prev-button = + .title = Previous + +# The "▶" button above the assembly view. +AssemblyView--next-button = + .title = Next + ## UploadedRecordingsHome ## This is the page that displays all the profiles that user has uploaded. ## See: https://profiler.firefox.com/uploaded-recordings/ diff --git a/src/actions/profile-view.ts b/src/actions/profile-view.ts index 56bef8ff15..e739633c06 100644 --- a/src/actions/profile-view.ts +++ b/src/actions/profile-view.ts @@ -1962,6 +1962,15 @@ export function openAssemblyView(): Action { }; } +export function changeAssemblyViewNativeSymbolEntryIndex( + entryIndex: number +): Action { + return { + type: 'CHANGE_ASSEMBLY_VIEW_NATIVE_SYMBOL_ENTRY_INDEX', + entryIndex, + }; +} + export function closeAssemblyView(): Action { return { type: 'CLOSE_ASSEMBLY_VIEW', diff --git a/src/components/app/AssemblyViewNativeSymbolNavigator.tsx b/src/components/app/AssemblyViewNativeSymbolNavigator.tsx new file mode 100644 index 0000000000..55559e2036 --- /dev/null +++ b/src/components/app/AssemblyViewNativeSymbolNavigator.tsx @@ -0,0 +1,116 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import React from 'react'; +import classNames from 'classnames'; + +import { + getAssemblyViewCurrentNativeSymbolEntryIndex, + getAssemblyViewNativeSymbolEntryCount, +} from 'firefox-profiler/selectors/url-state'; +import { changeAssemblyViewNativeSymbolEntryIndex } from 'firefox-profiler/actions/profile-view'; +import explicitConnect from 'firefox-profiler/utils/connect'; + +import type { ConnectedProps } from 'firefox-profiler/utils/connect'; + +import { Localized } from '@fluent/react'; + +type StateProps = { + readonly assemblyViewCurrentNativeSymbolEntryIndex: number | null; + readonly assemblyViewNativeSymbolEntryCount: number; +}; + +type DispatchProps = { + readonly changeAssemblyViewNativeSymbolEntryIndex: typeof changeAssemblyViewNativeSymbolEntryIndex; +}; + +type Props = ConnectedProps<{}, StateProps, DispatchProps>; + +class AssemblyViewNativeSymbolNavigatorImpl extends React.PureComponent { + _onPreviousClick = () => { + this._changeIndexBy(-1); + }; + + _onNextClick = () => { + this._changeIndexBy(1); + }; + + _changeIndexBy(delta: number) { + const { + assemblyViewCurrentNativeSymbolEntryIndex: index, + assemblyViewNativeSymbolEntryCount: count, + changeAssemblyViewNativeSymbolEntryIndex, + } = this.props; + const newIndex = (index ?? 0) + delta; + if (newIndex >= 0 && newIndex < count) { + changeAssemblyViewNativeSymbolEntryIndex(newIndex); + } + } + + override render() { + const { + assemblyViewCurrentNativeSymbolEntryIndex: index, + assemblyViewNativeSymbolEntryCount: count, + } = this.props; + + if (index === null || count <= 1) { + return null; + } + + return ( + <> +

+ {index !== null && count > 1 ? `${index + 1} of ${count}` : ''} +

+ + + + + + + + ); + } +} + +export const AssemblyViewNativeSymbolNavigator = explicitConnect< + {}, + StateProps, + DispatchProps +>({ + mapStateToProps: (state) => ({ + assemblyViewCurrentNativeSymbolEntryIndex: + getAssemblyViewCurrentNativeSymbolEntryIndex(state), + assemblyViewNativeSymbolEntryCount: + getAssemblyViewNativeSymbolEntryCount(state), + }), + mapDispatchToProps: { + changeAssemblyViewNativeSymbolEntryIndex, + }, + component: AssemblyViewNativeSymbolNavigatorImpl, +}); diff --git a/src/components/app/BottomBox.css b/src/components/app/BottomBox.css index 69fad98226..d337882d52 100644 --- a/src/components/app/BottomBox.css +++ b/src/components/app/BottomBox.css @@ -51,7 +51,8 @@ line-height: 18px; } -.bottom-box-title { +.bottom-box-title, +.bottom-box-title-trailer { overflow: hidden; margin: 0 8px; font: inherit; @@ -59,6 +60,10 @@ white-space: nowrap; } +.bottom-box-title-trailer { + margin: 0; +} + .bottom-box-header-trailing-buttons { display: flex; height: 100%; @@ -67,7 +72,9 @@ } .bottom-close-button, -.bottom-assembly-button { +.bottom-assembly-button, +.bottom-prev-button, +.bottom-next-button { width: 24px; height: 24px; flex-shrink: 0; @@ -76,6 +83,16 @@ background-size: 16px 16px; } +.bottom-prev-button, +.bottom-next-button { + width: 16px; + font-size: 9px; +} + +.bottom-next-button { + margin-right: 8px; +} + .bottom-close-button { background-image: var(--internal-close-icon); } diff --git a/src/components/app/BottomBox.tsx b/src/components/app/BottomBox.tsx index 2411bd4fe1..3e3d161feb 100644 --- a/src/components/app/BottomBox.tsx +++ b/src/components/app/BottomBox.tsx @@ -9,6 +9,7 @@ import classNames from 'classnames'; import { SourceView } from '../shared/SourceView'; import { AssemblyView } from '../shared/AssemblyView'; import { AssemblyViewToggleButton } from './AssemblyViewToggleButton'; +import { AssemblyViewNativeSymbolNavigator } from './AssemblyViewNativeSymbolNavigator'; import { IonGraphView } from '../shared/IonGraphView'; import { CodeLoadingOverlay } from './CodeLoadingOverlay'; import { CodeErrorOverlay } from './CodeErrorOverlay'; @@ -192,6 +193,7 @@ class BottomBoxImpl extends React.PureComponent { // These trailing header buttons go into the bottom-box-bar of the last pane. const trailingHeaderButtons = (
+ {assemblyViewIsOpen ? : null}