mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-03 03:33:16 +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>
|
||||
<div class="flex w-full flex-col gap-y-2">
|
||||
{#each branch.commits as commit}
|
||||
<CommitCard branchId={branch.id} {commit} {projectId} />
|
||||
<CommitCard {commit} {projectId} />
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2,7 +2,6 @@
|
||||
import BranchLane from '../components/BranchLane.svelte';
|
||||
import NewBranchDropZone from './NewBranchDropZone.svelte';
|
||||
import type { BaseBranch, Branch } from '$lib/vbranches/types';
|
||||
import { dzHighlight } from '$lib/utils/dropZone';
|
||||
import type { BranchController } from '$lib/vbranches/branchController';
|
||||
import type { getCloudApiClient } from '$lib/backend/cloud';
|
||||
import type { LoadState } from '@square/svelte-store';
|
||||
@ -25,13 +24,6 @@
|
||||
|
||||
export let githubContext: GitHubIntegrationContext | undefined;
|
||||
|
||||
let dragged: any;
|
||||
let dropZone: HTMLDivElement;
|
||||
let priorPosition = 0;
|
||||
let dropPosition = 0;
|
||||
|
||||
const dzType = 'text/branch';
|
||||
|
||||
function handleEmpty() {
|
||||
const emptyIndex = branches?.findIndex((item) => !item.files || item.files.length == 0);
|
||||
if (emptyIndex && emptyIndex != -1) {
|
||||
@ -48,52 +40,9 @@
|
||||
{:else if branchesState.isError || baseBranchState.isError}
|
||||
<div class="p-4">Something went wrong...</div>
|
||||
{:else if branches}
|
||||
<div
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div id="branch-lanes" class="bg-color-2 flex h-full flex-shrink flex-grow items-start">
|
||||
{#each branches.filter((c) => c.active) as branch (branch.id)}
|
||||
<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}
|
||||
{branch}
|
||||
{projectId}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { dropzone } from '$lib/dragable';
|
||||
import { dropzone } from '$lib/utils/dragable';
|
||||
import type { BranchController } from '$lib/vbranches/branchController';
|
||||
import type { File, Hunk } from '$lib/vbranches/types';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<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 { BranchController } from '$lib/vbranches/branchController';
|
||||
import CommitCard from './CommitCard.svelte';
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { userStore } from '$lib/stores/user';
|
||||
import type { BaseBranch, Branch, File, Hunk, RemoteCommit } from '$lib/vbranches/types';
|
||||
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 IconKebabMenu from '$lib/icons/IconKebabMenu.svelte';
|
||||
import CommitCard from './CommitCard.svelte';
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { ContentSection, HunkSection, parseFileSections } from './fileSections';
|
||||
import { createEventDispatcher, onDestroy } from 'svelte';
|
||||
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 { Writable } from 'svelte/store';
|
||||
import RenderedLine from './RenderedLine.svelte';
|
||||
|
Loading…
Reference in New Issue
Block a user