@@ -60,6 +60,8 @@ mod imp {
60
60
61
61
#[ derive( Default ) ]
62
62
pub ( crate ) struct Background {
63
+ pub ( super ) chat_theme : RefCell < Option < tdlib:: types:: ChatTheme > > ,
64
+
63
65
pub ( super ) background_texture : RefCell < Option < gdk:: Texture > > ,
64
66
65
67
pub ( super ) last_size : Cell < ( f32 , f32 ) > ,
@@ -95,10 +97,10 @@ mod imp {
95
97
self . pattern . set ( pattern) . unwrap ( ) ;
96
98
97
99
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 ( ) ) ;
99
101
100
102
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( ) ) ;
102
104
} ) ) ;
103
105
104
106
if style_manager. is_high_contrast ( ) {
@@ -234,6 +236,40 @@ mod imp {
234
236
}
235
237
}
236
238
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
+
237
273
pub ( super ) fn gradient_shader_node (
238
274
& self ,
239
275
bounds : & graphene:: Rect ,
@@ -327,29 +363,41 @@ impl Background {
327
363
glib:: Object :: new ( )
328
364
}
329
365
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 ; } ;
332
373
let imp = self . imp ( ) ;
333
374
334
375
imp. dark . set ( background. is_dark ) ;
335
376
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 ,
339
380
tdlib:: enums:: BackgroundType :: Wallpaper ( _) => {
340
381
unimplemented ! ( "Wallpaper chat background" )
341
382
}
342
383
} ;
343
384
344
385
imp. bg_colors . replace ( fill_colors ( bg_fill) ) ;
345
386
imp. message_colors
346
- . replace ( fill_colors ( theme. outgoing_message_fill ) ) ;
387
+ . replace ( fill_colors ( & theme. outgoing_message_fill ) ) ;
347
388
348
389
imp. background_texture . take ( ) ;
349
390
self . queue_draw ( ) ;
350
391
}
351
392
352
393
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
+
353
401
let animation = self . imp ( ) . animation . get ( ) . unwrap ( ) ;
354
402
355
403
let val = animation. value ( ) ;
@@ -367,21 +415,18 @@ impl Background {
367
415
& self ,
368
416
bounds : & graphene:: Rect ,
369
417
gradient_bounds : & graphene:: Rect ,
370
- ) -> gsk:: GLShaderNode {
418
+ ) -> gsk:: RenderNode {
371
419
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 ( ) )
373
421
}
374
422
375
423
pub fn message_bg_node (
376
424
& self ,
377
425
bounds : & graphene:: Rect ,
378
426
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 ( ) )
385
430
}
386
431
387
432
fn ensure_shader ( & self ) {
@@ -403,6 +448,23 @@ impl Background {
403
448
}
404
449
} ;
405
450
}
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
+ }
406
468
}
407
469
408
470
impl Default for Background {
@@ -411,22 +473,30 @@ impl Default for Background {
411
473
}
412
474
}
413
475
414
- fn fill_colors ( fill : tdlib:: enums:: BackgroundFill ) -> Vec < graphene:: Vec3 > {
476
+ fn fill_colors ( fill : & tdlib:: enums:: BackgroundFill ) -> Vec < graphene:: Vec3 > {
415
477
match fill {
416
478
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 ( )
425
480
}
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
+ ] ,
426
486
_ => unimplemented ! ( "Unsupported background fill: {fill:?}" ) ,
427
487
}
428
488
}
429
489
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
+
430
500
fn hard_coded_themes ( dark : bool ) -> tdlib:: types:: ThemeSettings {
431
501
fn theme (
432
502
dark : bool ,
0 commit comments