Skip to content

Commit

Permalink
Introduce MessageSticker to show stickers in the chat-history
Browse files Browse the repository at this point in the history
  • Loading branch information
melix99 committed Sep 13, 2021
1 parent 66d1f99 commit a4c2643
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 14 deletions.
1 change: 1 addition & 0 deletions data/resources/resources.gresource.xml
Expand Up @@ -7,6 +7,7 @@
<file compressed="true" preprocess="xml-stripblanks">ui/content-event-row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-bubble.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/content-message-sticker.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/login.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/session.ui</file>
<file compressed="true" preprocess="xml-stripblanks" alias="gtk/help-overlay.ui">ui/shortcuts.ui</file>
Expand Down
8 changes: 8 additions & 0 deletions data/resources/ui/content-message-sticker.ui
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="ContentMessageSticker" parent="AdwBin">
<property name="child">
<object class="GtkPicture" id="sticker_picture"/>
</property>
</template>
</interface>
1 change: 1 addition & 0 deletions src/meson.build
Expand Up @@ -43,6 +43,7 @@ sources = files(
'session/content/item_row.rs',
'session/content/message_bubble.rs',
'session/content/message_row.rs',
'session/content/message_sticker.rs',
'session/content/mod.rs',
'session/sidebar/chat_row.rs',
'session/sidebar/mod.rs',
Expand Down
49 changes: 35 additions & 14 deletions src/session/content/message_row.rs
@@ -1,10 +1,10 @@
use adw::{prelude::BinExt, subclass::prelude::BinImpl};
use gtk::{glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use tdgrand::enums::ChatType;
use tdgrand::enums::{ChatType, MessageContent};

use crate::session::chat::{Message, MessageSender};
use crate::session::components::Avatar;
use crate::session::content::MessageBubble;
use crate::session::content::{MessageBubble, MessageSticker};

mod imp {
use super::*;
Expand Down Expand Up @@ -97,17 +97,38 @@ impl MessageRow {
}

// Show content widget
let content = if let Some(Ok(content)) = self_
.content_bin
.child()
.map(|w| w.downcast::<MessageBubble>())
{
content
} else {
let content = MessageBubble::new();
self_.content_bin.set_child(Some(&content));
content
};
content.set_message(message);
match message.content().0 {
// TODO: Support animated and mask stickers
MessageContent::MessageSticker(data)
if !data.sticker.is_animated && !data.sticker.is_mask =>
{
let content = if let Some(Ok(content)) = self_
.content_bin
.child()
.map(|w| w.downcast::<MessageSticker>())
{
content
} else {
let content = MessageSticker::new();
self_.content_bin.set_child(Some(&content));
content
};
content.set_message(message);
}
_ => {
let content = if let Some(Ok(content)) = self_
.content_bin
.child()
.map(|w| w.downcast::<MessageBubble>())
{
content
} else {
let content = MessageBubble::new();
self_.content_bin.set_child(Some(&content));
content
};
content.set_message(message);
}
}
}
}
91 changes: 91 additions & 0 deletions src/session/content/message_sticker.rs
@@ -0,0 +1,91 @@
use glib::clone;
use gtk::{glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use tdgrand::{enums::MessageContent, types::File};

use crate::session::chat::Message;

mod imp {
use super::*;
use adw::subclass::prelude::BinImpl;

#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/com/github/melix99/telegrand/ui/content-message-sticker.ui")]
pub struct MessageSticker {
#[template_child]
pub sticker_picture: TemplateChild<gtk::Picture>,
}

#[glib::object_subclass]
impl ObjectSubclass for MessageSticker {
const NAME: &'static str = "ContentMessageSticker";
type Type = super::MessageSticker;
type ParentType = adw::Bin;

fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass);
}

fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}

impl ObjectImpl for MessageSticker {}
impl WidgetImpl for MessageSticker {}
impl BinImpl for MessageSticker {}
}

glib::wrapper! {
pub struct MessageSticker(ObjectSubclass<imp::MessageSticker>)
@extends gtk::Widget, adw::Bin;
}

impl Default for MessageSticker {
fn default() -> Self {
Self::new()
}
}

impl MessageSticker {
pub fn new() -> Self {
glib::Object::new(&[]).expect("Failed to create MessageSticker")
}

pub fn set_message(&self, message: &Message) {
if let MessageContent::MessageSticker(data) = message.content().0 {
let self_ = imp::MessageSticker::from_instance(self);
self_
.sticker_picture
.set_height_request((data.sticker.height as f32 / 2.3) as i32);

if data.sticker.sticker.local.is_downloading_completed {
self.load_sticker(&data.sticker.sticker.local.path);
} else {
let (sender, receiver) =
glib::MainContext::sync_channel::<File>(Default::default(), 5);

receiver.attach(
None,
clone!(@weak self as obj => @default-return glib::Continue(false), move |file| {
if file.local.is_downloading_completed {
obj.load_sticker(&file.local.path);
}

glib::Continue(true)
}),
);

message
.chat()
.session()
.download_file(data.sticker.sticker.id, sender);
}
}
}

fn load_sticker(&self, path: &str) {
let self_ = imp::MessageSticker::from_instance(self);
let media = gtk::MediaFile::for_filename(path);
self_.sticker_picture.set_paintable(Some(&media));
}
}
2 changes: 2 additions & 0 deletions src/session/content/mod.rs
Expand Up @@ -3,12 +3,14 @@ mod event_row;
mod item_row;
mod message_bubble;
mod message_row;
mod message_sticker;

use self::chat_history::ChatHistory;
use self::event_row::EventRow;
use self::item_row::ItemRow;
use self::message_bubble::MessageBubble;
use self::message_row::MessageRow;
use self::message_sticker::MessageSticker;

use gtk::glib;
use gtk::prelude::*;
Expand Down

0 comments on commit a4c2643

Please sign in to comment.