@@ -6,7 +6,7 @@ import { PureComponent } from 'react';
66import memoize from 'memoize-immutable' ;
77
88import explicitConnect from '../../utils/connect' ;
9- import { type SortableColumn , type Tree , TreeView } from '../shared/TreeView' ;
9+ import { ColumnSortState , TreeView } from '../shared/TreeView' ;
1010import { MarkerTableEmptyReasons } from './MarkerTableEmptyReasons' ;
1111import {
1212 getZeroAt ,
@@ -15,11 +15,15 @@ import {
1515 getCurrentTableViewOptions ,
1616} from '../../selectors/profile' ;
1717import { selectedThreadSelectors } from '../../selectors/per-thread' ;
18- import { getSelectedThreadsKey } from '../../selectors/url-state' ;
18+ import {
19+ getSelectedThreadsKey ,
20+ getMarkerTableSort ,
21+ } from '../../selectors/url-state' ;
1922import {
2023 changeSelectedMarker ,
2124 changeRightClickedMarker ,
2225 changeTableViewOptions ,
26+ changeMarkerTableSort ,
2327} from '../../actions/profile-view' ;
2428import { MarkerSettings } from '../shared/MarkerSettings' ;
2529import { formatSeconds , formatTimestamp } from '../../utils/format-numbers' ;
@@ -37,12 +41,21 @@ import type {
3741 TableViewOptions ,
3842 SelectionContext ,
3943} from 'firefox-profiler/types' ;
44+ import type {
45+ SingleColumnSortState ,
46+ Tree ,
47+ SortableColumn ,
48+ } from '../shared/TreeView' ;
4049
4150import type { ConnectedProps } from '../../utils/connect' ;
4251
4352// Limit how many characters in the description get sent to the DOM.
4453const MAX_DESCRIPTION_CHARACTERS = 500 ;
4554
55+ const DEFAULT_MARKER_TABLE_SORT : SingleColumnSortState [ ] = [
56+ { column : 'start' , ascending : true } ,
57+ ] ;
58+
4659type MarkerDisplayData = {
4760 start : string ;
4861 duration : string | null ;
@@ -73,8 +86,14 @@ class MarkerTree implements Tree<MarkerDisplayData> {
7386 this . _getMarkerLabel = getMarkerLabel ;
7487 }
7588
89+ static _sortableColumns : SortableColumn [ ] = [
90+ { name : 'start' , prefersDescending : false } ,
91+ { name : 'duration' , prefersDescending : true } ,
92+ { name : 'name' , prefersDescending : false } ,
93+ ] ;
94+
7695 getSortableColumns ( ) : SortableColumn [ ] {
77- return [ ] ;
96+ return MarkerTree . _sortableColumns ;
7897 }
7998
8099 copyTable = (
@@ -171,12 +190,49 @@ class MarkerTree implements Tree<MarkerDisplayData> {
171190 copy ( text ) ;
172191 } ;
173192
174- getRoots ( ) : MarkerIndex [ ] {
193+ getRoots ( sort : ColumnSortState | null = null ) : MarkerIndex [ ] {
194+ if ( sort !== null ) {
195+ return sort . sortItemsHelper (
196+ this . _markerIndexes ,
197+ ( first : MarkerIndex , second : MarkerIndex , column : string ) => {
198+ const firstValue = this . _getSortValueForColumn ( first , column ) ;
199+ const secondValue = this . _getSortValueForColumn ( second , column ) ;
200+ if ( typeof firstValue === 'string' ) {
201+ return firstValue . localeCompare ( secondValue as string ) ;
202+ }
203+ return ( firstValue as number ) - ( secondValue as number ) ;
204+ }
205+ ) ;
206+ }
175207 return this . _markerIndexes ;
176208 }
177209
178- getChildren ( markerIndex : MarkerIndex ) : MarkerIndex [ ] {
179- return markerIndex === - 1 ? this . getRoots ( ) : [ ] ;
210+ getChildren (
211+ markerIndex : MarkerIndex ,
212+ sort : ColumnSortState | null = null
213+ ) : MarkerIndex [ ] {
214+ return markerIndex === - 1 ? this . getRoots ( sort ) : [ ] ;
215+ }
216+
217+ _getSortValueForColumn (
218+ markerIndex : MarkerIndex ,
219+ column : string
220+ ) : string | number {
221+ const marker = this . _getMarker ( markerIndex ) ;
222+ switch ( column ) {
223+ case 'start' :
224+ return marker . start ;
225+ case 'duration' : {
226+ if ( marker . incomplete || marker . end === null ) {
227+ return - Infinity ;
228+ }
229+ return marker . end - marker . start ;
230+ }
231+ case 'name' :
232+ return marker . name ;
233+ default :
234+ throw new Error ( 'Invalid column ' + column ) ;
235+ }
180236 }
181237
182238 hasChildren ( _markerIndex : MarkerIndex ) : boolean {
@@ -209,10 +265,11 @@ class MarkerTree implements Tree<MarkerDisplayData> {
209265 }
210266
211267 let duration = null ;
268+ const markerEnd = marker . end ;
212269 if ( marker . incomplete ) {
213270 duration = 'unknown' ;
214- } else if ( marker . end !== null ) {
215- duration = formatTimestamp ( marker . end - marker . start ) ;
271+ } else if ( markerEnd !== null ) {
272+ duration = formatTimestamp ( markerEnd - marker . start ) ;
216273 }
217274
218275 displayData = {
@@ -242,12 +299,14 @@ type StateProps = {
242299 readonly markerSchemaByName : MarkerSchemaByName ;
243300 readonly getMarkerLabel : ( param : MarkerIndex ) => string ;
244301 readonly tableViewOptions : TableViewOptions ;
302+ readonly sort : SingleColumnSortState [ ] ;
245303} ;
246304
247305type DispatchProps = {
248306 readonly changeSelectedMarker : typeof changeSelectedMarker ;
249307 readonly changeRightClickedMarker : typeof changeRightClickedMarker ;
250308 readonly onTableViewOptionsChange : ( param : TableViewOptions ) => any ;
309+ readonly changeMarkerTableSort : typeof changeMarkerTableSort ;
251310} ;
252311
253312type Props = ConnectedProps < { } , StateProps , DispatchProps > ;
@@ -284,6 +343,11 @@ class MarkerTableImpl extends PureComponent<Props> {
284343 this . _treeView = treeView ;
285344 } ;
286345
346+ _getSortedColumns = memoize (
347+ ( sort : SingleColumnSortState [ ] ) =>
348+ new ColumnSortState ( sort . length > 0 ? sort : DEFAULT_MARKER_TABLE_SORT )
349+ ) ;
350+
287351 getMarkerTree = memoize (
288352 (
289353 getMarker : any ,
@@ -335,6 +399,10 @@ class MarkerTableImpl extends PureComponent<Props> {
335399 changeSelectedMarker ( threadsKey , selectedMarker , context ) ;
336400 } ;
337401
402+ _onColumnSortChange = ( sortedColumns : ColumnSortState ) => {
403+ this . props . changeMarkerTableSort ( sortedColumns . sortedColumns ) ;
404+ } ;
405+
338406 _onRightClickSelection = ( selectedMarker : MarkerIndex ) => {
339407 const { threadsKey, changeRightClickedMarker } = this . props ;
340408 changeRightClickedMarker ( threadsKey , selectedMarker ) ;
@@ -385,6 +453,8 @@ class MarkerTableImpl extends PureComponent<Props> {
385453 indentWidth = { 10 }
386454 viewOptions = { this . props . tableViewOptions }
387455 onViewOptionsChange = { this . props . onTableViewOptionsChange }
456+ sortedColumns = { this . _getSortedColumns ( this . props . sort ) }
457+ onColumnSortChange = { this . _onColumnSortChange }
388458 />
389459 ) }
390460 </ div >
@@ -405,12 +475,14 @@ export const MarkerTable = explicitConnect<{}, StateProps, DispatchProps>({
405475 markerSchemaByName : getMarkerSchemaByName ( state ) ,
406476 getMarkerLabel : selectedThreadSelectors . getMarkerTableLabelGetter ( state ) ,
407477 tableViewOptions : getCurrentTableViewOptions ( state ) ,
478+ sort : getMarkerTableSort ( state ) ,
408479 } ) ,
409480 mapDispatchToProps : {
410481 changeSelectedMarker,
411482 changeRightClickedMarker,
412483 onTableViewOptionsChange : ( tableViewOptions ) =>
413484 changeTableViewOptions ( 'marker-table' , tableViewOptions ) ,
485+ changeMarkerTableSort,
414486 } ,
415487 component : MarkerTableImpl ,
416488} ) ;
0 commit comments