From de8814ced2e1624d3b87423a6ac971c12f117921 Mon Sep 17 00:00:00 2001
From: Mistivia <i@mistivia.com>
Date: Sun, 9 Feb 2025 16:33:44 +0800
Subject: support custom card order

---
 src/components/CardThumb.svelte  |  5 +--
 src/components/MainPanel.svelte  | 50 ++++++++++----------------
 src/components/RightPanel.svelte |  4 +--
 src/control/deck.js              | 78 ++++++++++++++++------------------------
 4 files changed, 54 insertions(+), 83 deletions(-)

diff --git a/src/components/CardThumb.svelte b/src/components/CardThumb.svelte
index be6af81..2f722a9 100644
--- a/src/components/CardThumb.svelte
+++ b/src/components/CardThumb.svelte
@@ -3,20 +3,21 @@
     import {setLeftPanelCard} from '../control/left_panel';
     import { cardImageUrl } from '../utils';
 
-    let {id, area} = $props();
+    let {id, area, idx} = $props();
 
     function onhover() {
         setLeftPanelCard(id); 
     }
 
     function onDragStart(e) {
-        e.dataTransfer.setData('text', JSON.stringify({id, area}))
+        e.dataTransfer.setData('text', JSON.stringify({id, area, idx}))
     }
 
 </script>
 
 {#if id}
     <img
+        style="margin:2px;"
         draggable="true"
         onmouseover={onhover}
         onfocus={onhover}
diff --git a/src/components/MainPanel.svelte b/src/components/MainPanel.svelte
index f9f0d74..2d89b68 100644
--- a/src/components/MainPanel.svelte
+++ b/src/components/MainPanel.svelte
@@ -55,32 +55,21 @@
             });
     }
 
-    function onDrop(to, event) {
+    function onDrop(to, event, targetIdx) {
         event.preventDefault();
+        event.stopPropagation();
         const data = JSON.parse(event.dataTransfer.getData('text'));
         let from = data.area;
         if (from === 'search') {
             if (to === 'main') {
-                deckOps.add2main(data.id);
+                deckOps.add2main(data.id, targetIdx);
             } else if (to === 'side') {
-                deckOps.add2side(data.id);
+                deckOps.add2side(data.id, targetIdx);
             } else if (to === 'extra') {
-                deckOps.add2extra(data.id);
-            }
-        } else if (from === 'main') {
-            if (to == 'side') {
-                deckOps.main2side(data.id);
-            }
-        } else if (from === 'extra') {
-            if (to == 'side') {
-                deckOps.extra2side(data.id);
-            }
-        } else if (from === 'side') {
-            if (to == 'main') {
-                deckOps.side2main(data.id);
-            } else if (to == 'extra') {
-                deckOps.side2extra(data.id);
+                deckOps.add2extra(data.id, targetIdx);
             }
+        } else {
+            deckOps.move(from, to, data.idx, targetIdx);
         }
     }
 
@@ -99,30 +88,30 @@
     <div class="deck-section">
         <div class="deck-group">
             <h3>主卡组（{$deck.main.length}）</h3>
-            <div role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("main", e)} class="card-grid main-deck">
-                {#each $deck.main as card}
-                    <div class="card-grid-thumb">
-                        <CardThumb id={card} area="main" />
+            <div role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("main", e, -1)} class="card-grid main-deck">
+                {#each $deck.main as card, i}
+                    <div class="card-grid-thumb" role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("main", e, i)}>
+                        <CardThumb id={card} idx={i} area="main" />
                     </div>
                 {/each}
             </div>
         </div>
         <div class="deck-group">
             <h3>额外卡组（{$deck.extra.length}）</h3>
-            <div role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("extra", e)} class="card-grid extra-deck">
-                {#each $deck.extra as card}
-                    <div class="card-grid-thumb">
-                        <CardThumb id={card} area="extra" />
+            <div role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("extra", e, -1)} class="card-grid extra-deck">
+                {#each $deck.extra as card, i}
+                    <div class="card-grid-thumb" role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("extra", e, i)}>
+                        <CardThumb id={card} idx={i} area="extra" />
                     </div>
                 {/each}
             </div>
         </div>
         <div class="deck-group">
             <h3>副卡组（{$deck.side.length}）</h3>
-            <div role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("side", e)} class="card-grid side-deck">
-                {#each $deck.side as card}
-                    <div class="card-grid-thumb">
-                        <CardThumb id={card} area="side" />
+            <div role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("side", e, -1)} class="card-grid side-deck">
+                {#each $deck.side as card, i}
+                    <div class="card-grid-thumb" role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("side", e, i)}>
+                        <CardThumb id={card} idx={i} area="side" />
                     </div>
                 {/each}
             </div>
