{path ?? '(no source file)'}
@@ -299,6 +331,7 @@ function convertErrors(errors: ApiQueryError[]): SourceCodeLoadingError[] {
export const BottomBox = explicitConnect<{}, StateProps, DispatchProps>({
mapStateToProps: (state) => ({
+ isFullscreen: getIsBottomBoxFullscreen(state),
sourceViewFile: getSourceViewFile(state),
sourceViewCode: getSourceViewCode(state),
globalLineTimings: selectedThreadSelectors.getSourceViewLineTimings(state),
@@ -318,6 +351,7 @@ export const BottomBox = explicitConnect<{}, StateProps, DispatchProps>({
}),
mapDispatchToProps: {
closeBottomBox,
+ toggleBottomBoxFullscreen,
},
component: BottomBoxImpl,
});
diff --git a/src/components/app/FullscreenToggleButton.tsx b/src/components/app/FullscreenToggleButton.tsx
new file mode 100644
index 0000000000..9a28f60156
--- /dev/null
+++ b/src/components/app/FullscreenToggleButton.tsx
@@ -0,0 +1,77 @@
+/* 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 { getIsBottomBoxFullscreen } from 'firefox-profiler/selectors/url-state';
+import { toggleBottomBoxFullscreen } 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 isBottomBoxFullscreen: boolean;
+};
+
+type DispatchProps = {
+ readonly toggleBottomBoxFullscreen: typeof toggleBottomBoxFullscreen;
+};
+
+type Props = ConnectedProps<{}, StateProps, DispatchProps>;
+
+class FullscreenToggleButtonImpl extends React.PureComponent
{
+ _onClick = () => {
+ this.props.toggleBottomBoxFullscreen();
+ };
+
+ override render() {
+ const { isBottomBoxFullscreen } = this.props;
+
+ return isBottomBoxFullscreen ? (
+
+
+
+ ) : (
+
+
+
+ );
+ }
+}
+
+export const FullscreenToggleButton = explicitConnect<
+ {},
+ StateProps,
+ DispatchProps
+>({
+ mapStateToProps: (state) => ({
+ isBottomBoxFullscreen: getIsBottomBoxFullscreen(state),
+ }),
+ mapDispatchToProps: {
+ toggleBottomBoxFullscreen,
+ },
+ component: FullscreenToggleButtonImpl,
+});
diff --git a/src/reducers/url-state.ts b/src/reducers/url-state.ts
index bebe69468d..30f1b7e5a1 100644
--- a/src/reducers/url-state.ts
+++ b/src/reducers/url-state.ts
@@ -648,6 +648,16 @@ const isBottomBoxOpenPerPanel: Reducer = (
}
};
+const isBottomBoxFullscreen: Reducer = (state = false, action) => {
+ switch (action.type) {
+ case 'TOGGLE_BOTTOM_BOX_FULLSCREEN': {
+ return !state;
+ }
+ default:
+ return state;
+ }
+};
+
/**
* This value is only set from the URL and never changed.
*/
@@ -673,6 +683,7 @@ const profileSpecific = combineReducers({
sourceView,
assemblyView,
isBottomBoxOpenPerPanel,
+ isBottomBoxFullscreen,
timelineType,
globalTrackOrder,
hiddenGlobalTracks,
diff --git a/src/selectors/url-state.ts b/src/selectors/url-state.ts
index 48b7e17146..c9a45513d4 100644
--- a/src/selectors/url-state.ts
+++ b/src/selectors/url-state.ts
@@ -219,6 +219,10 @@ export const getIsBottomBoxOpen: Selector = (state) => {
return getProfileSpecificState(state).isBottomBoxOpenPerPanel[tab];
};
+export const getIsBottomBoxFullscreen: Selector = (state) => {
+ return getProfileSpecificState(state).isBottomBoxFullscreen;
+};
+
/**
* The URL predictor is used to generate a link for an uploaded profile, to predict
* what the URL will be.
diff --git a/src/types/actions.ts b/src/types/actions.ts
index 940b018500..dc7ff44672 100644
--- a/src/types/actions.ts
+++ b/src/types/actions.ts
@@ -354,6 +354,9 @@ type ProfileAction =
| {
readonly type: 'CLOSE_BOTTOM_BOX_FOR_TAB';
readonly tab: TabSlug;
+ }
+ | {
+ readonly type: 'TOGGLE_BOTTOM_BOX_FULLSCREEN';
};
type ReceiveProfileAction =
diff --git a/src/types/state.ts b/src/types/state.ts
index aa6956090a..360c539764 100644
--- a/src/types/state.ts
+++ b/src/types/state.ts
@@ -361,6 +361,7 @@ export type ProfileSpecificUrlState = {
sourceView: SourceViewState;
assemblyView: AssemblyViewState;
isBottomBoxOpenPerPanel: IsOpenPerPanelState;
+ isBottomBoxFullscreen: boolean;
globalTrackOrder: TrackIndex[];
hiddenGlobalTracks: Set;
hiddenLocalTracksByPid: Map>;