Skip to content

Commit

Permalink
Merge pull request #492 from melix99/melix99/better-downloading
Browse files Browse the repository at this point in the history
Better file downloading
  • Loading branch information
melix99 committed Mar 6, 2023
2 parents cdba268 + 73e9683 commit 0828da1
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 102 deletions.
34 changes: 18 additions & 16 deletions src/components/avatar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use glib::{clone, closure};
use gtk::prelude::*;
use gtk::subclass::prelude::*;
use gtk::{gdk, glib};
use tdlib::types::File;

use crate::tdlib::{Avatar as AvatarItem, Chat, User};
use crate::utils::spawn;
use crate::{expressions, Session};

mod imp {
Expand Down Expand Up @@ -158,27 +158,29 @@ impl Avatar {
let texture = gdk::Texture::from_filename(&file.local.path).unwrap();
self.imp().avatar.set_custom_image(Some(&texture));
} 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 {
let texture = gdk::Texture::from_filename(&file.local.path).unwrap();
obj.imp().avatar.set_custom_image(Some(&texture));
}
glib::Continue(true)
}),
);

session.download_file(file.id, sender);
let file_id = file.id;

spawn(clone!(@weak self as obj, @weak session => async move {
obj.download_avatar(file_id, &session).await;
}));
}
} else {
self.imp().avatar.set_custom_image(gdk::Paintable::NONE);
}
}

async fn download_avatar(&self, file_id: i32, session: &Session) {
match session.download_file(file_id).await {
Ok(file) => {
let texture = gdk::Texture::from_filename(file.local.path).unwrap();
self.imp().avatar.set_custom_image(Some(&texture));
}
Err(e) => {
log::warn!("Failed to download an avatar: {e:?}");
}
}
}

