Skip to content

Commit ac2050e

Browse files
committed
fix -- properly implement drag reordering
1 parent 5f1c8ff commit ac2050e

5 files changed

Lines changed: 65 additions & 30 deletions

File tree

src/parts/subtitle.ghost.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ interface Props {
99
dragging: DraggingData;
1010
}
1111
12-
let { dragging }: Props = $props();
12+
let { dragging = $bindable() }: Props = $props();
1313
1414
</script>
1515

1616

1717
<div
1818
class="ghost subtitle"
19-
class:haunting={dragging.grabbed}
19+
class:haunting={dragging.sub_id}
2020
bind:this={dragging.ghost}
2121
style:top="{dragging.mouse_y + dragging.offset_y - dragging.layer_y}px"
2222
>

src/parts/subtitle.svelte

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { slide } from "svelte/transition";
1515
import { expoOut } from "svelte/easing";
1616
1717
import { getContext } from "svelte";
18-
import { json } from "@sveltejs/kit";
1918
2019
2120
interface Props {
@@ -33,7 +32,7 @@ let self: HTMLElement;
3332
3433
function onmousedown(e: MouseEvent)
3534
{
36-
dragging.grabbed = self;
35+
dragging.sub_id = subtitle.id;
3736
3837
if (dragging.ghost) {
3938
dragging.ghost.innerHTML = self.innerHTML;
@@ -48,17 +47,22 @@ function onmouseenter(e: MouseEvent)
4847
{
4948
e.stopPropagation();
5049
51-
if (
52-
dragging.grabbed
53-
&& e.target != dragging.grabbed
54-
&& e.target?.classList.contains("subtitle")
55-
) {
56-
$subtitles.reorder_before_by_id(
57-
parseInt(dragging.grabbed.dataset.subtitleId),
58-
parseInt(e.target.dataset.subtitleId)
59-
);
60-
$subtitles.subs = $subtitles.subs;
50+
console.log("dragging.sub_id =", dragging.sub_id);
51+
console.log("subtitle.id =", subtitle.id);
52+
53+
if (!dragging.sub_id || dragging.sub_id === subtitle.id) return;
54+
55+
// console.log("$subtitles.subs.before =", $subtitles.subs.map(sub => `${sub.id}-${sub.body}`));
56+
if (dragging.direction === "up") {
57+
$subtitles.reorder_before_by_id(dragging.sub_id, subtitle.id);
58+
} else {
59+
$subtitles.reorder_after_by_id(dragging.sub_id, subtitle.id);
6160
}
61+
// console.log("$subtitles.subs.after =", $subtitles.subs.map(sub => `${sub.id}-${sub.body}`));
62+
$subtitles.subs = $subtitles.subs;
63+
64+
dragging.reordering_id = subtitle.id;
65+
requestAnimationFrame(() => { dragging.reordering_id = null; });
6266
}
6367
6468
@@ -94,11 +98,10 @@ function get(
9498
<!-- svelte-ignore a11y_no_static_element_interactions -->
9599
<div
96100
class="subtitle"
97-
class:grabbed={dragging.grabbed?.dataset.subtitleId === subtitle.id.toString()}
101+
class:grabbed={dragging.sub_id === subtitle.id}
98102
bind:this={self}
99103
{onmousedown}
100104
{onmouseenter}
101-
data-subtitle-id={subtitle.id}
102105
transition:slide={{ duration: 400, easing: expoOut }}
103106
>
104107
<div class="grabber">

src/routes/+page.svelte

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import "#styles/essence.scss";
55
import SubtitlesView from "./subtitles-view.svelte";
66
import Preview from "./preview.svelte";
77
8-
98
</script>
109

1110

src/routes/subtitles-view.svelte

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@
22

33
<script module>
44
5+
import type { Int } from "#scripts/types";
6+
57
export interface DraggingData {
6-
root: HTMLElement | null,
7-
grabbed: HTMLElement | null,
8-
ghost: HTMLElement | null,
8+
root: HTMLElement | null;
9+
ghost: HTMLElement | null;
10+
11+
sub_id: Int | null;
12+
reordering_id: Int | null;
13+
14+
direction: "up" | "down";
15+
mouse_y_previous: number;
916
10-
mouse_y: number,
11-
offset_y: number,
12-
layer_y: number,
17+
mouse_y: number;
18+
offset_y: number;
19+
layer_y: number;
1320
}
1421
1522
</script>
@@ -29,9 +36,14 @@ import { expoOut } from "svelte/easing";
2936
3037
let dragging: DraggingData = $state({
3138
root: null,
32-
grabbed: null,
3339
ghost: null,
3440
41+
sub_id: null,
42+
reordering_id: null,
43+
44+
direction: "down",
45+
mouse_y_previous: 0,
46+
3547
mouse_y: 0,
3648
offset_y: 0,
3749
layer_y: 0,
@@ -51,16 +63,24 @@ function onmousemove(e: MouseEvent)
5163
{
5264
e.stopPropagation();
5365
54-
if (dragging.grabbed) {
66+
if (dragging.sub_id) {
67+
dragging.mouse_y_previous = dragging.mouse_y;
5568
dragging.mouse_y = e.clientY;
5669
dragging.layer_y = self.getBoundingClientRect().y;
70+
71+
if (dragging.mouse_y < dragging.mouse_y_previous) {
72+
dragging.direction = "up";
73+
} else {
74+
dragging.direction = "down";
75+
}
5776
}
5877
}
5978
6079
function onmouseup(e: MouseEvent)
6180
{
6281
e.stopPropagation();
63-
dragging.grabbed = null;
82+
dragging.sub_id = null;
83+
dragging.reordering_id = null;
6484
}
6585
6686
</script>
@@ -72,7 +92,7 @@ function onmouseup(e: MouseEvent)
7292
{onmousemove}
7393
{onmouseup}
7494
>
75-
<SubtitleGhost {dragging} />
95+
<SubtitleGhost bind:dragging />
7696

7797
{#each $subtitles.subs as sub, index (sub.id)}
7898
<div animate:flip={{ duration: 500, easing: expoOut }}>

src/scripts/stores/subtitles-data.svelte.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@ export class SubtitlesData
3636
}
3737

3838
/** Change the ordering of one subtitle to a new index in the list. */
39-
reorder_to_by_idx(index: Int, new_index: Int): boolean
39+
reorder_to_by_idx(index: Int, new_index: Int, correct?: boolean): boolean
4040
{
41+
let idx = new_index - (index < new_index && correct ? 1 : 0);
4142
let sub = this.subs.splice(index, 1)[0];
42-
this.subs.splice(new_index, 0, sub);
43+
this.subs.splice(idx, 0, sub);
4344

4445
return true;
4546
}
@@ -52,7 +53,18 @@ export class SubtitlesData
5253
let j = this.subs.findIndex(sub => sub.id === target_id);
5354
if (j === -1) return false;
5455

55-
return this.reorder_to_by_idx(i, j);
56+
return this.reorder_to_by_idx(i, j, true);
57+
}
58+
59+
reorder_after_by_id(subtitle_id: Int, target_id: Int): boolean
60+
{
61+
let i = this.subs.findIndex(sub => sub.id === subtitle_id);
62+
if (i === -1) return false;
63+
64+
let j = this.subs.findIndex(sub => sub.id === target_id);
65+
if (j === -1) return false;
66+
67+
return this.reorder_to_by_idx(i, j, false);
5668
}
5769

5870
/** Delete the given `subtitle`. */
@@ -107,6 +119,7 @@ export class SubtitlesData
107119
let data = JSON.parse(json);
108120

109121
let out = new SubtitlesData();
122+
/* @ts-ignore */
110123
out.subs = data.subtitles?.map(sub => Subtitle.from_json(sub)) ?? out.subs;
111124

112125
return out;

0 commit comments

Comments
 (0)