Skip to content

Commit a791906

Browse files
authored
refactor(file transfers): massive refactoring (#136)
In order to accomplish a complete refactoring of the `ChatView` code, I merged both `InlineImageMessageListRow` and `InlineFileMessageListRow` into `FileListRow`, also currently working on having progress bar + inline images working correctly. This commit also add the ability to paste an image into Ricin to send it: * Firefox: Right click an image → Copy image. * Ricin: `ctrl+v` → Image is sent to friend.
1 parent d524c1e commit a791906

7 files changed

Lines changed: 600 additions & 23 deletions

File tree

res/ricin.gresource.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<file preprocess="xml-stripblanks" compressed="true">ui/main-window.ui</file>
55
<file preprocess="xml-stripblanks" compressed="true">ui/profile-chooser-window.ui</file>
66
<file preprocess="xml-stripblanks" compressed="true">ui/friend-list-row.ui</file>
7+
<file preprocess="xml-stripblanks" compressed="true">ui/file-list-row.ui</file>
78
<file preprocess="xml-stripblanks" compressed="true">ui/status-message-list-row.ui</file>
89
<file preprocess="xml-stripblanks" compressed="true">ui/system-message-list-row.ui</file>
910
<file preprocess="xml-stripblanks" compressed="true">ui/inline-image-message-list-row.ui</file>

res/ui/file-list-row.ui

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!-- Generated with glade 3.19.0 -->
3+
<interface>
4+
<requires lib="gtk+" version="3.16"/>
5+
<template class="RicinFileListRow" parent="GtkListBoxRow">
6+
<property name="width_request">250</property>
7+
<property name="height_request">20</property>
8+
<property name="visible">True</property>
9+
<property name="can_focus">True</property>
10+
<property name="resize_mode">queue</property>
11+
<property name="activatable">False</property>
12+
<property name="selectable">False</property>
13+
<child>
14+
<object class="GtkEventBox" id="eventbox1">
15+
<property name="visible">True</property>
16+
<property name="can_focus">False</property>
17+
<child>
18+
<object class="GtkBox" id="box1">
19+
<property name="visible">True</property>
20+
<property name="can_focus">False</property>
21+
<property name="spacing">5</property>
22+
<child>
23+
<object class="GtkLabel" id="label_name">
24+
<property name="width_request">80</property>
25+
<property name="height_request">20</property>
26+
<property name="visible">True</property>
27+
<property name="can_focus">False</property>
28+
<property name="halign">start</property>
29+
<property name="valign">start</property>
30+
<property name="label">label</property>
31+
<property name="selectable">True</property>
32+
<property name="ellipsize">end</property>
33+
<property name="width_chars">12</property>
34+
<property name="single_line_mode">True</property>
35+
<property name="max_width_chars">12</property>
36+
<property name="track_visited_links">False</property>
37+
<attributes>
38+
<attribute name="weight" value="bold"/>
39+
</attributes>
40+
</object>
41+
<packing>
42+
<property name="expand">False</property>
43+
<property name="fill">False</property>
44+
<property name="position">0</property>
45+
</packing>
46+
</child>
47+
<child>
48+
<object class="GtkBox" id="box_widget">
49+
<property name="visible">True</property>
50+
<property name="can_focus">False</property>
51+
<property name="valign">start</property>
52+
<child>
53+
<object class="GtkBox" id="box2">
54+
<property name="visible">True</property>
55+
<property name="can_focus">False</property>
56+
<property name="orientation">vertical</property>
57+
<child>
58+
<object class="GtkAspectFrame" id="aspectframe_preview">
59+
<property name="visible">True</property>
60+
<property name="can_focus">False</property>
61+
<property name="label_xalign">0</property>
62+
<property name="shadow_type">none</property>
63+
<child>
64+
<object class="GtkImage" id="image_preview">
65+
<property name="can_focus">False</property>
66+
<property name="stock">gtk-missing-image</property>
67+
</object>
68+
</child>
69+
</object>
70+
<packing>
71+
<property name="expand">False</property>
72+
<property name="fill">False</property>
73+
<property name="position">0</property>
74+
</packing>
75+
</child>
76+
<child>
77+
<object class="GtkBox" id="box3">
78+
<property name="visible">True</property>
79+
<property name="can_focus">False</property>
80+
<property name="spacing">5</property>
81+
<child>
82+
<object class="GtkBox" id="box_background">
83+
<property name="visible">True</property>
84+
<property name="can_focus">False</property>
85+
<property name="spacing">5</property>
86+
<child>
87+
<object class="GtkImage" id="image_file_type">
88+
<property name="name">50</property>
89+
<property name="width_request">30</property>
90+
<property name="visible">True</property>
91+
<property name="can_focus">False</property>
92+
<property name="halign">start</property>
93+
<property name="icon_name">text-x-generic-symbolic</property>
94+
</object>
95+
<packing>
96+
<property name="expand">False</property>
97+
<property name="fill">True</property>
98+
<property name="position">0</property>
99+
</packing>
100+
</child>
101+
<child>
102+
<object class="GtkLabel" id="label_file_name">
103+
<property name="visible">True</property>
104+
<property name="can_focus">False</property>
105+
<property name="halign">start</property>
106+
<property name="margin_top">2</property>
107+
<property name="margin_bottom">2</property>
108+
<property name="label">file_name.ext</property>
109+
<property name="ellipsize">end</property>
110+
<property name="max_width_chars">30</property>
111+
</object>
112+
<packing>
113+
<property name="expand">False</property>
114+
<property name="fill">True</property>
115+
<property name="position">1</property>
116+
</packing>
117+
</child>
118+
<child>
119+
<object class="GtkProgressBar" id="progress_file_percent">
120+
<property name="can_focus">False</property>
121+
<property name="valign">center</property>
122+
</object>
123+
<packing>
124+
<property name="expand">True</property>
125+
<property name="fill">True</property>
126+
<property name="position">2</property>
127+
</packing>
128+
</child>
129+
<child>
130+
<object class="GtkLabel" id="label_file_size">
131+
<property name="visible">True</property>
132+
<property name="can_focus">False</property>
133+
<property name="halign">end</property>
134+
<property name="label">(0 Kb)</property>
135+
</object>
136+
<packing>
137+
<property name="expand">False</property>
138+
<property name="fill">True</property>
139+
<property name="position">3</property>
140+
</packing>
141+
</child>
142+
</object>
143+
<packing>
144+
<property name="expand">True</property>
145+
<property name="fill">True</property>
146+
<property name="position">0</property>
147+
</packing>
148+
</child>
149+
<child>
150+
<object class="GtkBox" id="box4">
151+
<property name="visible">True</property>
152+
<property name="can_focus">False</property>
153+
<child>
154+
<object class="GtkButton" id="button_reject">
155+
<property name="width_request">20</property>
156+
<property name="height_request">20</property>
157+
<property name="visible">True</property>
158+
<property name="can_focus">True</property>
159+
<property name="receives_default">True</property>
160+
<property name="tooltip_text" translatable="yes">Cancel/pause file</property>
161+
<property name="halign">center</property>
162+
<property name="valign">center</property>
163+
<property name="always_show_image">True</property>
164+
<signal name="clicked" handler="reject_file" swapped="no"/>
165+
<child>
166+
<object class="GtkImage" id="image_reject_inline">
167+
<property name="visible">True</property>
168+
<property name="can_focus">False</property>
169+
<property name="pixel_size">16</property>
170+
<property name="icon_name">window-close-symbolic</property>
171+
</object>
172+
</child>
173+
<style>
174+
<class name="btn-save-image"/>
175+
</style>
176+
</object>
177+
<packing>
178+
<property name="expand">False</property>
179+
<property name="fill">True</property>
180+
<property name="position">0</property>
181+
</packing>
182+
</child>
183+
<child>
184+
<object class="GtkButton" id="button_save">
185+
<property name="width_request">20</property>
186+
<property name="height_request">20</property>
187+
<property name="visible">True</property>
188+
<property name="can_focus">True</property>
189+
<property name="receives_default">True</property>
190+
<property name="tooltip_text" translatable="yes">Accept/Resume file</property>
191+
<property name="halign">center</property>
192+
<property name="valign">center</property>
193+
<property name="always_show_image">True</property>
194+
<signal name="clicked" handler="save_file" swapped="no"/>
195+
<child>
196+
<object class="GtkImage" id="image_save_inline">
197+
<property name="visible">True</property>
198+
<property name="can_focus">False</property>
199+
<property name="pixel_size">16</property>
200+
<property name="icon_name">object-select-symbolic</property>
201+
</object>
202+
</child>
203+
<style>
204+
<class name="btn-save-image"/>
205+
</style>
206+
</object>
207+
<packing>
208+
<property name="expand">False</property>
209+
<property name="fill">True</property>
210+
<property name="position">1</property>
211+
</packing>
212+
</child>
213+
</object>
214+
<packing>
215+
<property name="expand">False</property>
216+
<property name="fill">True</property>
217+
<property name="position">1</property>
218+
</packing>
219+
</child>
220+
<style>
221+
<class name="image-desc"/>
222+
</style>
223+
</object>
224+
<packing>
225+
<property name="expand">False</property>
226+
<property name="fill">True</property>
227+
<property name="position">1</property>
228+
</packing>
229+
</child>
230+
</object>
231+
<packing>
232+
<property name="expand">True</property>
233+
<property name="fill">True</property>
234+
<property name="position">0</property>
235+
</packing>
236+
</child>
237+
</object>
238+
<packing>
239+
<property name="expand">True</property>
240+
<property name="fill">True</property>
241+
<property name="position">1</property>
242+
</packing>
243+
</child>
244+
<child>
245+
<object class="GtkLabel" id="label_timestamp">
246+
<property name="width_request">70</property>
247+
<property name="height_request">20</property>
248+
<property name="visible">True</property>
249+
<property name="can_focus">False</property>
250+
<property name="halign">end</property>
251+
<property name="valign">start</property>
252+
<property name="label">00:00.00</property>
253+
<property name="justify">right</property>
254+
<property name="selectable">True</property>
255+
<property name="ellipsize">end</property>
256+
<property name="single_line_mode">True</property>
257+
<attributes>
258+
<attribute name="size" value="9000"/>
259+
</attributes>
260+
</object>
261+
<packing>
262+
<property name="expand">False</property>
263+
<property name="fill">True</property>
264+
<property name="position">2</property>
265+
</packing>
266+
</child>
267+
</object>
268+
</child>
269+
</object>
270+
</child>
271+
<style>
272+
<class name="message"/>
273+
</style>
274+
</template>
275+
</interface>

src/ChatView.vala

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ class Ricin.ChatView : Gtk.Box {
183183
this.entry.grab_focus_without_selecting ();
184184
});
185185

