aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdino/src/entity/file_transfer.vala1
-rw-r--r--libdino/src/service/file_manager.vala5
-rw-r--r--libdino/src/service/jingle_file_transfers.vala14
-rw-r--r--main/src/ui/conversation_content_view/file_default_widget.vala15
-rw-r--r--main/src/ui/conversation_content_view/file_widget.vala12
-rw-r--r--main/src/ui/file_send_overlay.vala3
-rw-r--r--plugins/http-files/src/file_sender.vala12
-rw-r--r--xmpp-vala/src/module/xep/0234_jingle_file_transfer.vala19
8 files changed, 71 insertions, 10 deletions
diff --git a/libdino/src/entity/file_transfer.vala b/libdino/src/entity/file_transfer.vala
index 20bc1a7a..b58348a0 100644
--- a/libdino/src/entity/file_transfer.vala
+++ b/libdino/src/entity/file_transfer.vala
@@ -70,6 +70,7 @@ public class FileTransfer : Object {
public State state { get; set; default=State.NOT_STARTED; }
public int provider { get; set; }
public string info { get; set; }
+ public uint64 transferred_bytes {get; set; }
public Cancellable cancellable { get; default=new Cancellable(); }
private Database? db;
diff --git a/libdino/src/service/file_manager.vala b/libdino/src/service/file_manager.vala
index 2ef79d84..a83af2d5 100644
--- a/libdino/src/service/file_manager.vala
+++ b/libdino/src/service/file_manager.vala
@@ -120,6 +120,7 @@ public class FileManager : StreamInteractionModule, Object {
}
yield file_sender.send_file(conversation, file_transfer, file_send_data, file_meta);
+ file_transfer.state = FileTransfer.State.COMPLETE;
} catch (Error e) {
warning("Send file error: %s", e.message);
@@ -253,6 +254,7 @@ public class FileManager : StreamInteractionModule, Object {
ssize_t read;
while ((read = yield input_stream.read_async(buffer, Priority.LOW, file_transfer.cancellable)) > 0) {
buffer.length = (int) read;
+ file_transfer.transferred_bytes += (uint64)read;
yield os.write_async(buffer, Priority.LOW, file_transfer.cancellable);
buffer.length = 1024;
}
@@ -288,6 +290,7 @@ public class FileManager : StreamInteractionModule, Object {
file_transfer.file_name = file_meta.file_name;
file_transfer.size = (int)file_meta.size;
file_transfer.info = info;
+ file_transfer.transferred_bytes = 0;
var encryption = file_provider.get_encryption(file_transfer, receive_data, file_meta);
if (encryption != Encryption.NONE) file_transfer.encryption = encryption;
@@ -324,7 +327,7 @@ public class FileManager : StreamInteractionModule, Object {
File file = File.new_for_path(Path.build_filename(get_storage_dir(), filename));
OutputStream os = file.create(FileCreateFlags.REPLACE_DESTINATION);
yield os.splice_async(file_transfer.input_stream, OutputStreamSpliceFlags.CLOSE_SOURCE|OutputStreamSpliceFlags.CLOSE_TARGET);
- file_transfer.state = FileTransfer.State.COMPLETE;
+ file_transfer.state = FileTransfer.State.IN_PROGRESS;
file_transfer.path = filename;
file_transfer.input_stream = yield file.read_async();
} catch (Error e) {
diff --git a/libdino/src/service/jingle_file_transfers.vala b/libdino/src/service/jingle_file_transfers.vala
index 624be607..733376ba 100644
--- a/libdino/src/service/jingle_file_transfers.vala
+++ b/libdino/src/service/jingle_file_transfers.vala
@@ -220,7 +220,19 @@ public class JingleFileSender : FileSender, Object {
}
}
try {
- yield stream.get_module(Xep.JingleFileTransfer.Module.IDENTITY).offer_file_stream(stream, full_jid, file_transfer.input_stream, file_transfer.server_file_name, file_meta.size, precondition_name, precondition_options);
+ var? module = stream.get_module(Xep.JingleFileTransfer.Module.IDENTITY);
+
+ if (module == null)
+ throw new FileSendError.UPLOAD_FAILED("unexpected null module");
+
+ module.transferred_bytes.connect((bytes) => {
+ file_transfer.transferred_bytes += bytes;
+ });
+
+ yield module.offer_file_stream(stream, full_jid,
+ file_transfer.cancellable, file_transfer.input_stream,
+ file_transfer.server_file_name, file_meta.size,
+ precondition_name, precondition_options);
} catch (Error e) {
throw new FileSendError.UPLOAD_FAILED(@"offer_file_stream failed: $(e.message)");
}
diff --git a/main/src/ui/conversation_content_view/file_default_widget.vala b/main/src/ui/conversation_content_view/file_default_widget.vala
index 638dab15..79d22fe4 100644
--- a/main/src/ui/conversation_content_view/file_default_widget.vala
+++ b/main/src/ui/conversation_content_view/file_default_widget.vala
@@ -31,7 +31,8 @@ public class FileDefaultWidget : EventBox {
cancel_button = new ModelButton() { text=_("Cancel"), visible=true };
}
- public void update_file_info(string? mime_type, FileTransfer.State state, long size) {
+ public void update_file_info(string? mime_type, uint64 transferred_bytes,
+ bool direction, FileTransfer.State state, long size) {
this.state = state;
spinner.active = false; // A hidden spinning spinner still uses CPU. Deactivate asap
@@ -58,7 +59,17 @@ public class FileDefaultWidget : EventBox {
popover_menu.closed.connect(on_pointer_left);
break;
case FileTransfer.State.IN_PROGRESS:
- mime_label.label = _("Downloading %s…").printf(get_size_string(size));
+ uint progress = 0;
+
+ if (size > 0)
+ progress = (uint)((transferred_bytes * (uint64)100) / (uint64)size);
+
+ if (direction == FileTransfer.DIRECTION_SENT) {
+ mime_label.label = _("Uploading %s (%u%%)…").printf(get_size_string(size), progress);
+ }
+ else {
+ mime_label.label = _("Downloading %s (%u%%)…").printf(get_size_string(size), progress);
+ }
spinner.active = true;
image_stack.set_visible_child_name("spinner");
diff --git a/main/src/ui/conversation_content_view/file_widget.vala b/main/src/ui/conversation_content_view/file_widget.vala
index cac6fda4..54953d72 100644
--- a/main/src/ui/conversation_content_view/file_widget.vala
+++ b/main/src/ui/conversation_content_view/file_widget.vala
@@ -65,7 +65,8 @@ public class FileWidget : SizeRequestBox {
}
private async void update_widget() {
- if (show_image() && state != State.IMAGE) {
+ if (show_image() && state != State.IMAGE
+ && file_transfer.state == FileTransfer.State.COMPLETE) {
var content_bak = content;
FileImageWidget file_image_widget = null;
@@ -120,6 +121,7 @@ public class FileDefaultWidgetController : Object {
public string file_transfer_path { get; set; }
public string file_transfer_state { get; set; }
public string file_transfer_mime_type { get; set; }
+ public uint64 file_transfer_transferred_bytes { get; set; }
private StreamInteractor? stream_interactor;
private string file_uri;
@@ -143,10 +145,12 @@ public class FileDefaultWidgetController : Object {
file_transfer.bind_property("path", this, "file-transfer-path");
file_transfer.bind_property("state", this, "file-transfer-state");
file_transfer.bind_property("mime-type", this, "file-transfer-mime-type");
+ file_transfer.bind_property("transferred-bytes", this, "file-transfer-transferred-bytes");
this.notify["file-transfer-path"].connect(update_file_info);
this.notify["file-transfer-state"].connect(update_file_info);
this.notify["file-transfer-mime-type"].connect(update_file_info);
+ this.notify["file-transfer-transferred-bytes"].connect(update_file_info);
update_file_info();
}
@@ -155,13 +159,15 @@ public class FileDefaultWidgetController : Object {
file_uri = file.get_uri();
state = FileTransfer.State.COMPLETE;
widget.name_label.label = this.file_name = file_name;
- widget.update_file_info(mime_type, state, -1);
+ widget.update_file_info(mime_type, 0, false, state, -1);
}
private void update_file_info() {
file_uri = file_transfer.get_file().get_uri();
state = file_transfer.state;
- widget.update_file_info(file_transfer.mime_type, file_transfer.state, file_transfer.size);
+ widget.update_file_info(file_transfer.mime_type,
+ file_transfer.transferred_bytes,
+ file_transfer.direction, file_transfer.state, file_transfer.size);
}
private void open_file() {
diff --git a/main/src/ui/file_send_overlay.vala b/main/src/ui/file_send_overlay.vala
index 369d291a..ac3a275b 100644
--- a/main/src/ui/file_send_overlay.vala
+++ b/main/src/ui/file_send_overlay.vala
@@ -74,7 +74,8 @@ public class FileSendOverlay : Gtk.EventBox {
if (widget == null) {
FileDefaultWidget default_widget = new FileDefaultWidget() { visible=true };
default_widget.name_label.label = file_name;
- default_widget.update_file_info(mime_type, FileTransfer.State.COMPLETE, (long)file_info.get_size());
+ default_widget.update_file_info(mime_type, 0, FileTransfer.DIRECTION_SENT,
+ FileTransfer.State.COMPLETE, (long)file_info.get_size());
widget = default_widget;
}
diff --git a/plugins/http-files/src/file_sender.vala b/plugins/http-files/src/file_sender.vala
index 8f9f02fc..17dbc6cf 100644
--- a/plugins/http-files/src/file_sender.vala
+++ b/plugins/http-files/src/file_sender.vala
@@ -106,6 +106,18 @@ public class HttpFileSender : FileSender, Object {
put_message.wrote_headers.connect(() => transfer_more_bytes(file_transfer.input_stream, put_message.request_body));
put_message.wrote_chunk.connect(() => transfer_more_bytes(file_transfer.input_stream, put_message.request_body));
#endif
+
+ file_transfer.transferred_bytes = 0;
+ put_message.wrote_body_data.connect((chunk) => {
+ if (file_transfer.size != 0) {
+#if SOUP_3_0
+ file_transfer.transferred_bytes += chunk;
+#else
+ file_transfer.transferred_bytes += chunk.length;
+#endif
+ }
+ });
+
foreach (var entry in file_send_data.headers.entries) {
put_message.request_headers.append(entry.key, entry.value);
}
diff --git a/xmpp-vala/src/module/xep/0234_jingle_file_transfer.vala b/xmpp-vala/src/module/xep/0234_jingle_file_transfer.vala
index f85049ac..d9c3b658 100644
--- a/xmpp-vala/src/module/xep/0234_jingle_file_transfer.vala
+++ b/xmpp-vala/src/module/xep/0234_jingle_file_transfer.vala
@@ -8,6 +8,7 @@ private const string NS_URI = "urn:xmpp:jingle:apps:file-transfer:5";
public class Module : Jingle.ContentType, XmppStreamModule {
+ public signal void transferred_bytes(size_t bytes);
public signal void file_incoming(XmppStream stream, FileTransfer file_transfer);
public static Xmpp.ModuleIdentity<Module> IDENTITY = new Xmpp.ModuleIdentity<Module>(NS_URI, "0234_jingle_file_transfer");
@@ -42,7 +43,10 @@ public class Module : Jingle.ContentType, XmppStreamModule {
return yield stream.get_module(Jingle.Module.IDENTITY).is_available(stream, required_transport_type, required_components, full_jid);
}
- public async void offer_file_stream(XmppStream stream, Jid receiver_full_jid, InputStream input_stream, string basename, int64 size, string? precondition_name = null, Object? precondition_options = null) throws Jingle.Error {
+ public async void offer_file_stream(XmppStream stream, Jid receiver_full_jid,
+ Cancellable cancellable, InputStream input_stream, string basename,
+ int64 size, string? precondition_name = null,
+ Object? precondition_options = null) throws Jingle.Error {
StanzaNode file_node;
StanzaNode description = new StanzaNode.build("description", NS_URI)
.add_self_xmlns()
@@ -107,7 +111,18 @@ public class Module : Jingle.ContentType, XmppStreamModule {
}
IOStream io_stream = yield connection.stream.wait_async();
yield io_stream.input_stream.close_async();
- yield io_stream.output_stream.splice_async(input_stream, OutputStreamSpliceFlags.CLOSE_SOURCE|OutputStreamSpliceFlags.CLOSE_TARGET);
+
+ ssize_t read;
+ var buffer = new uint8[1024];
+ while ((read = yield input_stream.read_async(buffer, Priority.LOW, cancellable)) > 0) {
+ buffer.length = (int) read;
+ transferred_bytes((size_t)read);
+ yield io_stream.output_stream.write_async(buffer, Priority.LOW, cancellable);
+ buffer.length = 1024;
+ }
+
+ yield input_stream.close_async();
+ yield io_stream.output_stream.close_async();
yield connection.terminate(true);
} catch (Error e) {
if (session != null) {