@@ -60,6 +60,8 @@ mod imp {
6060
6161 #[ derive( Default ) ]
6262 pub ( crate ) struct Background {
63+ pub ( super ) chat_theme : RefCell < Option < tdlib:: types:: ChatTheme > > ,
64+
6365 pub ( super ) background_texture : RefCell < Option < gdk:: Texture > > ,
6466
6567 pub ( super ) last_size : Cell < ( f32 , f32 ) > ,
@@ -95,10 +97,10 @@ mod imp {
9597 self . pattern . set ( pattern) . unwrap ( ) ;
9698
9799 let style_manager = adw:: StyleManager :: default ( ) ;
98- obj. set_theme ( hard_coded_themes ( style_manager. is_dark ( ) ) ) ;
100+ obj. refresh_theme ( style_manager. is_dark ( ) ) ;
99101
100102 style_manager. connect_dark_notify ( clone ! ( @weak obj => move |style_manager| {
101- obj. set_theme ( hard_coded_themes ( style_manager. is_dark( ) ) )
103+ obj. refresh_theme ( style_manager. is_dark( ) ) ;
102104 } ) ) ;
103105
104106 if style_manager. is_high_contrast ( ) {
@@ -234,6 +236,40 @@ mod imp {
234236 }
235237 }
236238
239+ pub ( super ) fn fill_node (
240+ & self ,
241+ bounds : & graphene:: Rect ,
242+ gradient_bounds : & graphene:: Rect ,
243+ colors : & [ graphene:: Vec3 ] ,
244+ ) -> gsk:: RenderNode {
245+ match colors. len ( ) {
246+ 1 => gsk:: ColorNode :: new ( & vec3_to_rgba ( & colors[ 0 ] ) , bounds) . upcast ( ) ,
247+ 2 => gsk:: LinearGradientNode :: new (
248+ & bounds,
249+ & gradient_bounds. top_left ( ) ,
250+ & gradient_bounds. bottom_left ( ) ,
251+ & [
252+ gsk:: ColorStop :: new ( 0.0 , vec3_to_rgba ( & colors[ 0 ] ) ) ,
253+ gsk:: ColorStop :: new ( 1.0 , vec3_to_rgba ( & colors[ 1 ] ) ) ,
254+ ] ,
255+ )
256+ . upcast ( ) ,
257+ 3 => {
258+ log:: error!( "Three color gradients aren't supported yet" ) ;
259+
260+ let mut colors = colors. to_vec ( ) ;
261+ colors. push ( colors[ 2 ] ) ;
262+
263+ self . gradient_shader_node ( bounds, gradient_bounds, & colors)
264+ . upcast ( )
265+ }
266+ 4 => self
267+ . gradient_shader_node ( bounds, gradient_bounds, colors)
268+ . upcast ( ) ,
269+ _ => unreachable ! ( "Unsupported color count" ) ,
270+ }
271+ }
272+
237273 pub ( super ) fn gradient_shader_node (
238274 & self ,
239275 bounds : & graphene:: Rect ,
@@ -327,29 +363,41 @@ impl Background {
327363 glib:: Object :: new ( )
328364 }
329365
330- pub ( crate ) fn set_theme ( & self , theme : tdlib:: types:: ThemeSettings ) {
331- let Some ( background) = theme. background else { return ; } ;
366+ pub ( crate ) fn set_chat_theme ( & self , theme : Option < tdlib:: types:: ChatTheme > ) {
367+ self . imp ( ) . chat_theme . replace ( theme) ;
368+ self . refresh_theme ( adw:: StyleManager :: default ( ) . is_dark ( ) ) ;
369+ }
370+
371+ pub ( crate ) fn set_theme ( & self , theme : & tdlib:: types:: ThemeSettings ) {
372+ let Some ( background) = & theme. background else { return ; } ;
332373 let imp = self . imp ( ) ;
333374
334375 imp. dark . set ( background. is_dark ) ;
335376
336- let bg_fill = match background. r#type {
337- tdlib:: enums:: BackgroundType :: Pattern ( pattern) => pattern. fill ,
338- tdlib:: enums:: BackgroundType :: Fill ( fill) => fill. fill ,
377+ let bg_fill = match & background. r#type {
378+ tdlib:: enums:: BackgroundType :: Pattern ( pattern) => & pattern. fill ,
379+ tdlib:: enums:: BackgroundType :: Fill ( fill) => & fill. fill ,
339380 tdlib:: enums:: BackgroundType :: Wallpaper ( _) => {
340381 unimplemented ! ( "Wallpaper chat background" )
341382 }
342383 } ;
343384
344385 imp. bg_colors . replace ( fill_colors ( bg_fill) ) ;
345386 imp. message_colors
346- . replace ( fill_colors ( theme. outgoing_message_fill ) ) ;
387+ . replace ( fill_colors ( & theme. outgoing_message_fill ) ) ;
347388
348389 imp. background_texture . take ( ) ;
349390 self . queue_draw ( ) ;
350391 }
351392
352393 pub ( crate ) fn animate ( & self ) {
394+ let nothing_to_animate = self . imp ( ) . bg_colors . borrow ( ) . len ( ) <= 2
395+ && self . imp ( ) . message_colors . borrow ( ) . len ( ) <= 2 ;
396+
397+ if nothing_to_animate {
398+ return ;
399+ }
400+
353401 let animation = self . imp ( ) . animation . get ( ) . unwrap ( ) ;
354402
355403 let val = animation. value ( ) ;
@@ -367,21 +415,18 @@ impl Background {
367415 & self ,
368416 bounds : & graphene:: Rect ,
369417 gradient_bounds : & graphene:: Rect ,
370- ) -> gsk:: GLShaderNode {
418+ ) -> gsk:: RenderNode {
371419 self . imp ( )
372- . gradient_shader_node ( bounds, gradient_bounds, & self . imp ( ) . bg_colors . borrow ( ) )
420+ . fill_node ( bounds, gradient_bounds, & self . imp ( ) . bg_colors . borrow ( ) )
373421 }
374422
375423 pub fn message_bg_node (
376424 & self ,
377425 bounds : & graphene:: Rect ,
378426 gradient_bounds : & graphene:: Rect ,
379- ) -> gsk:: GLShaderNode {
380- self . imp ( ) . gradient_shader_node (
381- bounds,
382- gradient_bounds,
383- & self . imp ( ) . message_colors . borrow ( ) ,
384- )
427+ ) -> gsk:: RenderNode {
428+ self . imp ( )
429+ . fill_node ( bounds, gradient_bounds, & self . imp ( ) . message_colors . borrow ( ) )
385430 }
386431
387432 fn ensure_shader ( & self ) {
@@ -403,6 +448,23 @@ impl Background {
403448 }
404449 } ;
405450 }
451+
452+ fn refresh_theme ( & self , dark : bool ) {
453+ if let Some ( chat_theme) = & * self . imp ( ) . chat_theme . borrow ( ) {
454+ let theme = if dark {
455+ & chat_theme. dark_settings
456+ } else {
457+ & chat_theme. light_settings
458+ } ;
459+
460+ self . set_theme ( theme) ;
461+
462+ // For some reason tdlib tells that light theme is dark
463+ self . imp ( ) . dark . set ( dark) ;
464+ } else {
465+ self . set_theme ( & hard_coded_themes ( dark) ) ;
466+ }
467+ }
406468}
407469
408470impl Default for Background {
@@ -411,22 +473,30 @@ impl Default for Background {
411473 }
412474}
413475
414- fn fill_colors ( fill : tdlib:: enums:: BackgroundFill ) -> Vec < graphene:: Vec3 > {
476+ fn fill_colors ( fill : & tdlib:: enums:: BackgroundFill ) -> Vec < graphene:: Vec3 > {
415477 match fill {
416478 tdlib:: enums:: BackgroundFill :: FreeformGradient ( gradient) if gradient. colors . len ( ) == 4 => {
417- gradient
418- . colors
419- . into_iter ( )
420- . map ( |int_color| {
421- let [ _, r, g, b] = int_color. to_be_bytes ( ) ;
422- graphene:: Vec3 :: new ( r as f32 / 255.0 , g as f32 / 255.0 , b as f32 / 255.0 )
423- } )
424- . collect ( )
479+ gradient. colors . iter ( ) . map ( int_color_to_vec3) . collect ( )
425480 }
481+ tdlib:: enums:: BackgroundFill :: Solid ( solid) => vec ! [ int_color_to_vec3( & solid. color) ] ,
482+ tdlib:: enums:: BackgroundFill :: Gradient ( gradient) => vec ! [
483+ int_color_to_vec3( & gradient. top_color) ,
484+ int_color_to_vec3( & gradient. bottom_color) ,
485+ ] ,
426486 _ => unimplemented ! ( "Unsupported background fill: {fill:?}" ) ,
427487 }
428488}
429489
490+ fn int_color_to_vec3 ( color : & i32 ) -> graphene:: Vec3 {
491+ let [ _, r, g, b] = color. to_be_bytes ( ) ;
492+ graphene:: Vec3 :: new ( r as f32 / 255.0 , g as f32 / 255.0 , b as f32 / 255.0 )
493+ }
494+
495+ fn vec3_to_rgba ( vec3 : & graphene:: Vec3 ) -> gdk:: RGBA {
496+ let [ red, green, blue] = vec3. to_float ( ) ;
497+ gdk:: RGBA :: new ( red, green, blue, 1.0 )
498+ }
499+
430500fn hard_coded_themes ( dark : bool ) -> tdlib:: types:: ThemeSettings {
431501 fn theme (
432502 dark : bool ,
0 commit comments