@@ -110,7 +110,7 @@ window.QPixel = {
110110 } ,
111111
112112 /**
113- * @type {QPixelFlag []|null }
113+ * @type {QPixelFilter []|null }
114114 */
115115 _filters : null ,
116116
@@ -206,7 +206,8 @@ window.QPixel = {
206206 headers : { 'Accept' : 'application/json' }
207207 } ) ;
208208
209- const data = await resp . json ( ) ;
209+ /** @type {QPixelResponseJSON<{ preferences: UserPreferences }> } */
210+ const data = await QPixel . parseJSONResponse ( resp , 'Failed to save preference' ) ;
210211
211212 QPixel . handleJSONResponse ( data , ( data ) => {
212213 QPixel . _updatePreferencesLocally ( data . preferences ) ;
@@ -239,27 +240,19 @@ window.QPixel = {
239240 return data . name ;
240241 } ,
241242
242- setFilterAsDefault : async ( categoryId , name ) => {
243- await QPixel . fetchJSON ( `/categories/${ categoryId } /filters/default` , { name } , {
244- headers : { 'Accept' : 'application/json' }
245- } ) ;
246- } ,
247-
248243 setFilter : async ( name , filter , category , isDefault ) => {
249244 const resp = await QPixel . fetchJSON ( '/users/me/filters' ,
250245 Object . assign ( filter , { name, category, is_default : isDefault } ) , {
251246 headers : { 'Accept' : 'application/json' }
252247 } ) ;
248+
249+ /** @type {QPixelResponseJSON<{ filters: QPixelFilter[] }> } */
250+ const data = await QPixel . parseJSONResponse ( resp , 'Failed to save filter' ) ;
253251
254- const data = await resp . json ( ) ;
255- if ( data . status !== 'success' ) {
256- console . error ( `Filter persist failed (${ name } )` ) ;
257- console . error ( resp ) ;
258- }
259- else {
252+ QPixel . handleJSONResponse ( data , ( data ) => {
260253 this . _filters = data . filters ;
261254 QPixel . Storage ?. set ( 'user_filters' , this . _filters ) ;
262- }
255+ } ) ;
263256 } ,
264257
265258 deleteFilter : async ( name , system = false ) => {
@@ -268,16 +261,13 @@ window.QPixel = {
268261 method : 'DELETE'
269262 } ) ;
270263
271- const data = await resp . json ( ) ;
264+ /** @type {QPixelResponseJSON<{ filters: QPixelFilter[] }> } */
265+ const data = await QPixel . parseJSONResponse ( resp , 'Failed to delete filter' ) ;
272266
273- if ( data . status !== 'success' ) {
274- console . error ( `Filter deletion failed (${ name } )` ) ;
275- console . error ( resp ) ;
276- }
277- else {
267+ QPixel . handleJSONResponse ( data , ( data ) => {
278268 this . _filters = data . filters ;
279269 QPixel . Storage ?. set ( 'user_filters' , this . _filters ) ;
280- }
270+ } ) ;
281271 } ,
282272
283273 _preferencesLocalStorageKey : ( ) => {
@@ -410,11 +400,30 @@ window.QPixel = {
410400 return content ;
411401 } ,
412402
403+ parseJSONResponse : async ( response , errorMessage ) => {
404+ try {
405+ const data = await response . json ( ) ;
406+
407+ return data ;
408+ }
409+ catch ( error ) {
410+ if ( response . ok ) {
411+ console . error ( error ) ;
412+ }
413+
414+ return {
415+ status : 'failed' ,
416+ message : errorMessage
417+ } ;
418+ }
419+ } ,
420+
413421 handleJSONResponse : ( data , onSuccess , onFinally ) => {
422+ const is_modified = data . status === 'modified' ;
414423 const is_success = data . status === 'success' ;
415424
416- if ( is_success ) {
417- onSuccess ( data ) ;
425+ if ( is_modified || is_success ) {
426+ onSuccess ( /** @type { Parameters<typeof onSuccess>[0] } */ ( data ) ) ;
418427 }
419428 else {
420429 QPixel . createNotification ( 'danger' , data . message ) ;
@@ -430,9 +439,16 @@ window.QPixel = {
430439 headers : { 'Accept' : 'application/json' }
431440 } ) ;
432441
433- const data = await resp . json ( ) ;
442+ return QPixel . parseJSONResponse ( resp , 'Failed to flag' ) ;
443+ } ,
434444
435- return data ;
445+ vote : async ( postId , voteType ) => {
446+ const resp = await QPixel . fetchJSON ( '/votes/new' , {
447+ post_id : postId ,
448+ vote_type : voteType
449+ } ) ;
450+
451+ return QPixel . parseJSONResponse ( resp , 'Failed to vote' ) ;
436452 } ,
437453
438454 deleteComment : async ( id ) => {
@@ -441,19 +457,15 @@ window.QPixel = {
441457 method : 'DELETE'
442458 } ) ;
443459
444- const data = await resp . json ( ) ;
445-
446- return data ;
460+ return QPixel . parseJSONResponse ( resp , 'Failed to delete comment' ) ;
447461 } ,
448462
449463 followComments : async ( postId ) => {
450464 const resp = await QPixel . fetchJSON ( `/comments/post/${ postId } /follow` , { } , {
451465 headers : { 'Accept' : 'application/json' }
452466 } ) ;
453467
454- const data = await resp . json ( ) ;
455-
456- return data ;
468+ return QPixel . parseJSONResponse ( resp , 'Failed to follow post comments' ) ;
457469 } ,
458470
459471 deleteDraft : async ( ) => {
@@ -463,9 +475,7 @@ window.QPixel = {
463475 headers : { 'Accept' : 'application/json' }
464476 } ) ;
465477
466- const data = await resp . json ( ) ;
467-
468- return data ;
478+ return QPixel . parseJSONResponse ( resp , 'Failed to delete post draft' ) ;
469479 } ,
470480
471481 undeleteComment : async ( id ) => {
@@ -474,39 +484,37 @@ window.QPixel = {
474484 method : 'PATCH'
475485 } ) ;
476486
477- const data = await resp . json ( ) ;
478-
479- return data ;
487+ return QPixel . parseJSONResponse ( resp , 'Failed to undelete comment' ) ;
480488 } ,
481489
482490 unfollowComments : async ( postId ) => {
483491 const resp = await QPixel . fetchJSON ( `/comments/post/${ postId } /unfollow` , { } , {
484492 headers : { 'Accept' : 'application/json' }
485493 } ) ;
486494
487- const data = await resp . json ( ) ;
488-
489- return data ;
495+ return QPixel . parseJSONResponse ( resp , 'Failed to unfollow post comments' ) ;
490496 } ,
491497
492498 lockThread : async ( id ) => {
493499 const resp = await QPixel . fetchJSON ( `/comments/thread/${ id } /restrict` , {
494500 type : 'lock'
495501 } ) ;
496502
497- const data = await resp . json ( ) ;
498-
499- return data ;
503+ return QPixel . parseJSONResponse ( resp , 'Failed to lock thread' ) ;
500504 } ,
501505
502506 renameTag : async ( categoryId , tagId , name ) => {
503507 const resp = await QPixel . fetchJSON ( `/categories/${ categoryId } /tags/${ tagId } /rename` , { name } , {
504508 headers : { 'Accept' : 'application/json' }
505509 } ) ;
506510
507- const data = await resp . json ( ) ;
511+ return QPixel . parseJSONResponse ( resp , 'Failed to rename tag' ) ;
512+ } ,
508513
509- return data ;
514+ retractVote : async ( id ) => {
515+ const resp = await QPixel . fetchJSON ( `/votes/${ id } ` , { } , { method : 'DELETE' } ) ;
516+
517+ return QPixel . parseJSONResponse ( resp , 'Failed to retract vote' ) ;
510518 } ,
511519
512520 saveDraft : async ( draft ) => {
@@ -515,8 +523,6 @@ window.QPixel = {
515523 path : location . pathname
516524 } ) ;
517525
518- const data = await resp . json ( ) ;
519-
520- return data ;
526+ return QPixel . parseJSONResponse ( resp , 'Failed to save draft' ) ;
521527 } ,
522528} ;
0 commit comments