@@ -18,7 +18,7 @@ import { requestDeleteOperation } from 'apis/copilotOperation'
18
18
import { useOperation } from 'apis/query'
19
19
import { apiPostRating } from 'apis/rating'
20
20
import { useAtom } from 'jotai'
21
- import { merge } from 'lodash-es'
21
+ import { noop } from 'lodash-es'
22
22
import { ComponentType , FC , useMemo , useState } from 'react'
23
23
import { Link } from 'react-router-dom'
24
24
@@ -118,7 +118,6 @@ export const OperationViewer: ComponentType<{
118
118
const levels = useLevels ( ) ?. data ?. data || [ ]
119
119
120
120
const [ auth ] = useAtom ( authAtom )
121
- const authed = ! ! auth . token
122
121
123
122
// make eslint happy: we got Suspense out there
124
123
if ( ! operation ) return null
@@ -129,15 +128,12 @@ export const OperationViewer: ComponentType<{
129
128
)
130
129
}
131
130
132
- const handleCopyShortCode = ( ) => {
133
- if ( ! operation ?. id ) {
134
- AppToaster . show ( {
135
- message : '获取作业失败' ,
136
- intent : 'danger' ,
137
- } )
138
- return
139
- }
131
+ const operationDoc = useMemo (
132
+ ( ) => toCopilotOperation ( operation ) ,
133
+ [ operation ] ,
134
+ )
140
135
136
+ const handleCopyShortCode = ( ) => {
141
137
const shortCode = toShortCode ( operation . id )
142
138
navigator . clipboard . writeText ( shortCode )
143
139
@@ -148,22 +144,15 @@ export const OperationViewer: ComponentType<{
148
144
}
149
145
150
146
const handleDownloadJSON = ( ) => {
151
- const content = operation ?. content
152
- if ( ! content ) {
153
- AppToaster . show ( {
154
- message : '获取作业失败' ,
155
- intent : 'danger' ,
156
- } )
157
- return
158
- }
159
-
160
- const blob = new Blob ( [ content ] , {
147
+ // pretty print the JSON
148
+ const json = JSON . stringify ( operationDoc , null , 2 )
149
+ const blob = new Blob ( [ json ] , {
161
150
type : 'application/json' ,
162
151
} )
163
152
const url = URL . createObjectURL ( blob )
164
153
const link = document . createElement ( 'a' )
165
154
link . href = url
166
- link . download = `MAACopilot_作业 ${ operation . id } .json`
155
+ link . download = `MAACopilot_ ${ operationDoc . doc . title } .json`
167
156
link . click ( )
168
157
URL . revokeObjectURL ( url )
169
158
@@ -174,35 +163,20 @@ export const OperationViewer: ComponentType<{
174
163
}
175
164
176
165
const handleRating = async ( decision : OpRatingType ) => {
177
- if ( ! authed ) {
178
- AppToaster . show ( {
179
- message : '请先登录' ,
180
- intent : 'warning' ,
181
- } )
182
- return
166
+ // cancel rating if already rated by the same type
167
+ if ( decision === operation . ratingType ) {
168
+ decision = OpRatingType . None
183
169
}
184
170
185
- mutate ( async ( val ) => {
186
- try {
187
- return await wrapErrorMessage (
188
- ( e : NetworkError ) => `提交评分失败:${ e . message } ` ,
189
- ( async ( ) => {
190
- const response = await apiPostRating ( operationId , decision )
191
-
192
- return merge ( val , response )
193
- } ) ( ) ,
194
- )
195
- } catch ( e ) {
171
+ wrapErrorMessage (
172
+ ( e : NetworkError ) => `提交评分失败:${ e . message } ` ,
173
+ mutate ( async ( val ) => {
174
+ await apiPostRating ( operationId , decision )
196
175
return val
197
- }
198
- } )
176
+ } ) ,
177
+ ) . catch ( noop )
199
178
}
200
179
201
- const operationDoc = useMemo (
202
- ( ) => toCopilotOperation ( operation ) ,
203
- [ operation ] ,
204
- )
205
-
206
180
return (
207
181
< OperationDrawer
208
182
title = {
@@ -274,24 +248,24 @@ export const OperationViewer: ComponentType<{
274
248
< Button
275
249
icon = "thumbs-up"
276
250
intent = {
277
- operation ? .ratingType === OpRatingType . Like
251
+ operation . ratingType === OpRatingType . Like
278
252
? 'success'
279
253
: 'none'
280
254
}
281
255
className = "mr-2"
282
- active = { operation ? .ratingType === OpRatingType . Like }
256
+ active = { operation . ratingType === OpRatingType . Like }
283
257
onClick = { ( ) => handleRating ( OpRatingType . Like ) }
284
258
/>
285
259
</ Tooltip2 >
286
260
< Tooltip2 content = " ヽ(。>д<)p" placement = "bottom" >
287
261
< Button
288
262
icon = "thumbs-down"
289
263
intent = {
290
- operation ? .ratingType === OpRatingType . Dislike
264
+ operation . ratingType === OpRatingType . Dislike
291
265
? 'danger'
292
266
: 'none'
293
267
}
294
- active = { operation ? .ratingType === OpRatingType . Dislike }
268
+ active = { operation . ratingType === OpRatingType . Dislike }
295
269
onClick = { ( ) => handleRating ( OpRatingType . Dislike ) }
296
270
/>
297
271
</ Tooltip2 >
0 commit comments