refactor(mobile): remove unused PR and review code (#13404)
This commit is contained in:
parent
ced2719b26
commit
954de38507
|
|
@ -1,52 +0,0 @@
|
||||||
import { Linking } from 'react-native'
|
|
||||||
import { BottomDrawer } from './BottomDrawer'
|
|
||||||
import { MobilePrComposeForm, type PrComposePrefill } from './pr-sidebar/MobilePrComposeForm'
|
|
||||||
import type { RpcClient } from '../transport/rpc-client'
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
visible: boolean
|
|
||||||
client: RpcClient | null
|
|
||||||
worktreeId: string
|
|
||||||
prefill: PrComposePrefill
|
|
||||||
// Head branch — enables the base≠head guard and the "from <branch>" hint.
|
|
||||||
head?: string | null
|
|
||||||
onClose: () => void
|
|
||||||
onCreated: (url: string, warning?: string) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
// BottomDrawer wrapper around the inline compose form, for full-screen roots
|
|
||||||
// (source-control modals). The PR sidebar empty-state renders MobilePrComposeForm
|
|
||||||
// inline instead, since a BottomDrawer overlay nested in a ScrollView clips it.
|
|
||||||
export function MobilePrComposeSheet({
|
|
||||||
visible,
|
|
||||||
client,
|
|
||||||
worktreeId,
|
|
||||||
prefill,
|
|
||||||
head,
|
|
||||||
onClose,
|
|
||||||
onCreated
|
|
||||||
}: Props) {
|
|
||||||
return (
|
|
||||||
<BottomDrawer visible={visible} onClose={onClose}>
|
|
||||||
{/* Why: key on visible + prefill fields so reopening (or a new prefill)
|
|
||||||
remounts the form with fresh initial values; the previous sheet reset
|
|
||||||
its fields via an effect on the same signals. */}
|
|
||||||
<MobilePrComposeForm
|
|
||||||
key={`${visible}:${prefill.title}:${prefill.base}:${prefill.body}`}
|
|
||||||
client={client}
|
|
||||||
worktreeId={worktreeId}
|
|
||||||
prefill={prefill}
|
|
||||||
head={head}
|
|
||||||
onCancel={onClose}
|
|
||||||
onCreated={onCreated}
|
|
||||||
/>
|
|
||||||
</BottomDrawer>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function openMobilePrUrl(url: string): void {
|
|
||||||
// Why: Linking.openURL rejects when iOS/Android can't open the URL (no app,
|
|
||||||
// bad scheme, etc.). Without a catch that surfaces as LogBox "Uncaught
|
|
||||||
// (in promise) Error: Unable to open URL…" over the PR screen.
|
|
||||||
void Linking.openURL(url).catch(() => {})
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { Linking } from 'react-native'
|
||||||
|
|
||||||
|
export function openMobilePrUrl(url: string): void {
|
||||||
|
// Prevent unhandled rejections when no app accepts the URL.
|
||||||
|
void Linking.openURL(url).catch(() => {})
|
||||||
|
}
|
||||||
|
|
@ -38,11 +38,7 @@ type Props = {
|
||||||
onCreated: (url: string, warning?: string) => void
|
onCreated: (url: string, warning?: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
// PR compose form body: title/body/base/draft with AI prefill (git.generate
|
// A plain View keeps the compose form usable inside the PR sidebar ScrollView.
|
||||||
// PullRequestFields), submitting via createMobilePr. Renders a plain View so it
|
|
||||||
// can sit inline inside the PR sidebar's existing ScrollView (a BottomDrawer
|
|
||||||
// overlay trapped in a ScrollView clips the form). The BottomDrawer wrapper
|
|
||||||
// MobilePrComposeSheet reuses this body at full-screen roots.
|
|
||||||
export function MobilePrComposeForm({
|
export function MobilePrComposeForm({
|
||||||
client,
|
client,
|
||||||
worktreeId,
|
worktreeId,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import type { MobilePrTitleAction } from '../../session/use-mobile-pr-title-acti
|
||||||
import { prStateBadge } from './pr-checks-presentation'
|
import { prStateBadge } from './pr-checks-presentation'
|
||||||
import { statusColor } from './pr-sidebar-status-color'
|
import { statusColor } from './pr-sidebar-status-color'
|
||||||
import { canEditPRTitle } from '../../session/pr-title-edit'
|
import { canEditPRTitle } from '../../session/pr-title-edit'
|
||||||
import { openMobilePrUrl } from '../MobilePrComposeSheet'
|
import { openMobilePrUrl } from '../mobile-pr-url'
|
||||||
import { mobilePrSidebarStyles as styles } from './mobile-pr-sidebar-styles'
|
import { mobilePrSidebarStyles as styles } from './mobile-pr-sidebar-styles'
|
||||||
import { prCommentComposerStyles as composerStyles } from './pr-comment-composer-styles'
|
import { prCommentComposerStyles as composerStyles } from './pr-comment-composer-styles'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import {
|
||||||
runMobileHostedReviewCreateIntent
|
runMobileHostedReviewCreateIntent
|
||||||
} from '../../source-control/mobile-hosted-review-create-intent-runner'
|
} from '../../source-control/mobile-hosted-review-create-intent-runner'
|
||||||
import { fetchWorktreeLinkedPR } from '../../source-control/mobile-pr-link'
|
import { fetchWorktreeLinkedPR } from '../../source-control/mobile-pr-link'
|
||||||
import { openMobilePrUrl } from '../MobilePrComposeSheet'
|
import { openMobilePrUrl } from '../mobile-pr-url'
|
||||||
import { MobileLinkPrForm } from './MobileLinkPrForm'
|
import { MobileLinkPrForm } from './MobileLinkPrForm'
|
||||||
import { prCreateEmptyStateStyles as styles } from './pr-create-empty-state-styles'
|
import { prCreateEmptyStateStyles as styles } from './pr-create-empty-state-styles'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,31 +104,6 @@ export function mergeMobileDiffReviewState(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function markMobileDiffReviewFileOpened(
|
|
||||||
state: MobileDiffReviewState,
|
|
||||||
descriptor: MobileDiffReviewFileDescriptor,
|
|
||||||
now: number
|
|
||||||
): MobileDiffReviewState {
|
|
||||||
const previous = state.files[descriptor.key]
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
updatedAt: now,
|
|
||||||
files: {
|
|
||||||
...state.files,
|
|
||||||
[descriptor.key]: {
|
|
||||||
key: descriptor.key,
|
|
||||||
filePath: descriptor.filePath,
|
|
||||||
oldPath: descriptor.oldPath,
|
|
||||||
scope: descriptor.scope,
|
|
||||||
reviewedAt: previous?.reviewedAt,
|
|
||||||
reviewDiffIdentity: previous?.reviewDiffIdentity,
|
|
||||||
lastOpenedAt: now,
|
|
||||||
lastSeenDiffIdentity: descriptor.diffIdentity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function markMobileDiffReviewFileReviewed(
|
export function markMobileDiffReviewFileReviewed(
|
||||||
state: MobileDiffReviewState,
|
state: MobileDiffReviewState,
|
||||||
descriptor: MobileDiffReviewFileDescriptor,
|
descriptor: MobileDiffReviewFileDescriptor,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
import type { MobileNativeChatSendOutcome } from './mobile-native-chat-send'
|
|
||||||
|
|
||||||
/** Wraps a chat card action so an accepted write also retires the route's held
|
/** Wraps a chat card action so an accepted write also retires the route's held
|
||||||
* failure banner.
|
* failure banner.
|
||||||
|
|
@ -23,15 +22,3 @@ export function useNativeChatAcceptedAction<Params extends unknown[]>(
|
||||||
[action, onAccepted]
|
[action, onAccepted]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Boolean surface for callers with no pre-pasted input: 'unknown' stays true
|
|
||||||
* (the send usually landed; the optimistic echo is already held unconfirmed). */
|
|
||||||
export function useNativeChatSentFlag(
|
|
||||||
send: (text: string, images?: string[]) => Promise<MobileNativeChatSendOutcome>
|
|
||||||
): (text: string, images?: string[]) => Promise<boolean> {
|
|
||||||
return useCallback(
|
|
||||||
async (text: string, images?: string[]): Promise<boolean> =>
|
|
||||||
(await send(text, images)) !== 'rejected',
|
|
||||||
[send]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { ActionSheetModal, type ActionSheetAction } from '../components/ActionSheetModal'
|
import { ActionSheetModal, type ActionSheetAction } from '../components/ActionSheetModal'
|
||||||
import { ConfirmModal } from '../components/ConfirmModal'
|
import { ConfirmModal } from '../components/ConfirmModal'
|
||||||
import { PickerModal } from '../components/PickerModal'
|
import { PickerModal } from '../components/PickerModal'
|
||||||
import { openMobilePrUrl } from '../components/MobilePrComposeSheet'
|
import { openMobilePrUrl } from '../components/mobile-pr-url'
|
||||||
import { MobileBranchDiffPreviewDrawer } from './MobileBranchDiffPreviewDrawer'
|
import { MobileBranchDiffPreviewDrawer } from './MobileBranchDiffPreviewDrawer'
|
||||||
import type { MobileSourceControlState } from './use-mobile-source-control-state'
|
import type { MobileSourceControlState } from './use-mobile-source-control-state'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import { isMobileConflictAborting } from './mobile-source-control-conflict-abort
|
||||||
import { useMobilePrSidebarController } from '../session/use-mobile-pr-sidebar-controller'
|
import { useMobilePrSidebarController } from '../session/use-mobile-pr-sidebar-controller'
|
||||||
import { prSidebarDetailsNeedFetch } from '../session/mobile-pr-sidebar-state'
|
import { prSidebarDetailsNeedFetch } from '../session/mobile-pr-sidebar-state'
|
||||||
import { MobilePrViewPanelBody } from '../components/pr-sidebar/MobilePrViewPanel'
|
import { MobilePrViewPanelBody } from '../components/pr-sidebar/MobilePrViewPanel'
|
||||||
import { openMobilePrUrl } from '../components/MobilePrComposeSheet'
|
import { openMobilePrUrl } from '../components/mobile-pr-url'
|
||||||
|
|
||||||
export type MobileSourceControlPanelProps = {
|
export type MobileSourceControlPanelProps = {
|
||||||
hostId: string
|
hostId: string
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,6 @@ import type { RpcClient } from '../transport/rpc-client'
|
||||||
import type { RpcSuccess } from '../transport/types'
|
import type { RpcSuccess } from '../transport/types'
|
||||||
import { mobileRepoSelectorFromWorktreeId } from './mobile-pr-create'
|
import { mobileRepoSelectorFromWorktreeId } from './mobile-pr-create'
|
||||||
|
|
||||||
// Base-branch selection for the create-PR composer, mirroring the desktop
|
|
||||||
// useCreatePullRequestDialogFields flow: a default ref from repo.baseRefDefault and
|
|
||||||
// a debounced search via repo.searchRefs (both allowlisted for mobile). Result
|
|
||||||
// mapping is pure + unit-tested; the wrappers are thin sendRequest calls.
|
|
||||||
|
|
||||||
// Defensively normalize the repo.searchRefs payload (`{ refs: string[] }`) to a
|
|
||||||
// clean string[] — drops non-string / malformed entries instead of throwing.
|
|
||||||
export function mapBaseRefResults(raw: unknown): string[] {
|
export function mapBaseRefResults(raw: unknown): string[] {
|
||||||
if (raw === null || typeof raw !== 'object') {
|
if (raw === null || typeof raw !== 'object') {
|
||||||
return []
|
return []
|
||||||
|
|
@ -20,20 +13,6 @@ export function mapBaseRefResults(raw: unknown): string[] {
|
||||||
return refs.filter((r): r is string => typeof r === 'string' && r.length > 0)
|
return refs.filter((r): r is string => typeof r === 'string' && r.length > 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchDefaultBaseRef(
|
|
||||||
client: Pick<RpcClient, 'sendRequest'>,
|
|
||||||
worktreeId: string
|
|
||||||
): Promise<string | null> {
|
|
||||||
const response = await client.sendRequest('repo.baseRefDefault', {
|
|
||||||
repo: mobileRepoSelectorFromWorktreeId(worktreeId)
|
|
||||||
})
|
|
||||||
if (!response.ok) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
const result = (response as RpcSuccess).result as { defaultBaseRef?: string | null }
|
|
||||||
return typeof result?.defaultBaseRef === 'string' ? result.defaultBaseRef : null
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function searchBaseRefs(
|
export async function searchBaseRefs(
|
||||||
client: Pick<RpcClient, 'sendRequest'>,
|
client: Pick<RpcClient, 'sendRequest'>,
|
||||||
worktreeId: string,
|
worktreeId: string,
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,7 @@
|
||||||
import type { RpcClient } from '../transport/rpc-client'
|
|
||||||
import { readMobileGitStatusResult } from '../session/mobile-diff-review-rpc'
|
import { readMobileGitStatusResult } from '../session/mobile-diff-review-rpc'
|
||||||
import type { MobileGitStatusResult } from './mobile-git-status'
|
import type { MobileGitStatusResult } from './mobile-git-status'
|
||||||
import { resolveMobilePrPrefill, type MobilePrPrefill } from './mobile-pr-create'
|
|
||||||
|
|
||||||
// Resolves the create-PR prefill from a git status snapshot. Split from the
|
// Refresh after a push when possible so readiness reflects the new upstream state.
|
||||||
// runners hook to keep that file under the line limit.
|
|
||||||
|
|
||||||
// Reads a fresh git.status after a push so the prefill reflects the just-pushed
|
|
||||||
// branch's upstream/ahead data instead of the pre-push captured status. Best-effort:
|
|
||||||
// returns the captured status on any read failure.
|
|
||||||
export async function readFreshGitStatus(
|
export async function readFreshGitStatus(
|
||||||
worktreeId: string,
|
worktreeId: string,
|
||||||
fallback: MobileGitStatusResult | null,
|
fallback: MobileGitStatusResult | null,
|
||||||
|
|
@ -22,23 +15,6 @@ export async function readFreshGitStatus(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function buildOpenPrPrefill(
|
|
||||||
client: Pick<RpcClient, 'sendRequest'> | null,
|
|
||||||
worktreeId: string,
|
|
||||||
status: MobileGitStatusResult | null,
|
|
||||||
branchLabel: string
|
|
||||||
): Promise<MobilePrPrefill> {
|
|
||||||
if (!client) {
|
|
||||||
return { provider: 'github', base: 'main', title: branchLabel, body: '' }
|
|
||||||
}
|
|
||||||
const gitReadiness = getMobilePrEligibilityReadiness(status)
|
|
||||||
return resolveMobilePrPrefill(client, worktreeId, {
|
|
||||||
branch: status?.branch,
|
|
||||||
title: branchLabel,
|
|
||||||
...gitReadiness
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getMobilePrEligibilityReadiness(status: MobileGitStatusResult | null): {
|
export function getMobilePrEligibilityReadiness(status: MobileGitStatusResult | null): {
|
||||||
hasUncommittedChanges?: boolean
|
hasUncommittedChanges?: boolean
|
||||||
hasUpstream?: boolean
|
hasUpstream?: boolean
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue