Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/web/src/components/ChatView.logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ export function collectUserMessageBlobPreviewUrls(message: ChatMessage): string[
}

export interface PullRequestDialogState {
open: boolean;
initialReference: string | null;
key: number;
}
Expand Down
43 changes: 31 additions & 12 deletions apps/web/src/components/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1392,7 +1392,12 @@ function ChatViewContent(props: ChatViewProps) {
const composerRef = useComposerHandleContext() ?? localComposerRef;
const [isWorkspaceFileDragActive, setIsWorkspaceFileDragActive] = useState(false);
const [showScrollToBottom, setShowScrollToBottom] = useState(false);
const [expandedImage, setExpandedImage] = useState<ExpandedImagePreview | null>(null);
const [expandedImageDialog, setExpandedImageDialog] = useState<{
readonly open: boolean;
readonly preview: ExpandedImagePreview;
readonly generation: number;
} | null>(null);
const expandedImage = expandedImageDialog?.preview ?? null;
const [optimisticUserMessages, setOptimisticUserMessages] = useState<ChatMessage[]>([]);
const [feedbackSubmissionsByThreadKey, setFeedbackSubmissionsByThreadKey] = useState<
Record<string, ReadonlyArray<CodexFeedbackSubmission>>
Expand Down Expand Up @@ -1978,6 +1983,7 @@ function ChatViewContent(props: ChatViewProps) {
return;
}
setPullRequestDialogState({
open: true,
initialReference: reference ?? null,
key: Date.now(),
});
Expand All @@ -1986,7 +1992,7 @@ function ChatViewContent(props: ChatViewProps) {
);

const closePullRequestDialog = useCallback(() => {
setPullRequestDialogState(null);
setPullRequestDialogState((current) => (current ? { ...current, open: false } : current));
}, []);

const openOrReuseProjectDraftThread = useCallback(
Expand Down Expand Up @@ -4232,11 +4238,11 @@ function ChatViewContent(props: ChatViewProps) {
return [];
});
resetLocalDispatch();
setExpandedImage(null);
setExpandedImageDialog(null);
}, [draftId, resetLocalDispatch, threadId]);

const closeExpandedImage = useCallback(() => {
setExpandedImage(null);
setExpandedImageDialog((current) => (current ? { ...current, open: false } : current));
}, []);

const activeWorktreePath = activeThread?.worktreePath ?? null;
Expand Down Expand Up @@ -6382,7 +6388,11 @@ function ChatViewContent(props: ChatViewProps) {
};

