mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-05-03 05:54:15 +02:00
Handle remote branches
This commit is contained in:
@@ -12,6 +12,7 @@ import classNames from 'classnames';
|
||||
|
||||
import { useMemo, useState } from 'react';
|
||||
import { fallbackRequestName } from '../lib/fallbackRequestName';
|
||||
import { showToast } from '../lib/toast';
|
||||
import { Banner } from './core/Banner';
|
||||
import { Button } from './core/Button';
|
||||
import type { CheckboxProps } from './core/Checkbox';
|
||||
@@ -46,8 +47,9 @@ export function GitCommitDialog({ syncDir, onDone, workspace }: Props) {
|
||||
};
|
||||
|
||||
const handleCreateCommitAndPush = async () => {
|
||||
await handleCreateCommit();
|
||||
await commit.mutateAsync({ message });
|
||||
await push.mutateAsync();
|
||||
showToast({ id: 'git-push-success', message: 'Pushed changes', color: 'success' });
|
||||
onDone();
|
||||
};
|
||||
|
||||
|
||||
@@ -34,9 +34,16 @@ export function GitDropdown() {
|
||||
|
||||
function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) {
|
||||
const workspace = useActiveWorkspace();
|
||||
const [{ status, log }, { branch, deleteBranch, mergeBranch, push, pull, checkout }] =
|
||||
const [{ status, log }, { branch, deleteBranch, fetchAll, mergeBranch, push, pull, checkout }] =
|
||||
useGit(syncDir);
|
||||
|
||||
const localBranches = status.data?.localBranches ?? [];
|
||||
const remoteBranches = status.data?.remoteBranches ?? [];
|
||||
const remoteOnlyBranches = remoteBranches.filter(
|
||||
(b) => !localBranches.includes(b.replace(/^origin\//, '')),
|
||||
);
|
||||
const currentBranch = status.data?.headRefShorthand ?? 'UNKNOWN';
|
||||
|
||||
if (workspace == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -69,12 +76,12 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) {
|
||||
showErrorToast('git-checkout-error', String(err));
|
||||
}
|
||||
},
|
||||
async onSuccess() {
|
||||
async onSuccess(branchName) {
|
||||
showToast({
|
||||
id: 'git-checkout-success',
|
||||
message: (
|
||||
<>
|
||||
Switched branch <InlineCode>{branch}</InlineCode>
|
||||
Switched branch <InlineCode>{branchName}</InlineCode>
|
||||
</>
|
||||
),
|
||||
color: 'success',
|
||||
@@ -124,7 +131,7 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) {
|
||||
{
|
||||
label: 'Merge Branch',
|
||||
leftSlot: <Icon icon="merge" />,
|
||||
hidden: (status.data?.branches ?? []).length <= 1,
|
||||
hidden: localBranches.length <= 1,
|
||||
async onSelect() {
|
||||
showDialog({
|
||||
id: 'git-merge',
|
||||
@@ -132,15 +139,13 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) {
|
||||
size: 'sm',
|
||||
description: (
|
||||
<>
|
||||
Select a branch to merge into <InlineCode>{status.data?.headRefShorthand}</InlineCode>
|
||||
Select a branch to merge into <InlineCode>{currentBranch}</InlineCode>
|
||||
</>
|
||||
),
|
||||
render: ({ hide }) => (
|
||||
<BranchSelectionDialog
|
||||
selectText="Merge"
|
||||
branches={(status.data?.branches ?? []).filter(
|
||||
(b) => b !== status.data?.headRefShorthand,
|
||||
)}
|
||||
branches={localBranches.filter((b) => b !== currentBranch)}
|
||||
onCancel={hide}
|
||||
onSelect={async (branch) => {
|
||||
await mergeBranch.mutateAsync(
|
||||
@@ -153,7 +158,7 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) {
|
||||
message: (
|
||||
<>
|
||||
Merged <InlineCode>{branch}</InlineCode> into{' '}
|
||||
<InlineCode>{status.data?.headRefShorthand}</InlineCode>
|
||||
<InlineCode>{currentBranch}</InlineCode>
|
||||
</>
|
||||
),
|
||||
});
|
||||
@@ -173,10 +178,9 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) {
|
||||
{
|
||||
label: 'Delete Branch',
|
||||
leftSlot: <Icon icon="trash" />,
|
||||
hidden: (status.data?.branches ?? []).length <= 1,
|
||||
hidden: localBranches.length <= 1,
|
||||
color: 'danger',
|
||||
async onSelect() {
|
||||
const currentBranch = status.data?.headRefShorthand;
|
||||
if (currentBranch == null) return;
|
||||
|
||||
const confirmed = await showConfirmDelete({
|
||||
@@ -256,9 +260,17 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) {
|
||||
});
|
||||
},
|
||||
},
|
||||
{ type: 'separator', label: 'Branches', hidden: (status.data?.branches ?? []).length < 1 },
|
||||
...(status.data?.branches ?? []).map((branch) => {
|
||||
const isCurrent = status.data?.headRefShorthand === branch;
|
||||
{ type: 'separator', label: 'Branches', hidden: localBranches.length < 1 },
|
||||
...localBranches.map((branch) => {
|
||||
const isCurrent = currentBranch === branch;
|
||||
return {
|
||||
label: branch,
|
||||
leftSlot: <Icon icon={isCurrent ? 'check' : 'empty'} />,
|
||||
onSelect: isCurrent ? undefined : () => tryCheckout(branch, false),
|
||||
};
|
||||
}),
|
||||
...remoteOnlyBranches.map((branch) => {
|
||||
const isCurrent = currentBranch === branch;
|
||||
return {
|
||||
label: branch,
|
||||
leftSlot: <Icon icon={isCurrent ? 'check' : 'empty'} />,
|
||||
@@ -268,9 +280,9 @@ function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) {
|
||||
];
|
||||
|
||||
return (
|
||||
<Dropdown fullWidth items={items}>
|
||||
<Dropdown fullWidth items={items} onOpen={fetchAll.mutate}>
|
||||
<GitMenuButton>
|
||||
{noRepo ? 'Configure Git' : <InlineCode>{status.data?.headRefShorthand}</InlineCode>}
|
||||
<InlineCode>{currentBranch}</InlineCode>
|
||||
<Icon icon="git_branch" size="sm" />
|
||||
</GitMenuButton>
|
||||
</Dropdown>
|
||||
|
||||
@@ -71,6 +71,7 @@ export interface DropdownProps {
|
||||
items: DropdownItem[];
|
||||
fullWidth?: boolean;
|
||||
hotKeyAction?: HotkeyAction;
|
||||
onOpen?: () => void;
|
||||
}
|
||||
|
||||
export interface DropdownRef {
|
||||
@@ -89,7 +90,7 @@ export interface DropdownRef {
|
||||
const openAtom = atom<string | null>(null);
|
||||
|
||||
export const Dropdown = forwardRef<DropdownRef, DropdownProps>(function Dropdown(
|
||||
{ children, items, hotKeyAction, fullWidth }: DropdownProps,
|
||||
{ children, items, hotKeyAction, fullWidth, onOpen }: DropdownProps,
|
||||
ref,
|
||||
) {
|
||||
const id = useRef(generateId());
|
||||
@@ -116,13 +117,14 @@ export const Dropdown = forwardRef<DropdownRef, DropdownProps>(function Dropdown
|
||||
const newIsOpen = typeof o === 'function' ? o(prevIsOpen) : o;
|
||||
// Persist background color of button until we close the dropdown
|
||||
if (newIsOpen) {
|
||||
onOpen?.();
|
||||
buttonRef.current!.style.backgroundColor = window
|
||||
.getComputedStyle(buttonRef.current!)
|
||||
.getPropertyValue('background-color');
|
||||
}
|
||||
return newIsOpen ? id.current : null; // Set global atom to current ID to signify open state
|
||||
});
|
||||
}, []);
|
||||
}, [onOpen]);
|
||||
|
||||
// Because a different dropdown can cause ours to close, a useEffect([isOpen]) is the only method
|
||||
// we have of detecting the dropdown closed, to do cleanup.
|
||||
|
||||
Reference in New Issue
Block a user