fix(ui): hide GitHub surfaces in non-GitHub repositories
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { GitProvider } from '@/lib/gitProvider';
|
||||
|
||||
type ComposerAttachmentControlsProps = {
|
||||
isVSCode: boolean;
|
||||
@@ -26,6 +27,8 @@ type ComposerAttachmentControlsProps = {
|
||||
handlePickLocalFiles: () => void;
|
||||
openIssuePicker: () => void;
|
||||
openPrPicker: () => void;
|
||||
/** Only shows the GitHub issue/PR attach actions when the repo is GitHub. */
|
||||
gitProvider?: GitProvider | null;
|
||||
onOpenSettings?: () => void;
|
||||
onMenuOpenChange?: (open: boolean) => void;
|
||||
/** Mobile: open the attachment bottom sheet instead of the dropdown menu. */
|
||||
@@ -41,6 +44,7 @@ export const ComposerAttachmentControls = React.memo(function ComposerAttachment
|
||||
handlePickLocalFiles,
|
||||
openIssuePicker,
|
||||
openPrPicker,
|
||||
gitProvider,
|
||||
onOpenSettings,
|
||||
} = props;
|
||||
|
||||
@@ -98,22 +102,26 @@ export const ComposerAttachmentControls = React.memo(function ComposerAttachment
|
||||
<Icon name="attachment-2"/>
|
||||
{t('chat.chatInput.actions.attachFiles')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onSelect={() => {
|
||||
requestAnimationFrame(openIssuePicker);
|
||||
}}
|
||||
>
|
||||
<Icon name="github"/>
|
||||
{t('chat.chatInput.actions.linkGithubIssue')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onSelect={() => {
|
||||
requestAnimationFrame(openPrPicker);
|
||||
}}
|
||||
>
|
||||
<Icon name="git-pull-request"/>
|
||||
{t('chat.chatInput.actions.linkGithubPr')}
|
||||
</DropdownMenuItem>
|
||||
{gitProvider === 'github' ? (
|
||||
<>
|
||||
<DropdownMenuItem
|
||||
onSelect={() => {
|
||||
requestAnimationFrame(openIssuePicker);
|
||||
}}
|
||||
>
|
||||
<Icon name="github"/>
|
||||
{t('chat.chatInput.actions.linkGithubIssue')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onSelect={() => {
|
||||
requestAnimationFrame(openPrPicker);
|
||||
}}
|
||||
>
|
||||
<Icon name="git-pull-request"/>
|
||||
{t('chat.chatInput.actions.linkGithubPr')}
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
) : null}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)}
|
||||
@@ -136,6 +144,7 @@ export const ComposerAttachmentControls = React.memo(function ComposerAttachment
|
||||
prev.isVSCode === next.isVSCode
|
||||
&& prev.footerIconButtonClass === next.footerIconButtonClass
|
||||
&& prev.iconSizeClass === next.iconSizeClass
|
||||
&& prev.gitProvider === next.gitProvider
|
||||
&& prev.onOpenSettings === next.onOpenSettings
|
||||
&& prev.onMenuOpenChange === next.onMenuOpenChange
|
||||
&& prev.onOpenMobileSheet === next.onOpenMobileSheet
|
||||
|
||||
@@ -18,6 +18,7 @@ import { ComposerDictation } from '@/components/dictation/ComposerDictation';
|
||||
import { Icon } from '@/components/icon/Icon';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useGitProvider } from '@/lib/gitProvider';
|
||||
import { ModelControls } from '../../ModelControls';
|
||||
import { ComposerActionButtons } from './ComposerActionButtons';
|
||||
import { ComposerAttachmentControls } from './ComposerAttachmentControls';
|
||||
@@ -106,6 +107,8 @@ export function ComposerFooter(props: ComposerFooterProps) {
|
||||
onDictationContentHeightChange,
|
||||
} = props;
|
||||
|
||||
const gitProvider = useGitProvider(directory);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
@@ -130,6 +133,7 @@ export function ComposerFooter(props: ComposerFooterProps) {
|
||||
handlePickLocalFiles={onPickLocalFiles}
|
||||
openIssuePicker={onOpenIssuePicker}
|
||||
openPrPicker={onOpenPrPicker}
|
||||
gitProvider={gitProvider}
|
||||
onOpenSettings={onOpenSettings}
|
||||
onOpenMobileSheet={onOpenAttachSheet}
|
||||
/>
|
||||
@@ -199,6 +203,7 @@ export function ComposerFooter(props: ComposerFooterProps) {
|
||||
handlePickLocalFiles={onPickLocalFiles}
|
||||
openIssuePicker={onOpenIssuePicker}
|
||||
openPrPicker={onOpenPrPicker}
|
||||
gitProvider={gitProvider}
|
||||
onOpenSettings={onOpenSettings}
|
||||
/>
|
||||
<FocusModeButton
|
||||
|
||||
@@ -17,6 +17,7 @@ import { SessionGoalRow } from '@/components/chat/SessionGoalRow';
|
||||
import { SessionSuggestionChip } from '@/components/chat/SessionSuggestionChip';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useGitProvider } from '@/lib/gitProvider';
|
||||
import type { Theme } from '@/types/theme';
|
||||
import { ComposerAttachmentControls } from './ComposerAttachmentControls';
|
||||
|
||||
@@ -68,6 +69,8 @@ export function MobilePillComposer(props: MobilePillComposerProps) {
|
||||
onAbort,
|
||||
} = props;
|
||||
|
||||
const gitProvider = useGitProvider(directory);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<SessionGoalRow
|
||||
@@ -94,6 +97,7 @@ export function MobilePillComposer(props: MobilePillComposerProps) {
|
||||
handlePickLocalFiles={onPickLocalFiles}
|
||||
openIssuePicker={onOpenIssuePicker}
|
||||
openPrPicker={onOpenPrPicker}
|
||||
gitProvider={gitProvider}
|
||||
onOpenMobileSheet={onOpenAttachSheet}
|
||||
/>
|
||||
<button
|
||||
|
||||
@@ -23,6 +23,7 @@ import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
import { useBrowserFaviconStore } from '@/stores/useBrowserFaviconStore';
|
||||
import { useGitProvider } from '@/lib/gitProvider';
|
||||
import { useFilesViewTabsStore } from '@/stores/useFilesViewTabsStore';
|
||||
import { useUIStore, type ContextPanelMode, type PendingDiffScope } from '@/stores/useUIStore';
|
||||
import { markSessionViewed } from '@/sync/notification-store';
|
||||
@@ -440,6 +441,7 @@ export const ContextPanel: React.FC = () => {
|
||||
const { t } = useI18n();
|
||||
const effectiveDirectory = useEffectiveDirectory() ?? '';
|
||||
const directoryKey = React.useMemo(() => normalizeDirectoryKey(effectiveDirectory), [effectiveDirectory]);
|
||||
const gitProvider = useGitProvider(effectiveDirectory);
|
||||
|
||||
const panelState = useUIStore((state) => (directoryKey ? state.contextPanelByDirectory[directoryKey] : undefined));
|
||||
const closeContextPanel = useUIStore((state) => state.closeContextPanel);
|
||||
@@ -936,7 +938,7 @@ export const ContextPanel: React.FC = () => {
|
||||
: activeTab?.mode === 'git'
|
||||
? <React.Suspense fallback={null}><GitView isActive={isOpen} /></React.Suspense>
|
||||
: activeTab?.mode === 'pr'
|
||||
? <PullRequestView />
|
||||
? (gitProvider === 'github' ? <PullRequestView /> : null)
|
||||
: activeTab?.mode === 'notes'
|
||||
? <ProjectContextPanel />
|
||||
: activeTab?.mode === 'plan'
|
||||
|
||||
@@ -33,6 +33,7 @@ import { useSessionUIStore } from '@/sync/session-ui-store';
|
||||
import { useSelectionStore } from '@/sync/selection-store';
|
||||
import * as sessionActions from '@/sync/session-actions';
|
||||
import { buildLinkedIssue } from '@/lib/linkedIssues';
|
||||
import { useGitProvider } from '@/lib/gitProvider';
|
||||
import { useConfigStore } from '@/stores/useConfigStore';
|
||||
import { validateWorktreeCreate, createWorktree } from '@/lib/worktrees/worktreeManager';
|
||||
import { withWorktreeUpstreamDefaults } from '@/lib/worktrees/worktreeCreate';
|
||||
@@ -1307,6 +1308,13 @@ export function NewWorktreeDialog({
|
||||
// GitLab connection check
|
||||
const isGitLabConnected = gitlabAuthChecked && gitlabAuthStatus?.connected === true;
|
||||
|
||||
// Only offer the provider's start-from flow when the repo actually belongs
|
||||
// to that provider: a GitLab repo must not surface the GitHub picker and
|
||||
// vice versa.
|
||||
const gitProvider = useGitProvider(projectDirectory);
|
||||
const showGitHubStartFrom = isGitHubConnected && gitProvider === 'github';
|
||||
const showGitLabStartFrom = isGitLabConnected && gitProvider === 'gitlab';
|
||||
|
||||
// Check if form is valid for submission
|
||||
const isFormValid = mode === 'existing-branch'
|
||||
? !!existingBranchState.selectedBranch && !!existingBranchState.worktreeName && !validation.branchError && !validation.worktreeError
|
||||
@@ -1557,9 +1565,9 @@ export function NewWorktreeDialog({
|
||||
<label className="typography-ui-label text-foreground block font-semibold">
|
||||
{t('session.newWorktree.branchName')}
|
||||
</label>
|
||||
{mode === 'new-branch' && (isGitHubConnected || isGitLabConnected) && (
|
||||
{mode === 'new-branch' && (showGitHubStartFrom || showGitLabStartFrom) && (
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
{isGitHubConnected && (
|
||||
{showGitHubStartFrom && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@@ -1570,7 +1578,7 @@ export function NewWorktreeDialog({
|
||||
{newBranchState.linkedIssue || newBranchState.linkedPr ? t('session.newWorktree.actions.change') : t('session.newWorktree.actions.startFromGitHubIssuePr')}
|
||||
</Button>
|
||||
)}
|
||||
{isGitLabConnected && (
|
||||
{showGitLabStartFrom && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@@ -2085,9 +2093,9 @@ export function NewWorktreeDialog({
|
||||
<label className="typography-ui-label text-foreground block font-semibold">
|
||||
{t('session.newWorktree.branchName')}
|
||||
</label>
|
||||
{mode === 'new-branch' && (isGitHubConnected || isGitLabConnected) && (
|
||||
{mode === 'new-branch' && (showGitHubStartFrom || showGitLabStartFrom) && (
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
{isGitHubConnected && (
|
||||
{showGitHubStartFrom && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@@ -2098,7 +2106,7 @@ export function NewWorktreeDialog({
|
||||
{newBranchState.linkedIssue || newBranchState.linkedPr ? t('session.newWorktree.actions.change') : t('session.newWorktree.actions.startFromGitHubIssuePr')}
|
||||
</Button>
|
||||
)}
|
||||
{isGitLabConnected && (
|
||||
{showGitLabStartFrom && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { useI18n, type Locale } from '@/lib/i18n';
|
||||
import { openExternalUrl } from '@/lib/url';
|
||||
import { useGitProvider } from '@/lib/gitProvider';
|
||||
import { buildWalkthroughView } from '@/lib/walkthrough/model';
|
||||
import type { WalkthroughSource, WalkthroughWorkingTreeScope } from '@/lib/walkthrough/types';
|
||||
import { ModelSelector } from '@/components/sections/agents/ModelSelector';
|
||||
@@ -208,9 +209,10 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
|
||||
const ensurePrStatusEntry = useGitHubPrStatusStore((state) => state.ensureEntry);
|
||||
const setPrStatusParams = useGitHubPrStatusStore((state) => state.setParams);
|
||||
const refreshPrStatusTargets = useGitHubPrStatusStore((state) => state.refreshTargets);
|
||||
const gitProvider = useGitProvider(directory);
|
||||
|
||||
useEffect(() => {
|
||||
if (!directory || !currentBranch || !githubAuthChecked || !githubConnected) return;
|
||||
if (!directory || !currentBranch || !githubAuthChecked || !githubConnected || gitProvider !== 'github') return;
|
||||
const key = getGitHubPrStatusKey(directory, currentBranch);
|
||||
ensurePrStatusEntry(key);
|
||||
setPrStatusParams(key, {
|
||||
@@ -230,6 +232,7 @@ export const WalkthroughView = ({ directory }: WalkthroughViewProps) => {
|
||||
github,
|
||||
githubAuthChecked,
|
||||
githubConnected,
|
||||
gitProvider,
|
||||
refreshPrStatusTargets,
|
||||
setPrStatusParams,
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user