Skip to content

Commit ed012e0

Browse files
committed
feat: add branch sorting option
1 parent ab975c4 commit ed012e0

11 files changed

Lines changed: 108 additions & 1 deletion

File tree

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/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: 3 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: {
@@ -3457,6 +3458,7 @@ export class App extends React.Component<IAppProps, IAppState> {
34573458
dispatcher={this.props.dispatcher}
34583459
isOpen={isOpen}
34593460
branchDropdownWidth={this.state.branchDropdownWidth}
3461+
branchSortOrder={this.state.branchSortOrder}
34603462
onDropDownStateChanged={this.onBranchDropdownStateChanged}
34613463
repository={repository}
34623464
repositoryState={selection.state}
@@ -3635,6 +3637,7 @@ export class App extends React.Component<IAppProps, IAppState> {
36353637
stashedFilesWidth={state.stashedFilesWidth}
36363638
issuesStore={this.props.issuesStore}
36373639
gitHubUserStore={this.props.gitHubUserStore}
3640+
branchSortOrder={state.branchSortOrder}
36383641
onViewCommitOnGitHub={this.onViewCommitOnGitHub}
36393642
imageDiffType={state.imageDiffType}
36403643
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 ?? BranchSortOrder.LastModified
183188
)
184189
}
185190

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}

app/src/ui/preferences/appearance.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import { tabSizeDefault } from '../../lib/stores/app-store'
1414
import { Checkbox, CheckboxValue } from '../lib/checkbox'
1515
import { ShowBranchNameInRepoListSetting } from '../../models/show-branch-name-in-repo-list'
1616
import { parseEnumValue } from '../../lib/enum'
17+
import { assertNever } from '../../lib/fatal-error'
18+
import { BranchSortOrder } from '../../models/branch-sort-order'
1719

1820
interface IAppearanceProps {
1921
readonly selectedTheme: ApplicationTheme
@@ -30,6 +32,8 @@ interface IAppearanceProps {
3032
readonly onShowBranchNameInRepoListChanged: (
3133
value: ShowBranchNameInRepoListSetting
3234
) => void
35+
readonly branchSortOrder: BranchSortOrder
36+
readonly onBranchSortOrderChanged: (sortOrder: BranchSortOrder) => void
3337
}
3438

3539
interface IAppearanceState {
@@ -231,6 +235,45 @@ export class Appearance extends React.Component<
231235
}
232236
}
233237

