mirror of
https://github.com/stablyai/orca.git
synced 2026-11-14 09:57:48 +00:00
fix(mobile): keep Resolve and its feedback after the PR tab's conflicts box went away (#37234)
The diff-review dock has no next-step bar, so its bottom action now offers Resolve with <agent> for a conflicting pull request, with the launch notice. In the hub the bar shows its agent launch notice on the Pull request tab too, since the removed box was the one that showed it there, and an Unlink failure reaches the bar's notice now that the PR tab has no footer.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { ActivityIndicator, Pressable, Text, View } from 'react-native'
|
||||
import { GitMerge, GitPullRequest, type LucideIcon } from 'lucide-react-native'
|
||||
import { GitMerge, GitPullRequest, Sparkles, type LucideIcon } from 'lucide-react-native'
|
||||
import { colors, feedback, pressedStyle } from '../../theme/mobile-theme'
|
||||
import { useMobileColorScheme } from '../../theme/use-mobile-color-scheme'
|
||||
import { useMobileTranslation } from '../../i18n/use-mobile-translation'
|
||||
@@ -7,19 +7,33 @@ import { resolveGitHubPRMergeMethods } from '../../../../src/shared/github/pull-
|
||||
import { resolveGitHubPRMergeState } from '../../../../src/shared/github/pull-request-merge-state'
|
||||
import { MOBILE_GITHUB_MARK_PR_READY_RUNTIME_CAPABILITY } from '../../../../src/shared/source-control-runtime-capabilities'
|
||||
import { useRouteCapability } from '../../transport/use-workspace-client'
|
||||
import { buildResolveConflictsPrompt } from '../../session/pr-ai-triage-prompt'
|
||||
import { useMobileLaunchAgentLabel } from '../../session/use-mobile-launch-agent-label'
|
||||
import { useHostProtocolGates } from '../host-protocol-gates-context'
|
||||
import { AgentLaunchNotice } from '../AgentLaunchNotice'
|
||||
import { presentPrMerge } from './pr-actions-state'
|
||||
import type { MobilePrTab } from './use-mobile-pr-tab'
|
||||
import { prTabStyles as styles } from './pr-tab-styles'
|
||||
|
||||
type Tone = 'primary' | 'merge' | 'secondary'
|
||||
|
||||
// The PR tab's foot: the diff-review dock always shows it, the hub only while its bar is on a local step.
|
||||
// The diff-review dock's bottom action; in the hub the next-step bar is the one bottom action instead.
|
||||
export function PrTabBottomAction({ tab, bottomInset }: { tab: MobilePrTab; bottomInset: number }) {
|
||||
useMobileColorScheme()
|
||||
const t = useMobileTranslation()
|
||||
const { state, actions } = tab
|
||||
const canMarkReady = useRouteCapability(MOBILE_GITHUB_MARK_PR_READY_RUNTIME_CAPABILITY)
|
||||
const footerStyle = [styles.footer, { paddingBottom: Math.max(bottomInset, 12) }]
|
||||
const conflicting =
|
||||
state.kind === 'ready' && resolveGitHubPRMergeState(state.data.pr).kind === 'conflicts'
|
||||
const { hostCapabilities } = useHostProtocolGates()
|
||||
const agent = useMobileLaunchAgentLabel({
|
||||
client: tab.client,
|
||||
worktreeId: tab.worktreeId,
|
||||
hostCapabilities,
|
||||
actionId: 'resolveConflicts',
|
||||
enabled: conflicting
|
||||
})
|
||||
|
||||
if (state.kind === 'none') {
|
||||
return (
|
||||
@@ -82,6 +96,42 @@ export function PrTabBottomAction({ tab, bottomInset }: { tab: MobilePrTab; bott
|
||||
const merge = presentPrMerge(effective, defaultMethod)
|
||||
const decision = resolveGitHubPRMergeState(effective)
|
||||
const autoMergeBusy = actions.isBusy({ kind: 'autoMerge' })
|
||||
// The dock has no bar, so conflicts get the bar's own fix here, named by the button rather than a reason line.
|
||||
if (decision.kind === 'conflicts') {
|
||||
const notice = tab.triage.noticeFor('resolve-conflicts')
|
||||
return (
|
||||
<View style={footerStyle}>
|
||||
{errorLine}
|
||||
<AgentLaunchNotice
|
||||
availability={tab.triage.availability}
|
||||
success={notice.success}
|
||||
error={notice.error}
|
||||
warning={notice.warning}
|
||||
undeliveredPrompt={notice.undeliveredPrompt}
|
||||
errorStyle={styles.errorText}
|
||||
/>
|
||||
<ActionButton
|
||||
tone="primary"
|
||||
icon={Sparkles}
|
||||
label={t('sourceControl.nextStep.resolveWithAgent', 'Resolve with {{agent}}', {
|
||||
agent: agent ?? t('sourceControl.nextStep.genericAgent', 'AI')
|
||||
})}
|
||||
onPress={() =>
|
||||
void tab.triage.launch('resolve-conflicts', () =>
|
||||
buildResolveConflictsPrompt({
|
||||
prNumber: pr.number,
|
||||
baseRef: pr.conflictSummary?.baseRef ?? pr.baseRefName ?? null,
|
||||
files: pr.conflictSummary?.files ?? [],
|
||||
worktreeId: tab.worktreeId
|
||||
})
|
||||
)
|
||||
}
|
||||
busy={tab.triage.isBusy('resolve-conflicts')}
|
||||
disabled={tab.triage.availability !== 'available'}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
const reason = merge.hint ? (
|
||||
<Text style={styles.reason}>
|
||||
<Text style={styles.reasonStrong}>
|
||||
|
||||
@@ -371,7 +371,7 @@ export function MobileSourceControlPanel({
|
||||
{ready ? (
|
||||
<MobileSourceControlNextStepBar
|
||||
view={nextStep.view}
|
||||
notice={nextStep.notice}
|
||||
notice={nextStep.notice ?? prTab.unlinkError}
|
||||
agentNotice={nextStep.agentNotice}
|
||||
mergeConfirm={nextStep.mergeConfirm}
|
||||
composer={state}
|
||||
|
||||
@@ -33,7 +33,6 @@ vi.mock('./MobileSourceControlHubCommitsPage', () => ({
|
||||
vi.mock('./MobileSourceControlNextStepBar', () => ({ MobileSourceControlNextStepBar: () => null }))
|
||||
vi.mock('./use-mobile-source-control-next-step', () => ({
|
||||
useMobileSourceControlNextStep: () => ({
|
||||
offersMerge: false,
|
||||
view: { kind: 'hidden' },
|
||||
notice: null,
|
||||
agentNotice: null,
|
||||
|
||||
@@ -253,11 +253,10 @@ export function useMobileSourceControlNextStep({
|
||||
: step.kind === 'resolve_conflicts'
|
||||
? 'resolve-conflicts'
|
||||
: null
|
||||
// On the PR tab the body's own AI button already shows this launcher's notice.
|
||||
const agentNotice =
|
||||
triageKey && !showWorkflowErrors
|
||||
? { ...triage.noticeFor(triageKey), availability: triage.availability }
|
||||
: null
|
||||
// The bar's agent button is the only one on either tab, so its launch notice shows under it.
|
||||
const agentNotice = triageKey
|
||||
? { ...triage.noticeFor(triageKey), availability: triage.availability }
|
||||
: null
|
||||
const workflowError = showWorkflowErrors
|
||||
? (state.actionError ?? state.commitFailureRecovery?.error ?? null)
|
||||
: null
|
||||
|
||||
Reference in New Issue
Block a user