@@ -33,6 +33,8 @@ pub struct Widgets {
3333 cancelbutton : gtk:: Button ,
3434 okbutton : gtk:: Button ,
3535 label : gtk:: Label ,
36+ whatsnew : gtk:: Label ,
37+ changelog_container : gtk:: ScrolledWindow ,
3638 sizelabel : gtk:: Label ,
3739 spinner : gtk:: Spinner ,
3840 progress : gtk:: ProgressBar ,
@@ -54,7 +56,7 @@ pub enum Output {
5456pub enum CmdOut {
5557 Checking ,
5658 /// The final output of the command.
57- Checked ( Result < bool , ( ) > ) ,
59+ Checked ( Result < ( bool , String ) , String > ) ,
5860 Download ,
5961 /// Progress update from a command.
6062 Progress ( String , f32 ) ,
@@ -72,8 +74,8 @@ impl Component for Updater {
7274
7375 fn init_root ( ) -> Self :: Root {
7476 gtk:: Window :: builder ( )
75- . width_request ( 300 )
76- . height_request ( 100 )
77+ . width_request ( 350 )
78+ . height_request ( 150 )
7779 . build ( )
7880 }
7981
@@ -108,6 +110,23 @@ impl Component for Updater {
108110 set_visible: false ,
109111 } ,
110112
113+ #[ name = "changelog_container" ]
114+ gtk:: ScrolledWindow {
115+ set_width_request: 250 ,
116+ set_height_request: 75 ,
117+ set_visible: false ,
118+ set_policy: ( gtk:: PolicyType :: Automatic , gtk:: PolicyType :: Automatic ) ,
119+
120+ //append: whatsnew = >k::Label {
121+ #[ name = "whatsnew" ]
122+ gtk:: Label {
123+ set_markup: "" ,
124+ set_hexpand: true ,
125+ set_align: gtk:: Align :: Start ,
126+ set_margin_all: 4 ,
127+ } ,
128+ } ,
129+
111130 append: progress = & gtk:: ProgressBar {
112131 set_width_request: 200 ,
113132 set_visible: false ,
@@ -154,6 +173,8 @@ impl Component for Updater {
154173 model : Updater :: default ( ) ,
155174 widgets : Widgets {
156175 label,
176+ whatsnew,
177+ changelog_container,
157178 sizelabel,
158179 checkbutton,
159180 updatebutton,
@@ -174,17 +195,37 @@ impl Component for Updater {
174195 shutdown
175196 . register ( async move {
176197 out. send ( CmdOut :: Checking ) . unwrap ( ) ;
177- //std::thread::sleep(std::time::Duration::from_secs(3));
178- //out.send(CmdOut::Checked(Ok(true))).unwrap();
179198 let result = fetch_latest_release ( ) . await . unwrap ( ) ;
180- //println!("{:#?}", result);
199+
181200 let compile_time = DateTime :: parse_from_rfc3339 (
182201 compile_time:: datetime_str!( )
183202 ) . unwrap ( ) . with_timezone ( & Utc ) ;
184203
185204 let difference = result. published_at - compile_time;
205+ let body = result. body . clone ( ) ;
206+ let mut changelog = String :: new ( ) ;
207+ let lines = body. lines ( ) . collect :: < Vec < _ > > ( ) ;
208+ for line in & lines[ 1 ..] {
209+ // trim end to avoid spurious `\r`
210+ let line = line. trim_end ( ) ;
211+
212+ if let Some ( text) = line. strip_prefix ( "## " ) {
213+ changelog. push_str ( & format ! ( "<b>{}</b>\n \n " , text) ) ;
214+ }
215+ else if let Some ( item) = line. strip_prefix ( "- " ) {
216+ let item = process_inline_code ( item) ;
217+ changelog. push_str ( & format ! ( "• {}\n " , item) ) ;
218+ }
219+ else if line. is_empty ( ) {
220+ changelog. push ( '\n' ) ;
221+ }
222+ else {
223+ let text = process_inline_code ( line) ;
224+ changelog. push_str ( & format ! ( "{}\n " , text) ) ;
225+ }
226+ }
186227 out. send ( CmdOut :: Checked (
187- Ok ( difference > chrono:: Duration :: minutes ( 5 ) )
228+ Ok ( ( difference > chrono:: Duration :: minutes ( 5 ) , changelog ) )
188229 ) ) . unwrap ( ) ;
189230 } )
190231 . drop_on_shutdown ( )
@@ -346,19 +387,29 @@ impl Component for Updater {
346387 CmdOut :: Checked ( result) => {
347388 widgets. spinner . set_visible ( false ) ;
348389 widgets. checkbutton . set_visible ( false ) ;
349- if result. unwrap ( ) {
350- widgets. label . set_label ( "Do you want to update?" ) ;
351- widgets. updatebutton . set_visible ( true ) ;
352- widgets. cancelbutton . set_visible ( true ) ;
353- }
354- else {
355- widgets. label . set_text ( "No update available." ) ;
356- widgets. okbutton . set_visible ( true ) ;
390+ match result {
391+ Ok ( ( check, changelog) ) => {
392+ if * check {
393+ widgets. label . set_label ( "What's new?" ) ;
394+ widgets. whatsnew . set_markup ( & changelog) ;
395+ widgets. changelog_container . set_visible ( true ) ;
396+ widgets. whatsnew . set_visible ( true ) ;
397+ widgets. updatebutton . set_visible ( true ) ;
398+ widgets. cancelbutton . set_visible ( true ) ;
399+ }
400+ else {
401+ widgets. label . set_text ( "No update available." ) ;
402+ widgets. okbutton . set_visible ( true ) ;
403+ }
404+ }
405+ Err ( e) => widgets. label . set_label ( & format ! ( "Error: {e}" ) ) ,
357406 }
358407 }
359408 CmdOut :: Download => {
360409 widgets. updatebutton . set_visible ( false ) ;
361410 widgets. cancelbutton . set_visible ( false ) ;
411+ widgets. whatsnew . set_visible ( false ) ;
412+ widgets. changelog_container . set_visible ( false ) ;
362413 widgets. label . set_label ( "Downloading..." ) ;
363414 widgets. label . set_halign ( gtk:: Align :: Start ) ;
364415 widgets. sizelabel . set_halign ( gtk:: Align :: End ) ;
@@ -395,6 +446,7 @@ const REPO: &str = "codlinux";
395446struct GHRelease {
396447 published_at : DateTime < Utc > ,
397448 assets : Vec < ReleaseAsset > ,
449+ body : String ,
398450}
399451
400452#[ derive( Debug , Deserialize ) ]
@@ -426,3 +478,23 @@ async fn fetch_latest_release() ->Result<GHRelease, reqwest::Error>
426478 Ok ( release)
427479 //}
428480}
481+
482+ fn process_inline_code ( s : & str ) -> String {
483+ let mut out = String :: new ( ) ;
484+ let mut parts = s. split ( "``" ) ;
485+ if let Some ( first) = parts. next ( ) {
486+ out. push_str ( first) ;
487+ }
488+ let mut inside = true ;
489+ for piece in parts {
490+ if inside {
491+ out. push_str ( "<tt>" ) ;
492+ out. push_str ( piece) ;
493+ out. push_str ( "</tt>" ) ;
494+ } else {
495+ out. push_str ( piece) ;
496+ }
497+ inside = !inside;
498+ }
499+ out
500+ }
0 commit comments