186+
this.entry.paste_clipboard.connect (this.paste_clipboard);
187+
186188
fr.friend_info.connect ((message) => {
187189
this.last_message_sender = "friend";
188190
messages_list.add (new SystemMessageListRow (message));
@@ -289,20 +291,21 @@ class Ricin.ChatView : Gtk.Box {
289291
/**
290292
* TODO: debug this.
291293
**/
292-
/*if (file_content_type.has_prefix ("image/")) {
293-
var image_row = new InlineImageMessageListRow (this.handle, fr, id, fr.name, path, time (), false);
294-
image_row.accept_image.connect ((response, file_id) => {
294+
if (file_content_type.has_prefix ("image/")) {
295+
this.last_message_sender = "friend";
296+
var image_row = new FileListRow (this.handle, fr, id, fr.name, path, size, time ());
297+
image_row.accept_file.connect ((response, file_id) => {
295298
fr.reply_file_transfer (response, file_id);
296299
});
297300
messages_list.add (image_row);
298-
} else {*/
299-
this.last_message_sender = "friend";
300-
var file_row = new InlineFileMessageListRow (this.handle, fr, id, fr.name, path, size, time ());
301-
file_row.accept_file.connect ((response, file_id) => {
302-
fr.reply_file_transfer (response, file_id);
303-
});
304-
messages_list.add (file_row);
305-
//}
301+
} else {
302+
this.last_message_sender = "friend";
303+
var file_row = new FileListRow (this.handle, fr, id, fr.name, path, size, time ());
304+
file_row.accept_file.connect ((response, file_id) => {
305+
fr.reply_file_transfer (response, file_id);
306+
});
307+
messages_list.add (file_row);
308+
}
306309
});
307310

