diff --git a/data/resources/style-dark.css b/data/resources/style-dark.css index e932ba802..69d787002 100644 --- a/data/resources/style-dark.css +++ b/data/resources/style-dark.css @@ -19,6 +19,11 @@ messagebubble.outgoing { background-color: #2c52ac; } +messagebubble.document.outgoing .file > overlay > image { + background: @accent_fg_color; + color: @accent_bg_color; +} + .event-row { background-color: alpha(#404040, 0.8); } diff --git a/data/resources/style.css b/data/resources/style.css index 80198e73e..0ca11d49a 100644 --- a/data/resources/style.css +++ b/data/resources/style.css @@ -205,8 +205,9 @@ messagebubble.document .file > overlay > image { } messagebubble.document.outgoing .file > overlay > image { - background: @accent_fg_color; - color: @accent_bg_color; + /* depends on bubble color */ + background: #79c271; + color: #eafcd2; } messagebubble.document .file:hover > overlay > image { @@ -326,6 +327,10 @@ messagereply label.message { color: @window_fg_color; } +messagebubble.outgoing messagereply label.message { + color: currentColor; +} + messagesticker { border-spacing: 6px; } diff --git a/src/session/content/message_row/bubble.rs b/src/session/content/message_row/bubble.rs index a3a4f139e..9ebd9e205 100644 --- a/src/session/content/message_row/bubble.rs +++ b/src/session/content/message_row/bubble.rs @@ -1,6 +1,7 @@ use adw::prelude::*; +use glib::clone; use gtk::subclass::prelude::*; -use gtk::{glib, CompositeTemplate}; +use gtk::{gdk, glib, graphene, gsk, CompositeTemplate}; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; @@ -28,6 +29,8 @@ mod imp { using Adw 1; template $MessageBubble { + overflow: hidden; + Overlay overlay { Box { orientation: vertical; @@ -60,6 +63,7 @@ mod imp { pub(crate) struct MessageBubble { pub(super) sender_color_class: RefCell>, pub(super) sender_binding: RefCell>, + pub(super) parent_list_view: RefCell>, #[template_child] pub(super) overlay: TemplateChild, #[template_child] @@ -119,6 +123,45 @@ mod imp { } impl WidgetImpl for MessageBubble { + fn realize(&self) { + self.parent_realize(); + + let widget = self.obj(); + + if let Some(view) = widget.parent_list_view() { + self.parent_list_view.replace(view.downgrade()); + view.vadjustment() + .unwrap() + .connect_value_notify(clone!(@weak widget => move |_| { + widget.queue_draw(); + })); + } + } + + fn snapshot(&self, snapshot: >k::Snapshot) { + let widget = self.obj(); + if widget.has_css_class("outgoing") { + let width = widget.width() as f32; + let height = widget.height() as f32; + + let bounds = graphene::Rect::new(0.0, 0.0, width, height); + let gradient_bounds = widget.gradient_bounds(); + let [first, second] = widget.linear_gradient_colors(); + + snapshot.append_linear_gradient( + &bounds, + &graphene::Point::new(0.0, gradient_bounds.y()), + &graphene::Point::new(0.0, gradient_bounds.height()), + &[ + gsk::ColorStop::new(0.0, first), + gsk::ColorStop::new(1.0, second), + ], + ); + } + + self.parent_snapshot(snapshot); + } + fn measure(&self, orientation: gtk::Orientation, for_size: i32) -> (i32, i32, i32, i32) { // Limit the widget width if orientation == gtk::Orientation::Horizontal { @@ -308,4 +351,44 @@ impl MessageBubble { .set_indicators(Some(imp.indicators.clone())); } } + + fn parent_list_view(&self) -> Option { + let mut parent = self.parent()?; + loop { + match parent.downcast() { + Ok(list_view) => return Some(list_view), + Err(not_list_view) => parent = not_list_view.parent()?, + } + } + } + + fn gradient_bounds(&self) -> graphene::Rect { + if let Some(view) = self.imp().parent_list_view.borrow().upgrade() { + let view_bounds = view.compute_bounds(self.imp().obj().as_ref()).unwrap(); + + graphene::Rect::new( + view_bounds.x(), + view_bounds.y(), + view_bounds.width() + view_bounds.x(), + view_bounds.height() + view_bounds.y(), + ) + } else { + panic!("can't get parent ListView"); + } + } + + fn linear_gradient_colors(&self) -> [gdk::RGBA; 2] { + // default colors from iOS + if !adw::StyleManager::default().is_dark() { + [ + gdk::RGBA::new(0.91764706, 0.9882353, 0.8235294, 1.0), + gdk::RGBA::new(0.91764706, 0.9882353, 0.8235294, 1.0), + ] + } else { + [ + gdk::RGBA::new(0.21960784, 0.32156864, 0.89411765, 1.0), + gdk::RGBA::new(0.63529414, 0.3372549, 0.58431375, 1.0), + ] + } + } }