238+
private onBranchSortOrderChanged = (branchSortOrder: BranchSortOrder) => {
239+
this.props.onBranchSortOrderChanged(branchSortOrder)
240+
}
241+
242+
private renderBranchSortOrder() {
243+
const { branchSortOrder } = this.props
244+
245+
return (
246+
<div className="advanced-section">
247+
<h2 id="branch-sort-order-heading">Sort branches</h2>
248+
249+
<RadioGroup<BranchSortOrder>
250+
ariaLabelledBy="branch-sort-order-heading"
251+
selectedKey={branchSortOrder}
252+
radioButtonKeys={[
253+
BranchSortOrder.Alphabetical,
254+
BranchSortOrder.LastModified,
255+
]}
256+
onSelectionChanged={this.onBranchSortOrderChanged}
257+
renderRadioButtonLabelContents={this.renderBranchSortOptionLabel}
258+
/>
259+
</div>
260+
)
261+
}
262+
263+
private renderBranchSortOptionLabel = (branchSortOrder: BranchSortOrder) => {
264+
switch (branchSortOrder) {
265+
case BranchSortOrder.Alphabetical:
266+
return 'Alphabetical'
267+
case BranchSortOrder.LastModified:
268+
return 'Last modified'
269+
default:
270+
return assertNever(
271+
branchSortOrder,
272+
`Unknown branch sort order: ${branchSortOrder}`
273+
)
274+
}
275+
}
276+
234277
private renderRepositoryList() {
235278
return (
236279
<div className="advanced-section">
@@ -303,6 +346,7 @@ export class Appearance extends React.Component<
303346
<DialogContent>
304347
{this.renderSelectedTheme()}
305348
{this.renderRepositoryList()}
349+
{this.renderBranchSortOrder()}
306350
{this.renderWorktreeVisibility()}
307351
{this.renderSelectedTabSize()}
308352
{this.renderTitleBarStyleDropdown()}

app/src/ui/preferences/preferences.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { ApplicationTheme } from '../lib/application-theme'
2424
import { TitleBarStyle } from '../lib/title-bar-style'
2525
import { OkCancelButtonGroup } from '../dialog/ok-cancel-button-group'
2626
import { Integrations } from './integrations'
27+
import { BranchSortOrder } from '../../models/branch-sort-order'
2728
import {
2829
UncommittedChangesStrategy,
2930
defaultUncommittedChangesStrategy,
@@ -95,6 +96,7 @@ interface IPreferencesProps {
9596
readonly showWorktrees: boolean
9697
readonly repositoryIndicatorsEnabled: boolean
9798
readonly showBranchNameInRepoList: ShowBranchNameInRepoListSetting
99+
readonly branchSortOrder: BranchSortOrder
98100
readonly hideWindowOnQuit: boolean
99101
readonly onEditGlobalGitConfig: () => void
100102
readonly underlineLinks: boolean
@@ -147,6 +149,7 @@ interface IPreferencesState {
147149
readonly existingLockFilePath?: string
148150
readonly repositoryIndicatorsEnabled: boolean
149151
readonly showBranchNameInRepoList: ShowBranchNameInRepoListSetting
152+
readonly branchSortOrder: BranchSortOrder
150153
readonly hideWindowOnQuit: boolean
151154

152155
readonly initiallySelectedTheme: ApplicationTheme
@@ -223,6 +226,7 @@ export class Preferences extends React.Component<
223226
showWorktrees: this.props.showWorktrees,
224227
repositoryIndicatorsEnabled: this.props.repositoryIndicatorsEnabled,
225228
showBranchNameInRepoList: this.props.showBranchNameInRepoList,
229+
branchSortOrder: this.props.branchSortOrder,
226230
hideWindowOnQuit: this.props.hideWindowOnQuit,
227231
initiallySelectedTheme: this.props.selectedTheme,
228232
initiallySelectedTabSize: this.props.selectedTabSize,
@@ -560,6 +564,8 @@ export class Preferences extends React.Component<
560564
onShowBranchNameInRepoListChanged={
561565
this.onShowBranchNameInRepoListChanged
562566
}
567+
branchSortOrder={this.state.branchSortOrder}
568+
onBranchSortOrderChanged={this.onBranchSortOrderChanged}
563569
/>
564570
)
565571
break
@@ -811,6 +817,10 @@ export class Preferences extends React.Component<
811817
this.setState({ showBranchNameInRepoList })
812818
}
813819

820+
private onBranchSortOrderChanged = (branchSortOrder: BranchSortOrder) => {
821+
this.setState({ branchSortOrder })
822+
}
823+
814824
private onSelectedTabSizeChanged = (tabSize: number) => {
815825
this.props.dispatcher.setSelectedTabSize(tabSize)
816826
}
@@ -1017,6 +1027,7 @@ export class Preferences extends React.Component<
10171027
dispatcher.setDiffCheckMarksSetting(this.state.showDiffCheckMarks)
10181028

10191029
dispatcher.setShowBranchNameInRepoList(this.state.showBranchNameInRepoList)
1030+
dispatcher.setBranchSortOrder(this.state.branchSortOrder)
10201031

10211032
this.props.onDismissed()
10221033
}

app/src/ui/repository.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { clamp } from '../lib/clamp'
3838
import { Emoji } from '../lib/emoji'
3939
import { PopupType } from '../models/popup'
4040
import { Branch } from '../models/branch'
41+
import { BranchSortOrder } from '../models/branch-sort-order'
4142

4243
interface IRepositoryViewProps {
4344
readonly repository: Repository
@@ -113,6 +114,8 @@ interface IRepositoryViewProps {
113114
sourceBranch?: Branch
114115
) => void
115116

117+
readonly branchSortOrder: BranchSortOrder
118+
116119
/** The user's preference of pull request suggested next action to use **/
117120
readonly pullRequestSuggestedNextAction?: PullRequestSuggestedNextAction
118121

@@ -417,6 +420,7 @@ export class RepositoryView extends React.Component<
417420
repository={repository}
418421
isLocalRepository={remote === null}
419422
compareState={compareState}
423+
branchSortOrder={this.props.branchSortOrder}
420424
selectedCommitShas={shas}
421425
shasToHighlight={compareState.shasToHighlight}
422426
currentBranch={currentBranch}
@@ -473,6 +477,7 @@ export class RepositoryView extends React.Component<
473477
repository={repository}
474478
isLocalRepository={remote === null}
475479
compareState={compareState}
480+
branchSortOrder={this.props.branchSortOrder}
476481
selectedCommitShas={shas}
477482
shasToHighlight={compareState.shasToHighlight}
478483
currentBranch={currentBranch}

0 commit comments

Comments
 (0)