@@ -2,13 +2,13 @@ prpr_l10n::tl_file!("favorites");
22
33use super :: { Illustration , NextPage , Page , SharedState } ;
44use crate :: {
5- client:: { recv_raw , Chart , ChartRef , Client , Collection , CollectionContent , CollectionPatch , LocalCollection , UserManager } ,
5+ client:: { Chart , ChartRef , Client , Collection , CollectionContent , CollectionCover , CollectionPatch , File , LocalCollection , Ptr , UserManager , recv_raw } ,
66 get_data, get_data_mut,
77 icons:: Icons ,
8- page:: SFader ,
8+ page:: { CHOOSE_COVER , SFader } ,
99 popup:: Popup ,
1010 save_data,
11- scene:: { confirm_dialog , ProfileScene , TEX_BACKGROUND } ,
11+ scene:: { ProfileScene , TEX_BACKGROUND , confirm_dialog } ,
1212} ;
1313use anyhow:: Result ;
1414use chrono:: { DateTime , Utc } ;
@@ -96,16 +96,19 @@ pub struct FavoritesPage {
9696 sf : SFader ,
9797 next_page : Option < NextPage > ,
9898
99+ chosen_cover : Option < Result < i32 , String > > ,
100+
99101 upload_task : Option < Task < Result < Collection > > > ,
100102 delete_from_cloud_task : Option < Task < Result < ( ) > > > ,
101103 set_public_task : Option < Task < Result < Collection > > > ,
102104 sync_task : Option < Task < Result < Option < Collection > > > > ,
103105 import_task : Option < Task < Result < Collection > > > ,
104106 batch_import_task : Option < Task < Result < Vec < Chart > > > > ,
107+ set_cover_task : Option < Task < Result < Result < Collection , File > > > > ,
105108}
106109
107110impl FavoritesPage {
108- pub fn new ( icons : Arc < Icons > , rank_icons : [ SafeTexture ; 8 ] , active_folder : Option < usize > ) -> Self {
111+ pub fn new ( icons : Arc < Icons > , rank_icons : [ SafeTexture ; 8 ] , active_folder : Option < usize > , chosen_cover : Option < Result < i32 , String > > ) -> Self {
109112 let mut page = Self {
110113 icons,
111114 rank_icons,
@@ -142,12 +145,15 @@ impl FavoritesPage {
142145 sf : SFader :: new ( ) ,
143146 next_page : None ,
144147
148+ chosen_cover,
149+
145150 upload_task : None ,
146151 delete_from_cloud_task : None ,
147152 set_public_task : None ,
148153 sync_task : None ,
149154 import_task : None ,
150155 batch_import_task : None ,
156+ set_cover_task : None ,
151157 } ;
152158 page. rebuild_folders ( ) ;
153159 page
@@ -239,6 +245,7 @@ impl FavoritesPage {
239245 || self . sync_task . is_some ( )
240246 || self . import_task . is_some ( )
241247 || self . batch_import_task . is_some ( )
248+ || self . set_cover_task . is_some ( )
242249 }
243250
244251 fn collect_chart_ids ( & self , col : & LocalCollection , allow_local : bool ) -> Option < Vec < i32 > > {
@@ -400,6 +407,7 @@ impl Page for FavoritesPage {
400407 if col. is_owned ( ) {
401408 options. push ( "rename" ) ;
402409 options. push ( "set-description" ) ;
410+ options. push ( "set-cover" ) ;
403411 }
404412 if !is_default && col. is_owned ( ) {
405413 options. push ( "set-as-default" ) ;
@@ -477,6 +485,42 @@ impl Page for FavoritesPage {
477485 folder. cover . settle ( t) ;
478486 }
479487
488+ if let Some ( chosen_cover) = self . chosen_cover . take ( ) {
489+ let data = get_data_mut ( ) ;
490+ let col = & mut data. collections [ self . active_folder . unwrap ( ) ] ;
491+ match chosen_cover {
492+ Ok ( chart_id) => {
493+ let col_id = col. id ;
494+ self . set_cover_task = Some ( Task :: new ( async move {
495+ if let Some ( col_id) = col_id {
496+ // Collection is synced, update cloud directly
497+ let resp: Collection =
498+ recv_raw ( Client :: request ( Method :: PATCH , format ! ( "/collection/{col_id}" ) ) . json ( & CollectionPatch :: Cover ( chart_id) ) )
499+ . await ?
500+ . json ( )
501+ . await ?;
502+ Ok ( Ok ( resp) )
503+ } else {
504+ // Collection is not synced, fetch chart
505+ // illustration and set as cover locally
506+ let chart = Ptr :: < Chart > :: new ( chart_id) . fetch ( ) . await ?;
507+ Ok ( Err ( chart. illustration . clone ( ) ) )
508+ }
509+ } ) ) ;
510+ }
511+ Err ( local_path) => {
512+ if col. id . is_some ( ) {
513+ Dialog :: simple ( ttl ! ( "favorites-online-only" ) ) . show ( ) ;
514+ } else {
515+ col. cover = CollectionCover :: LocalChart ( local_path) ;
516+ let _ = save_data ( ) ;
517+ show_message ( tl ! ( "updated" ) ) . ok ( ) ;
518+ self . rebuild_folders ( ) ;
519+ }
520+ }
521+ }
522+ }
523+
480524 // 处理输入事件 || Handle input events
481525 if let Some ( ( id, text) ) = take_input ( ) {
482526 match id. as_str ( ) {
@@ -578,6 +622,12 @@ impl Page for FavoritesPage {
578622 "set-description" => {
579623 request_input ( "fav_description" , & data. collections [ index] . description ) ;
580624 }
625+ "set-cover" => {
626+ FAV_PAGE_RESULT . with ( |it| * it. borrow_mut ( ) = Some ( Some ( index) ) ) ;
627+ CHOOSE_COVER . store ( true , Ordering :: Relaxed ) ;
628+ show_message ( tl ! ( "select-cover" ) ) ;
629+ self . next_page = Some ( NextPage :: Pop ) ;
630+ }
581631 "duplicate" => {
582632 let col = & data. collections [ index] ;
583633 data. collections . push ( LocalCollection {
@@ -822,6 +872,33 @@ impl Page for FavoritesPage {
822872 self . batch_import_task = None ;
823873 }
824874 }
875+ if let Some ( task) = & mut self . set_cover_task {
876+ if let Some ( result) = task. take ( ) {
877+ match result {
878+ Ok ( Ok ( col) ) => {
879+ let data = get_data_mut ( ) ;
880+ let local = & mut data. collections [ self . active_folder . unwrap ( ) ] ;
881+ local. id = Some ( col. id ) ;
882+ local. assign_from ( & col) ;
883+ let _ = save_data ( ) ;
884+ show_message ( tl ! ( "updated" ) ) . ok ( ) ;
885+ self . rebuild_folders ( ) ;
886+ }
887+ Ok ( Err ( cover) ) => {
888+ let data = get_data_mut ( ) ;
889+ let col = & mut data. collections [ self . active_folder . unwrap ( ) ] ;
890+ col. cover = CollectionCover :: Online ( cover) ;
891+ let _ = save_data ( ) ;
892+ show_message ( tl ! ( "updated" ) ) . ok ( ) ;
893+ self . rebuild_folders ( ) ;
894+ }
895+ Err ( err) => {
896+ show_error ( err) ;
897+ }
898+ }
899+ self . set_cover_task = None ;
900+ }
901+ }
825902
826903 Ok ( ( ) )
827904 }
0 commit comments