Skip to content

Commit 77bcd2b

Browse files
committed
feat(theme-settings): Add theme settings
1 parent e780d7b commit 77bcd2b

File tree

13 files changed

+387
-57
lines changed

13 files changed

+387
-57
lines changed

data/app.drey.PaperPlane.gschema.xml.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,10 @@
3131
<summary>Color Scheme</summary>
3232
<description>The color scheme to be used in the app</description>
3333
</key>
34+
<key name="theme-name" type="s">
35+
<default>'🏠'</default>
36+
<summary>Theme Name</summary>
37+
<description>The chat theme name to be used in the app</description>
38+
</key>
3439
</schema>
3540
</schemalist>

data/resources/style-dark.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,7 @@ messagebubble.document.outgoing .file > overlay > statusindicator {
6464
background: #303030;
6565
}
6666
/* End of values for cairo renderer */
67+
68+
themepreview {
69+
color: #303030;
70+
}

data/resources/style.css

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,3 +411,41 @@ window.chat-info .main-page > list {
411411
.small-pill {
412412
border-radius: 18px;
413413
}
414+
415+
themepreview {
416+
color: white;
417+
}
418+
419+
themepreview .card {
420+
border-radius: 6px;
421+
}
422+
423+
themepreview > label {
424+
text-shadow: 0 -1px rgba(0, 0, 0, 0.05), 1px 0 rgba(0, 0, 0, 0.1),
425+
0 1px rgba(0, 0, 0, 0.3), -1px 0 rgba(0, 0, 0, 0.1);
426+
}
427+
428+
.theme-variants {
429+
padding: 4px;
430+
}
431+
432+
.theme-variants button {
433+
margin: 4px;
434+
background: none;
435+
border-radius: 9px;
436+
padding: 3px;
437+
box-shadow: none;
438+
outline: none;
439+
}
440+
441+
.theme-variants button:checked {
442+
box-shadow: 0 0 0 3px @accent_color;
443+
}
444+
445+
.theme-variants button:focus:focus-visible {
446+
box-shadow: 0 0 0 3px alpha(@accent_color, 0.3);
447+
}
448+
449+
.theme-variants button:checked:focus:focus-visible {
450+
box-shadow: 0 0 0 3px @accent_color, 0 0 0 6px alpha(@accent_color, 0.3);
451+
}

data/resources/ui/preferences-window.blp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@ using Adw 1;
33

44
template $PreferencesWindow : Adw.PreferencesWindow {
55
Adw.PreferencesPage {
6+
Adw.PreferencesGroup {
7+
title: _("Theme");
8+
9+
FlowBox theme_variants_box {
10+
styles ["theme-variants", "card"]
11+
overflow: hidden;
12+
13+
selection-mode: none;
14+
}
15+
}
16+
617
Adw.PreferencesGroup {
718
title: _("Color Scheme");
819

src/session/content/background.rs renamed to src/components/background.rs

Lines changed: 55 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,16 @@ void mainImage(out vec4 fragColor,
5555
"#
5656
.as_bytes();
5757

58+
static mut SHADER: Option<gsk::GLShader> = None;
59+
5860
mod imp {
5961
use super::*;
6062

6163
#[derive(Default)]
6264
pub(crate) struct Background {
65+
pub(super) settings: OnceCell<gio::Settings>,
66+
pub(super) settings_handler: RefCell<Option<glib::SignalHandlerId>>,
67+
6368
pub(super) chat_theme: RefCell<Option<tdlib::types::ChatTheme>>,
6469

6570
pub(super) background_texture: RefCell<Option<gdk::Texture>>,
@@ -92,6 +97,21 @@ mod imp {
9297

9398
let obj = self.obj();
9499

100+
let settings = gio::Settings::new(crate::config::APP_ID);
101+
let settings_handler = settings.connect_changed(
102+
Some("theme-name"),
103+
clone!(@weak obj => move |_, _| {
104+
let imp = obj.imp();
105+
106+
if imp.chat_theme.borrow().is_none() {
107+
obj.refresh_theme(imp.dark.get());
108+
}
109+
}),
110+
);
111+
112+
self.settings.set(settings).unwrap();
113+
self.settings_handler.replace(Some(settings_handler));
114+
95115
let pattern = gdk::Texture::from_resource("/app/drey/paper-plane/images/pattern.svg");
96116

97117
self.pattern.set(pattern).unwrap();
@@ -140,6 +160,12 @@ mod imp {
140160

141161
self.animation.set(animation).unwrap();
142162
}
163+
164+
fn dispose(&self) {
165+
if let Some(settings) = self.settings.get() {
166+
settings.disconnect(self.settings_handler.take().unwrap());
167+
}
168+
}
143169
}
144170

145171
impl WidgetImpl for Background {
@@ -432,6 +458,12 @@ impl Background {
432458
fn ensure_shader(&self) {
433459
let imp = self.imp();
434460
if imp.shader.borrow().is_none() {
461+
unsafe {
462+
if SHADER.is_some() {
463+
imp.shader.replace(SHADER.clone());
464+
}
465+
}
466+
435467
let renderer = self.native().unwrap().renderer();
436468

437469
let shader = gsk::GLShader::from_bytes(&GRADIENT_SHADER.into());
@@ -443,7 +475,11 @@ impl Background {
443475
self.add_css_class("fallback");
444476
}
445477
Ok(_) => {
446-
imp.shader.replace(Some(shader));
478+
imp.shader.replace(Some(shader.clone()));
479+
480+
unsafe {
481+
SHADER = Some(shader);
482+
}
447483
}
448484
}
449485
};
@@ -458,11 +494,25 @@ impl Background {
458494
};
459495

460496
self.set_theme(theme);
461-
462-
// For some reason tdlib tells that light theme is dark
463-
self.imp().dark.set(dark);
464497
} else {
465-
self.set_theme(&hard_coded_themes(dark));
498+
let chat_theme = self
499+
.ancestor(crate::Session::static_type())
500+
.and_downcast::<crate::Session>()
501+
.map(|s| s.default_chat_theme())
502+
.unwrap_or(crate::utils::default_theme());
503+
504+
if dark {
505+
self.set_theme(&chat_theme.dark_settings);
506+
} else {
507+
self.set_theme(&chat_theme.light_settings);
508+
}
509+
}
510+
511+
// For some reason tdlib tells that light theme is dark
512+
self.imp().dark.set(dark);
513+
514+
if let Some(animation) = self.imp().animation.get() {
515+
animation.notify("value");
466516
}
467517
}
468518
}
@@ -496,50 +546,3 @@ fn vec3_to_rgba(vec3: &graphene::Vec3) -> gdk::RGBA {
496546
let [red, green, blue] = vec3.to_float();
497547
gdk::RGBA::new(red, green, blue, 1.0)
498548
}
499-
500-
fn hard_coded_themes(dark: bool) -> tdlib::types::ThemeSettings {
501-
fn theme(
502-
dark: bool,
503-
bg_colors: Vec<i32>,
504-
message_colors: Vec<i32>,
505-
) -> tdlib::types::ThemeSettings {
506-
use tdlib::enums::BackgroundFill::*;
507-
use tdlib::enums::BackgroundType::Fill;
508-
use tdlib::types::*;
509-
510-
ThemeSettings {
511-
background: Some(Background {
512-
is_default: true,
513-
is_dark: dark,
514-
r#type: Fill(BackgroundTypeFill {
515-
fill: FreeformGradient(BackgroundFillFreeformGradient { colors: bg_colors }),
516-
}),
517-
id: 0,
518-
name: String::new(),
519-
document: None,
520-
}),
521-
accent_color: 0,
522-
animate_outgoing_message_fill: false,
523-
outgoing_message_accent_color: 0,
524-
outgoing_message_fill: FreeformGradient(BackgroundFillFreeformGradient {
525-
colors: message_colors,
526-
}),
527-
}
528-
}
529-
530-
// tr tl bl br
531-
532-
if dark {
533-
theme(
534-
dark,
535-
vec![0xd6932e, 0xbc40db, 0x4280d7, 0x614ed5],
536-
vec![0x2d52ab, 0x4036a1, 0x9f388d, 0x9d3941],
537-
)
538-
} else {
539-
theme(
540-
dark,
541-
vec![0x94dae9, 0x9aeddb, 0x94c3f6, 0xac96f7],
542-
vec![0xddecff, 0xe0ddfd, 0xdbffff, 0xddffdf],
543-
)
544-
}
545-
}

src/components/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
mod avatar;
2+
mod background;
23
mod message_entry;
34
mod snow;
45
mod sticker;
6+
mod theme_preview;
57

68
pub(crate) use self::avatar::Avatar;
9+
pub(crate) use self::background::Background;
710
pub(crate) use self::message_entry::MessageEntry;
811
pub(crate) use self::snow::Snow;
912
pub(crate) use self::sticker::Sticker;
13+
pub(crate) use self::theme_preview::ThemePreview;

0 commit comments

Comments
 (0)