@@ -165,7 +154,6 @@
 .card-grid {
     display: grid;
     grid-template-columns: repeat(auto-fill, minmax(52px, 1fr));
-    gap: 5px;
     grid-auto-flow: dense;
     overflow-y: auto;
     padding: 10px;
diff --git a/src/components/RightPanel.svelte b/src/components/RightPanel.svelte
index 03cc272..c9904fa 100644
--- a/src/components/RightPanel.svelte
+++ b/src/components/RightPanel.svelte
@@ -11,7 +11,7 @@
         event.preventDefault();
         const data = JSON.parse(event.dataTransfer.getData('text'));
         if (data.area === 'main' || data.area === 'side' || data.area === 'extra') {
-            deckOps.deleteCard(data.area, data.id);
+            deckOps.deleteCard(data.area, data.idx);
         }
     }
 </script>
@@ -24,7 +24,7 @@
            {#each $showingCards as card}
                <div class="card-item">
                    <div class="card-thumbnail">
-                       <CardThumb id= {card.id} area="search" />
+                       <CardThumb id={card.id} idx={-1} area="search" />
                    </div>
                    <span>{card.name}</span>
                </div>
diff --git a/src/control/deck.js b/src/control/deck.js
index ab46a02..ba6a1ff 100644
--- a/src/control/deck.js
+++ b/src/control/deck.js
@@ -19,10 +19,6 @@ function setDeck(d) {
     d.main = sanitizeDeck(d.main);
     d.side = sanitizeDeck(d.side);
     d.extra = sanitizeDeck(d.extra);
-    let sortFn = (a, b) => {return cardDb[a].cid - cardDb[b].cid;}
-    d.main.sort(sortFn);
-    d.extra.sort(sortFn);
-    d.side.sort(sortFn);
     deckState = d;
     deck.set(d);
     localStorage.setItem('cachedDeck', JSON.stringify(d));
@@ -43,75 +39,61 @@ function canAdd(d, id) {
     return true;
 }
 
-function delCard(deck, id) {
-    for (let i = 0; i < deck.length; i++) {
-        if (deck[i] == id) {
-            deck.splice(i, 1);
-            return true;
-        }
-    }
-    return false;
-}
-
 let deckOps = {
-    "deleteCard": (from, id) => {
+    "deleteCard": (from, idx) => {
         if (from === 'main') {
-            delCard(deckState.main, id);
+            deckState.main.splice(idx, 1);
             setDeck(deckState);
         } else if (from === 'side') {
-            delCard(deckState.side, id);
+            deckState.side.splice(idx, 1);
             setDeck(deckState);
         } else if (from === 'extra') {
-            delCard(deckState.extra, id);
+            deckState.extra.splice(idx, 1);
             setDeck(deckState);
         }
     },
-    "main2side": (id) => {
-        if (delCard(deckState.main, id)) {
-            deckState.side.push(id);
-        }
-        setDeck(deckState);
-    },
-    "extra2side": (id) => {
-        if (delCard(deckState.extra, id)) {
-            deckState.side.push(id);
-        }
-        setDeck(deckState);
-    },
-    "side2main": (id) => {
-        if (cardDb[id].isExtra) return;
-        if (delCard(deckState.side, id)) {
-            deckState.main.push(id);
-        }
-        setDeck(deckState);
-    },
-    "side2extra": (id) => {
-        if (!cardDb[id].isExtra) return;
-        if (delCard(deckState.side, id)) {
-            deckState.extra.push(id);
-        }
+    "move": (from, to, fromIdx, toIdx) => {
+        let id = deckState[from][fromIdx];
+        if (cardDb[id].isExtra && to === 'main') return;
+        if (!cardDb[id].isExtra && to === 'extra') return;
+        deckState[from].splice(fromIdx, 1);
+        if (toIdx === -1) deckState[to].push(id);
+        else deckState[to].splice(toIdx, 0, id);
         setDeck(deckState);
     },
-    "add2extra": (id) => {
+    "add2extra": (id, targetIdx) => {
         if (!cardDb[id].isExtra) return;
         let d = deckState;
         if (canAdd(d, id)) {
-            d.extra.push(id);
+            if (targetIdx === -1) 
+                d.extra.push(id);
+            else {
+                d.extra.splice(targetIdx, 0, id);
+            }
             setDeck(d);
         }
     },
-    "add2main": (id) => {
+    "add2main": (id, targetIdx) => {
+        console.log(targetIdx);
         if (cardDb[id].isExtra) return;
         let d = deckState;
         if (canAdd(d, id)) {
-            d.main.push(id);
+            if (targetIdx === -1) 
+                d.main.push(id);
+            else {
+                d.main.splice(targetIdx, 0, id);
+            }
             setDeck(d);
         }
     },
-    "add2side": (id) => {
+    "add2side": (id, targetIdx) => {
         let d = deckState;
         if (canAdd(d, id)) {
-            d.side.push(id);
+            if (targetIdx === -1) 
+                d.side.push(id);
+            else {
+                d.side.splice(targetIdx, 0, id);
+            }
             setDeck(d);
         }
     }
-- 
cgit v1.0

