mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-04 11:53:18 +03:00
purge branch re-order
This commit is contained in:
parent
f4f140afa5
commit
26800a81c6
@ -1,175 +0,0 @@
|
|||||||
const zoneMap = new Map<string, Set<HTMLElement>>();
|
|
||||||
const optionsMap = new Map<HTMLElement, DzOptions>();
|
|
||||||
|
|
||||||
export interface DzOptions {
|
|
||||||
type: string;
|
|
||||||
hover: string;
|
|
||||||
active: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultOptions: DzOptions = {
|
|
||||||
hover: 'drop-zone-hover',
|
|
||||||
active: 'drop-zone-active',
|
|
||||||
type: 'default'
|
|
||||||
};
|
|
||||||
|
|
||||||
function inactivateZones(zones: Set<HTMLElement>) {
|
|
||||||
zones?.forEach((zone) => {
|
|
||||||
const opts = optionsMap.get(zone);
|
|
||||||
opts && zone.classList.remove(opts.active);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function activateZones(zones: Set<HTMLElement>, activeZone: HTMLElement) {
|
|
||||||
zones?.forEach((zone) => {
|
|
||||||
if (zone !== activeZone && !isChildOf(activeZone, zone)) {
|
|
||||||
const opts = optionsMap.get(zone);
|
|
||||||
opts && zone.classList.add(opts.active);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getZones(type: string): Set<HTMLElement> {
|
|
||||||
let zones = zoneMap.get(type);
|
|
||||||
if (!zones) {
|
|
||||||
zones = new Set([]);
|
|
||||||
zoneMap.set(type, zones);
|
|
||||||
}
|
|
||||||
return zones;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isChildOf(child: any, parent: HTMLElement): boolean {
|
|
||||||
if (parent === child) return false;
|
|
||||||
if (!child.parentElement) return false;
|
|
||||||
if (child.parentElement == parent) return true;
|
|
||||||
return isChildOf(child.parentElement, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function dzTrigger(node: HTMLElement, opts: Partial<DzOptions> | undefined) {
|
|
||||||
const options = { ...defaultOptions, ...opts };
|
|
||||||
const zones = getZones(options.type);
|
|
||||||
|
|
||||||
let clone: HTMLElement;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The problem with the ghost element is that it gets clipped after rotation unless we enclose
|
|
||||||
* it within a larger bounding box. This means we have an extra `<div>` in the html that is
|
|
||||||
* only present to support the rotation
|
|
||||||
*/
|
|
||||||
function handleDragStart(e: DragEvent) {
|
|
||||||
// Start by cloning the node for the ghost element
|
|
||||||
clone = node.cloneNode(true) as HTMLElement;
|
|
||||||
clone.style.position = 'absolute';
|
|
||||||
clone.style.top = '-9999px'; // Element has to be in the DOM so we move it out of sight
|
|
||||||
clone.style.display = 'inline-block';
|
|
||||||
clone.style.padding = '30px'; // To prevent clipping of rotated element
|
|
||||||
|
|
||||||
// Style the inner node so it retains the shape and then rotate
|
|
||||||
const inner = clone.children[0] as HTMLElement;
|
|
||||||
inner.style.height = node.clientHeight + 'px';
|
|
||||||
inner.style.width = node.clientWidth + 'px';
|
|
||||||
inner.style.rotate = `${Math.floor(Math.random() * 3)}deg`;
|
|
||||||
document.body.appendChild(clone);
|
|
||||||
|
|
||||||
// Dim the original element while dragging
|
|
||||||
node.style.opacity = '0.6';
|
|
||||||
|
|
||||||
e.dataTransfer?.setDragImage(clone, e.offsetX + 30, e.offsetY + 30); // Adds the padding
|
|
||||||
activateZones(zones, node);
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDragEnd(e: DragEvent) {
|
|
||||||
node.style.opacity = '1'; // Undo the dimming from `dragstart`
|
|
||||||
clone.remove(); // Remove temporary ghost element
|
|
||||||
|
|
||||||
e.stopPropagation();
|
|
||||||
inactivateZones(zones);
|
|
||||||
}
|
|
||||||
|
|
||||||
node.addEventListener('dragstart', handleDragStart);
|
|
||||||
node.addEventListener('dragend', handleDragEnd);
|
|
||||||
|
|
||||||
return {
|
|
||||||
destroy() {
|
|
||||||
node.removeEventListener('dragstart', handleDragStart);
|
|
||||||
node.removeEventListener('dragend', handleDragEnd);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function dzHighlight(node: HTMLElement, opts: Partial<DzOptions> | undefined) {
|
|
||||||
const options = { ...defaultOptions, ...opts };
|
|
||||||
const zones = getZones(options.type);
|
|
||||||
zones.add(node);
|
|
||||||
optionsMap.set(node, options);
|
|
||||||
|
|
||||||
function setHover(value: boolean) {
|
|
||||||
if (value) {
|
|
||||||
// We do this so we can set pointer-events-none on all dropzones from main css file,
|
|
||||||
// without it onMouseLeave fires every time a child container is left.
|
|
||||||
node.classList.add(defaultOptions.hover);
|
|
||||||
node.classList.add(options.hover);
|
|
||||||
} else {
|
|
||||||
node.classList.remove(defaultOptions.hover);
|
|
||||||
node.classList.remove(options.hover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDragEnter(e: DragEvent) {
|
|
||||||
if (!e.dataTransfer?.types.includes(options.type)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setHover(true);
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDragLeave(e: DragEvent) {
|
|
||||||
if (!e.dataTransfer?.types.includes(options.type)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isChildOf(e.target, node)) {
|
|
||||||
setHover(false);
|
|
||||||
}
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDragEnd(e: DragEvent) {
|
|
||||||
setHover(false);
|
|
||||||
inactivateZones(zones);
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDrop(e: DragEvent) {
|
|
||||||
if (!e.dataTransfer?.types.includes(options.type)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setHover(false);
|
|
||||||
inactivateZones(zones);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleDragOver(e: DragEvent) {
|
|
||||||
if (!e.dataTransfer?.types.includes(options.type)) {
|
|
||||||
e.stopImmediatePropagation(); // Stops event from reaching `on:dragover` on the element
|
|
||||||
}
|
|
||||||
if (e.dataTransfer?.types.includes(options.type)) e.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
node.addEventListener('dragend', handleDragEnd);
|
|
||||||
node.addEventListener('dragenter', handleDragEnter);
|
|
||||||
node.addEventListener('dragleave', handleDragLeave);
|
|
||||||
node.addEventListener('dragover', handleDragOver);
|
|
||||||
node.addEventListener('drop', handleDrop);
|
|
||||||
node.classList.add('drop-zone');
|
|
||||||
|
|
||||||
return {
|
|
||||||
destroy() {
|
|
||||||
node.removeEventListener('dragend', handleDragEnd);
|
|
||||||
node.removeEventListener('dragenter', handleDragEnter);
|
|
||||||
node.removeEventListener('dragleave', handleDragLeave);
|
|
||||||
node.removeEventListener('dragover', handleDragOver);
|
|
||||||
node.removeEventListener('drop', handleDrop);
|
|
||||||
zones?.delete(node);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -88,7 +88,7 @@
|
|||||||
<p class="mb-2 w-full overflow-hidden font-semibold">Commits</p>
|
<p class="mb-2 w-full overflow-hidden font-semibold">Commits</p>
|
||||||
<div class="flex w-full flex-col gap-y-2">
|
<div class="flex w-full flex-col gap-y-2">
|
||||||
{#each branch.commits as commit}
|
{#each branch.commits as commit}
|
||||||
<CommitCard branchId={branch.id} {commit} {projectId} />
|
<CommitCard {commit} {projectId} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
import BranchLane from '../components/BranchLane.svelte';
|
import BranchLane from '../components/BranchLane.svelte';
|
||||||
import NewBranchDropZone from './NewBranchDropZone.svelte';
|
import NewBranchDropZone from './NewBranchDropZone.svelte';
|
||||||
import type { BaseBranch, Branch } from '$lib/vbranches/types';
|
import type { BaseBranch, Branch } from '$lib/vbranches/types';
|
||||||
import { dzHighlight } from '$lib/utils/dropZone';
|
|
||||||
import type { BranchController } from '$lib/vbranches/branchController';
|
import type { BranchController } from '$lib/vbranches/branchController';
|
||||||
import type { getCloudApiClient } from '$lib/backend/cloud';
|
import type { getCloudApiClient } from '$lib/backend/cloud';
|
||||||
import type { LoadState } from '@square/svelte-store';
|
import type { LoadState } from '@square/svelte-store';
|
||||||
@ -25,13 +24,6 @@
|
|||||||
|
|
||||||
export let githubContext: GitHubIntegrationContext | undefined;
|
export let githubContext: GitHubIntegrationContext | undefined;
|
||||||
|
|
||||||
let dragged: any;
|
|
||||||
let dropZone: HTMLDivElement;
|
|
||||||
let priorPosition = 0;
|
|
||||||
let dropPosition = 0;
|
|
||||||
|
|
||||||
const dzType = 'text/branch';
|
|
||||||
|
|
||||||
function handleEmpty() {
|
function handleEmpty() {
|
||||||
const emptyIndex = branches?.findIndex((item) => !item.files || item.files.length == 0);
|
const emptyIndex = branches?.findIndex((item) => !item.files || item.files.length == 0);
|
||||||
if (emptyIndex && emptyIndex != -1) {
|
if (emptyIndex && emptyIndex != -1) {
|
||||||
@ -48,52 +40,9 @@
|
|||||||
{:else if branchesState.isError || baseBranchState.isError}
|
{:else if branchesState.isError || baseBranchState.isError}
|
||||||
<div class="p-4">Something went wrong...</div>
|
<div class="p-4">Something went wrong...</div>
|
||||||
{:else if branches}
|
{:else if branches}
|
||||||
<div
|
<div id="branch-lanes" class="bg-color-2 flex h-full flex-shrink flex-grow items-start">
|
||||||
bind:this={dropZone}
|
|
||||||
id="branch-lanes"
|
|
||||||
class="bg-color-2 flex h-full flex-shrink flex-grow items-start"
|
|
||||||
role="group"
|
|
||||||
use:dzHighlight={{ type: dzType, active: 'board-dz-active', hover: 'board-dz-hover' }}
|
|
||||||
on:dragover={(e) => {
|
|
||||||
const children = [...e.currentTarget.children];
|
|
||||||
dropPosition = 0;
|
|
||||||
// We account for the NewBranchDropZone by subtracting 2
|
|
||||||
for (let i = 0; i < children.length - 2; i++) {
|
|
||||||
const pos = children[i].getBoundingClientRect();
|
|
||||||
if (e.clientX > pos.left + pos.width) {
|
|
||||||
dropPosition = i + 1; // Note that this is declared in the <script>
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const idx = children.indexOf(dragged);
|
|
||||||
if (idx != dropPosition) {
|
|
||||||
idx >= dropPosition
|
|
||||||
? children[dropPosition].before(dragged)
|
|
||||||
: children[dropPosition].after(dragged);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
on:drop={() => {
|
|
||||||
if (!branches) return;
|
|
||||||
if (priorPosition != dropPosition) {
|
|
||||||
const el = branches.splice(priorPosition, 1);
|
|
||||||
branches.splice(dropPosition, 0, ...el);
|
|
||||||
branches.forEach((branch, i) => {
|
|
||||||
if (branch.order !== i) {
|
|
||||||
branchController.updateBranchOrder(branch.id, i);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{#each branches.filter((c) => c.active) as branch (branch.id)}
|
{#each branches.filter((c) => c.active) as branch (branch.id)}
|
||||||
<BranchLane
|
<BranchLane
|
||||||
on:dragstart={(e) => {
|
|
||||||
if (!e.dataTransfer) return;
|
|
||||||
e.dataTransfer.setData(dzType, branch.id);
|
|
||||||
dragged = e.currentTarget;
|
|
||||||
priorPosition = Array.from(dropZone.children).indexOf(dragged);
|
|
||||||
}}
|
|
||||||
on:empty={handleEmpty}
|
on:empty={handleEmpty}
|
||||||
{branch}
|
{branch}
|
||||||
{projectId}
|
{projectId}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { dropzone } from '$lib/dragable';
|
import { dropzone } from '$lib/utils/dragable';
|
||||||
import type { BranchController } from '$lib/vbranches/branchController';
|
import type { BranchController } from '$lib/vbranches/branchController';
|
||||||
import type { File, Hunk } from '$lib/vbranches/types';
|
import type { File, Hunk } from '$lib/vbranches/types';
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { dropzone } from '$lib/dragable';
|
import { dropzone } from '$lib/utils/dragable';
|
||||||
import type { Hunk, File, RemoteCommit } from '$lib/vbranches/types';
|
import type { Hunk, File, RemoteCommit } from '$lib/vbranches/types';
|
||||||
import type { BranchController } from '$lib/vbranches/branchController';
|
import type { BranchController } from '$lib/vbranches/branchController';
|
||||||
import CommitCard from './CommitCard.svelte';
|
import CommitCard from './CommitCard.svelte';
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { userStore } from '$lib/stores/user';
|
import { userStore } from '$lib/stores/user';
|
||||||
import type { BaseBranch, Branch, File, Hunk, RemoteCommit } from '$lib/vbranches/types';
|
import type { BaseBranch, Branch, File, Hunk, RemoteCommit } from '$lib/vbranches/types';
|
||||||
import { getContext, onDestroy, onMount } from 'svelte';
|
import { getContext, onDestroy, onMount } from 'svelte';
|
||||||
import { dragable, dropzone } from '$lib/dragable';
|
import { dragable, dropzone } from '$lib/utils/dragable';
|
||||||
import { Ownership } from '$lib/vbranches/ownership';
|
import { Ownership } from '$lib/vbranches/ownership';
|
||||||
import IconKebabMenu from '$lib/icons/IconKebabMenu.svelte';
|
import IconKebabMenu from '$lib/icons/IconKebabMenu.svelte';
|
||||||
import CommitCard from './CommitCard.svelte';
|
import CommitCard from './CommitCard.svelte';
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { ContentSection, HunkSection, parseFileSections } from './fileSections';
|
import { ContentSection, HunkSection, parseFileSections } from './fileSections';
|
||||||
import { createEventDispatcher, onDestroy } from 'svelte';
|
import { createEventDispatcher, onDestroy } from 'svelte';
|
||||||
import type { File, Hunk } from '$lib/vbranches/types';
|
import type { File, Hunk } from '$lib/vbranches/types';
|
||||||
import { dragable } from '$lib/dragable';
|
import { dragable } from '$lib/utils/dragable';
|
||||||
import type { Ownership } from '$lib/vbranches/ownership';
|
import type { Ownership } from '$lib/vbranches/ownership';
|
||||||
import type { Writable } from 'svelte/store';
|
import type { Writable } from 'svelte/store';
|
||||||
import RenderedLine from './RenderedLine.svelte';
|
import RenderedLine from './RenderedLine.svelte';
|
||||||
|
Loading…
Reference in New Issue
Block a user