Skip to content

Commit 3a33154

Browse files
authored
Merge pull request #88 from kurtextrem/feature/branch-sorting
feat: add branch sorting option
2 parents ab975c4 + a8ea128 commit 3a33154

23 files changed

Lines changed: 154 additions & 1 deletion

app/src/lib/app-state.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { IStashEntry } from '../models/stash-entry'
4141
import { TutorialStep } from '../models/tutorial-step'
4242
import { UncommittedChangesStrategy } from '../models/uncommitted-changes-strategy'
4343
import { ShowBranchNameInRepoListSetting } from '../models/show-branch-name-in-repo-list'
44+
import { BranchSortOrder } from '../models/branch-sort-order'
4445
import { DragElement } from '../models/drag-drop'
4546
import { ILastThankYou } from '../models/last-thank-you'
4647
import {
@@ -398,6 +399,9 @@ export interface IAppState {
398399
/** Controls when to show the current branch name next to each repository in the repository list */
399400
readonly showBranchNameInRepoList: ShowBranchNameInRepoListSetting
400401

402+
/** Controls the sort order for branch lists in branch-selection views */
403+
readonly branchSortOrder: BranchSortOrder
404+
401405
/**
402406
* Cached repo rulesets. Used to prevent repeatedly querying the same
403407
* rulesets to check their bypass status.

app/src/lib/format-relative.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ const getRelativeFormatter = mem(
1515
)
1616

1717
export function formatRelative(ms: number) {
18+
if (!Number.isFinite(ms)) {
19+
return 'Invalid date'
20+
}
21+
1822
const formatter = getRelativeFormatter('en-US', { numeric: 'auto' })
1923

2024
const sign = ms < 0 ? -1 : 1

app/src/lib/stores/app-store.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ import {
182182
defaultShowBranchNameInRepoListSetting,
183183
ShowBranchNameInRepoListSetting,
184184
} from '../../models/show-branch-name-in-repo-list'
185+
import {
186+
BranchSortOrder,
187+
DEFAULT_BRANCH_SORT_ORDER,
188+
} from '../../models/branch-sort-order'
185189
import { WorkflowPreferences } from '../../models/workflow-preferences'
186190
import { TrashNameLabel } from '../../ui/lib/context-menu'
187191
import { getDefaultDir } from '../../ui/lib/default-dir'
@@ -494,6 +498,7 @@ export const showDiffCheckMarksDefault = true
494498
export const showDiffCheckMarksKey = 'diff-check-marks-visible'
495499

496500
export const showBranchNameInRepoListKey = 'show-branch-name-in-repo-list'
501+
const branchSortOrderKey = 'branch-sort-order'
497502

498503
const commitMessageGenerationDisclaimerLastSeenKey =
499504
'commit-message-generation-disclaimer-last-seen'
@@ -663,6 +668,8 @@ export class AppStore extends TypedBaseStore<IAppState> {
663668
private showBranchNameInRepoList: ShowBranchNameInRepoListSetting =
664669
defaultShowBranchNameInRepoListSetting
665670

671+
private branchSortOrder: BranchSortOrder = DEFAULT_BRANCH_SORT_ORDER
672+
666673
private cachedRepoRulesets = new Map<number, IAPIRepoRuleset>()
667674

668675
private underlineLinks: boolean = underlineLinksDefault
@@ -1212,6 +1219,7 @@ export class AppStore extends TypedBaseStore<IAppState> {
12121219
underlineLinks: this.underlineLinks,
12131220
showDiffCheckMarks: this.showDiffCheckMarks,
12141221
showBranchNameInRepoList: this.showBranchNameInRepoList,
1222+
branchSortOrder: this.branchSortOrder,
12151223
updateState: updateStore.state,
12161224
commitMessageGenerationDisclaimerLastSeen:
12171225
this.commitMessageGenerationDisclaimerLastSeen,
@@ -2619,6 +2627,9 @@ export class AppStore extends TypedBaseStore<IAppState> {
26192627
getEnum(showBranchNameInRepoListKey, ShowBranchNameInRepoListSetting) ??
26202628
defaultShowBranchNameInRepoListSetting
26212629

2630+
this.branchSortOrder =
2631+
getEnum(branchSortOrderKey, BranchSortOrder) ?? DEFAULT_BRANCH_SORT_ORDER
2632+
26222633
this.commitMessageGenerationDisclaimerLastSeen =
26232634
getNumber(commitMessageGenerationDisclaimerLastSeenKey) ?? null
26242635

@@ -9202,6 +9213,14 @@ export class AppStore extends TypedBaseStore<IAppState> {
92029213
}
92039214
}
92049215

9216+
public _updateBranchSortOrder(branchSortOrder: BranchSortOrder) {
9217+
if (branchSortOrder !== this.branchSortOrder) {
9218+
this.branchSortOrder = branchSortOrder
9219+
localStorage.setItem(branchSortOrderKey, branchSortOrder)
9220+
this.emitUpdate()
9221+
}
9222+
}
9223+
92059224
public _updateFileListFilter(
92069225
repository: Repository,
92079226
filterUpdate: Partial<IFileListFilterState>

app/src/ui/app.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,6 +1659,7 @@ export class App extends React.Component<IAppProps, IAppState> {
16591659
underlineLinks={this.state.underlineLinks}
16601660
showDiffCheckMarks={this.state.showDiffCheckMarks}
16611661
showBranchNameInRepoList={this.state.showBranchNameInRepoList}
1662+
branchSortOrder={this.state.branchSortOrder}
16621663
/>
16631664
)
16641665
case PopupType.RepositorySettings: {
@@ -2280,6 +2281,7 @@ export class App extends React.Component<IAppProps, IAppState> {
22802281
askForConfirmationOnForcePush={
22812282
this.state.askForConfirmationOnForcePush
22822283
}
2284+
branchSortOrder={this.state.branchSortOrder}
22832285
accounts={this.state.accounts}
22842286
cachedRepoRulesets={this.state.cachedRepoRulesets}
22852287
openFileInExternalEditor={this.getOpenFileInExternalEditorHandler(
@@ -2522,6 +2524,7 @@ export class App extends React.Component<IAppProps, IAppState> {
25222524
externalEditorLabel={externalEditorLabel}
25232525
showSideBySideDiff={showSideBySideDiff}
25242526
currentBranchHasPullRequest={currentBranchHasPullRequest}
2527+
branchSortOrder={this.state.branchSortOrder}
25252528
onDismissed={onPopupDismissedFn}
25262529
onOpenInExternalEditor={this.onOpenInExternalEditor}
25272530
/>
@@ -3457,6 +3460,7 @@ export class App extends React.Component<IAppProps, IAppState> {
34573460
dispatcher={this.props.dispatcher}
34583461
isOpen={isOpen}
34593462
branchDropdownWidth={this.state.branchDropdownWidth}
3463+
branchSortOrder={this.state.branchSortOrder}
34603464
onDropDownStateChanged={this.onBranchDropdownStateChanged}
34613465
repository={repository}
34623466
repositoryState={selection.state}
@@ -3635,6 +3639,7 @@ export class App extends React.Component<IAppProps, IAppState> {
36353639
stashedFilesWidth={state.stashedFilesWidth}
36363640
issuesStore={this.props.issuesStore}
36373641
gitHubUserStore={this.props.gitHubUserStore}
3642+
branchSortOrder={state.branchSortOrder}
36383643
onViewCommitOnGitHub={this.onViewCommitOnGitHub}
36393644
imageDiffType={state.imageDiffType}
36403645
hideWhitespaceInChangesDiff={state.hideWhitespaceInChangesDiff}

app/src/ui/branches/branch-list.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ interface IBranchListProps {
5858
*/
5959
readonly allWorktrees: ReadonlyArray<WorktreeEntry>
6060

61+
/**
62+
* The sort order for branch lists in the current user preferences.
63+
*/
64+
readonly branchSortOrder: BranchSortOrder
65+
6166
/**
6267
* The currently selected branch in the list, see the onSelectionChanged prop.
6368
*/
@@ -179,7 +184,7 @@ export class BranchList extends React.Component<IBranchListProps> {
179184
this.props.allBranches,
180185
this.props.recentBranches,
181186
this.props.allWorktrees,
182-
BranchSortOrder.LastModified
187+
this.props.branchSortOrder
183188
)
184189
}
185190

app/src/ui/branches/branch-renderer.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ export function getDefaultAriaLabelForBranch(item: IBranchListItem): string {
4646
return branch.name
4747
}
4848

49+
if (Number.isNaN(authorDate.getTime())) {
50+
return branch.name
51+
}
52+
4953
const { relativeText } = getRelativeTimeInfoFromDate(authorDate, true)
5054
return `${item.branch.name} ${relativeText}`
5155
}

