Skip to content

Commit c3ba612

Browse files
committed
chat-history: Add linear gradient to outgoing messages
1 parent 21fddc3 commit c3ba612

3 files changed

Lines changed: 97 additions & 4 deletions

File tree

data/resources/style-dark.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ messagebubble.outgoing {
1919
background-color: #2C52AC;
2020
}
2121

22+
messagebubble.document.outgoing .file > overlay > image {
23+
background: @accent_fg_color;
24+
color: @accent_bg_color;
25+
}
26+
2227
.event-row {
2328
background-color: alpha(#404040, 0.8);
2429
}

data/resources/style.css

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ messagebubble {
156156
}
157157

158158
messagebubble.outgoing {
159-
background-color: #ddecff;
159+
background: transparent;
160160
color: @window_fg_color;
161161
}
162162

@@ -213,8 +213,9 @@ messagebubble.document .file > overlay > image {
213213
}
214214

215215
messagebubble.document.outgoing .file > overlay > image {
216-
background: @accent_fg_color;
217-
color: @accent_bg_color;
216+
/* depends on bubble color */
217+
background: #79c271;
218+
color: #eafcd2;
218219
}
219220

220221
messagebubble.document .file:hover > overlay > image {
@@ -334,6 +335,10 @@ messagereply label.message {
334335
color: @window_fg_color;
335336
}
336337

338+
messagebubble.outgoing messagereply label.message {
339+
color: currentColor;
340+
}
341+
337342
messagesticker {
338343
border-spacing: 6px;
339344
}

src/session/content/message_row/bubble.rs

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use adw::prelude::*;
2+
use glib::clone;
23
use gtk::subclass::prelude::*;
3-
use gtk::{glib, CompositeTemplate};
4+
use gtk::{gdk, glib, graphene, gsk, CompositeTemplate};
45
use std::collections::hash_map::DefaultHasher;
56
use std::hash::{Hash, Hasher};
67

@@ -28,6 +29,8 @@ mod imp {
2829
using Adw 1;
2930
3031
template $MessageBubble {
32+
overflow: hidden;
33+
3134
Overlay overlay {
3235
Box {
3336
orientation: vertical;
@@ -60,6 +63,7 @@ mod imp {
6063
pub(crate) struct MessageBubble {
6164
pub(super) sender_color_class: RefCell<Option<String>>,
6265
pub(super) sender_binding: RefCell<Option<gtk::ExpressionWatch>>,
66+
pub(super) parent_list_view: RefCell<glib::WeakRef<gtk::ListView>>,
6367
#[template_child]
6468
pub(super) overlay: TemplateChild<gtk::Overlay>,
6569
#[template_child]
@@ -119,6 +123,45 @@ mod imp {
119123
}
120124

121125
impl WidgetImpl for MessageBubble {
126+
fn realize(&self) {
127+
self.parent_realize();
128+
129+
let widget = self.obj();
130+
131+
if let Some(view) = widget.parent_list_view() {
132+
self.parent_list_view.replace(view.downgrade());
133+
view.vadjustment()
134+
.unwrap()
135+
.connect_value_notify(clone!(@weak widget => move |_| {
136+
widget.queue_draw();
137+
}));
138+
}
139+
}
140+
141+
fn snapshot(&self, snapshot: &gtk::Snapshot) {
142+
let widget = self.obj();
143+
if widget.has_css_class("outgoing") {
144+
let width = widget.width() as f32;
145+
let height = widget.height() as f32;
146+
147+
let bounds = graphene::Rect::new(0.0, 0.0, width, height);
148+
let gradient_bounds = widget.gradient_bounds();
149+
let [first, second] = widget.linear_gradient_colors();
150+
151+
snapshot.append_linear_gradient(
152+
&bounds,
153+
&graphene::Point::new(0.0, gradient_bounds.y()),
154+
&graphene::Point::new(0.0, gradient_bounds.height()),
155+
&[
156+
gsk::ColorStop::new(0.0, first),
157+
gsk::ColorStop::new(1.0, second),
158+
],
159+
);
160+
}
161+
162+
self.parent_snapshot(snapshot);
163+
}
164+
122165
fn measure(&self, orientation: gtk::Orientation, for_size: i32) -> (i32, i32, i32, i32) {
123166
// Limit the widget width
124167
if orientation == gtk::Orientation::Horizontal {
@@ -308,4 +351,44 @@ impl MessageBubble {
308351
.set_indicators(Some(imp.indicators.clone()));
309352
}
310353
}
354+
355+
fn parent_list_view(&self) -> Option<gtk::ListView> {
356+
let mut parent = self.parent()?;
357+
loop {
358+
match parent.downcast() {
359+
Ok(list_view) => return Some(list_view),
360+
Err(not_list_view) => parent = not_list_view.parent()?,
361+
}
362+
}
363+
}
364+
365+
fn gradient_bounds(&self) -> graphene::Rect {
366+
if let Some(view) = self.imp().parent_list_view.borrow().upgrade() {
367+
let view_bounds = view.compute_bounds(self.imp().obj().as_ref()).unwrap();
368+
369+
graphene::Rect::new(
370+
view_bounds.x(),
371+
view_bounds.y(),
372+
view_bounds.width() + view_bounds.x(),
373+
view_bounds.height() + view_bounds.y(),
374+
)
375+
} else {
376+
panic!("can't get parent ListView");
377+
}
378+
}
379+
380+
fn linear_gradient_colors(&self) -> [gdk::RGBA; 2] {
381+
// default colors from iOS
382+
if !adw::StyleManager::default().is_dark() {
383+
[
384+
gdk::RGBA::new(0.91764706, 0.9882353, 0.8235294, 1.0),
385+
gdk::RGBA::new(0.91764706, 0.9882353, 0.8235294, 1.0),
386+
]
387+
} else {
388+
[
389+
gdk::RGBA::new(0.21960784, 0.32156864, 0.89411765, 1.0),
390+
gdk::RGBA::new(0.63529414, 0.3372549, 0.58431375, 1.0),
391+
]
392+
}
393+
}
311394
}

0 commit comments

Comments
 (0)