308311
fr.bind_property ("connected", entry, "sensitive", BindingFlags.DEFAULT);
@@ -622,6 +625,26 @@ class Ricin.ChatView : Gtk.Box {
622625
}
623626
}
624627

628+
public void paste_clipboard () {
629+
Gtk.Clipboard clipboard = Gtk.Clipboard.get (Gdk.SELECTION_CLIPBOARD);
630+
Gdk.Pixbuf image = clipboard.wait_for_image ();
631+
632+
Rand rnd = new Rand.with_seed ((uint32)new DateTime.now_local ().hash ());
633+
uint32 rnd_id = rnd.next_int ();
634+
string image_name = @"ricin-$rnd_id.png";
635+
636+
if (image != null) { // Cool, the content is an image, let's send it to our friend!
637+
uint32 file_id = this.fr.send_image (image, image_name);
638+
639+
// Finally, add the inline image to the ChatView
640+
var image_widget = new FileListRow (
641+
this.handle, this.fr, file_id, this.handle.username,
642+
"", image.get_byte_length (), time (), false, image, image_name
643+
);
644+
messages_list.add (image_widget);
645+
}
646+
}
647+
625648
[GtkCallback]
626649
private void toggle_friend_menu () {
627650
this.revealer_friend_menu.set_reveal_child (!this.revealer_friend_menu.child_revealed);
@@ -722,12 +745,18 @@ class Ricin.ChatView : Gtk.Box {
722745

723746
if (file_content_type.has_prefix ("image/")) {
724747
/*var pixbuf = new Gdk.Pixbuf.from_file_at_scale (filename, 400, 250, true);*/
725-
var image_widget = new InlineImageMessageListRow (this.handle, fr, file_id, this.handle.username, file.get_path (), time (), true);
726-
image_widget.button_save_inline.visible = false;
748+
var image_widget = new FileListRow (
749+
this.handle, fr, file_id, this.handle.username,
750+
file.get_path (), size, time (), true
751+
);
752+
//image_widget.button_save_inline.visible = false;
727753
messages_list.add (image_widget);
728754
} else {
729755
//fr.friend_info (@"Sending file $filename");
730-
var file_row = new InlineFileMessageListRow (this.handle, fr, file_id, this.handle.username, filename, size, time ());
756+
var file_row = new FileListRow (
757+
this.handle, fr, file_id, this.handle.username,
758+
filename, size, time (), false
759+
);
731760
messages_list.add (file_row);
732761
}
733762
}

0 commit comments

Comments
 (0)