pub(crate) fn item(&self) -> Option<glib::Object> {
self.imp().item.borrow().clone()
}
Expand Down
13 changes: 4 additions & 9 deletions src/session/content/message_row/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,12 @@ impl MessageDocument {
// Download file
image.set_icon_name(Some("document-save-symbolic"));
click.connect_released(clone!(@weak self as obj, @weak session => move |click, _, _, _| {
let (sender, receiver) = glib::MainContext::sync_channel::<File>(Default::default(), 5);
receiver.attach(
None,
clone!(@weak obj, @weak session => @default-return glib::Continue(false), move |file| {
// TODO: fix bug mentioned here
// https://github.com/melix99/telegrand/pull/372#discussion_r968841370
glib::Continue(obj.update_status(file, session) != FileStatus::Downloaded)
// TODO: Fix bug mentioned here
// https://github.com/melix99/telegrand/pull/372#discussion_r968841370
session.download_file_with_updates(file_id, clone!(@weak obj, @weak session => move |file| {
obj.update_status(file, session);
}));

session.download_file(file_id, sender);

obj.imp().file_status_image.set_icon_name(Some("media-playback-stop-symbolic"));
let handler_id = click.connect_released(clone!(@weak session => move |_, _, _, _| {
session.cancel_download_file(file_id);
Expand Down
31 changes: 14 additions & 17 deletions src/session/content/message_row/photo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use gtk::prelude::*;
use gtk::subclass::prelude::*;
use gtk::{gdk, gio, glib, CompositeTemplate};
use tdlib::enums::MessageContent;
use tdlib::types::File;

use crate::session::content::message_row::{
MediaPicture, MessageBase, MessageBaseImpl, MessageBubble,
Expand Down Expand Up @@ -176,26 +175,24 @@ impl MessagePhoto {
.as_ref(),
);

self.download_photo(photo_size.photo.id, &message.chat().session());
let file_id = photo_size.photo.id;
let session = message.chat().session();
spawn(clone!(@weak self as obj, @weak session => async move {
obj.download_photo(file_id, &session).await;
}));
}
}
}

fn download_photo(&self, file_id: i32, session: &Session) {
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_photo(file.local.path);
}

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

session.download_file(file_id, sender);
async fn download_photo(&self, file_id: i32, session: &Session) {
match session.download_file(file_id).await {
Ok(file) => {
self.load_photo(file.local.path);
}
Err(e) => {
log::warn!("Failed to download a photo: {e:?}");
}
}
}

fn load_photo(&self, path: String) {
Expand Down
37 changes: 18 additions & 19 deletions src/session/content/message_row/sticker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use gtk::prelude::*;
use gtk::subclass::prelude::*;
use gtk::{gio, glib, CompositeTemplate};
use tdlib::enums::MessageContent;
use tdlib::types::File;

use crate::session::content::message_row::{
MessageBase, MessageBaseImpl, MessageIndicators, StickerPicture,
};
use crate::tdlib::Message;
use crate::utils::{decode_image_from_path, spawn};
use crate::Session;

use super::base::MessageBaseExt;

Expand Down Expand Up @@ -107,24 +107,12 @@ impl MessageBaseExt for MessageSticker {
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);
let file_id = data.sticker.sticker.id;
let session = message.chat().session();

spawn(clone!(@weak self as obj, @weak session => async move {
obj.download_sticker(file_id, &session).await;
}));
}
}

Expand All @@ -133,6 +121,17 @@ impl MessageBaseExt for MessageSticker {
}

impl MessageSticker {
async fn download_sticker(&self, file_id: i32, session: &Session) {
match session.download_file(file_id).await {
Ok(file) => {
self.load_sticker(file.local.path);
}
Err(e) => {
log::warn!("Failed to download a sticker: {e:?}");
}
}
}

fn load_sticker(&self, path: String) {
let message_id = self.message().id();

Expand Down
36 changes: 16 additions & 20 deletions src/session/content/message_row/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ use gtk::prelude::*;
use gtk::subclass::prelude::*;
use gtk::{gdk, glib, CompositeTemplate};
use tdlib::enums::MessageContent;
use tdlib::types::File;

use crate::session::content::message_row::{
MediaPicture, MessageBase, MessageBaseImpl, MessageBubble,
};
use crate::tdlib::Message;
use crate::utils::parse_formatted_text;
use crate::utils::{parse_formatted_text, spawn};
use crate::Session;

use super::base::MessageBaseExt;
Expand Down Expand Up @@ -166,7 +165,7 @@ impl MessageVideo {
imp.picture.set_aspect_ratio(aspect_ratio);

if file.local.is_downloading_completed {
self.load_video_from_path(&file.local.path);
self.load_video(&file.local.path);
} else {
imp.picture.set_paintable(
minithumbnail
Expand All @@ -179,28 +178,25 @@ impl MessageVideo {
.as_ref(),
);

self.download_video(file.id, session);
let file_id = file.id;
spawn(clone!(@weak self as obj, @weak session => async move {
obj.download_video(file_id, &session).await;
}));
}
}

fn download_video(&self, file_id: i32, session: &Session) {
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_video_from_path(&file.local.path);
}

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

session.download_file(file_id, sender);
async fn download_video(&self, file_id: i32, session: &Session) {
match session.download_file(file_id).await {
Ok(file) => {
self.load_video(&file.local.path);
}
Err(e) => {
log::warn!("Failed to download a video: {e:?}");
}
}
}

fn load_video_from_path(&self, path: &str) {
fn load_video(&self, path: &str) {
let imp = self.imp();

let media = gtk::MediaFile::for_filename(path);
Expand Down
27 changes: 24 additions & 3 deletions src/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use self::content::Content;
use self::preferences_window::PreferencesWindow;
use self::sidebar::Sidebar;

use glib::{clone, SyncSender};
use glib::{clone, Sender};
use gtk::glib::WeakRef;
use gtk::prelude::*;
use gtk::subclass::prelude::*;
Expand Down Expand Up @@ -54,7 +54,7 @@ mod imp {
RefCell<Option<BoxedScopeNotificationSettings>>,
pub(super) channel_chats_notification_settings:
RefCell<Option<BoxedScopeNotificationSettings>>,
pub(super) downloading_files: RefCell<HashMap<i32, Vec<SyncSender<File>>>>,
pub(super) downloading_files: RefCell<HashMap<i32, Vec<Sender<File>>>>,
#[template_child]
pub(super) leaflet: TemplateChild<adw::Leaflet>,
#[template_child]
Expand Down Expand Up @@ -428,7 +428,28 @@ impl Session {
})
}

pub(crate) fn download_file(&self, file_id: i32, sender: SyncSender<File>) {
/// Downloads a file of the specified id. This will only return when the file
/// downloading has completed or has failed.
pub(crate) async fn download_file(&self, file_id: i32) -> Result<File, TdError> {
let client_id = self.client_id();
let result = functions::download_file(file_id, 5, 0, 0, true, client_id).await;

result.map(|data| {
let tdlib::enums::File::File(file) = data;
file
})
}

/// Downloads a file of the specified id and calls a closure every time there's an update
/// about the progress or when the download has completed.
pub(crate) fn download_file_with_updates<F: Fn(File) + 'static>(&self, file_id: i32, f: F) {
let (sender, receiver) = glib::MainContext::channel::<File>(glib::PRIORITY_DEFAULT);
receiver.attach(None, move |file| {
let is_downloading_active = file.local.is_downloading_active;
f(file);
glib::Continue(is_downloading_active)
});

let mut downloading_files = self.imp().downloading_files.borrow_mut();
match downloading_files.entry(file_id) {
Entry::Occupied(mut entry) => {
Expand Down
33 changes: 15 additions & 18 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,27 +242,24 @@ impl Window {
Some(&notification_id.to_string()),
&notification,
);
let (sender, receiver) = glib::MainContext::sync_channel::<
tdlib::types::File,
>(
Default::default(), 5
);
receiver.attach(
None,
clone!(@weak app => @default-return glib::Continue(false), move |file| {
if file.local.is_downloading_completed {
if let Ok(texture) = gdk::Texture::from_filename(&file.local.path) {

let file_id = avatar_file.id;
let session = &client.session;
spawn(
clone!(@weak self as obj, @weak session, @weak app => async move {
match session.download_file(file_id).await {
Ok(file) => {
let texture = gdk::Texture::from_filename(file.local.path).unwrap();
notification.set_icon(&texture);

app.send_notification(Some(&notification_id.to_string()), &notification);
}
Err(e) => {
log::warn!("Failed to download an avatar: {e:?}");
}
app.send_notification(Some(&notification_id.to_string()), &notification);
glib::Continue(false)
}
else {
glib::Continue(true)
}
}));

client.session.download_file(avatar_file.id, sender);
}),
);
}
}
}
Expand Down

0 comments on commit 0828da1

Please sign in to comment.