ソースを参照

impl ydke share

Mistivia 1 ヶ月 前
コミット
ea9350a570

+ 20 - 1
src/components/MainPanel.svelte

@@ -1,7 +1,12 @@
 <script lang="js">
     import CardThumb from './CardThumb.svelte';
     import { deck, setDeck } from '../control/deck';
-    import { parseYdk, genYdk, downloadStringAsFile} from '../utils'
+    import {
+        parseYdk,
+        genYdk,
+        genYdke,
+        downloadStringAsFile,
+    } from '../utils';
 
     let fileInput;
     
@@ -26,6 +31,19 @@
         downloadStringAsFile('mydeck.ydk', deckString)
     }
 
+    function shareDeck() {
+        let url = window.location.href;
+        url = url.split('#')[0]
+        url = url + '#' + genYdke($deck);
+        navigator.clipboard.writeText(url)
+            .then(() => {
+              alert('分享链接已复制到剪贴板')
+            })
+            .catch(err => {
+              alert("失败!");
+            });
+    }
+
 </script>
 
 <input bind:this={fileInput} style="display:none;" onchange={loadDeck} type="file" class="file-input" accept=".ydk" />
@@ -34,6 +52,7 @@
     <div class="control-bar">
         <button class="btn" onclick={openDeck}>打开</button>
         <button class="btn" onclick={saveDeck}>保存</button>
+        <button class="btn" onclick={shareDeck}>分享</button>
     </div>
     <div class="deck-section">
         <div class="deck-group">

+ 12 - 7
src/components/RightPanel.svelte

@@ -1,9 +1,14 @@
-<script lang="ts">
+<script lang="js">
+    import CardThumb from './CardThumb.svelte';
+    import { resultCards } from '../control/search'
 
-import CardThumb from './CardThumb.svelte';
+    function onPrevPage() {
 
-let cardList = $state([]);
+    }
 
+    function onNextPage() {
+        
+    }
 </script>
 
 <div class="right-panel">
@@ -11,9 +16,9 @@ let cardList = $state([]);
         <input type="text" placeholder="搜索卡牌...">
     </div>
     <div class="card-list">
-        {#if cardList.length > 0}
+        {#if $resultCards.length > 0}
             <div class="card-item">
-                {#each cardList as card}
+                {#each $resultCards as card}
                     <div class="card-thumbnail">
                         <CardThumb id= {card.id} />
                     </div>
@@ -23,8 +28,8 @@ let cardList = $state([]);
         {/if}
     </div>
     <div class="pagination">
-        <button class="page-btn">上一页</button>
-        <button class="page-btn">下一页</button>
+        <button class="page-btn" onclick={onPrevPage}>上一页</button>
+        <button class="page-btn" onclick={onNextPage}>下一页</button>
     </div>
 </div>
 

+ 26 - 1
src/control/deck.js

@@ -1,11 +1,36 @@
 import { writable } from "svelte/store";
+import { parseYdke } from '../utils';
 
 let deck = writable({main: [], extra: [], side: []});
 
-let setDeck = (d) => {
+function setDeck(d) {
+    d.main.sort();
+    d.extra.sort();
+    d.side.sort();
     deck.set(d);
+    localStorage.setItem('cachedDeck', JSON.stringify(d));
 };
 
+function initDeck() {
+    let url = window.location.href.split('#');
+    if (url.length === 2) {
+        let deck = parseYdke(url[1]);
+        if (deck.main.length > 0 || deck.extra.length > 0 || deck.extra.length > 0) {
+            setDeck(deck);
+            window.location.replace("/");
+            return;
+        }
+    }
+    let cachedDeck = localStorage.getItem('cachedDeck');
+    if (cachedDeck !== null) {
+        cachedDeck = JSON.parse(cachedDeck); 
+        setDeck(cachedDeck)
+        return;
+    }
+}
+
+initDeck();
+
 export {
     deck,
     setDeck,

+ 7 - 0
src/control/search.js

@@ -0,0 +1,7 @@
+import { writable } from 'svelte/store';
+
+let resultCards = writable([]);
+
+export {
+    resultCards,
+};

+ 46 - 0
src/utils.js

@@ -55,10 +55,56 @@ function downloadStringAsFile(filename, text) {
     URL.revokeObjectURL(link.href);
 }
 
+function ydkeEncode(d) {
+    let deck = [];
+    for (let card of d) {
+        let num = parseInt(card);
+        if (isNaN(num)) continue;
+        deck.push(num);
+    }
+    const buffer = new ArrayBuffer(deck.length * 4);
+    const view = new DataView(buffer);
+    for (let i = 0; i < deck.length; i++) {
+        // Little-endian
+        view.setUint32(i * 4, deck[i], true);
+    }
+    return btoa(String.fromCharCode(...new Uint8Array(buffer)));
+}
+
+function ydkeDecode(encodedDeck) {
+    const binaryString = atob(encodedDeck);
+    const buffer = new ArrayBuffer(binaryString.length);
+    const view = new DataView(buffer);
+    for (let i = 0; i < binaryString.length; i++) {
+        view.setUint8(i, binaryString.charCodeAt(i));
+    }
+    const deck = [];
+    for (let i = 0; i < buffer.byteLength; i += 4) {
+        deck.push(String(view.getUint32(i, true))); // Little-endian
+    }
+    return deck;
+}
+
+function parseYdke(ydkeString) {
+    const [mainEncoded, extraEncoded, sideEncoded] = ydkeString.split('!');
+    const main = ydkeDecode(mainEncoded);
+    const extra = ydkeDecode(extraEncoded);
+    const side = ydkeDecode(sideEncoded);
+    return { main, extra, side };
+}
+
+function genYdke(deck) {
+    const mainEncoded = ydkeEncode(deck.main);
+    const extraEncoded = ydkeEncode(deck.extra);
+    const sideEncoded = ydkeEncode(deck.side);
+    return `${mainEncoded}!${extraEncoded}!${sideEncoded}`;
+}
 
 export {
     parseYdk,
     genYdk,
+    parseYdke,
+    genYdke,
     downloadStringAsFile,
 };