Skip to content

Commit 6f3e651

Browse files
committed
rlottie: Add support of animated stickers and emojis
1 parent eb4980f commit 6f3e651

File tree

15 files changed

+661
-298
lines changed

15 files changed

+661
-298
lines changed

Cargo.lock

Lines changed: 203 additions & 36 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ regex = "1.7"
2222
tdlib = { version = "0.4", default-features = false }
2323
temp-dir = "0.1"
2424
thiserror = "1.0"
25+
rlt = { package="gtk-rlottie", git="https://github.com/YuraIz/gtk-rlottie-rs" }

build-aux/com.github.melix99.telegrand.Devel.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@
3636
"*.a"
3737
],
3838
"modules": [
39+
{
40+
"name": "rlottie",
41+
"buildsystem": "meson",
42+
"config-opts": ["-Dwerror=false"],
43+
"sources": [
44+
{
45+
"type": "git",
46+
"url": "https://github.com/melix99/rlottie",
47+
"branch": "fix-build"
48+
}
49+
]
50+
},
3951
{
4052
"name": "gtk",
4153
"buildsystem": "meson",
Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,48 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<gresources>
3-
<gresource prefix="/com/github/melix99/telegrand/">
4-
<file preprocess="xml-stripblanks">icons/scalable/actions/big-x-symbolic.svg</file>
5-
<file preprocess="xml-stripblanks">icons/scalable/actions/clear-symbolic.svg</file>
6-
<file preprocess="xml-stripblanks">icons/scalable/actions/send-symbolic.svg</file>
7-
<file preprocess="xml-stripblanks">icons/scalable/status/message-failed-symbolic.svg</file>
8-
<file preprocess="xml-stripblanks">icons/scalable/status/message-pending-symbolic.svg</file>
9-
<file preprocess="xml-stripblanks">icons/scalable/status/message-read-symbolic.svg</file>
10-
<file preprocess="xml-stripblanks">icons/scalable/status/message-unread-left-symbolic.svg</file>
11-
<file preprocess="xml-stripblanks">icons/scalable/status/message-unread-right-symbolic.svg</file>
3+
<gresource prefix="/com/github/melix99/telegrand/">
4+
<file preprocess="xml-stripblanks">icons/scalable/actions/big-x-symbolic.svg</file>
5+
<file preprocess="xml-stripblanks">icons/scalable/actions/clear-symbolic.svg</file>
6+
<file preprocess="xml-stripblanks">icons/scalable/actions/send-symbolic.svg</file>
7+
<file preprocess="xml-stripblanks">icons/scalable/status/message-failed-symbolic.svg</file>
8+
<file preprocess="xml-stripblanks">icons/scalable/status/message-pending-symbolic.svg</file>
9+
<file preprocess="xml-stripblanks">icons/scalable/status/message-read-symbolic.svg</file>
10+
<file preprocess="xml-stripblanks">icons/scalable/status/message-unread-left-symbolic.svg</file>
11+
<file preprocess="xml-stripblanks">icons/scalable/status/message-unread-right-symbolic.svg</file>
1212

13-
<file compressed="true" preprocess="xml-stripblanks">ui/add-account-row.ui</file>
14-
<file compressed="true" preprocess="xml-stripblanks">ui/avatar-with-selection.ui</file>
15-
<file compressed="true" preprocess="xml-stripblanks">ui/components-avatar.ui</file>
16-
<file compressed="true" preprocess="xml-stripblanks">ui/components-message-entry.ui</file>
17-
<file compressed="true" preprocess="xml-stripblanks">ui/content.ui</file>
18-
<file compressed="true" preprocess="xml-stripblanks">ui/content-chat-action-bar.ui</file>
19-
<file compressed="true" preprocess="xml-stripblanks">ui/content-chat-history.ui</file>
20-
<file compressed="true" preprocess="xml-stripblanks">ui/content-chat-info-window.ui</file>
21-
<file compressed="true" preprocess="xml-stripblanks">ui/content-event-row.ui</file>
22-
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-document.ui</file>
23-
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-photo.ui</file>
24-
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-sticker.ui</file>
25-
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-text.ui</file>
26-
<file compressed="true" preprocess="xml-stripblanks">ui/content-send-photo-dialog.ui</file>
27-
<file compressed="true" preprocess="xml-stripblanks">ui/login.ui</file>
28-
<file compressed="true" preprocess="xml-stripblanks">ui/message-menu.ui</file>
29-
<file compressed="true" preprocess="xml-stripblanks">ui/phone-number-input.ui</file>
30-
<file compressed="true" preprocess="xml-stripblanks">ui/preferences-window.ui</file>
31-
<file compressed="true" preprocess="xml-stripblanks">ui/session-entry-row.ui</file>
32-
<file compressed="true" preprocess="xml-stripblanks">ui/session-manager.ui</file>
33-
<file compressed="true" preprocess="xml-stripblanks">ui/session.ui</file>
34-
<file compressed="true" preprocess="xml-stripblanks" alias="gtk/help-overlay.ui">ui/shortcuts.ui</file>
35-
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar-avatar.ui</file>
36-
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar-row.ui</file>
37-
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar-row-menu.ui</file>
38-
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar-search.ui</file>
39-
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar-session-switcher.ui</file>
40-
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar.ui</file>
41-
<file compressed="true" preprocess="xml-stripblanks">ui/window.ui</file>
13+
<file compressed="true" preprocess="xml-stripblanks">ui/add-account-row.ui</file>
14+
<file compressed="true" preprocess="xml-stripblanks">ui/avatar-with-selection.ui</file>
15+
<file compressed="true" preprocess="xml-stripblanks">ui/components-avatar.ui</file>
16+
<file compressed="true" preprocess="xml-stripblanks">ui/components-message-entry.ui</file>
17+
<file compressed="true" preprocess="xml-stripblanks">ui/content.ui</file>
18+
<file compressed="true" preprocess="xml-stripblanks">ui/content-chat-action-bar.ui</file>
19+
<file compressed="true" preprocess="xml-stripblanks">ui/content-chat-history.ui</file>
20+
<file compressed="true" preprocess="xml-stripblanks">ui/content-chat-info-window.ui</file>
21+
<file compressed="true" preprocess="xml-stripblanks">ui/content-event-row.ui</file>
22+
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-document.ui</file>
23+
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-animated-emoji.ui</file>
24+
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-photo.ui</file>
25+
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-sticker.ui</file>
26+
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-text.ui</file>
27+
<file compressed="true" preprocess="xml-stripblanks">ui/content-send-photo-dialog.ui</file>
28+
<file compressed="true" preprocess="xml-stripblanks">ui/login.ui</file>
29+
<file compressed="true" preprocess="xml-stripblanks">ui/message-menu.ui</file>
30+
<file compressed="true" preprocess="xml-stripblanks">ui/phone-number-input.ui</file>
31+
<file compressed="true" preprocess="xml-stripblanks">ui/preferences-window.ui</file>
32+
<file compressed="true" preprocess="xml-stripblanks">ui/session-entry-row.ui</file>
33+
<file compressed="true" preprocess="xml-stripblanks">ui/session-manager.ui</file>
34+
<file compressed="true" preprocess="xml-stripblanks">ui/session.ui</file>
35+
<file compressed="true" preprocess="xml-stripblanks" alias="gtk/help-overlay.ui">ui/shortcuts.ui</file>
36+
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar-avatar.ui</file>
37+
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar-row.ui</file>
38+
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar-row-menu.ui</file>
39+
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar-search.ui</file>
40+
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar-session-switcher.ui</file>
41+
<file compressed="true" preprocess="xml-stripblanks">ui/sidebar.ui</file>
42+
<file compressed="true" preprocess="xml-stripblanks">ui/window.ui</file>
4243

43-
<file compressed="true">style.css</file>
44-
<file compressed="true">style-dark.css</file>
45-
<file compressed="true">style-hc.css</file>
46-
</gresource>
44+
<file compressed="true">style.css</file>
45+
<file compressed="true">style-dark.css</file>
46+
<file compressed="true">style-hc.css</file>
47+
</gresource>
4748
</gresources>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<interface>
3+
<template class="ContentMessageAnimatedEmoji" parent="ContentMessageBase">
4+
<child>
5+
<object class="GtkBox" id="gtk_box">
6+
<property name="orientation">vertical</property>
7+
<property name="vexpand">true</property>
8+
<child>
9+
<object class="GtkGestureClick" id="click">
10+
<property name="button">1</property>
11+
</object>
12+
</child>
13+
<child>
14+
<object class="AdwBin" id="bin">
15+
<property name="vexpand">true</property>
16+
</object>
17+
</child>
18+
<child>
19+
<object class="MessageIndicators" id="indicators">
20+
<property name="halign">end</property>
21+
<property name="valign">end</property>
22+
</object>
23+
</child>
24+
</object>
25+
</child>
26+
</template>
27+
</interface>

data/resources/ui/content-message-sticker.ui

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<interface>
33
<template class="ContentMessageSticker" parent="ContentMessageBase">
4-
<property name="layout-manager">
5-
<object class="GtkBinLayout"/>
6-
</property>
74
<child>
8-
<object class="GtkOverlay">
5+
<object class="GtkOverlay" id="overlay">
96
<child>
10-
<object class="ContentStickerPicture" id="picture"/>
7+
<object class="AdwBin" id="bin"/>
118
</child>
129
<child type="overlay">
1310
<object class="MessageIndicators" id="indicators">

src/session/components/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
mod avatar;
22
mod message_entry;
33
mod snow;
4+
mod vector_path;
45

56
pub(crate) use self::avatar::Avatar;
67
pub(crate) use self::message_entry::MessageEntry;
78
pub(crate) use self::snow::Snow;
9+
pub(crate) use self::vector_path::StickerPreview;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use gtk::glib;
2+
use gtk::prelude::*;
3+
use gtk::subclass::prelude::*;
4+
5+
use tdlib::types::ClosedVectorPath;
6+
7+
mod imp {
8+
use super::*;
9+
use gtk::graphene;
10+
use std::cell::RefCell;
11+
use tdlib::enums::VectorPathCommand::{CubicBezierCurve, Line};
12+
use tdlib::types::VectorPathCommandCubicBezierCurve as Curve;
13+
14+
#[derive(Default)]
15+
pub struct StickerPreview {
16+
pub(super) path: RefCell<Vec<ClosedVectorPath>>,
17+
}
18+
19+
#[glib::object_subclass]
20+
impl ObjectSubclass for StickerPreview {
21+
const NAME: &'static str = "ComponentsVectorPath";
22+
type Type = super::StickerPreview;
23+
type ParentType = gtk::Widget;
24+
}
25+
26+
impl ObjectImpl for StickerPreview {}
27+
28+
impl WidgetImpl for StickerPreview {
29+
fn snapshot(&self, snapshot: &gtk::Snapshot) {
30+
let widget = self.obj();
31+
32+
let context = snapshot.append_cairo(&graphene::Rect::new(0.0, 0.0, 512.0, 512.0));
33+
34+
let scale = widget.width().min(widget.height()) as f64 / 512.0;
35+
context.scale(scale, scale);
36+
37+
context.set_source_rgba(0.5, 0.5, 0.5, 0.4);
38+
39+
let outline = &*self.path.borrow();
40+
41+
for closed_path in outline {
42+
for command in &closed_path.commands {
43+
match command {
44+
Line(line) => {
45+
let e = &line.end_point;
46+
context.line_to(e.x, e.y);
47+
}
48+
CubicBezierCurve(curve) => {
49+
let Curve {
50+
start_control_point: sc,
51+
end_control_point: ec,
52+
end_point: e,
53+
} = curve;
54+
55+
context.curve_to(sc.x, sc.y, ec.x, ec.y, e.x, e.y);
56+
}
57+
}
58+
}
59+
_ = context.fill();
60+
}
61+
}
62+
}
63+
}
64+
65+
glib::wrapper! {
66+
pub struct StickerPreview(ObjectSubclass<imp::StickerPreview>)
67+
@extends gtk::Widget;
68+
}
69+
70+
impl StickerPreview {
71+
pub fn new(outline: Vec<ClosedVectorPath>) -> Self {
72+
let obj: Self = glib::Object::new(&[]);
73+
obj.imp().path.replace(outline);
74+
obj
75+
}
76+
}

src/session/content/chat_action_bar.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ impl ChatActionBar {
250250
let chooser = gtk::EmojiChooser::new();
251251
chooser.set_parent(parent);
252252
chooser.connect_emoji_picked(clone!(@weak self as obj => move |_, emoji| {
253-
obj.imp().message_entry.insert_at_cursor(emoji);
253+
obj.imp().message_entry.insert_at_cursor(emoji.trim_end_matches('\u{fe0f}'));
254254
}));
255255
chooser.connect_hide(clone!(@weak self as obj => move |_| {
256256
obj.imp().message_entry.grab_focus();
@@ -303,9 +303,10 @@ impl ChatActionBar {
303303
client_id,
304304
)
305305
.await;
306+
306307
if let Err(e) = result {
307-
log::warn!("Error sending a message: {:?}", e);
308-
}
308+
log::warn!("Error sending a message: {:?}", e)
309+
};
309310

310311
self.reset();
311312
}

0 commit comments

Comments
 (0)