Create new branches through dedicated dropzone

This commit is contained in:
Mattias Granlund 2023-06-17 16:06:44 +01:00
parent 19eeadfd65
commit daf296c647
4 changed files with 93 additions and 11 deletions

View File

@ -74,7 +74,7 @@
"reflect-metadata": "^0.1.13",
"svelte": "~3.55.1",
"svelte-check": "^3.0.1",
"svelte-dnd-action": "github:gitbutlerapp/svelte-dnd-action#0d9263ffd8bfb2fb11877ba91732a80070848505",
"svelte-dnd-action": "github:gitbutlerapp/svelte-dnd-action#daeabaf6b34207c4ff6c487c0eb090b4bc6032c5",
"svelte-floating-ui": "^1.5.2",
"svelte-french-toast": "^1.0.3",
"svelte-loadable-store": "^1.2.3",

View File

@ -176,8 +176,8 @@ devDependencies:
specifier: ^3.0.1
version: 3.0.3(postcss-load-config@4.0.1)(postcss@8.4.21)(svelte@3.55.1)
svelte-dnd-action:
specifier: github:gitbutlerapp/svelte-dnd-action#0d9263ffd8bfb2fb11877ba91732a80070848505
version: github.com/gitbutlerapp/svelte-dnd-action/0d9263ffd8bfb2fb11877ba91732a80070848505(svelte@3.55.1)
specifier: github:gitbutlerapp/svelte-dnd-action#daeabaf6b34207c4ff6c487c0eb090b4bc6032c5
version: github.com/gitbutlerapp/svelte-dnd-action/daeabaf6b34207c4ff6c487c0eb090b4bc6032c5(svelte@3.55.1)
svelte-floating-ui:
specifier: ^1.5.2
version: 1.5.2
@ -4290,9 +4290,9 @@ packages:
engines: {node: '>=10'}
dev: true
github.com/gitbutlerapp/svelte-dnd-action/0d9263ffd8bfb2fb11877ba91732a80070848505(svelte@3.55.1):
resolution: {tarball: https://codeload.github.com/gitbutlerapp/svelte-dnd-action/tar.gz/0d9263ffd8bfb2fb11877ba91732a80070848505}
id: github.com/gitbutlerapp/svelte-dnd-action/0d9263ffd8bfb2fb11877ba91732a80070848505
github.com/gitbutlerapp/svelte-dnd-action/daeabaf6b34207c4ff6c487c0eb090b4bc6032c5(svelte@3.55.1):
resolution: {tarball: https://codeload.github.com/gitbutlerapp/svelte-dnd-action/tar.gz/daeabaf6b34207c4ff6c487c0eb090b4bc6032c5}
id: github.com/gitbutlerapp/svelte-dnd-action/daeabaf6b34207c4ff6c487c0eb090b4bc6032c5
name: svelte-dnd-action
version: 0.9.22
peerDependencies:

View File

@ -1,18 +1,21 @@
<script lang="ts">
import { flip } from 'svelte/animate';
import { dndzone } from 'svelte-dnd-action';
import Lane from './BranchLane.svelte';
import { Branch, File, Hunk } from './types';
import type { DndEvent } from 'svelte-dnd-action/typings';
import { createBranch, createFile } from './helpers';
import { createEventDispatcher } from 'svelte';
import NewBranchDropZone from './NewBranchDropZone.svelte';
export let branches: Branch[];
const flipDurationMs = 300;
const dispatch = createEventDispatcher();
const newBranchClass = 'new-branch-active';
function handleDndEvent(e: CustomEvent<DndEvent<Branch | File | Hunk>>) {
if (e.type == 'consider' && !e.detail.info.types?.includes('branch')) {
return; // No shadow element while considering drop.
}
const newItems = e.detail.items;
const branchItems = newItems.filter((item) => item instanceof Branch) as Branch[];
@ -33,6 +36,10 @@
}
}
function handleNewBranch(e: CustomEvent<Branch[]>) {
branches.push(...e.detail);
}
function handleEmpty() {
const emptyIndex = branches.findIndex((item) => !item.files || item.files.length == 0);
if (emptyIndex != -1) {
@ -42,18 +49,33 @@
</script>
<section
class="swimlane-container flex h-full w-full snap-x gap-x-4 overflow-x-scroll bg-zinc-900 p-4"
id="branch-lanes"
class="flex h-full snap-x gap-x-4 overflow-x-scroll bg-zinc-900 p-4"
use:dndzone={{
items: branches,
types: ['branch'],
receives: ['branch']
receives: ['branch', 'file', 'hunk'],
dropTargetClassMap: {
file: [newBranchClass],
hunk: [newBranchClass]
}
}}
on:consider={handleDndEvent}
on:finalize={handleDndEvent}
>
{#each branches.filter((c) => c.active) as { id, name, files, description } (id)}
<div class="swimlane flex h-full w-96 snap-start scroll-ml-4 rounded-lg bg-zinc-900">
<div
id="branch-{id}"
class="branch flex h-full w-96 snap-start scroll-ml-4 rounded-lg bg-zinc-900"
>
<Lane {name} {description} bind:files on:empty={handleEmpty} />
</div>
{/each}
<NewBranchDropZone on:finalize={handleNewBranch} />
</section>
<style lang="postcss">
:global(#branch-lanes.new-branch-active [data-dnd-ignore]) {
@apply visible flex;
}
</style>

View File

@ -0,0 +1,60 @@
<script lang="ts">
import { dndzone } from 'svelte-dnd-action';
import { Branch, File, Hunk } from './types';
import type { DndEvent } from 'svelte-dnd-action/typings';
import { createBranch, createFile } from './helpers';
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
let items: Branch[] = [];
function handleDndFinalize(e: CustomEvent<DndEvent<Branch | File | Hunk>>) {
console.log(e);
const newItems = e.detail.items;
const branchItems = newItems.filter((item) => item instanceof Branch) as Branch[];
const hunkItems = newItems.filter((item) => item instanceof Hunk) as Hunk[];
for (const hunk of hunkItems) {
branchItems.push(createBranch(createFile(hunk.filePath, hunk)));
}
const fileItems = newItems.filter((item) => item instanceof File) as File[];
for (const file of fileItems) {
branchItems.push(createBranch(file));
}
if (e.type == 'finalize') {
dispatch('finalize', branchItems);
items = [];
return;
}
items = branchItems;
}
</script>
<section
id="new-branch-dz"
class="invisible flex h-full items-center bg-zinc-900"
use:dndzone={{
items: items,
types: ['new-branch'],
receives: ['file', 'hunk'],
dropTargetClassMap: {
file: ['new-branch-active'],
hunk: ['new-branch-active']
}
}}
on:finalize={handleDndFinalize}
>
<div
class="h-full w-64 items-center rounded-lg border border-dashed bg-zinc-800 p-8 text-center text-xl font-bold"
>
drop here to create a new branch
</div>
</section>
<style lang="postcss">
:global(#new-branch-dz.new-branch-active) {
@apply visible flex;
}
</style>