const onExpandTimelineImage = useCallback((preview: ExpandedImagePreview) => {
setExpandedImage(preview);
setExpandedImageDialog((current) => ({
open: true,
preview,
generation: (current?.generation ?? 0) + 1,
}));
}, []);
const onOpenTurnDiff = useCallback(
(turnId: TurnId, filePath?: string) => {
Expand Down Expand Up @@ -6943,7 +6953,7 @@ function ChatViewContent(props: ChatViewProps) {
{pullRequestDialogState ? (
<PullRequestThreadDialog
key={pullRequestDialogState.key}
open
open={pullRequestDialogState.open}
environmentId={activeThread.environmentId}
threadId={activeThread.id}
cwd={activeProject?.workspaceRoot ?? null}
Expand All @@ -6953,6 +6963,9 @@ function ChatViewContent(props: ChatViewProps) {
closePullRequestDialog();
}
}}
onOpenChangeComplete={(open) => {
if (!open) setPullRequestDialogState(null);
}}
onPrepared={handlePreparedPullRequestThread}
/>
) : null}
Expand Down Expand Up @@ -7016,8 +7029,8 @@ function ChatViewContent(props: ChatViewProps) {
{rightPanelContent}
</RightPanelTabs>
) : null}
{shouldUseRightPanelSheet && rightPanelOpen && activeThreadRef ? (
<RightPanelSheet open onClose={closePreviewPanel}>
{shouldUseRightPanelSheet && activeThreadRef ? (
<RightPanelSheet open={rightPanelOpen} onClose={closePreviewPanel}>
<RightPanelTabs
mode="sheet"
// Same effective inset as the closed-state titlebar controls
Expand Down Expand Up @@ -7058,13 +7071,19 @@ function ChatViewContent(props: ChatViewProps) {
</RightPanelSheet>
) : null}

{expandedImage && (
{expandedImageDialog ? (
<ExpandedImageDialog
key={`${expandedImage.images[expandedImage.index]?.src ?? "image"}:${expandedImage.index}`}
key={expandedImageDialog.generation}
open={expandedImageDialog.open}
preview={expandedImage}
onClose={closeExpandedImage}
onOpenChange={(open) => {
if (!open) closeExpandedImage();
}}
onOpenChangeComplete={(open) => {
if (!open) setExpandedImageDialog(null);
}}
/>
)}
) : null}
</div>
);
}
Expand Down
43 changes: 29 additions & 14 deletions apps/web/src/components/CommandPalette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -396,13 +396,23 @@ export function CommandPalette({ children }: { children: ReactNode }) {
mode: "command",
openIntent: null,
});
const setOpen = useCallback((open: boolean) => dispatch({ _tag: "SetOpen", open }), []);
const toggleMode = useCallback(
(mode: SearchOverlayMode) => dispatch({ _tag: "ToggleMode", mode }),
[],
);
const openAddProject = useCallback(() => dispatch({ _tag: "OpenAddProject" }), []);
const openNewThreadIn = useCallback(() => dispatch({ _tag: "OpenNewThreadIn" }), []);
const [dialogContentMounted, setDialogContentMounted] = useState(false);
const setOpen = useCallback((open: boolean) => {
if (open) setDialogContentMounted(true);
dispatch({ _tag: "SetOpen", open });
}, []);
const toggleMode = useCallback((mode: SearchOverlayMode) => {
setDialogContentMounted(true);
dispatch({ _tag: "ToggleMode", mode });
}, []);
const openAddProject = useCallback(() => {
setDialogContentMounted(true);
dispatch({ _tag: "OpenAddProject" });
}, []);
const openNewThreadIn = useCallback(() => {
setDialogContentMounted(true);
dispatch({ _tag: "OpenNewThreadIn" });
}, []);
const clearOpenIntent = useCallback(() => dispatch({ _tag: "ClearOpenIntent" }), []);
const keybindings = useAtomValue(primaryServerKeybindingsAtom);
const { theme, themeHalves, resolvedTheme } = useTheme();
Expand Down Expand Up @@ -496,15 +506,20 @@ export function CommandPalette({ children }: { children: ReactNode }) {
}
setOpen(open);
}}
onOpenChangeComplete={(open) => {
if (!open) setDialogContentMounted(false);
}}
>
{children}
<CommandPaletteDialog
mode={state.mode}
openIntent={state.openIntent}
setOpen={setOpen}
openOverlayMode={toggleMode}
clearOpenIntent={clearOpenIntent}
/>
{dialogContentMounted ? (
<CommandPaletteDialog
mode={state.mode}
openIntent={state.openIntent}
setOpen={setOpen}
openOverlayMode={toggleMode}
clearOpenIntent={clearOpenIntent}
/>
) : null}
</CommandDialog>
</ComposerHandleContext>
);
Expand Down
68 changes: 32 additions & 36 deletions apps/web/src/components/GitActionsControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ interface GitActionsControlProps {
}

