Skip to content

Commit

Permalink
support moving tab to another panel at specific place
Browse files Browse the repository at this point in the history
  • Loading branch information
anastasiya1155 committed Jan 11, 2024
1 parent 48879dc commit 8599983
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 48 deletions.
46 changes: 32 additions & 14 deletions client/src/Project/CurrentTabContent/Header/TabButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ type Props = TabType & {
isActive: boolean;
side: 'left' | 'right';
isOnlyTab: boolean;
moveTab: (i: number, j: number) => void;
moveTab: (
i: number,
j: number,
sourceSide: 'left' | 'right',
targetSide: 'left' | 'right',
) => void;
i: number;
repoRef?: string;
path?: string;
Expand Down Expand Up @@ -59,21 +64,23 @@ const TabButton = ({
useContext(TabsContext.Handlers);
const ref = useRef<HTMLAnchorElement>(null);
const [{ handlerId }, drop] = useDrop({
accept: `tab-${side}`,
canDrop: (item: DraggableTabItem) => item.side === side,
accept: [`tab-left`, `tab-right`],
canDrop: (item: DraggableTabItem) => true,
collect(monitor) {
return {
handlerId: monitor.getHandlerId(),
};
},
hover(item: DraggableTabItem, monitor) {
if (!ref.current || item.side !== side) {
if (!ref.current) {
return;
}
const dragIndex = item.index;
const hoverIndex = i;
const sourceSide = item.side as 'left' | 'right';
const targetSide = side as 'left' | 'right';
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
if (dragIndex === hoverIndex && sourceSide === targetSide) {
return;
}
// Determine rectangle on screen
Expand All @@ -83,26 +90,37 @@ const TabButton = ({
(hoverBoundingRect.right - hoverBoundingRect.left) / 2;
// Determine mouse position
const clientOffset = monitor.getClientOffset();
// Get pixels to the top
// Get pixels to the left
const hoverClientX = (clientOffset?.x || 0) - hoverBoundingRect.left;
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientX < hoverMiddleX) {
// Only perform the move when the mouse has crossed half of the items width
// When dragging left, only move when the cursor is below 50%
// When dragging right, only move when the cursor is above 50%
// Dragging left
if (
dragIndex < hoverIndex &&
hoverClientX < hoverMiddleX &&
sourceSide === targetSide
) {
return;
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientX > hoverMiddleX) {
// Dragging right
if (
dragIndex > hoverIndex &&
hoverClientX > hoverMiddleX &&
sourceSide === targetSide
) {
return;
}
// Time to actually perform the action
moveTab(dragIndex, hoverIndex);
moveTab(dragIndex, hoverIndex, sourceSide, targetSide);
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
item.index = hoverIndex;
if (sourceSide !== targetSide) {
item.side = targetSide;
}
},
});
const [{ isDragging }, drag] = useDrag({
Expand Down
70 changes: 53 additions & 17 deletions client/src/Project/CurrentTabContent/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { memo, useCallback, useContext, useMemo } from 'react';
import HeaderRightPart from '../../../components/Header/HeaderRightPart';
import { TabsContext } from '../../../context/tabsContext';
import { TabTypesEnum } from '../../../types/general';
import { TabType, TabTypesEnum } from '../../../types/general';
import AddTabButton from './AddTabButton';
import TabButton from './TabButton';

Expand All @@ -14,27 +14,63 @@ const ProjectHeader = ({ side }: Props) => {
const { tab } = useContext(
TabsContext[side === 'left' ? 'CurrentLeft' : 'CurrentRight'],
);
const { setLeftTabs, setRightTabs } = useContext(TabsContext.Handlers);
const { setLeftTabs, setRightTabs, setActiveRightTab, setActiveLeftTab } =
useContext(TabsContext.Handlers);
const tabs = useMemo(() => {
return side === 'left' ? leftTabs : rightTabs;
}, [side, rightTabs, leftTabs]);

const moveTab = useCallback(
(dragIndex: number, hoverIndex: number) => {
const action = side === 'left' ? setLeftTabs : setRightTabs;
action((prevTabs) => {
const newTabs = JSON.parse(JSON.stringify(prevTabs));
newTabs.splice(dragIndex, 1);
const newTab = prevTabs[dragIndex];
newTabs.splice(
hoverIndex,
0,
newTab.type === TabTypesEnum.FILE && newTab.isTemp
? { ...newTab, isTemp: false }
: newTab,
);
return newTabs;
});
(
dragIndex: number,
hoverIndex: number,
sourceSide: 'left' | 'right',
targetSide: 'left' | 'right',
) => {
if (sourceSide === targetSide) {
const action = side === 'left' ? setLeftTabs : setRightTabs;
action((prevTabs) => {
const newTabs = JSON.parse(JSON.stringify(prevTabs));
newTabs.splice(dragIndex, 1);
const newTab = prevTabs[dragIndex];
newTabs.splice(
hoverIndex,
0,
newTab.type === TabTypesEnum.FILE && newTab.isTemp
? { ...newTab, isTemp: false }
: newTab,
);
return newTabs;
});
} else {
const sourceAction = sourceSide === 'left' ? setLeftTabs : setRightTabs;
const sourceTabAction =
sourceSide === 'left' ? setActiveLeftTab : setActiveRightTab;
const targetAction = targetSide === 'left' ? setLeftTabs : setRightTabs;
const targetTabAction =
targetSide === 'left' ? setActiveLeftTab : setActiveRightTab;

sourceAction((prevSourceTabs) => {
const newSourceTabs = JSON.parse(JSON.stringify(prevSourceTabs));
const [movedTab] = newSourceTabs.splice(dragIndex, 1);
sourceTabAction(
newSourceTabs.length
? newSourceTabs[dragIndex - 1] || newSourceTabs[0]
: null,
);

targetAction((prevTargetTabs) => {
const newTargetTabs = JSON.parse(JSON.stringify(prevTargetTabs));
if (!newTargetTabs.find((t: TabType) => t.key === movedTab.key)) {
newTargetTabs.splice(hoverIndex, 0, movedTab);
}
targetTabAction(movedTab);
return newTargetTabs;
});

return newSourceTabs;
});
}
},
[side],
);
Expand Down
36 changes: 19 additions & 17 deletions client/src/context/providers/RepositoriesContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,25 @@ const RepositoriesContextProvider = ({
const data = JSON.parse(ev.data);
console.log('data', data);
if (data.ev?.status_change === SyncStatus.Done) {
toast(t('Repository indexed'), {
id: `${data.ref}-indexed`,
description: (
<Trans
values={{
repoName: splitPath(data.ref)
.slice(data.ref.startsWith('github.com/') ? -2 : -1)
.join('/'),
}}
>
<span className="text-label-base body-s-b">repoName</span> has
finished indexing. You can use it in your projects now.
</Trans>
),
icon: <RepositoryIcon sizeClassName="w-4 h-4" />,
unstyled: true,
});
if (!data.ev?.rsync) {
toast(t('Repository indexed'), {
id: `${data.ref}-indexed`,
description: (
<Trans
values={{
repoName: splitPath(data.ref)
.slice(data.ref.startsWith('github.com/') ? -2 : -1)
.join('/'),
}}
>
<span className="text-label-base body-s-b">repoName</span> has
finished indexing. You can use it in your projects now.
</Trans>
),
icon: <RepositoryIcon sizeClassName="w-4 h-4" />,
unstyled: true,
});
}
if (project?.repos.find((r) => r.repo.ref === data.ref)) {
refreshCurrentProjectRepos();
}
Expand Down

0 comments on commit 8599983

Please sign in to comment.