Skip to content

Commit 01be696

Browse files
committed
feat: new short code format for operation set
1 parent 46d18aa commit 01be696

File tree

8 files changed

+105
-30
lines changed

8 files changed

+105
-30
lines changed

src/apis/operation.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import useSWRInfinite from 'swr/infinite'
44

55
import { toCopilotOperation } from 'models/converter'
66
import { OpRatingType, Operation } from 'models/operation'
7-
import { parseShortCode } from 'models/shortCode'
7+
import { ShortCodeContent, parseShortCode } from 'models/shortCode'
88
import { OperationApi } from 'utils/maa-copilot-client'
99
import { useSWRRefresh } from 'utils/swr'
1010

@@ -48,16 +48,32 @@ export function useOperations({
4848
return null // reached the end
4949
}
5050

51-
// 用户输入 maa://xxxxxx 时,只传这个 id,其他参数都不传
51+
// 用户输入神秘代码时,只传这个 id,其他参数都不传
5252
if (keyword) {
53-
const id = parseShortCode(keyword)
53+
let content: ShortCodeContent | null = null
54+
55+
try {
56+
content = parseShortCode(keyword)
57+
} catch (e) {
58+
console.warn(e)
59+
}
60+
61+
if (content) {
62+
let error: string | undefined
63+
64+
if (content.type === 'operationSet') {
65+
error = '该神秘代码属于作业集,无法在此使用⊙﹏⊙∥'
66+
}
5467

55-
if (id) {
5668
return [
5769
'operations',
5870
{
59-
copilotIds: [id],
71+
copilotIds: [content.id],
6072
} satisfies QueriesCopilotRequest,
73+
74+
// 如果直接抛出 error 的话,useSWRInfinite 会把这个 error 吞掉,所以传到 fetcher 里再抛出
75+
// https://github.com/vercel/swr/issues/2102
76+
error,
6177
]
6278
}
6379
}
@@ -77,7 +93,11 @@ export function useOperations({
7793
} satisfies QueriesCopilotRequest,
7894
]
7995
},
80-
async ([, req]) => {
96+
async ([, req, error]) => {
97+
if (error) {
98+
throw new Error(error)
99+
}
100+
81101
// 如果指定了 id 列表,但是列表为空,就直接返回空数据。不然要是直接传空列表,就相当于没有这个参数,
82102
// 会导致后端返回所有数据
83103
if (req.copilotIds?.length === 0) {

src/components/OperationCard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Button, Card, Elevation, H4, H5, Icon, Tag } from '@blueprintjs/core'
22
import { Tooltip2 } from '@blueprintjs/popover2'
33

44
import clsx from 'clsx'
5-
import { handleCopyShortCode, handleDownloadJSON } from 'services/operation'
5+
import { copyShortCode, handleDownloadJSON } from 'services/operation'
66

77
import { ReLink } from 'components/ReLink'
88
import { RelativeTime } from 'components/RelativeTime'
@@ -263,7 +263,7 @@ const CardActions = ({
263263
<Button
264264
small
265265
icon="clipboard"
266-
onClick={() => handleCopyShortCode(operation)}
266+
onClick={() => copyShortCode(operation)}
267267
/>
268268
</Tooltip2>
269269
<Tooltip2

src/components/OperationSetCard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Button, Card, Elevation, H4, Icon, Tag } from '@blueprintjs/core'
22
import { Tooltip2 } from '@blueprintjs/popover2'
33

4-
import { handleCopyShortCode } from 'services/operation'
4+
import { copyShortCode } from 'services/operation'
55

66
import { ReLink } from 'components/ReLink'
77
import { RelativeTime } from 'components/RelativeTime'
@@ -163,7 +163,7 @@ const CardActions = ({
163163
icon="clipboard"
164164
onClick={(e) => {
165165
e.stopPropagation()
166-
handleCopyShortCode(operationSet)
166+
copyShortCode(operationSet)
167167
}}
168168
/>
169169
</Tooltip2>

src/components/editor/source/ShortCodeImporter.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,18 @@ export const ShortCodeImporter: FC<{
4141
try {
4242
setPending(true)
4343

44-
const id = parseShortCode(code)
44+
const shortCodeContent = parseShortCode(code)
4545

46-
if (!id) {
46+
if (!shortCodeContent) {
4747
throw new Error('无效的神秘代码')
4848
}
4949

50+
const { type, id } = shortCodeContent
51+
52+
if (type === 'operationSet') {
53+
throw new Error('该神秘代码属于作业集,无法在此使用⊙﹏⊙∥')
54+
}
55+
5056
const operationContent = (await getOperation({ id })).parsedContent
5157

5258
if (operationContent === INVALID_OPERATION_CONTENT) {

src/components/viewer/OperationSetViewer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
} from 'apis/operation-set'
2020
import { useAtom } from 'jotai'
2121
import { ComponentType, FC, useEffect, useState } from 'react'
22-
import { handleCopyShortCode } from 'services/operation'
22+
import { copyShortCode } from 'services/operation'
2323

2424
import { FactItem } from 'components/FactItem'
2525
import { OperationList } from 'components/OperationList'
@@ -179,7 +179,7 @@ export const OperationSetViewer: ComponentType<{
179179
icon="clipboard"
180180
text="复制神秘代码"
181181
intent="primary"
182-
onClick={() => handleCopyShortCode(operationSet)}
182+
onClick={() => copyShortCode(operationSet)}
183183
/>
184184
</>
185185
}

src/components/viewer/OperationViewer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
import { useAtom } from 'jotai'
2525
import { ComponentType, FC, useEffect, useState } from 'react'
2626
import { Link } from 'react-router-dom'
27-
import { handleCopyShortCode, handleDownloadJSON } from 'services/operation'
27+
import { copyShortCode, handleDownloadJSON } from 'services/operation'
2828

2929
import { FactItem } from 'components/FactItem'
3030
import { Paragraphs } from 'components/Paragraphs'
@@ -216,7 +216,7 @@ export const OperationViewer: ComponentType<{
216216
icon="clipboard"
217217
text="复制神秘代码"
218218
intent="primary"
219-
onClick={() => handleCopyShortCode(operation)}
219+
onClick={() => copyShortCode(operation)}
220220
/>
221221
</>
222222
}

src/models/shortCode.ts

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,44 @@
1-
import { Operation } from './operation'
1+
/*
2+
* operation: maa://123456
3+
* operationSet: maa://c123456
4+
*/
25

3-
export const shortCodeScheme = 'maa://'
6+
const shortCodeScheme = 'maa://'
47

5-
export function toShortCode(id: Operation['id']) {
6-
return shortCodeScheme + id
8+
export interface ShortCodeContent {
9+
id: number
10+
type: 'operation' | 'operationSet'
711
}
812

9-
export function parseShortCode(code: string): number | null {
13+
export function toShortCode({ id, type }: ShortCodeContent) {
14+
if (type === 'operation') {
15+
return shortCodeScheme + id
16+
} else if (type === 'operationSet') {
17+
return shortCodeScheme + 'c' + id
18+
}
19+
throw new Error('无效的神秘代码类型')
20+
}
21+
22+
export function parseShortCode(code: string): ShortCodeContent | null {
1023
if (code.startsWith(shortCodeScheme)) {
11-
return +code.slice(shortCodeScheme.length) || null
24+
const idStr = code.slice(shortCodeScheme.length)
25+
let content: ShortCodeContent
26+
27+
if (idStr.startsWith('c')) {
28+
content = {
29+
id: +idStr.slice(1),
30+
type: 'operationSet',
31+
}
32+
} else {
33+
content = {
34+
id: +idStr,
35+
type: 'operation',
36+
}
37+
}
38+
39+
if (!isNaN(content.id)) {
40+
return content
41+
}
1242
}
1343
return null
1444
}

src/services/operation.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { AppToaster } from 'components/Toaster'
22

33
import { CopilotDocV1 } from '../models/copilot.schema'
4-
import { toShortCode } from '../models/shortCode'
4+
import { ShortCodeContent, toShortCode } from '../models/shortCode'
5+
import { formatError } from '../utils/error'
56
import { snakeCaseKeysUnicode } from '../utils/object'
67

78
export const handleDownloadJSON = (operationDoc: CopilotDocV1.Operation) => {
@@ -28,12 +29,30 @@ export const handleDownloadJSON = (operationDoc: CopilotDocV1.Operation) => {
2829
})
2930
}
3031

31-
export const handleCopyShortCode = (operation: { id: number }) => {
32-
const shortCode = toShortCode(operation.id)
33-
navigator.clipboard.writeText(shortCode)
32+
/**
33+
* @param target - Either an operation or an operation set
34+
*/
35+
export const copyShortCode = async (target: {
36+
id: number
37+
copilotIds?: number[]
38+
}) => {
39+
try {
40+
const content: ShortCodeContent = {
41+
id: target.id,
42+
type: target.copilotIds ? 'operationSet' : 'operation',
43+
}
3444

35-
AppToaster.show({
36-
message: '已复制神秘代码,前往 MAA 粘贴即可使用~',
37-
intent: 'success',
38-
})
45+
const shortCode = toShortCode(content)
46+
navigator.clipboard.writeText(shortCode)
47+
48+
AppToaster.show({
49+
message: '已复制神秘代码,前往 MAA 粘贴即可使用~',
50+
intent: 'success',
51+
})
52+
} catch (e) {
53+
AppToaster.show({
54+
message: '复制神秘代码失败:' + formatError(e),
55+
intent: 'danger',
56+
})
57+
}
3958
}

0 commit comments

Comments
 (0)