interface PendingDefaultBranchAction {
open: boolean;
action: DefaultBranchConfirmableAction;
branchName: string;
includesCommit: boolean;
Expand Down Expand Up @@ -538,11 +539,8 @@ function PublishRepositoryDialog(props: PublishRepositoryDialogProps) {
const handleOpenChange = useCallback(
(open: boolean) => {
props.onOpenChange(open);
if (!open) {
resetState();
}
},
[props, resetState],
[props.onOpenChange],
);

const openSourceControlSettings = useCallback(() => {
Expand All @@ -551,7 +549,13 @@ function PublishRepositoryDialog(props: PublishRepositoryDialogProps) {
}, [handleOpenChange, navigate]);

return (
<Dialog open={props.open} onOpenChange={handleOpenChange}>
<Dialog
open={props.open}
onOpenChange={handleOpenChange}
onOpenChangeComplete={(open) => {
if (!open) resetState();
}}
>
<DialogPopup className="max-w-xl overflow-hidden">
<div className="flex min-h-0 flex-col overflow-hidden border-foreground/10 bg-transparent">
<DialogHeader className="border-b border-border/70 bg-foreground/[0.025] dark:border-transparent dark:bg-transparent">
Expand Down Expand Up @@ -1293,6 +1297,7 @@ export default function GitActionsControl({
return;
}
setPendingDefaultBranchAction({
open: true,
action,
branchName: actionBranch,
includesCommit,
Expand Down Expand Up @@ -1496,9 +1501,9 @@ export default function GitActionsControl({
);

const continuePendingDefaultBranchAction = () => {
if (!pendingDefaultBranchAction) return;
if (!pendingDefaultBranchAction?.open) return;
const { action, commitMessage, onConfirmed, filePaths } = pendingDefaultBranchAction;
setPendingDefaultBranchAction(null);
setPendingDefaultBranchAction({ ...pendingDefaultBranchAction, open: false });
void runGitActionWithToast({
action,
...(commitMessage ? { commitMessage } : {}),
Expand All @@ -1509,9 +1514,9 @@ export default function GitActionsControl({
};

const checkoutFeatureBranchAndContinuePendingAction = () => {
if (!pendingDefaultBranchAction) return;
if (!pendingDefaultBranchAction?.open) return;
const { action, commitMessage, onConfirmed, filePaths } = pendingDefaultBranchAction;
setPendingDefaultBranchAction(null);
setPendingDefaultBranchAction({ ...pendingDefaultBranchAction, open: false });
void runGitActionWithToast({
action,
...(commitMessage ? { commitMessage } : {}),
Expand All @@ -1527,9 +1532,6 @@ export default function GitActionsControl({
const commitMessage = dialogCommitMessage.trim();

setIsCommitDialogOpen(false);
setDialogCommitMessage("");
setExcludedFiles(new Set());
setIsEditingFiles(false);

void runGitActionWithToast({
action: "commit",
Expand Down Expand Up @@ -1626,9 +1628,6 @@ export default function GitActionsControl({
if (!isCommitDialogOpen) return;
const commitMessage = dialogCommitMessage.trim();
setIsCommitDialogOpen(false);
setDialogCommitMessage("");
setExcludedFiles(new Set());
setIsEditingFiles(false);
void runGitActionWithToast({
action: "commit",
...(commitMessage ? { commitMessage } : {}),
Expand Down Expand Up @@ -1835,13 +1834,12 @@ export default function GitActionsControl({

<Dialog
open={isCommitDialogOpen}
onOpenChange={(open) => {
if (!open) {
setIsCommitDialogOpen(false);
setDialogCommitMessage("");
setExcludedFiles(new Set());
setIsEditingFiles(false);
}
onOpenChange={setIsCommitDialogOpen}
onOpenChangeComplete={(open) => {
if (open) return;
setDialogCommitMessage("");
setExcludedFiles(new Set());
setIsEditingFiles(false);
}}
>
<DialogPopup>
Expand Down Expand Up @@ -1972,16 +1970,7 @@ export default function GitActionsControl({
</div>
</DialogPanel>
<DialogFooter variant="bare">
<Button
variant="outline"
size="sm"
onClick={() => {
setIsCommitDialogOpen(false);
setDialogCommitMessage("");
setExcludedFiles(new Set());
setIsEditingFiles(false);
}}
>
<Button variant="outline" size="sm" onClick={() => setIsCommitDialogOpen(false)}>
Cancel
</Button>
<Button
Expand All @@ -2007,12 +1996,15 @@ export default function GitActionsControl({
/>

<Dialog
open={pendingDefaultBranchAction !== null}
open={pendingDefaultBranchAction?.open ?? false}
onOpenChange={(open) => {
if (!open) {
setPendingDefaultBranchAction(null);
if (!open && pendingDefaultBranchAction) {
setPendingDefaultBranchAction({ ...pendingDefaultBranchAction, open: false });
}
}}
onOpenChangeComplete={(open) => {
if (!open) setPendingDefaultBranchAction(null);
}}
>
<DialogPopup className="max-w-xl">
<DialogHeader>
Expand All @@ -2026,7 +2018,11 @@ export default function GitActionsControl({
className="w-full sm:mr-auto sm:w-auto"
variant="outline"
size="sm"
onClick={() => setPendingDefaultBranchAction(null)}
onClick={() => {
if (pendingDefaultBranchAction) {
setPendingDefaultBranchAction({ ...pendingDefaultBranchAction, open: false });
}
}}
>
Abort
</Button>
Expand Down
3 changes: 3 additions & 0 deletions apps/web/src/components/PullRequestThreadDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ interface PullRequestThreadDialogProps {
cwd: string | null;
initialReference: string | null;
onOpenChange: (open: boolean) => void;
onOpenChangeComplete: (open: boolean) => void;
onPrepared: (input: { branch: string; worktreePath: string | null }) => Promise<void> | void;
}

Expand All @@ -43,6 +44,7 @@ export function PullRequestThreadDialog({
cwd,
initialReference,
onOpenChange,
onOpenChangeComplete,
onPrepared,
}: PullRequestThreadDialogProps) {
const referenceInputRef = useRef<HTMLInputElement>(null);
Expand Down Expand Up @@ -193,6 +195,7 @@ export function PullRequestThreadDialog({
onOpenChange(nextOpen);
}
}}
onOpenChangeComplete={onOpenChangeComplete}
>
<DialogPopup className="max-w-xl">
<DialogHeader>
Expand Down
7 changes: 1 addition & 6 deletions apps/web/src/components/RightPanelSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ export function RightPanelSheet(props: {
}
}}
>
<SheetPopup
side="right"
showCloseButton={false}
keepMounted
className={RIGHT_PANEL_SHEET_CLASS_NAME}
>
<SheetPopup side="right" showCloseButton={false} className={RIGHT_PANEL_SHEET_CLASS_NAME}>
{props.children}
</SheetPopup>
</Sheet>
Expand Down
Loading
Loading