Commit df5d859d authored by timel's avatar timel

Merge branch 'dev/copy-deck-to-clipboard' into 'main'

feat: copy deck to clipboard

See merge request !258
parents f0a2423d f24a07ec
import { import {
CopyOutlined,
DeleteOutlined, DeleteOutlined,
DownloadOutlined, DownloadOutlined,
FileAddOutlined, FileAddOutlined,
InboxOutlined, InboxOutlined,
PlusOutlined, PlusOutlined,
CopyOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { App, Button, Dropdown, MenuProps, Upload, UploadProps } from "antd"; import { App, Button, Dropdown, MenuProps, Upload, UploadProps } from "antd";
import React, { useRef, useState } from "react"; import React, { useRef, useState } from "react";
...@@ -20,7 +20,8 @@ export const DeckSelect: React.FC<{ ...@@ -20,7 +20,8 @@ export const DeckSelect: React.FC<{
onSelect: (deckName: string) => any; onSelect: (deckName: string) => any;
onDelete: (deckName: string) => Promise<any>; onDelete: (deckName: string) => Promise<any>;
onDownload: (deckName: string) => any; onDownload: (deckName: string) => any;
}> = ({ decks, selected, onSelect, onDelete, onDownload }) => { onCopy: (deckName: string) => Promise<any>;
}> = ({ decks, selected, onSelect, onDelete, onDownload, onCopy }) => {
const newDeck = useRef<IDeck[]>([]); const newDeck = useRef<IDeck[]>([]);
const { modal, message } = App.useApp(); const { modal, message } = App.useApp();
...@@ -130,6 +131,17 @@ export const DeckSelect: React.FC<{ ...@@ -130,6 +131,17 @@ export const DeckSelect: React.FC<{
{selected === deckName && <div className={styles.selected} />} {selected === deckName && <div className={styles.selected} />}
<span>{deckName}</span> <span>{deckName}</span>
<div className={styles.btns}> <div className={styles.btns}>
<Button
icon={<CopyOutlined />}
type="text"
size="small"
onClick={cancelBubble(async () => {
const result = await onCopy(deckName);
result
? message.success("复制成功")
: message.error("复制失败");
})}
/>
<Button <Button
icon={<DeleteOutlined />} icon={<DeleteOutlined />}
type="text" type="text"
...@@ -139,6 +151,7 @@ export const DeckSelect: React.FC<{ ...@@ -139,6 +151,7 @@ export const DeckSelect: React.FC<{
onSelect(decks[0].deckName); onSelect(decks[0].deckName);
})} })}
/> />
<Button <Button
icon={<DownloadOutlined />} icon={<DownloadOutlined />}
type="text" type="text"
......
...@@ -44,6 +44,7 @@ import { Filter } from "./Filter"; ...@@ -44,6 +44,7 @@ import { Filter } from "./Filter";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import { editDeckStore } from "./store"; import { editDeckStore } from "./store";
import { import {
copyDeckToClipboard,
downloadDeckAsYDK, downloadDeckAsYDK,
editingDeckToIDeck, editingDeckToIDeck,
iDeckToEditingDeck, iDeckToEditingDeck,
...@@ -106,6 +107,11 @@ export const Component: React.FC = () => { ...@@ -106,6 +107,11 @@ export const Component: React.FC = () => {
const deck = deckStore.get(name); const deck = deckStore.get(name);
if (deck) downloadDeckAsYDK(deck); if (deck) downloadDeckAsYDK(deck);
}} }}
onCopy={async (name) => {
const deck = deckStore.get(name);
if (deck) return await copyDeckToClipboard(deck);
else return false;
}}
/> />
</ScrollableArea> </ScrollableArea>
<HigherCardDetail /> <HigherCardDetail />
......
...@@ -36,8 +36,8 @@ export const compareCards = (a: CardMeta, b: CardMeta): number => { ...@@ -36,8 +36,8 @@ export const compareCards = (a: CardMeta, b: CardMeta): number => {
return a.id - b.id; return a.id - b.id;
}; };
/** 下载卡组YDK文件 **/ /** 生成ydk格式的卡组文本 */
export function downloadDeckAsYDK(deck: IDeck) { function genYdkText(deck: IDeck): string {
const lines: string[] = []; const lines: string[] = [];
lines.push("#created by neos"); lines.push("#created by neos");
lines.push("#main"); lines.push("#main");
...@@ -46,7 +46,12 @@ export function downloadDeckAsYDK(deck: IDeck) { ...@@ -46,7 +46,12 @@ export function downloadDeckAsYDK(deck: IDeck) {
lines.push(...deck.extra.map((cardId) => cardId.toString())); lines.push(...deck.extra.map((cardId) => cardId.toString()));
lines.push("!side"); lines.push("!side");
lines.push(...deck.side.map((cardId) => cardId.toString())); lines.push(...deck.side.map((cardId) => cardId.toString()));
const text = lines.join("\n"); return lines.join("\n");
}
/** 下载卡组YDK文件 **/
export function downloadDeckAsYDK(deck: IDeck) {
const text = genYdkText(deck);
const blob = new Blob([text], { type: "text/plain" }); const blob = new Blob([text], { type: "text/plain" });
const url = URL.createObjectURL(blob); const url = URL.createObjectURL(blob);
...@@ -58,3 +63,14 @@ export function downloadDeckAsYDK(deck: IDeck) { ...@@ -58,3 +63,14 @@ export function downloadDeckAsYDK(deck: IDeck) {
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
} }
/** 将卡组复制到剪贴板 */
export async function copyDeckToClipboard(deck: IDeck): Promise<boolean> {
const text = genYdkText(deck);
try {
await navigator.clipboard.writeText(text);
return true;
} catch (e) {
return false;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment