diff options
author | TheJackiMonster <thejackimonster@gmail.com> | 2021-11-14 17:31:52 +0100 |
---|---|---|
committer | TheJackiMonster <thejackimonster@gmail.com> | 2021-11-14 17:31:52 +0100 |
commit | 56a206cd17e1caf23fbfd679c39752e5e194f35d (patch) | |
tree | e1667b9a2ef09c269bb8ee7260af719e28583f5f | |
parent | 83bf19ca1bc25c2162fa7e1d9f06644dd7e6b267 (diff) | |
download | messenger-gtk-56a206cd17e1caf23fbfd679c39752e5e194f35d.tar.gz messenger-gtk-56a206cd17e1caf23fbfd679c39752e5e194f35d.zip |
Implemented multiple chats in parallel
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | resources/ui/chat.ui | 268 | ||||
-rw-r--r-- | resources/ui/messenger.ui | 250 | ||||
-rw-r--r-- | src/application.c | 4 | ||||
-rw-r--r-- | src/event.c | 86 | ||||
-rw-r--r-- | src/ui/chat.c | 249 | ||||
-rw-r--r-- | src/ui/chat.h | 59 | ||||
-rw-r--r-- | src/ui/chat_entry.c | 14 | ||||
-rw-r--r-- | src/ui/chat_entry.h | 12 | ||||
-rw-r--r-- | src/ui/messenger.c | 215 | ||||
-rw-r--r-- | src/ui/messenger.h | 17 |
11 files changed, 672 insertions, 503 deletions
@@ -7,6 +7,7 @@ SOURCES = messenger_gtk.c\ | |||
7 | application.c\ | 7 | application.c\ |
8 | event.c\ | 8 | event.c\ |
9 | chat/messenger.c\ | 9 | chat/messenger.c\ |
10 | ui/chat.c\ | ||
10 | ui/chat_entry.c\ | 11 | ui/chat_entry.c\ |
11 | ui/message.c\ | 12 | ui/message.c\ |
12 | ui/messenger.c\ | 13 | ui/messenger.c\ |
diff --git a/resources/ui/chat.ui b/resources/ui/chat.ui new file mode 100644 index 0000000..c7f333c --- /dev/null +++ b/resources/ui/chat.ui | |||
@@ -0,0 +1,268 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <!-- Generated with glade 3.38.2 | ||
3 | |||
4 | Copyright (C) 2021 GNUnet e.V. | ||
5 | |||
6 | GNUnet is free software: you can redistribute it and/or modify it | ||
7 | under the terms of the GNU Affero General Public License as published | ||
8 | by the Free Software Foundation, either version 3 of the License, | ||
9 | or (at your option) any later version. | ||
10 | |||
11 | GNUnet is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | Affero General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU Affero General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | |||
19 | SPDX-License-Identifier: AGPL3.0-or-later | ||
20 | Author: Tobias Frisch | ||
21 | |||
22 | --> | ||
23 | <interface> | ||
24 | <requires lib="gtk+" version="3.24"/> | ||
25 | <object class="GtkBox" id="chat_box"> | ||
26 | <property name="visible">True</property> | ||
27 | <property name="can-focus">False</property> | ||
28 | <property name="orientation">vertical</property> | ||
29 | <child> | ||
30 | <object class="GtkBox" id="chat-header-box"> | ||
31 | <property name="visible">True</property> | ||
32 | <property name="can-focus">False</property> | ||
33 | <property name="margin-start">8</property> | ||
34 | <property name="margin-end">8</property> | ||
35 | <property name="margin-top">8</property> | ||
36 | <property name="margin-bottom">8</property> | ||
37 | <property name="spacing">8</property> | ||
38 | <child> | ||
39 | <object class="GtkButton" id="back_button"> | ||
40 | <property name="visible">True</property> | ||
41 | <property name="can-focus">True</property> | ||
42 | <property name="receives-default">True</property> | ||
43 | <property name="relief">none</property> | ||
44 | <child> | ||
45 | <object class="GtkImage"> | ||
46 | <property name="visible">True</property> | ||
47 | <property name="can-focus">False</property> | ||
48 | <property name="icon-name">go-previous-symbolic</property> | ||
49 | </object> | ||
50 | </child> | ||
51 | </object> | ||
52 | <packing> | ||
53 | <property name="expand">False</property> | ||
54 | <property name="fill">True</property> | ||
55 | <property name="position">0</property> | ||
56 | </packing> | ||
57 | </child> | ||
58 | <child> | ||
59 | <object class="GtkBox"> | ||
60 | <property name="visible">True</property> | ||
61 | <property name="can-focus">False</property> | ||
62 | <property name="halign">start</property> | ||
63 | <property name="margin-start">4</property> | ||
64 | <property name="margin-end">4</property> | ||
65 | <property name="orientation">vertical</property> | ||
66 | <child> | ||
67 | <object class="GtkLabel" id="chat_title"> | ||
68 | <property name="visible">True</property> | ||
69 | <property name="can-focus">False</property> | ||
70 | <property name="label" translatable="yes">Chat title</property> | ||
71 | <property name="xalign">0</property> | ||
72 | <attributes> | ||
73 | <attribute name="weight" value="bold"/> | ||
74 | </attributes> | ||
75 | </object> | ||
76 | <packing> | ||
77 | <property name="expand">False</property> | ||
78 | <property name="fill">True</property> | ||
79 | <property name="position">0</property> | ||
80 | </packing> | ||
81 | </child> | ||
82 | <child> | ||
83 | <object class="GtkLabel" id="chat_subtitle"> | ||
84 | <property name="visible">True</property> | ||
85 | <property name="can-focus">False</property> | ||
86 | <property name="label" translatable="yes">Chat subtitle</property> | ||
87 | <property name="xalign">0</property> | ||
88 | <attributes> | ||
89 | <attribute name="weight" value="light"/> | ||
90 | </attributes> | ||
91 | </object> | ||
92 | <packing> | ||
93 | <property name="expand">True</property> | ||
94 | <property name="fill">True</property> | ||
95 | <property name="position">1</property> | ||
96 | </packing> | ||
97 | </child> | ||
98 | </object> | ||
99 | <packing> | ||
100 | <property name="expand">True</property> | ||
101 | <property name="fill">True</property> | ||
102 | <property name="position">1</property> | ||
103 | </packing> | ||
104 | </child> | ||
105 | <child> | ||
106 | <object class="GtkButton" id="chat_details_button"> | ||
107 | <property name="visible">True</property> | ||
108 | <property name="can-focus">True</property> | ||
109 | <property name="receives-default">True</property> | ||
110 | <property name="relief">none</property> | ||
111 | <child> | ||
112 | <object class="GtkImage"> | ||
113 | <property name="visible">True</property> | ||
114 | <property name="can-focus">False</property> | ||
115 | <property name="icon-name">view-more-symbolic</property> | ||
116 | </object> | ||
117 | </child> | ||
118 | </object> | ||
119 | <packing> | ||
120 | <property name="expand">False</property> | ||
121 | <property name="fill">True</property> | ||
122 | <property name="pack-type">end</property> | ||
123 | <property name="position">1</property> | ||
124 | </packing> | ||
125 | </child> | ||
126 | </object> | ||
127 | <packing> | ||
128 | <property name="expand">False</property> | ||
129 | <property name="fill">True</property> | ||
130 | <property name="position">0</property> | ||
131 | </packing> | ||
132 | </child> | ||
133 | <child> | ||
134 | <object class="GtkScrolledWindow"> | ||
135 | <property name="visible">True</property> | ||
136 | <property name="can-focus">True</property> | ||
137 | <child> | ||
138 | <object class="GtkViewport"> | ||
139 | <property name="visible">True</property> | ||
140 | <property name="can-focus">False</property> | ||
141 | <child> | ||
142 | <object class="GtkStack"> | ||
143 | <property name="visible">True</property> | ||
144 | <property name="can-focus">False</property> | ||
145 | <child> | ||
146 | <object class="GtkListBox" id="messages_listbox"> | ||
147 | <property name="visible">True</property> | ||
148 | <property name="can-focus">False</property> | ||
149 | <property name="selection-mode">none</property> | ||
150 | <property name="activate-on-single-click">False</property> | ||
151 | </object> | ||
152 | <packing> | ||
153 | <property name="name">page0</property> | ||
154 | <property name="title" translatable="yes">page0</property> | ||
155 | </packing> | ||
156 | </child> | ||
157 | </object> | ||
158 | </child> | ||
159 | </object> | ||
160 | </child> | ||
161 | </object> | ||
162 | <packing> | ||
163 | <property name="expand">True</property> | ||
164 | <property name="fill">True</property> | ||
165 | <property name="position">1</property> | ||
166 | </packing> | ||
167 | </child> | ||
168 | <child> | ||
169 | <object class="GtkBox"> | ||
170 | <property name="visible">True</property> | ||
171 | <property name="can-focus">False</property> | ||
172 | <property name="margin-start">8</property> | ||
173 | <property name="margin-end">8</property> | ||
174 | <property name="margin-top">4</property> | ||
175 | <property name="margin-bottom">4</property> | ||
176 | <property name="spacing">4</property> | ||
177 | <child> | ||
178 | <object class="GtkButton" id="attach_file_button"> | ||
179 | <property name="visible">True</property> | ||
180 | <property name="can-focus">True</property> | ||
181 | <property name="receives-default">True</property> | ||
182 | <property name="valign">center</property> | ||
183 | <property name="relief">none</property> | ||
184 | <child> | ||
185 | <object class="GtkImage"> | ||
186 | <property name="visible">True</property> | ||
187 | <property name="can-focus">False</property> | ||
188 | <property name="icon-name">mail-attachment-symbolic</property> | ||
189 | </object> | ||
190 | </child> | ||
191 | </object> | ||
192 | <packing> | ||
193 | <property name="expand">False</property> | ||
194 | <property name="fill">True</property> | ||
195 | <property name="position">0</property> | ||
196 | </packing> | ||
197 | </child> | ||
198 | <child> | ||
199 | <object class="GtkTextView" id="send_text_view"> | ||
200 | <property name="width-request">210</property> | ||
201 | <property name="height-request">48</property> | ||
202 | <property name="visible">True</property> | ||
203 | <property name="can-focus">True</property> | ||
204 | <property name="valign">end</property> | ||
205 | <property name="wrap-mode">word-char</property> | ||
206 | <property name="left-margin">8</property> | ||
207 | <property name="right-margin">8</property> | ||
208 | <property name="top-margin">8</property> | ||
209 | <property name="bottom-margin">8</property> | ||
210 | <property name="input-hints">GTK_INPUT_HINT_SPELLCHECK | GTK_INPUT_HINT_WORD_COMPLETION | GTK_INPUT_HINT_INHIBIT_OSK | GTK_INPUT_HINT_EMOJI | GTK_INPUT_HINT_NONE</property> | ||
211 | </object> | ||
212 | <packing> | ||
213 | <property name="expand">True</property> | ||
214 | <property name="fill">True</property> | ||
215 | <property name="position">1</property> | ||
216 | </packing> | ||
217 | </child> | ||
218 | <child> | ||
219 | <object class="GtkButton" id="emoji_button"> | ||
220 | <property name="visible">True</property> | ||
221 | <property name="can-focus">True</property> | ||
222 | <property name="receives-default">True</property> | ||
223 | <property name="valign">center</property> | ||
224 | <property name="relief">none</property> | ||
225 | <child> | ||
226 | <object class="GtkImage"> | ||
227 | <property name="visible">True</property> | ||
228 | <property name="can-focus">False</property> | ||
229 | <property name="icon-name">face-smile-symbolic</property> | ||
230 | </object> | ||
231 | </child> | ||
232 | </object> | ||
233 | <packing> | ||
234 | <property name="expand">False</property> | ||
235 | <property name="fill">True</property> | ||
236 | <property name="position">2</property> | ||
237 | </packing> | ||
238 | </child> | ||
239 | <child> | ||
240 | <object class="GtkButton" id="send_record_button"> | ||
241 | <property name="visible">True</property> | ||
242 | <property name="can-focus">True</property> | ||
243 | <property name="receives-default">True</property> | ||
244 | <property name="valign">center</property> | ||
245 | <property name="relief">none</property> | ||
246 | <child> | ||
247 | <object class="GtkImage" id="send_record_symbol"> | ||
248 | <property name="visible">True</property> | ||
249 | <property name="can-focus">False</property> | ||
250 | <property name="icon-name">audio-input-microphone-symbolic</property> | ||
251 | </object> | ||
252 | </child> | ||
253 | </object> | ||
254 | <packing> | ||
255 | <property name="expand">False</property> | ||
256 | <property name="fill">True</property> | ||
257 | <property name="position">3</property> | ||
258 | </packing> | ||
259 | </child> | ||
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 | </interface> | ||
diff --git a/resources/ui/messenger.ui b/resources/ui/messenger.ui index 79ea388..1c9b2cd 100644 --- a/resources/ui/messenger.ui +++ b/resources/ui/messenger.ui | |||
@@ -717,248 +717,12 @@ Author: Tobias Frisch | |||
717 | <property name="flap-position">end</property> | 717 | <property name="flap-position">end</property> |
718 | <property name="reveal-flap">False</property> | 718 | <property name="reveal-flap">False</property> |
719 | <property name="fold-policy">always</property> | 719 | <property name="fold-policy">always</property> |
720 | <child type="content"> | 720 | <child> |
721 | <object class="GtkBox"> | 721 | <object class="GtkStack" id="chats_stack"> |
722 | <property name="visible">True</property> | 722 | <property name="visible">True</property> |
723 | <property name="can-focus">False</property> | 723 | <property name="can-focus">False</property> |
724 | <property name="orientation">vertical</property> | ||
725 | <child> | 724 | <child> |
726 | <object class="GtkBox" id="chat-header-box"> | 725 | <placeholder/> |
727 | <property name="visible">True</property> | ||
728 | <property name="can-focus">False</property> | ||
729 | <property name="margin-start">8</property> | ||
730 | <property name="margin-end">8</property> | ||
731 | <property name="margin-top">8</property> | ||
732 | <property name="margin-bottom">8</property> | ||
733 | <property name="spacing">8</property> | ||
734 | <child> | ||
735 | <object class="GtkButton" id="back_button"> | ||
736 | <property name="visible">True</property> | ||
737 | <property name="can-focus">True</property> | ||
738 | <property name="receives-default">True</property> | ||
739 | <property name="relief">none</property> | ||
740 | <child> | ||
741 | <object class="GtkImage"> | ||
742 | <property name="visible">True</property> | ||
743 | <property name="can-focus">False</property> | ||
744 | <property name="icon-name">go-previous-symbolic</property> | ||
745 | </object> | ||
746 | </child> | ||
747 | </object> | ||
748 | <packing> | ||
749 | <property name="expand">False</property> | ||
750 | <property name="fill">True</property> | ||
751 | <property name="position">0</property> | ||
752 | </packing> | ||
753 | </child> | ||
754 | <child> | ||
755 | <object class="GtkBox"> | ||
756 | <property name="visible">True</property> | ||
757 | <property name="can-focus">False</property> | ||
758 | <property name="halign">start</property> | ||
759 | <property name="margin-start">4</property> | ||
760 | <property name="margin-end">4</property> | ||
761 | <property name="orientation">vertical</property> | ||
762 | <child> | ||
763 | <object class="GtkLabel" id="chat_title"> | ||
764 | <property name="visible">True</property> | ||
765 | <property name="can-focus">False</property> | ||
766 | <property name="label" translatable="yes">Chat title</property> | ||
767 | <property name="xalign">0</property> | ||
768 | <attributes> | ||
769 | <attribute name="weight" value="bold"/> | ||
770 | </attributes> | ||
771 | </object> | ||
772 | <packing> | ||
773 | <property name="expand">False</property> | ||
774 | <property name="fill">True</property> | ||
775 | <property name="position">0</property> | ||
776 | </packing> | ||
777 | </child> | ||
778 | <child> | ||
779 | <object class="GtkLabel" id="chat_subtitle"> | ||
780 | <property name="visible">True</property> | ||
781 | <property name="can-focus">False</property> | ||
782 | <property name="label" translatable="yes">Chat subtitle</property> | ||
783 | <property name="xalign">0</property> | ||
784 | <attributes> | ||
785 | <attribute name="weight" value="light"/> | ||
786 | </attributes> | ||
787 | </object> | ||
788 | <packing> | ||
789 | <property name="expand">True</property> | ||
790 | <property name="fill">True</property> | ||
791 | <property name="position">1</property> | ||
792 | </packing> | ||
793 | </child> | ||
794 | </object> | ||
795 | <packing> | ||
796 | <property name="expand">True</property> | ||
797 | <property name="fill">True</property> | ||
798 | <property name="position">1</property> | ||
799 | </packing> | ||
800 | </child> | ||
801 | <child> | ||
802 | <object class="GtkButton" id="chat_details_button"> | ||
803 | <property name="visible">True</property> | ||
804 | <property name="can-focus">True</property> | ||
805 | <property name="receives-default">True</property> | ||
806 | <property name="relief">none</property> | ||
807 | <child> | ||
808 | <object class="GtkImage"> | ||
809 | <property name="visible">True</property> | ||
810 | <property name="can-focus">False</property> | ||
811 | <property name="icon-name">view-more-symbolic</property> | ||
812 | </object> | ||
813 | </child> | ||
814 | </object> | ||
815 | <packing> | ||
816 | <property name="expand">False</property> | ||
817 | <property name="fill">True</property> | ||
818 | <property name="pack-type">end</property> | ||
819 | <property name="position">1</property> | ||
820 | </packing> | ||
821 | </child> | ||
822 | </object> | ||
823 | <packing> | ||
824 | <property name="expand">False</property> | ||
825 | <property name="fill">True</property> | ||
826 | <property name="position">0</property> | ||
827 | </packing> | ||
828 | </child> | ||
829 | <child> | ||
830 | <object class="GtkScrolledWindow"> | ||
831 | <property name="visible">True</property> | ||
832 | <property name="can-focus">True</property> | ||
833 | <child> | ||
834 | <object class="GtkViewport"> | ||
835 | <property name="visible">True</property> | ||
836 | <property name="can-focus">False</property> | ||
837 | <child> | ||
838 | <object class="GtkStack"> | ||
839 | <property name="visible">True</property> | ||
840 | <property name="can-focus">False</property> | ||
841 | <child> | ||
842 | <object class="GtkListBox" id="messages_listbox"> | ||
843 | <property name="visible">True</property> | ||
844 | <property name="can-focus">False</property> | ||
845 | <property name="selection-mode">none</property> | ||
846 | <property name="activate-on-single-click">False</property> | ||
847 | </object> | ||
848 | <packing> | ||
849 | <property name="name">page0</property> | ||
850 | <property name="title" translatable="yes">page0</property> | ||
851 | </packing> | ||
852 | </child> | ||
853 | </object> | ||
854 | </child> | ||
855 | </object> | ||
856 | </child> | ||
857 | </object> | ||
858 | <packing> | ||
859 | <property name="expand">True</property> | ||
860 | <property name="fill">True</property> | ||
861 | <property name="position">1</property> | ||
862 | </packing> | ||
863 | </child> | ||
864 | <child> | ||
865 | <object class="GtkBox"> | ||
866 | <property name="visible">True</property> | ||
867 | <property name="can-focus">False</property> | ||
868 | <property name="margin-start">8</property> | ||
869 | <property name="margin-end">8</property> | ||
870 | <property name="margin-top">4</property> | ||
871 | <property name="margin-bottom">4</property> | ||
872 | <property name="spacing">4</property> | ||
873 | <child> | ||
874 | <object class="GtkButton" id="attach_file_button"> | ||
875 | <property name="visible">True</property> | ||
876 | <property name="can-focus">True</property> | ||
877 | <property name="receives-default">True</property> | ||
878 | <property name="valign">center</property> | ||
879 | <property name="relief">none</property> | ||
880 | <child> | ||
881 | <object class="GtkImage"> | ||
882 | <property name="visible">True</property> | ||
883 | <property name="can-focus">False</property> | ||
884 | <property name="icon-name">mail-attachment-symbolic</property> | ||
885 | </object> | ||
886 | </child> | ||
887 | </object> | ||
888 | <packing> | ||
889 | <property name="expand">False</property> | ||
890 | <property name="fill">True</property> | ||
891 | <property name="position">0</property> | ||
892 | </packing> | ||
893 | </child> | ||
894 | <child> | ||
895 | <object class="GtkTextView" id="send_text_view"> | ||
896 | <property name="width-request">210</property> | ||
897 | <property name="height-request">48</property> | ||
898 | <property name="visible">True</property> | ||
899 | <property name="can-focus">True</property> | ||
900 | <property name="valign">end</property> | ||
901 | <property name="wrap-mode">word-char</property> | ||
902 | <property name="left-margin">8</property> | ||
903 | <property name="right-margin">8</property> | ||
904 | <property name="top-margin">8</property> | ||
905 | <property name="bottom-margin">8</property> | ||
906 | <property name="input-hints">GTK_INPUT_HINT_SPELLCHECK | GTK_INPUT_HINT_WORD_COMPLETION | GTK_INPUT_HINT_INHIBIT_OSK | GTK_INPUT_HINT_EMOJI | GTK_INPUT_HINT_NONE</property> | ||
907 | </object> | ||
908 | <packing> | ||
909 | <property name="expand">True</property> | ||
910 | <property name="fill">True</property> | ||
911 | <property name="position">1</property> | ||
912 | </packing> | ||
913 | </child> | ||
914 | <child> | ||
915 | <object class="GtkButton" id="emoji_button"> | ||
916 | <property name="visible">True</property> | ||
917 | <property name="can-focus">True</property> | ||
918 | <property name="receives-default">True</property> | ||
919 | <property name="valign">center</property> | ||
920 | <property name="relief">none</property> | ||
921 | <child> | ||
922 | <object class="GtkImage"> | ||
923 | <property name="visible">True</property> | ||
924 | <property name="can-focus">False</property> | ||
925 | <property name="icon-name">face-smile-symbolic</property> | ||
926 | </object> | ||
927 | </child> | ||
928 | </object> | ||
929 | <packing> | ||
930 | <property name="expand">False</property> | ||
931 | <property name="fill">True</property> | ||
932 | <property name="position">2</property> | ||
933 | </packing> | ||
934 | </child> | ||
935 | <child> | ||
936 | <object class="GtkButton" id="send_record_button"> | ||
937 | <property name="visible">True</property> | ||
938 | <property name="can-focus">True</property> | ||
939 | <property name="receives-default">True</property> | ||
940 | <property name="valign">center</property> | ||
941 | <property name="relief">none</property> | ||
942 | <child> | ||
943 | <object class="GtkImage" id="send_record_symbol"> | ||
944 | <property name="visible">True</property> | ||
945 | <property name="can-focus">False</property> | ||
946 | <property name="icon-name">audio-input-microphone-symbolic</property> | ||
947 | </object> | ||
948 | </child> | ||
949 | </object> | ||
950 | <packing> | ||
951 | <property name="expand">False</property> | ||
952 | <property name="fill">True</property> | ||
953 | <property name="position">3</property> | ||
954 | </packing> | ||
955 | </child> | ||
956 | </object> | ||
957 | <packing> | ||
958 | <property name="expand">False</property> | ||
959 | <property name="fill">True</property> | ||
960 | <property name="position">2</property> | ||
961 | </packing> | ||
962 | </child> | 726 | </child> |
963 | </object> | 727 | </object> |
964 | </child> | 728 | </child> |
@@ -1108,12 +872,4 @@ Author: Tobias Frisch | |||
1108 | <widget name="settings-label"/> | 872 | <widget name="settings-label"/> |
1109 | </widgets> | 873 | </widgets> |
1110 | </object> | 874 | </object> |
1111 | <object class="GtkSizeGroup"> | ||
1112 | <property name="mode">vertical</property> | ||
1113 | <widgets> | ||
1114 | <widget name="chats-header-box"/> | ||
1115 | <widget name="chat-header-box"/> | ||
1116 | <widget name="details-header-box"/> | ||
1117 | </widgets> | ||
1118 | </object> | ||
1119 | </interface> | 875 | </interface> |
diff --git a/src/application.c b/src/application.c index e73d9de..764b8ea 100644 --- a/src/application.c +++ b/src/application.c | |||
@@ -48,7 +48,7 @@ _application_activate(UNUSED GtkApplication* application, | |||
48 | { | 48 | { |
49 | MESSENGER_Application *app = (MESSENGER_Application*) user_data; | 49 | MESSENGER_Application *app = (MESSENGER_Application*) user_data; |
50 | 50 | ||
51 | ui_messenger_run(app); | 51 | ui_messenger_init(app, &(app->ui.messenger)); |
52 | } | 52 | } |
53 | 53 | ||
54 | void | 54 | void |
@@ -140,6 +140,8 @@ application_run(MESSENGER_Application *app) | |||
140 | 140 | ||
141 | pthread_join(app->chat.tid, NULL); | 141 | pthread_join(app->chat.tid, NULL); |
142 | 142 | ||
143 | ui_messenger_cleanup(&(app->ui.messenger)); | ||
144 | |||
143 | g_hash_table_destroy(app->ui.bindings); | 145 | g_hash_table_destroy(app->ui.bindings); |
144 | 146 | ||
145 | notify_uninit(); | 147 | notify_uninit(); |
diff --git a/src/event.c b/src/event.c index d11b8cf..6683e63 100644 --- a/src/event.c +++ b/src/event.c | |||
@@ -27,21 +27,43 @@ | |||
27 | #include "ui/chat_entry.h" | 27 | #include "ui/chat_entry.h" |
28 | #include "ui/message.h" | 28 | #include "ui/message.h" |
29 | 29 | ||
30 | static int | 30 | static void |
31 | _iterate_profile_contacts(void *cls, | 31 | _add_new_chat_entry(MESSENGER_Application *app, |
32 | UNUSED struct GNUNET_CHAT_Handle *handle, | 32 | struct GNUNET_CHAT_Context *context) |
33 | UNUSED struct GNUNET_CHAT_Contact *contact) | ||
34 | { | 33 | { |
35 | MESSENGER_Application *app = (MESSENGER_Application*) cls; | ||
36 | |||
37 | UI_MESSENGER_Handle *ui = &(app->ui.messenger); | 34 | UI_MESSENGER_Handle *ui = &(app->ui.messenger); |
38 | 35 | ||
39 | UI_CHAT_ENTRY_Handle *entry = ui_chat_entry_new(); | 36 | UI_CHAT_ENTRY_Handle *entry = ui_chat_entry_new(app); |
40 | |||
41 | gtk_container_add(GTK_CONTAINER(ui->chats_listbox), entry->entry_box); | 37 | gtk_container_add(GTK_CONTAINER(ui->chats_listbox), entry->entry_box); |
38 | GNUNET_CHAT_context_set_user_pointer(context, entry); | ||
39 | |||
40 | char context_id [9]; | ||
41 | g_snprintf(context_id, sizeof(context_id), "%08lx", (gulong) context); | ||
42 | |||
43 | gtk_widget_set_name(entry->entry_box, context_id); | ||
42 | 44 | ||
43 | g_free(entry); //TODO: add to a list or similar? | 45 | gtk_stack_add_named( |
46 | ui->chats_stack, | ||
47 | entry->chat->chat_box, | ||
48 | context_id | ||
49 | ); | ||
44 | 50 | ||
51 | g_hash_table_insert( | ||
52 | app->ui.bindings, | ||
53 | entry->chat->send_text_view, | ||
54 | context | ||
55 | ); | ||
56 | |||
57 | ui->chat_entries = g_list_append(ui->chat_entries, entry); | ||
58 | } | ||
59 | |||
60 | static int | ||
61 | _iterate_profile_contacts(void *cls, | ||
62 | UNUSED struct GNUNET_CHAT_Handle *handle, | ||
63 | UNUSED struct GNUNET_CHAT_Contact *contact) | ||
64 | { | ||
65 | MESSENGER_Application *app = (MESSENGER_Application*) cls; | ||
66 | _add_new_chat_entry(app, GNUNET_CHAT_contact_get_context(contact)); | ||
45 | return GNUNET_YES; | 67 | return GNUNET_YES; |
46 | } | 68 | } |
47 | 69 | ||
@@ -51,15 +73,7 @@ _iterate_profile_groups(void *cls, | |||
51 | UNUSED struct GNUNET_CHAT_Group *group) | 73 | UNUSED struct GNUNET_CHAT_Group *group) |
52 | { | 74 | { |
53 | MESSENGER_Application *app = (MESSENGER_Application*) cls; | 75 | MESSENGER_Application *app = (MESSENGER_Application*) cls; |
54 | 76 | _add_new_chat_entry(app, GNUNET_CHAT_group_get_context(group)); | |
55 | UI_MESSENGER_Handle *ui = &(app->ui.messenger); | ||
56 | |||
57 | UI_CHAT_ENTRY_Handle *entry = ui_chat_entry_new(); | ||
58 | |||
59 | gtk_container_add(GTK_CONTAINER(ui->chats_listbox), entry->entry_box); | ||
60 | |||
61 | g_free(entry); //TODO: add to a list or similar? | ||
62 | |||
63 | return GNUNET_YES; | 77 | return GNUNET_YES; |
64 | } | 78 | } |
65 | 79 | ||
@@ -96,12 +110,6 @@ event_update_profile(MESSENGER_Application *app, | |||
96 | 110 | ||
97 | GNUNET_CHAT_iterate_contacts(chat->handle, _iterate_profile_contacts, app); | 111 | GNUNET_CHAT_iterate_contacts(chat->handle, _iterate_profile_contacts, app); |
98 | GNUNET_CHAT_iterate_groups(chat->handle, _iterate_profile_groups, app); | 112 | GNUNET_CHAT_iterate_groups(chat->handle, _iterate_profile_groups, app); |
99 | |||
100 | for (int i = 0; i < 8; i++) { | ||
101 | UI_MESSAGE_Handle *message = ui_message_new(app, i % 2 == 0); | ||
102 | gtk_container_add(GTK_CONTAINER(ui->messages_listbox), message->message_box); | ||
103 | g_free(message); // TODO: this is just a test! | ||
104 | } | ||
105 | } | 113 | } |
106 | 114 | ||
107 | void | 115 | void |
@@ -117,26 +125,7 @@ event_update_chats(MESSENGER_Application *app, | |||
117 | if (GNUNET_CHAT_context_get_user_pointer(context)) | 125 | if (GNUNET_CHAT_context_get_user_pointer(context)) |
118 | return; | 126 | return; |
119 | 127 | ||
120 | UI_MESSENGER_Handle *ui = &(app->ui.messenger); | 128 | _add_new_chat_entry(app, context); |
121 | |||
122 | UI_CHAT_ENTRY_Handle *entry = ui_chat_entry_new(); | ||
123 | gtk_container_add(GTK_CONTAINER(ui->chats_listbox), entry->entry_box); | ||
124 | g_free(entry); // TODO: free already? | ||
125 | |||
126 | // TODO: put something better here to attach it! | ||
127 | GNUNET_CHAT_context_set_user_pointer(context, ui); | ||
128 | |||
129 | g_hash_table_insert( | ||
130 | app->ui.bindings, | ||
131 | app->ui.messenger.send_record_button, | ||
132 | context | ||
133 | ); | ||
134 | |||
135 | g_hash_table_insert( | ||
136 | app->ui.bindings, | ||
137 | app->ui.messenger.send_text_view, | ||
138 | context | ||
139 | ); | ||
140 | } | 129 | } |
141 | 130 | ||
142 | void | 131 | void |
@@ -149,7 +138,9 @@ event_receive_message(MESSENGER_Application *app, | |||
149 | 138 | ||
150 | struct GNUNET_CHAT_Context *context = (struct GNUNET_CHAT_Context*) argv[0]; | 139 | struct GNUNET_CHAT_Context *context = (struct GNUNET_CHAT_Context*) argv[0]; |
151 | 140 | ||
152 | if (!GNUNET_CHAT_context_get_user_pointer(context)) | 141 | UI_CHAT_ENTRY_Handle *handle = GNUNET_CHAT_context_get_user_pointer(context); |
142 | |||
143 | if (!handle) | ||
153 | return; | 144 | return; |
154 | 145 | ||
155 | const struct GNUNET_CHAT_Message *msg; | 146 | const struct GNUNET_CHAT_Message *msg; |
@@ -185,9 +176,12 @@ event_receive_message(MESSENGER_Application *app, | |||
185 | // TODO: check read receipt | 176 | // TODO: check read receipt |
186 | 177 | ||
187 | gtk_container_add( | 178 | gtk_container_add( |
188 | GTK_CONTAINER(app->ui.messenger.messages_listbox), | 179 | GTK_CONTAINER(handle->chat->messages_listbox), |
189 | message->message_box | 180 | message->message_box |
190 | ); | 181 | ); |
191 | 182 | ||
192 | g_free(message); // TODO: this is just a test! | 183 | g_free(message); // TODO: this is just a test! |
184 | |||
185 | gtk_label_set_text(handle->text_label, text? text : ""); | ||
186 | gtk_label_set_text(handle->timestamp_label, time? time : ""); | ||
193 | } | 187 | } |
diff --git a/src/ui/chat.c b/src/ui/chat.c new file mode 100644 index 0000000..7e5c1fc --- /dev/null +++ b/src/ui/chat.c | |||
@@ -0,0 +1,249 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2021 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /* | ||
21 | * @author Tobias Frisch | ||
22 | * @file ui/chat.c | ||
23 | */ | ||
24 | |||
25 | #include "chat.h" | ||
26 | |||
27 | #include "messenger.h" | ||
28 | #include "../application.h" | ||
29 | |||
30 | static void | ||
31 | handle_flap_via_button_click(UNUSED GtkButton* button, | ||
32 | gpointer user_data) | ||
33 | { | ||
34 | HdyFlap* flap = HDY_FLAP(user_data); | ||
35 | |||
36 | if (TRUE == hdy_flap_get_reveal_flap(flap)) { | ||
37 | hdy_flap_set_reveal_flap(flap, FALSE); | ||
38 | } else { | ||
39 | hdy_flap_set_reveal_flap(flap, TRUE); | ||
40 | } | ||
41 | } | ||
42 | |||
43 | static void | ||
44 | handle_back_button_click(UNUSED GtkButton* button, | ||
45 | gpointer user_data) | ||
46 | { | ||
47 | HdyLeaflet* leaflet = HDY_LEAFLET(user_data); | ||
48 | |||
49 | GList* children = gtk_container_get_children(GTK_CONTAINER(leaflet)); | ||
50 | |||
51 | if (children) { | ||
52 | hdy_leaflet_set_visible_child(leaflet, GTK_WIDGET(children->data)); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | static void | ||
57 | handle_send_text_buffer_changed(GtkTextBuffer *buffer, | ||
58 | gpointer user_data) | ||
59 | { | ||
60 | GtkImage *symbol = GTK_IMAGE(user_data); | ||
61 | |||
62 | GtkTextIter start, end; | ||
63 | gtk_text_buffer_get_start_iter(buffer, &start); | ||
64 | gtk_text_buffer_get_end_iter(buffer, &end); | ||
65 | |||
66 | const gchar *text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); | ||
67 | |||
68 | gtk_image_set_from_icon_name( | ||
69 | symbol, | ||
70 | 0 < g_utf8_strlen(text, 1)? | ||
71 | "mail-send-symbolic" : | ||
72 | "audio-input-microphone-symbolic", | ||
73 | GTK_ICON_SIZE_BUTTON | ||
74 | ); | ||
75 | } | ||
76 | |||
77 | static gboolean | ||
78 | _send_text_from_view(MESSENGER_Application *app, | ||
79 | GtkTextView *text_view) | ||
80 | { | ||
81 | GtkTextBuffer *buffer = gtk_text_view_get_buffer(text_view); | ||
82 | |||
83 | GtkTextIter start, end; | ||
84 | gtk_text_buffer_get_start_iter(buffer, &start); | ||
85 | gtk_text_buffer_get_end_iter(buffer, &end); | ||
86 | |||
87 | const gchar *text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); | ||
88 | |||
89 | if (0 == g_utf8_strlen(text, 1)) | ||
90 | return FALSE; | ||
91 | |||
92 | struct GNUNET_CHAT_Context *context = g_hash_table_lookup( | ||
93 | app->ui.bindings, text_view | ||
94 | ); | ||
95 | |||
96 | if (context) | ||
97 | GNUNET_CHAT_context_send_text(context, text); | ||
98 | |||
99 | gtk_text_buffer_delete(buffer, &start, &end); | ||
100 | return TRUE; | ||
101 | } | ||
102 | |||
103 | static void | ||
104 | handle_send_record_button_click(GtkButton *button, | ||
105 | gpointer user_data) | ||
106 | { | ||
107 | MESSENGER_Application *app = (MESSENGER_Application*) user_data; | ||
108 | |||
109 | GtkTextView *text_view = GTK_TEXT_VIEW( | ||
110 | g_hash_table_lookup(app->ui.bindings, button) | ||
111 | ); | ||
112 | |||
113 | if (!_send_text_from_view(app, text_view)) | ||
114 | { | ||
115 | // TODO: record audio and attach as file? | ||
116 | } | ||
117 | } | ||
118 | |||
119 | static gboolean | ||
120 | handle_send_text_key_press (GtkWidget *widget, | ||
121 | GdkEventKey *event, | ||
122 | gpointer user_data) | ||
123 | { | ||
124 | MESSENGER_Application *app = (MESSENGER_Application*) user_data; | ||
125 | |||
126 | if ((app->ui.mobile) || | ||
127 | (event->state & GDK_SHIFT_MASK) || | ||
128 | ((event->keyval != GDK_KEY_Return) && | ||
129 | (event->keyval != GDK_KEY_KP_Enter))) | ||
130 | return FALSE; | ||
131 | |||
132 | return _send_text_from_view(app, GTK_TEXT_VIEW(widget)); | ||
133 | } | ||
134 | |||
135 | UI_CHAT_Handle* | ||
136 | ui_chat_new(MESSENGER_Application *app) | ||
137 | { | ||
138 | UI_CHAT_Handle *handle = g_malloc(sizeof(UI_CHAT_Handle)); | ||
139 | UI_MESSENGER_Handle *messenger = &(app->ui.messenger); | ||
140 | |||
141 | GtkBuilder* builder = gtk_builder_new_from_file( | ||
142 | "resources/ui/chat.ui" | ||
143 | ); | ||
144 | |||
145 | handle->chat_box = GTK_WIDGET( | ||
146 | gtk_builder_get_object(builder, "chat_box") | ||
147 | ); | ||
148 | |||
149 | handle->back_button = GTK_BUTTON( | ||
150 | gtk_builder_get_object(builder, "back_button") | ||
151 | ); | ||
152 | |||
153 | g_object_bind_property( | ||
154 | messenger->leaflet_chat, | ||
155 | "folded", | ||
156 | handle->back_button, | ||
157 | "visible", | ||
158 | G_BINDING_SYNC_CREATE | ||
159 | ); | ||
160 | |||
161 | g_signal_connect( | ||
162 | handle->back_button, | ||
163 | "clicked", | ||
164 | G_CALLBACK(handle_back_button_click), | ||
165 | messenger->leaflet_chat | ||
166 | ); | ||
167 | |||
168 | handle->chat_title = GTK_LABEL( | ||
169 | gtk_builder_get_object(builder, "chat_title") | ||
170 | ); | ||
171 | |||
172 | handle->chat_subtitle = GTK_LABEL( | ||
173 | gtk_builder_get_object(builder, "chat_subtitle") | ||
174 | ); | ||
175 | |||
176 | handle->chat_details_button = GTK_BUTTON( | ||
177 | gtk_builder_get_object(builder, "chat_details_button") | ||
178 | ); | ||
179 | |||
180 | g_signal_connect( | ||
181 | handle->chat_details_button, | ||
182 | "clicked", | ||
183 | G_CALLBACK(handle_flap_via_button_click), | ||
184 | messenger->flap_chat_details | ||
185 | ); | ||
186 | |||
187 | handle->messages_listbox = GTK_LIST_BOX( | ||
188 | gtk_builder_get_object(builder, "messages_listbox") | ||
189 | ); | ||
190 | |||
191 | handle->attach_file_button = GTK_BUTTON( | ||
192 | gtk_builder_get_object(builder, "attach_file_button") | ||
193 | ); | ||
194 | |||
195 | handle->send_text_view = GTK_TEXT_VIEW( | ||
196 | gtk_builder_get_object(builder, "send_text_view") | ||
197 | ); | ||
198 | |||
199 | handle->emoji_button = GTK_BUTTON( | ||
200 | gtk_builder_get_object(builder, "emoji_button") | ||
201 | ); | ||
202 | |||
203 | handle->send_record_button = GTK_BUTTON( | ||
204 | gtk_builder_get_object(builder, "send_record_button") | ||
205 | ); | ||
206 | |||
207 | handle->send_record_symbol = GTK_IMAGE( | ||
208 | gtk_builder_get_object(builder, "send_record_symbol") | ||
209 | ); | ||
210 | |||
211 | GtkTextBuffer *send_text_buffer = gtk_text_view_get_buffer( | ||
212 | handle->send_text_view | ||
213 | ); | ||
214 | |||
215 | g_signal_connect( | ||
216 | send_text_buffer, | ||
217 | "changed", | ||
218 | G_CALLBACK(handle_send_text_buffer_changed), | ||
219 | handle->send_record_symbol | ||
220 | ); | ||
221 | |||
222 | g_signal_connect( | ||
223 | handle->send_record_button, | ||
224 | "clicked", | ||
225 | G_CALLBACK(handle_send_record_button_click), | ||
226 | app | ||
227 | ); | ||
228 | |||
229 | g_signal_connect( | ||
230 | handle->send_text_view, | ||
231 | "key-press-event", | ||
232 | G_CALLBACK(handle_send_text_key_press), | ||
233 | app | ||
234 | ); | ||
235 | |||
236 | g_hash_table_insert( | ||
237 | app->ui.bindings, | ||
238 | handle->send_record_button, | ||
239 | handle->send_text_view | ||
240 | ); | ||
241 | |||
242 | return handle; | ||
243 | } | ||
244 | |||
245 | void | ||
246 | ui_chat_delete(UI_CHAT_Handle *handle) | ||
247 | { | ||
248 | g_free(handle); | ||
249 | } | ||
diff --git a/src/ui/chat.h b/src/ui/chat.h new file mode 100644 index 0000000..5415647 --- /dev/null +++ b/src/ui/chat.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2021 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /* | ||
21 | * @author Tobias Frisch | ||
22 | * @file ui/chat.h | ||
23 | */ | ||
24 | |||
25 | #ifndef UI_CHAT_H_ | ||
26 | #define UI_CHAT_H_ | ||
27 | |||
28 | #include <gtk-3.0/gtk/gtk.h> | ||
29 | #include <libhandy-1/handy.h> | ||
30 | #include <libnotify/notify.h> | ||
31 | |||
32 | typedef struct MESSENGER_Application MESSENGER_Application; | ||
33 | |||
34 | typedef struct UI_CHAT_Handle | ||
35 | { | ||
36 | GtkWidget *chat_box; | ||
37 | |||
38 | GtkButton *back_button; | ||
39 | |||
40 | GtkLabel *chat_title; | ||
41 | GtkLabel *chat_subtitle; | ||
42 | GtkButton *chat_details_button; | ||
43 | |||
44 | GtkListBox *messages_listbox; | ||
45 | |||
46 | GtkButton *attach_file_button; | ||
47 | GtkTextView *send_text_view; | ||
48 | GtkButton *emoji_button; | ||
49 | GtkButton *send_record_button; | ||
50 | GtkImage *send_record_symbol; | ||
51 | } UI_CHAT_Handle; | ||
52 | |||
53 | UI_CHAT_Handle* | ||
54 | ui_chat_new(MESSENGER_Application *app); | ||
55 | |||
56 | void | ||
57 | ui_chat_delete(UI_CHAT_Handle *handle); | ||
58 | |||
59 | #endif /* UI_CHAT_H_ */ | ||
diff --git a/src/ui/chat_entry.c b/src/ui/chat_entry.c index b314211..3de1ada 100644 --- a/src/ui/chat_entry.c +++ b/src/ui/chat_entry.c | |||
@@ -24,11 +24,15 @@ | |||
24 | 24 | ||
25 | #include "chat_entry.h" | 25 | #include "chat_entry.h" |
26 | 26 | ||
27 | #include "../application.h" | ||
28 | |||
27 | UI_CHAT_ENTRY_Handle* | 29 | UI_CHAT_ENTRY_Handle* |
28 | ui_chat_entry_new(void) | 30 | ui_chat_entry_new(MESSENGER_Application *app) |
29 | { | 31 | { |
30 | UI_CHAT_ENTRY_Handle* handle = g_malloc(sizeof(UI_CHAT_ENTRY_Handle)); | 32 | UI_CHAT_ENTRY_Handle* handle = g_malloc(sizeof(UI_CHAT_ENTRY_Handle)); |
31 | 33 | ||
34 | handle->chat = ui_chat_new(app); | ||
35 | |||
32 | GtkBuilder* builder = gtk_builder_new_from_file("resources/ui/chat_entry.ui"); | 36 | GtkBuilder* builder = gtk_builder_new_from_file("resources/ui/chat_entry.ui"); |
33 | 37 | ||
34 | handle->entry_box = GTK_WIDGET( | 38 | handle->entry_box = GTK_WIDGET( |
@@ -57,3 +61,11 @@ ui_chat_entry_new(void) | |||
57 | 61 | ||
58 | return handle; | 62 | return handle; |
59 | } | 63 | } |
64 | |||
65 | void | ||
66 | ui_chat_entry_delete(UI_CHAT_ENTRY_Handle *handle) | ||
67 | { | ||
68 | ui_chat_delete(handle->chat); | ||
69 | |||
70 | g_free(handle); | ||
71 | } | ||
diff --git a/src/ui/chat_entry.h b/src/ui/chat_entry.h index 2315686..4842eaf 100644 --- a/src/ui/chat_entry.h +++ b/src/ui/chat_entry.h | |||
@@ -25,13 +25,12 @@ | |||
25 | #ifndef UI_CHAT_ENTRY_H_ | 25 | #ifndef UI_CHAT_ENTRY_H_ |
26 | #define UI_CHAT_ENTRY_H_ | 26 | #define UI_CHAT_ENTRY_H_ |
27 | 27 | ||
28 | #include <gtk-3.0/gtk/gtk.h> | 28 | #include "chat.h" |
29 | #include <libhandy-1/handy.h> | ||
30 | |||
31 | typedef struct MESSENGER_Application MESSENGER_Application; | ||
32 | 29 | ||
33 | typedef struct UI_CHAT_ENTRY_Handle | 30 | typedef struct UI_CHAT_ENTRY_Handle |
34 | { | 31 | { |
32 | UI_CHAT_Handle *chat; | ||
33 | |||
35 | GtkWidget* entry_box; | 34 | GtkWidget* entry_box; |
36 | 35 | ||
37 | HdyAvatar* entry_avatar; | 36 | HdyAvatar* entry_avatar; |
@@ -44,6 +43,9 @@ typedef struct UI_CHAT_ENTRY_Handle | |||
44 | } UI_CHAT_ENTRY_Handle; | 43 | } UI_CHAT_ENTRY_Handle; |
45 | 44 | ||
46 | UI_CHAT_ENTRY_Handle* | 45 | UI_CHAT_ENTRY_Handle* |
47 | ui_chat_entry_new(void); | 46 | ui_chat_entry_new(MESSENGER_Application *app); |
47 | |||
48 | void | ||
49 | ui_chat_entry_delete(UI_CHAT_ENTRY_Handle *handle); | ||
48 | 50 | ||
49 | #endif /* UI_CHAT_ENTRY_H_ */ | 51 | #endif /* UI_CHAT_ENTRY_H_ */ |
diff --git a/src/ui/messenger.c b/src/ui/messenger.c index daabd17..2fc8c54 100644 --- a/src/ui/messenger.c +++ b/src/ui/messenger.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include <gtk-3.0/gdk/gdkkeys.h> | 27 | #include <gtk-3.0/gdk/gdkkeys.h> |
28 | 28 | ||
29 | #include "chat_entry.h" | ||
29 | #include "message.h" | 30 | #include "message.h" |
30 | #include "new_platform.h" | 31 | #include "new_platform.h" |
31 | #include "../application.h" | 32 | #include "../application.h" |
@@ -80,118 +81,25 @@ handle_new_platform_button_click(UNUSED GtkButton* button, | |||
80 | 81 | ||
81 | static void | 82 | static void |
82 | handle_chats_listbox_row_activated(UNUSED GtkListBox* listbox, | 83 | handle_chats_listbox_row_activated(UNUSED GtkListBox* listbox, |
83 | UNUSED GtkListBoxRow* row, | 84 | GtkListBoxRow* row, |
84 | gpointer user_data) | 85 | gpointer user_data) |
85 | { | 86 | { |
86 | HdyLeaflet* leaflet = HDY_LEAFLET(user_data); | 87 | UI_MESSENGER_Handle *handle = (UI_MESSENGER_Handle*) user_data; |
88 | |||
89 | GtkStack *stack = handle->chats_stack; | ||
90 | HdyLeaflet *leaflet = handle->leaflet_chat; | ||
87 | 91 | ||
88 | GList* children = gtk_container_get_children(GTK_CONTAINER(leaflet)); | 92 | GList *children = gtk_container_get_children(GTK_CONTAINER(leaflet)); |
89 | 93 | ||
90 | if ((children) && (children->next)) { | 94 | if ((children) && (children->next)) { |
91 | hdy_leaflet_set_visible_child(leaflet, GTK_WIDGET(children->next->data)); | 95 | hdy_leaflet_set_visible_child(leaflet, GTK_WIDGET(children->next->data)); |
92 | } | 96 | } |
93 | } | ||
94 | |||
95 | static void | ||
96 | handle_back_button_click(UNUSED GtkButton* button, | ||
97 | gpointer user_data) | ||
98 | { | ||
99 | HdyLeaflet* leaflet = HDY_LEAFLET(user_data); | ||
100 | |||
101 | GList* children = gtk_container_get_children(GTK_CONTAINER(leaflet)); | ||
102 | |||
103 | if (children) { | ||
104 | hdy_leaflet_set_visible_child(leaflet, GTK_WIDGET(children->data)); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | static void | ||
109 | handle_send_text_buffer_changed(GtkTextBuffer *buffer, | ||
110 | gpointer user_data) | ||
111 | { | ||
112 | GtkImage *symbol = GTK_IMAGE(user_data); | ||
113 | |||
114 | GtkTextIter start, end; | ||
115 | gtk_text_buffer_get_start_iter(buffer, &start); | ||
116 | gtk_text_buffer_get_end_iter(buffer, &end); | ||
117 | |||
118 | const gchar *text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); | ||
119 | |||
120 | gtk_image_set_from_icon_name( | ||
121 | symbol, | ||
122 | 0 < g_utf8_strlen(text, 1)? | ||
123 | "mail-send-symbolic" : | ||
124 | "audio-input-microphone-symbolic", | ||
125 | GTK_ICON_SIZE_BUTTON | ||
126 | ); | ||
127 | } | ||
128 | |||
129 | static void | ||
130 | handle_send_record_button_click(GtkButton *button, | ||
131 | gpointer user_data) | ||
132 | { | ||
133 | MESSENGER_Application *app = (MESSENGER_Application*) user_data; | ||
134 | |||
135 | GtkTextBuffer *buffer = gtk_text_view_get_buffer( | ||
136 | app->ui.messenger.send_text_view | ||
137 | ); | ||
138 | |||
139 | GtkTextIter start, end; | ||
140 | gtk_text_buffer_get_start_iter(buffer, &start); | ||
141 | gtk_text_buffer_get_end_iter(buffer, &end); | ||
142 | |||
143 | const gchar *text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); | ||
144 | |||
145 | if (0 < g_utf8_strlen(text, 1)) | ||
146 | { | ||
147 | struct GNUNET_CHAT_Context *context = g_hash_table_lookup( | ||
148 | app->ui.bindings, button | ||
149 | ); | ||
150 | |||
151 | if (context) | ||
152 | GNUNET_CHAT_context_send_text(context, text); | ||
153 | } | ||
154 | else | ||
155 | { | ||
156 | // TODO: record audio and attach as file? | ||
157 | } | ||
158 | |||
159 | gtk_text_buffer_delete(buffer, &start, &end); | ||
160 | } | ||
161 | 97 | ||
162 | static gboolean | 98 | GtkWidget *entry = GTK_WIDGET( |
163 | handle_send_text_key_press (GtkWidget *widget, | 99 | gtk_container_get_children(GTK_CONTAINER(row))->data |
164 | GdkEventKey *event, | ||
165 | gpointer user_data) | ||
166 | { | ||
167 | MESSENGER_Application *app = (MESSENGER_Application*) user_data; | ||
168 | |||
169 | if ((app->ui.mobile) || | ||
170 | (event->state & GDK_SHIFT_MASK) || | ||
171 | ((event->keyval != GDK_KEY_Return) && | ||
172 | (event->keyval != GDK_KEY_KP_Enter))) | ||
173 | return FALSE; | ||
174 | |||
175 | GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW (widget)); | ||
176 | |||
177 | GtkTextIter start, end; | ||
178 | gtk_text_buffer_get_start_iter(buffer, &start); | ||
179 | gtk_text_buffer_get_end_iter(buffer, &end); | ||
180 | |||
181 | const gchar *text = gtk_text_buffer_get_text(buffer, &start, &end, TRUE); | ||
182 | |||
183 | if (0 == g_utf8_strlen(text, 1)) | ||
184 | return FALSE; | ||
185 | |||
186 | struct GNUNET_CHAT_Context *context = g_hash_table_lookup( | ||
187 | app->ui.bindings, widget | ||
188 | ); | 100 | ); |
189 | 101 | ||
190 | if (context) | 102 | gtk_stack_set_visible_child_name(stack, gtk_widget_get_name(entry)); |
191 | GNUNET_CHAT_context_send_text(context, text); | ||
192 | |||
193 | gtk_text_buffer_delete(buffer, &start, &end); | ||
194 | return TRUE; | ||
195 | } | 103 | } |
196 | 104 | ||
197 | static void | 105 | static void |
@@ -207,6 +115,8 @@ void | |||
207 | ui_messenger_init(MESSENGER_Application *app, | 115 | ui_messenger_init(MESSENGER_Application *app, |
208 | UI_MESSENGER_Handle *handle) | 116 | UI_MESSENGER_Handle *handle) |
209 | { | 117 | { |
118 | handle->chat_entries = g_list_alloc(); | ||
119 | |||
210 | GtkBuilder* builder = gtk_builder_new_from_file("resources/ui/messenger.ui"); | 120 | GtkBuilder* builder = gtk_builder_new_from_file("resources/ui/messenger.ui"); |
211 | 121 | ||
212 | handle->main_window = GTK_APPLICATION_WINDOW( | 122 | handle->main_window = GTK_APPLICATION_WINDOW( |
@@ -257,25 +167,6 @@ ui_messenger_init(MESSENGER_Application *app, | |||
257 | G_BINDING_INVERT_BOOLEAN | 167 | G_BINDING_INVERT_BOOLEAN |
258 | ); | 168 | ); |
259 | 169 | ||
260 | handle->back_button = GTK_BUTTON( | ||
261 | gtk_builder_get_object(builder, "back_button") | ||
262 | ); | ||
263 | |||
264 | g_object_bind_property( | ||
265 | handle->leaflet_chat, | ||
266 | "folded", | ||
267 | handle->back_button, | ||
268 | "visible", | ||
269 | G_BINDING_SYNC_CREATE | ||
270 | ); | ||
271 | |||
272 | g_signal_connect( | ||
273 | handle->back_button, | ||
274 | "clicked", | ||
275 | G_CALLBACK(handle_back_button_click), | ||
276 | handle->leaflet_chat | ||
277 | ); | ||
278 | |||
279 | handle->profile_avatar = HDY_AVATAR( | 170 | handle->profile_avatar = HDY_AVATAR( |
280 | gtk_builder_get_object(builder, "profile_avatar") | 171 | gtk_builder_get_object(builder, "profile_avatar") |
281 | ); | 172 | ); |
@@ -372,26 +263,11 @@ ui_messenger_init(MESSENGER_Application *app, | |||
372 | handle->chats_listbox, | 263 | handle->chats_listbox, |
373 | "row-activated", | 264 | "row-activated", |
374 | G_CALLBACK(handle_chats_listbox_row_activated), | 265 | G_CALLBACK(handle_chats_listbox_row_activated), |
375 | handle->leaflet_chat | 266 | handle |
376 | ); | ||
377 | |||
378 | handle->chat_title = GTK_LABEL( | ||
379 | gtk_builder_get_object(builder, "chat_title") | ||
380 | ); | ||
381 | |||
382 | handle->chat_subtitle = GTK_LABEL( | ||
383 | gtk_builder_get_object(builder, "chat_subtitle") | ||
384 | ); | ||
385 | |||
386 | handle->chat_details_button = GTK_BUTTON( | ||
387 | gtk_builder_get_object(builder, "chat_details_button") | ||
388 | ); | 267 | ); |
389 | 268 | ||
390 | g_signal_connect( | 269 | handle->chats_stack = GTK_STACK( |
391 | handle->chat_details_button, | 270 | gtk_builder_get_object(builder, "chats_stack") |
392 | "clicked", | ||
393 | G_CALLBACK(handle_flap_via_button_click), | ||
394 | handle->flap_chat_details | ||
395 | ); | 271 | ); |
396 | 272 | ||
397 | handle->hide_chat_details_button = GTK_BUTTON( | 273 | handle->hide_chat_details_button = GTK_BUTTON( |
@@ -405,55 +281,6 @@ ui_messenger_init(MESSENGER_Application *app, | |||
405 | handle->flap_chat_details | 281 | handle->flap_chat_details |
406 | ); | 282 | ); |
407 | 283 | ||
408 | handle->messages_listbox = GTK_LIST_BOX( | ||
409 | gtk_builder_get_object(builder, "messages_listbox") | ||
410 | ); | ||
411 | |||
412 | handle->attach_file_button = GTK_BUTTON( | ||
413 | gtk_builder_get_object(builder, "attach_file_button") | ||
414 | ); | ||
415 | |||
416 | handle->send_text_view = GTK_TEXT_VIEW( | ||
417 | gtk_builder_get_object(builder, "send_text_view") | ||
418 | ); | ||
419 | |||
420 | handle->emoji_button = GTK_BUTTON( | ||
421 | gtk_builder_get_object(builder, "emoji_button") | ||
422 | ); | ||
423 | |||
424 | handle->send_record_button = GTK_BUTTON( | ||
425 | gtk_builder_get_object(builder, "send_record_button") | ||
426 | ); | ||
427 | |||
428 | handle->send_record_symbol = GTK_IMAGE( | ||
429 | gtk_builder_get_object(builder, "send_record_symbol") | ||
430 | ); | ||
431 | |||
432 | GtkTextBuffer *send_text_buffer = gtk_text_view_get_buffer( | ||
433 | handle->send_text_view | ||
434 | ); | ||
435 | |||
436 | g_signal_connect( | ||
437 | send_text_buffer, | ||
438 | "changed", | ||
439 | G_CALLBACK(handle_send_text_buffer_changed), | ||
440 | handle->send_record_symbol | ||
441 | ); | ||
442 | |||
443 | g_signal_connect( | ||
444 | handle->send_record_button, | ||
445 | "clicked", | ||
446 | G_CALLBACK(handle_send_record_button_click), | ||
447 | app | ||
448 | ); | ||
449 | |||
450 | g_signal_connect( | ||
451 | handle->send_text_view, | ||
452 | "key-press-event", | ||
453 | G_CALLBACK(handle_send_text_key_press), | ||
454 | app | ||
455 | ); | ||
456 | |||
457 | gtk_widget_show(GTK_WIDGET(handle->main_window)); | 284 | gtk_widget_show(GTK_WIDGET(handle->main_window)); |
458 | 285 | ||
459 | g_signal_connect( | 286 | g_signal_connect( |
@@ -464,8 +291,16 @@ ui_messenger_init(MESSENGER_Application *app, | |||
464 | ); | 291 | ); |
465 | } | 292 | } |
466 | 293 | ||
294 | static void | ||
295 | _free_ui_chat_entry (gpointer user_data) | ||
296 | { | ||
297 | UI_CHAT_ENTRY_Handle* handle = (UI_CHAT_ENTRY_Handle*) user_data; | ||
298 | |||
299 | ui_chat_entry_delete(handle); | ||
300 | } | ||
301 | |||
467 | void | 302 | void |
468 | ui_messenger_run(MESSENGER_Application *app) | 303 | ui_messenger_cleanup(UI_MESSENGER_Handle *handle) |
469 | { | 304 | { |
470 | ui_messenger_init(app, &(app->ui.messenger)); | 305 | g_list_free_full(handle->chat_entries, _free_ui_chat_entry); |
471 | } | 306 | } |
diff --git a/src/ui/messenger.h b/src/ui/messenger.h index c2e53a1..6cd4c9d 100644 --- a/src/ui/messenger.h +++ b/src/ui/messenger.h | |||
@@ -33,6 +33,8 @@ typedef struct MESSENGER_Application MESSENGER_Application; | |||
33 | 33 | ||
34 | typedef struct UI_MESSENGER_Handle | 34 | typedef struct UI_MESSENGER_Handle |
35 | { | 35 | { |
36 | GList *chat_entries; | ||
37 | |||
36 | GtkApplicationWindow *main_window; | 38 | GtkApplicationWindow *main_window; |
37 | 39 | ||
38 | HdyLeaflet *leaflet_chat; | 40 | HdyLeaflet *leaflet_chat; |
@@ -40,7 +42,6 @@ typedef struct UI_MESSENGER_Handle | |||
40 | HdyFlap *flap_chat_details; | 42 | HdyFlap *flap_chat_details; |
41 | 43 | ||
42 | HdyHeaderBar *title_bar; | 44 | HdyHeaderBar *title_bar; |
43 | GtkButton *back_button; | ||
44 | 45 | ||
45 | HdyAvatar *profile_avatar; | 46 | HdyAvatar *profile_avatar; |
46 | GtkLabel *profile_label; | 47 | GtkLabel *profile_label; |
@@ -63,19 +64,9 @@ typedef struct UI_MESSENGER_Handle | |||
63 | GtkSearchEntry *chats_search; | 64 | GtkSearchEntry *chats_search; |
64 | GtkListBox *chats_listbox; | 65 | GtkListBox *chats_listbox; |
65 | 66 | ||
66 | GtkLabel *chat_title; | 67 | GtkStack *chats_stack; |
67 | GtkLabel *chat_subtitle; | ||
68 | GtkButton *chat_details_button; | ||
69 | 68 | ||
70 | GtkButton *hide_chat_details_button; | 69 | GtkButton *hide_chat_details_button; |
71 | |||
72 | GtkListBox *messages_listbox; | ||
73 | |||
74 | GtkButton *attach_file_button; | ||
75 | GtkTextView *send_text_view; | ||
76 | GtkButton *emoji_button; | ||
77 | GtkButton *send_record_button; | ||
78 | GtkImage *send_record_symbol; | ||
79 | } UI_MESSENGER_Handle; | 70 | } UI_MESSENGER_Handle; |
80 | 71 | ||
81 | void | 72 | void |
@@ -83,6 +74,6 @@ ui_messenger_init(MESSENGER_Application *app, | |||
83 | UI_MESSENGER_Handle *handle); | 74 | UI_MESSENGER_Handle *handle); |
84 | 75 | ||
85 | void | 76 | void |
86 | ui_messenger_run(MESSENGER_Application *app); | 77 | ui_messenger_cleanup(UI_MESSENGER_Handle *handle); |
87 | 78 | ||
88 | #endif /* UI_MESSENGER_H_ */ | 79 | #endif /* UI_MESSENGER_H_ */ |