mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 01:57:57 +00:00
Shared remote dropdown builders take count/force-push sentence builders
through RemoteDropdownCopy; English defaults keep mobile and older callers
byte-identical. Desktop uses whole-sentence {{count}} plural keys, also for
the primary action tooltip. Refs #34144.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
228 lines
7.7 KiB
TypeScript
228 lines
7.7 KiB
TypeScript
import type { DropdownItem } from './source-control-dropdown-item-types'
|
|
import type { DropdownActionContext } from './source-control-dropdown-action-context'
|
|
import {
|
|
formatCountLabel,
|
|
formatRebaseBaseRef,
|
|
formatSyncLabel
|
|
} from './source-control-dropdown-labels'
|
|
import {
|
|
ENGLISH_REMOTE_DROPDOWN_COPY,
|
|
type RemoteDropdownCopy
|
|
} from './source-control-dropdown-remote-copy'
|
|
|
|
export type RemoteDropdownItems = {
|
|
push: DropdownItem
|
|
forcePush: DropdownItem
|
|
pull: DropdownItem
|
|
fastForward: DropdownItem
|
|
sync: DropdownItem
|
|
rebase: DropdownItem
|
|
fetch: DropdownItem
|
|
publish: DropdownItem
|
|
}
|
|
|
|
export function buildRemoteDropdownItems(
|
|
ctx: DropdownActionContext,
|
|
copy: RemoteDropdownCopy = ENGLISH_REMOTE_DROPDOWN_COPY
|
|
): RemoteDropdownItems {
|
|
const {
|
|
upstreamStatus,
|
|
branchCommitsAhead,
|
|
canPushLinkedReviewWithoutUpstream,
|
|
rebaseBaseRef,
|
|
hasDirtyLocalChanges,
|
|
globalBusy,
|
|
upstreamLoading,
|
|
hasUpstream,
|
|
canPushUntrackedHostedReview,
|
|
pushBlockedByOpenHostedReviewTarget,
|
|
publishBlockedByMergedPR,
|
|
publishBlockedByPRLoading,
|
|
publishBlockedByOpenHostedReview,
|
|
publishBlockedByDetachedHead,
|
|
ahead,
|
|
behind,
|
|
shouldForcePushWithLease,
|
|
pushLabelCount
|
|
} = ctx
|
|
|
|
const push: DropdownItem = {
|
|
kind: 'push',
|
|
label: formatCountLabel(copy.push, ahead),
|
|
title: publishBlockedByDetachedHead
|
|
? copy.checkOutBranchToPush
|
|
: pushBlockedByOpenHostedReviewTarget
|
|
? copy.linkedReviewTargetUnavailable
|
|
: upstreamLoading
|
|
? copy.pushAndSetUpstream
|
|
: canPushUntrackedHostedReview
|
|
? copy.pushToLinkedReview
|
|
: !hasUpstream
|
|
? copy.pushAndSetUpstream
|
|
: shouldForcePushWithLease
|
|
? copy.tryRegularPush
|
|
: behind > 0 && ahead > 0
|
|
? copy.pushMayNeedSync
|
|
: ahead === 0
|
|
? upstreamStatus?.upstreamName
|
|
? copy.nothingToPushTo(upstreamStatus.upstreamName)
|
|
: copy.nothingToPush
|
|
: copy.pushCount(ahead),
|
|
// Push can set upstream and coexist with force-with-lease; detached HEAD and unknown review targets still block it.
|
|
disabled: globalBusy || publishBlockedByDetachedHead || pushBlockedByOpenHostedReviewTarget
|
|
}
|
|
|
|
const forcePush: DropdownItem = {
|
|
kind: 'force_push',
|
|
label: formatCountLabel(copy.forcePush, pushLabelCount),
|
|
title: publishBlockedByDetachedHead
|
|
? copy.checkOutBranchToForcePush
|
|
: pushBlockedByOpenHostedReviewTarget
|
|
? copy.linkedReviewTargetUnavailable
|
|
: upstreamLoading
|
|
? copy.unpublishedForcePush(branchCommitsAhead)
|
|
: !hasUpstream
|
|
? copy.unpublishedForcePush(branchCommitsAhead)
|
|
: pushLabelCount === 0
|
|
? upstreamStatus?.upstreamName
|
|
? copy.nothingToForcePushTo(upstreamStatus.upstreamName)
|
|
: copy.nothingToForcePush
|
|
: shouldForcePushWithLease
|
|
? copy.forcePushWithLease(branchCommitsAhead, upstreamStatus?.upstreamName)
|
|
: copy.manualForcePush(pushLabelCount, behind, upstreamStatus?.upstreamName),
|
|
// Match Push target safety; force-with-lease must not push the wrong review head.
|
|
disabled: globalBusy || publishBlockedByDetachedHead || pushBlockedByOpenHostedReviewTarget
|
|
}
|
|
|
|
const pull: DropdownItem = {
|
|
kind: 'pull',
|
|
label: formatCountLabel(copy.pull, behind),
|
|
title: upstreamLoading
|
|
? copy.checkingBranchStatus
|
|
: publishBlockedByPRLoading
|
|
? copy.checkingPrStatus
|
|
: publishBlockedByMergedPR
|
|
? copy.prAlreadyMerged
|
|
: publishBlockedByDetachedHead
|
|
? copy.checkOutBranchToPull
|
|
: !hasUpstream
|
|
? copy.publishBranchFirstToPull
|
|
: shouldForcePushWithLease
|
|
? copy.nothingNewToPull
|
|
: behind === 0
|
|
? copy.nothingToPull
|
|
: copy.pullCount(behind),
|
|
disabled: globalBusy || upstreamLoading || !hasUpstream || publishBlockedByDetachedHead
|
|
}
|
|
|
|
const fastForward: DropdownItem = {
|
|
kind: 'fast_forward',
|
|
label: formatCountLabel(copy.fastForward, behind),
|
|
title: upstreamLoading
|
|
? copy.checkingBranchStatus
|
|
: publishBlockedByPRLoading
|
|
? copy.checkingPrStatus
|
|
: publishBlockedByMergedPR
|
|
? copy.prAlreadyMerged
|
|
: publishBlockedByDetachedHead
|
|
? copy.checkOutBranchToFastForward
|
|
: !hasUpstream
|
|
? copy.publishBranchFirstToFastForward
|
|
: shouldForcePushWithLease
|
|
? copy.nothingNewToFastForward
|
|
: behind === 0
|
|
? copy.nothingToFastForward
|
|
: ahead > 0
|
|
? copy.tryFastForwardPull
|
|
: copy.fastForwardCount(behind),
|
|
disabled: globalBusy || upstreamLoading || !hasUpstream || publishBlockedByDetachedHead
|
|
}
|
|
|
|
const sync: DropdownItem = {
|
|
kind: 'sync',
|
|
label: formatSyncLabel(copy.sync, ahead, behind),
|
|
title: upstreamLoading
|
|
? copy.checkingBranchStatus
|
|
: publishBlockedByPRLoading
|
|
? copy.checkingPrStatus
|
|
: publishBlockedByMergedPR
|
|
? copy.prAlreadyMerged
|
|
: publishBlockedByDetachedHead
|
|
? copy.checkOutBranchToSync
|
|
: !hasUpstream
|
|
? copy.publishBranchFirstToSync
|
|
: shouldForcePushWithLease
|
|
? copy.useForcePushToSync
|
|
: ahead === 0 && behind === 0
|
|
? copy.branchUpToDate
|
|
: copy.syncCounts(ahead, behind),
|
|
disabled:
|
|
globalBusy ||
|
|
upstreamLoading ||
|
|
!hasUpstream ||
|
|
publishBlockedByDetachedHead ||
|
|
shouldForcePushWithLease
|
|
}
|
|
|
|
const rebaseBaseLabel = rebaseBaseRef ? formatRebaseBaseRef(rebaseBaseRef) : null
|
|
const hasRemoteBaseRef = rebaseBaseLabel?.includes('/') === true
|
|
const rebase: DropdownItem = {
|
|
kind: 'rebase_base',
|
|
label: rebaseBaseLabel ? copy.rebaseFromNamedBase(rebaseBaseLabel) : copy.rebaseFromBase,
|
|
title: ((): string => {
|
|
if (!rebaseBaseLabel || !hasRemoteBaseRef) {
|
|
return copy.rebaseChooseRemoteBase
|
|
}
|
|
if (hasDirtyLocalChanges) {
|
|
return copy.rebaseDirtyHint
|
|
}
|
|
return copy.rebaseWithLatestFrom(rebaseBaseLabel)
|
|
})(),
|
|
disabled: globalBusy || !rebaseBaseRef || !hasRemoteBaseRef
|
|
}
|
|
|
|
const fetch: DropdownItem = {
|
|
kind: 'fetch',
|
|
label: copy.fetch,
|
|
title: copy.fetchTitle,
|
|
disabled: globalBusy
|
|
}
|
|
|
|
const publish: DropdownItem = {
|
|
kind: 'publish',
|
|
label:
|
|
publishBlockedByMergedPR || publishBlockedByPRLoading
|
|
? copy.publishPrStatus
|
|
: publishBlockedByOpenHostedReview
|
|
? copy.publishLinkedReview
|
|
: publishBlockedByDetachedHead
|
|
? copy.publishNoBranch
|
|
: copy.publishBranch,
|
|
title: upstreamLoading
|
|
? copy.checkingBranchStatus
|
|
: publishBlockedByPRLoading
|
|
? copy.checkingPrStatus
|
|
: publishBlockedByMergedPR
|
|
? copy.prAlreadyMerged
|
|
: publishBlockedByOpenHostedReview
|
|
? canPushLinkedReviewWithoutUpstream
|
|
? copy.linkedReviewBranchExists
|
|
: copy.linkedReviewTargetUnavailable
|
|
: publishBlockedByDetachedHead
|
|
? copy.checkOutBranchToPublish
|
|
: hasUpstream
|
|
? copy.branchAlreadyPublished
|
|
: copy.publishToOrigin,
|
|
disabled:
|
|
globalBusy ||
|
|
upstreamLoading ||
|
|
hasUpstream ||
|
|
publishBlockedByPRLoading ||
|
|
publishBlockedByMergedPR ||
|
|
publishBlockedByOpenHostedReview ||
|
|
publishBlockedByDetachedHead
|
|
}
|
|
|
|
return { push, forcePush, pull, fastForward, sync, rebase, fetch, publish }
|
|
}
|