Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/session/content/chat_history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ mod imp {
use once_cell::sync::Lazy;
use once_cell::unsync::OnceCell;
use std::cell::{Cell, RefCell};
use std::collections::HashSet;

#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/com/github/melix99/telegrand/ui/content-chat-history.ui")]
Expand All @@ -31,6 +32,7 @@ mod imp {
pub(super) message_menu: OnceCell<gtk::PopoverMenu>,
pub(super) is_auto_scrolling: Cell<bool>,
pub(super) sticky: Cell<bool>,
pub(super) visible_messages: RefCell<HashSet<i64>>,
#[template_child]
pub(super) window_title: TemplateChild<adw::WindowTitle>,
#[template_child]
Expand Down Expand Up @@ -76,6 +78,38 @@ mod imp {
widget.show_leave_chat_dialog().await;
},
);
klass.install_action_async(
"chat-history.add-visible-message",
Some("x"),
|widget, _, variant| async move {
let message_id = variant.and_then(|v| v.get()).unwrap();
if widget
.imp()
.visible_messages
.borrow_mut()
.insert(message_id)
{
println!("ADD {}", message_id);
widget.update_visible_messages().await;
}
},
);
klass.install_action_async(
"chat-history.remove-visible-message",
Some("x"),
|widget, _, variant| async move {
let message_id = variant.and_then(|v| v.get()).unwrap();
if widget
.imp()
.visible_messages
.borrow_mut()
.remove(&message_id)
{
println!("REMOVE {}", message_id);
widget.update_visible_messages().await;
}
},
);
}

fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
Expand Down Expand Up @@ -217,6 +251,39 @@ impl ChatHistory {
}
}

async fn update_visible_messages(&self) {
if let Some(chat) = self.chat() {
let client_id = chat.session().client_id();
let message_ids = self
.imp()
.visible_messages
.borrow()
.clone()
.into_iter()
.collect();
let result =
tdlib::functions::view_messages(chat.id(), 0, message_ids, false, client_id).await;

if let Err(e) = result {
log::warn!("Error setting visible messages: {e:?}");
}

let msgs: Vec<String> = self
.imp()
.visible_messages
.borrow()
.iter()
.map(|id| {
let message = self.chat().unwrap().message(*id).unwrap();
format!("{} ||| {}", crate::strings::message_content(&message), id)
})
.collect();
dbg!(msgs);
println!();
println!();
}
}

fn open_info_dialog(&self) {
if let Some(chat) = self.chat() {
ChatInfoWindow::new(&self.parent_window(), &chat).present();
Expand Down
40 changes: 39 additions & 1 deletion src/session/content/message_row/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ use crate::utils::spawn;

const AVATAR_SIZE: i32 = 32;
const SPACING: i32 = 6;
const VISIBLE_MESSAGE_DELAY_MILLIS: u64 = 100;

mod imp {
use super::*;
use once_cell::sync::Lazy;
use std::cell::RefCell;
use std::time::Duration;

#[derive(Debug, Default, CompositeTemplate)]
#[template(string = r#"
Expand Down Expand Up @@ -124,7 +126,43 @@ mod imp {
}
}

impl WidgetImpl for MessageRow {}
impl WidgetImpl for MessageRow {
fn map(&self) {
self.parent_map();

let obj = self.obj();
glib::timeout_add_local_once(
Duration::from_millis(VISIBLE_MESSAGE_DELAY_MILLIS),
clone!(@weak obj => move || if obj.is_mapped() {
if let Ok(message) = obj.message().downcast::<Message>() {
obj.activate_action(
"chat-history.add-visible-message",
Some(&message.id().to_variant()),
)
.unwrap();
}
}),
);
}

fn unmap(&self) {
self.parent_unmap();

let obj = self.obj();
glib::timeout_add_local_once(
Duration::from_millis(VISIBLE_MESSAGE_DELAY_MILLIS),
clone!(@weak obj => move || if !obj.is_mapped() {
if let Ok(message) = obj.message().downcast::<Message>() {
obj.activate_action(
"chat-history.remove-visible-message",
Some(&message.id().to_variant()),
)
.unwrap();
}
}),
);
}
}
}

glib::wrapper! {
Expand Down
20 changes: 19 additions & 1 deletion src/session/content/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ use self::event_row::EventRow;
use self::message_row::MessageRow;
use self::send_photo_dialog::SendPhotoDialog;

use glib::clone;
use gtk::glib;
use gtk::prelude::*;
use gtk::subclass::prelude::*;

use crate::tdlib::Chat;
use crate::utils::spawn;

mod imp {
use super::*;
Expand Down Expand Up @@ -140,7 +142,23 @@ impl Content {
imp.stack.set_visible_child(&imp.unselected_chat.get());
}

imp.chat.replace(chat);
// Mark the previous chat as closed, if any
if let Some(old_chat) = imp.chat.replace(chat) {
spawn(clone!(@weak old_chat => async move {
if let Err(e) = old_chat.close().await {
log::warn!("Error closing a chat: {e:?}");
}
}));
}

// Mark the new chat as opened, if any
if let Some(chat) = imp.chat.borrow().as_ref() {
spawn(clone!(@weak chat => async move {
if let Err(e) = chat.open().await {
log::warn!("Error opening a chat: {e:?}");
}
}));
}

self.notify("chat");
}
Expand Down
39 changes: 25 additions & 14 deletions src/tdlib/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,20 +264,16 @@ impl Chat {
self.set_unread_mention_count(update.unread_mention_count)
}
DeleteMessages(data) => {
// FIXME: This should be removed after we notify opened and closed chats to TDLib
// See discussion here: https://t.me/tdlibchat/65304
if !data.from_cache {
let mut messages = imp.messages.borrow_mut();
let deleted_messages: Vec<Message> = data
.message_ids
.into_iter()
.filter_map(|id| messages.remove(&id))
.collect();

drop(messages);
for message in deleted_messages {
self.emit_by_name::<()>("deleted-message", &[&message]);
}
let mut messages = imp.messages.borrow_mut();
let deleted_messages: Vec<Message> = data
.message_ids
.into_iter()
.filter_map(|id| messages.remove(&id))
.collect();

drop(messages);
for message in deleted_messages {
self.emit_by_name::<()>("deleted-message", &[&message]);
}
}
MessageContent(ref data) => {
Expand Down Expand Up @@ -522,6 +518,21 @@ impl Chat {
self.imp().messages.borrow().get(&message_id).cloned()
}

// Mark this chat as opened. This allows receiving additional updates for this
// chat and it's also needed to correctly manage the internal message cache.
pub(crate) async fn open(&self) -> Result<(), types::Error> {
let chat_id = self.id();
let client_id = self.session().client_id();
functions::open_chat(chat_id, client_id).await
}

// Mark this chat as closed.
pub(crate) async fn close(&self) -> Result<(), types::Error> {
let chat_id = self.id();
let client_id = self.session().client_id();
functions::close_chat(chat_id, client_id).await
}

pub(crate) async fn get_chat_history(
&self,
from_message_id: i64,
Expand Down