app/src/ui/branches/branch-select.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Branch } from '../../models/branch'
44
import { ClickSource } from '../lib/list'
55
import { PopoverDropdown } from '../lib/popover-dropdown'
66
import { BranchList } from './branch-list'
7+
import { BranchSortOrder } from '../../models/branch-sort-order'
78
import {
89
getDefaultAriaLabelForBranch,
910
renderDefaultBranch,
@@ -37,6 +38,11 @@ interface IBranchSelectProps {
3738
*/
3839
readonly recentBranches: ReadonlyArray<Branch>
3940

41+
/**
42+
* The sort order for branch lists in the current user preferences.
43+
*/
44+
readonly branchSortOrder: BranchSortOrder
45+
4046
/** Called when the user changes the selected branch. */
4147
readonly onChange?: (branch: Branch) => void
4248

@@ -115,6 +121,7 @@ export class BranchSelect extends React.Component<
115121
allBranches={allBranches}
116122
currentBranch={currentBranch}
117123
defaultBranch={defaultBranch}
124+
branchSortOrder={this.props.branchSortOrder}
118125
recentBranches={recentBranches}
119126
allWorktrees={[]}
120127
filterText={filterText}

app/src/ui/branches/branches-container.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { Button } from '../lib/button'
2424
import { BranchList } from './branch-list'
2525
import { PullRequestList } from './pull-request-list'
2626
import { IBranchListItem } from './group-branches'
27+
import { BranchSortOrder } from '../../models/branch-sort-order'
2728
import {
2829
getDefaultAriaLabelForBranch,
2930
renderDefaultBranch,
@@ -53,6 +54,8 @@ interface IBranchesContainerProps {
5354
readonly onSetAsDefaultBranch: (branchName: string) => void
5455
readonly onDeleteBranch: (branchName: string) => void
5556

57+
readonly branchSortOrder: BranchSortOrder
58+
5659
/** All worktrees in the repository. */
5760
readonly allWorktrees: ReadonlyArray<WorktreeEntry>
5861

@@ -272,6 +275,7 @@ export class BranchesContainer extends React.Component<
272275
currentBranch={this.props.currentBranch}
273276
allBranches={this.props.allBranches}
274277
recentBranches={this.props.recentBranches}
278+
branchSortOrder={this.props.branchSortOrder}
275279
allWorktrees={this.props.allWorktrees}
276280
onItemClick={this.onBranchItemClick}
277281
filterText={this.state.branchFilterText}

app/src/ui/dispatcher/dispatcher.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ import {
103103
} from '../../lib/stores/commit-status-store'
104104
import { MergeTreeResult } from '../../models/merge'
105105
import { UncommittedChangesStrategy } from '../../models/uncommitted-changes-strategy'
106+
import { BranchSortOrder } from '../../models/branch-sort-order'
106107
import { ShowBranchNameInRepoListSetting } from '../../models/show-branch-name-in-repo-list'
107108
import { IStashEntry } from '../../models/stash-entry'
108109
import { WorkflowPreferences } from '../../models/workflow-preferences'
@@ -4203,6 +4204,10 @@ export class Dispatcher {
42034204
)
42044205
}
42054206

4207+
public setBranchSortOrder(branchSortOrder: BranchSortOrder) {
4208+
return this.appStore._updateBranchSortOrder(branchSortOrder)
4209+
}
4210+
42064211
public testPruneBranches() {
42074212
return this.appStore._testPruneBranches()
42084213
}

app/src/ui/history/compare.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { DragType } from '../../models/drag-drop'
2929
import { PopupType } from '../../models/popup'
3030
import { getUniqueCoauthorsAsAuthors } from '../../lib/unique-coauthors-as-authors'
3131
import { getSquashedCommitDescription } from '../../lib/squash/squashed-commit-description'
32+
import { BranchSortOrder } from '../../models/branch-sort-order'
3233
import { doMergeCommitsExistAfterCommit } from '../../lib/git'
3334
import { KeyboardInsertionData } from '../lib/list'
3435
import { Account } from '../../models/account'
@@ -47,6 +48,7 @@ interface ICompareSidebarProps {
4748
readonly dispatcher: Dispatcher
4849
readonly currentBranch: Branch | null
4950
readonly selectedCommitShas: ReadonlyArray<string>
51+
readonly branchSortOrder: BranchSortOrder
5052
readonly onRevertCommit: (commit: Commit) => void
5153
readonly onAmendCommit: (commit: Commit, isLocalCommit: boolean) => void
5254
readonly onViewCommitOnGitHub: (sha: string) => void
@@ -413,6 +415,7 @@ export class CompareSidebar extends React.Component<
413415
allBranches={branches}
414416
recentBranches={recentBranches}
415417
allWorktrees={[]}
418+
branchSortOrder={this.props.branchSortOrder}
416419
filterText={filterText}
417420
textbox={this.textbox!}
418421
selectedBranch={this.state.focusedBranch}

0 commit comments

Comments
 (0)