@@ -8,7 +8,7 @@ public class Tuba.Widgets.CustomEmojiChooser : Gtk.Popover {
88 var emojis = accounts. active. instance_emojis;
99
1010 if (emojis != null && emojis. size > 0 ) {
11- emojis. @ foreach (e = > {
11+ emojis. foreach (e = > {
1212 if (! e. visible_in_picker) return true ;
1313
1414 if (res. has_key (e. category)) {
@@ -23,30 +23,30 @@ public class Tuba.Widgets.CustomEmojiChooser : Gtk.Popover {
2323 return true ;
2424 });
2525
26- res. @ foreach (e = > {
27- e. value . sort ((a, b) = > a . shortcode . collate (b . shortcode) );
26+ res. foreach (e = > {
27+ e. value . sort (sort_emojis );
2828
2929 return true ;
3030 });
31-
3231 }
3332
3433 return res;
3534 }
3635
36+ private int sort_emojis (API .Emoji a , API .Emoji b ) {
37+ return a. shortcode. collate (b. shortcode);
38+ }
39+
3740 ~CustomEmojiChooser () {
3841 debug (" Destroying CustomEmojiChooser" );
3942 }
4043
4144 private Gtk . Box custom_emojis_box;
4245 private Gtk . SearchEntry entry;
43- private Gtk . FlowBox results;
44- private Gtk . Label results_label;
4546 private Gtk . ScrolledWindow custom_emojis_scrolled;
4647
47- private Gtk . FlowBox recents;
48- private Gtk . Label recents_label;
49-
48+ private EmojiCategory recents;
49+ private EmojiCategory results;
5050 construct {
5151 this . add_css_class (" emoji-picker" );
5252 custom_emojis_box = new Gtk .Box (Gtk . Orientation . VERTICAL , 6 ) {
@@ -64,19 +64,16 @@ public class Tuba.Widgets.CustomEmojiChooser : Gtk.Popover {
6464 this . child = content_box;
6565 custom_emojis_scrolled. child = custom_emojis_box;
6666
67- results_label = create_category_label (_(" Results" ));
68- results_label. visible = false ;
69- custom_emojis_box. append (results_label);
70-
71- results = create_emoji_box ();
67+ results = new EmojiCategory (_(" Results" )) {
68+ visible = false
69+ };
70+ results. emoji_selected. connect (on_custom_emoji_picked);
7271 custom_emojis_box. append (results);
7372
74- recents_label = create_category_label (_(" Recently Used" ));
75- recents_label. visible = false ;
76- custom_emojis_box. append (recents_label);
77-
78- recents = create_emoji_box ();
79- recents. visible = false ;
73+ recents = new EmojiCategory (_(" Recently Used" )) {
74+ visible = false
75+ };
76+ recents. emoji_selected. connect (on_custom_emoji_picked);
8077 custom_emojis_box. append (recents);
8178
8279 entry = new Gtk .SearchEntry () {
@@ -95,26 +92,17 @@ public class Tuba.Widgets.CustomEmojiChooser : Gtk.Popover {
9592 entry. stop_search. connect (on_close);
9693 }
9794
98- private void add_to_results (API .Emoji emoji ) {
99- results. append (create_emoji_button (emoji));
100- }
101-
102- private void remove_all_from_results () {
103- results. remove_all ();
104- }
105-
10695 private void populate_recents () {
10796 recents. remove_all ();
10897
10998 if (settings. recently_used_custom_emojis. length == 0 ) {
11099 recents. visible = false ;
111- recents_label. visible = false ;
112100 return ;
113101 }
114102
115103 Gee . HashMap<string, API . Emoji > recents_to_api = new Gee .HashMap<string, API . Emoji > ();
116104 int total = settings. recently_used_custom_emojis. length;
117- accounts. active. instance_emojis. @ foreach (e = > {
105+ accounts. active. instance_emojis. foreach (e = > {
118106 if (! e. visible_in_picker) return true ;
119107
120108 if (e. shortcode in settings. recently_used_custom_emojis) {
@@ -128,11 +116,11 @@ public class Tuba.Widgets.CustomEmojiChooser : Gtk.Popover {
128116 });
129117
130118 for (int i = 0 ; i < settings. recently_used_custom_emojis. length; i++ ) {
131- recents. append (create_emoji_button ( recents_to_api. get (settings. recently_used_custom_emojis[i]) ));
119+ recents. add_emoji ( recents_to_api. get (settings. recently_used_custom_emojis[i]));
132120 }
133121
122+ recents_to_api. clear ();
134123 recents. visible = true ;
135- recents_label. visible = true ;
136124 }
137125
138126 static int max_recents = 12 ;
@@ -156,47 +144,43 @@ public class Tuba.Widgets.CustomEmojiChooser : Gtk.Popover {
156144
157145 protected void search () {
158146 query = entry. text. chug (). chomp (). down (). replace (" :" , " " );
159- remove_all_from_results ();
147+ results . remove_all ();
160148
161149 if (query == " " ) {
162- results_label . visible = false ;
150+ results . visible = false ;
163151 return ;
164152 }
165153
166154 var emojis = accounts. active. instance_emojis;
167-
168155 if (emojis != null && emojis. size > 0 ) {
169156 var at_least_one = false ;
170157 emojis. @foreach (e = > {
171158 if (! e. visible_in_picker) return true ;
172- if (query in e. shortcode) {
159+ if (query in e. shortcode. down () ) {
173160 at_least_one = true ;
174- add_to_results (e);
161+ results . add_emoji (e);
175162 };
176163
177164 return true ;
178165 });
179166
180167 if (at_least_one) {
181168 // translators: Used when there are results in the custom emoji picker
182- results_label . label = _(" Results" );
169+ results . label = _(" Results" );
183170 custom_emojis_scrolled. scroll_child (Gtk . ScrollType . START , false );
184171 } else {
185172 // translators: Used when there are 0 results in the custom emoji picker
186- results_label . label = _(" No Results" );
173+ results . label = _(" No Results" );
187174 }
188175
189- results_label . visible = true ;
176+ results . visible = true ;
190177 }
191178 }
192179
193- protected void on_custom_emoji_picked (Gtk .Button emoji_btn ) {
194- var emoji = emoji_btn. child as Emoji ;
195- if (emoji != null ) {
196- on_close ();
197- update_recents (emoji. shortcode);
198- emoji_picked (@" :$(emoji.shortcode):" );
199- }
180+ protected void on_custom_emoji_picked (string shortcode ) {
181+ on_close ();
182+ update_recents (shortcode);
183+ emoji_picked (@" :$shortcode : " );
200184 }
201185
202186 protected void on_close () {
@@ -206,84 +190,134 @@ public class Tuba.Widgets.CustomEmojiChooser : Gtk.Popover {
206190 public override void show () {
207191 base . show ();
208192
209- GLib . Idle . add (() = > {
210- populate_recents ();
211- if (! is_populated) populate_chooser ();
212- entry. grab_focus ();
213- return GLib . Source . REMOVE ;
214- });
193+ GLib . Idle . add (show_idle);
194+ }
195+
196+ private bool show_idle () {
197+ populate_recents ();
198+ if (! is_populated) populate_chooser ();
199+ entry. grab_focus ();
200+
201+ return GLib . Source . REMOVE ;
215202 }
216203
217204 protected void populate_chooser () {
218205 var categorized_custom_emojis = gen_emojis_cat_map ();
219206 var categories_keys = new Gee .ArrayList<string> .wrap (categorized_custom_emojis. keys. to_array ());
220- categories_keys. sort ((a, b) = > a . collate (b) );
207+ categories_keys. sort (sort_strings );
221208
222209 if (categorized_custom_emojis. has_key (_(" Other" ))) {
223- create_category (
224- categorized_custom_emojis. size > 1
225- ? _(" Other" )
226- : _(" Custom Emojis" ),
227- categorized_custom_emojis. get (_(" Other" ))
228- );
229-
210+ string cat_name = categorized_custom_emojis. size > 1
211+ ? _(" Other" )
212+ : _(" Custom Emojis" );
213+ var category = new EmojiCategory (cat_name);
214+ category. add_emojis (categorized_custom_emojis. get (_(" Other" )));
215+ category. emoji_selected. connect (on_custom_emoji_picked);
216+
217+ custom_emojis_box. append (category);
230218 categories_keys. remove (_(" Other" ));
231219 }
232220
233221
234222 foreach (var t_shortcode in categories_keys) {
235- create_category (
236- t_shortcode,
237- categorized_custom_emojis. get (t_shortcode)
238- );
223+ var category = new EmojiCategory (t_shortcode);
224+ category. add_emojis (categorized_custom_emojis. get (t_shortcode));
225+ category. emoji_selected. connect (on_custom_emoji_picked);
226+
227+ custom_emojis_box. append (category);
239228 };
240229
241230 is_populated = true ;
231+ categorized_custom_emojis. clear ();
232+ categories_keys. clear ();
242233 }
243234
244- protected Gtk .FlowBoxChild create_emoji_button (API .Emoji emoji ) {
245- var emoji_btn = new Gtk .Button () {
246- css_classes = { " flat" , " picker-emoji-button" },
247- child = new Widgets .Emoji (emoji. url, emoji. shortcode) { icon_size = Gtk . IconSize . LARGE }
248- };
249-
250- emoji_btn. clicked. connect (on_custom_emoji_picked);
251- return new Gtk .FlowBoxChild () {
252- child = emoji_btn,
253- focusable = false
254- };
235+ private int sort_strings (string a , string b ) {
236+ return a. collate (b);
255237 }
256238
257- protected void create_category ( string key , Gee . ArrayList< API . Emoji > value ) {
258- custom_emojis_box . append (create_category_label (key) );
239+ class EmojiCategory : Gtk . Box {
240+ public signal void emoji_selected ( string shortcode );
259241
260- var emojis_flowbox = create_emoji_box ();
261- value . @foreach (emoji = > {
262- emojis_flowbox. append (create_emoji_button (emoji));
242+ class EmojiButton : Gtk .Button {
243+ public signal void emoji_selected (string shortcode );
263244
264- return true ;
265- });
245+ string shortcode;
246+ construct {
247+ this . css_classes = { " flat" , " picker-emoji-button" };
248+ }
266249
267- custom_emojis_box . append (emojis_flowbox);
268- }
250+ public EmojiButton ( API . Emoji emoji ) {
251+ shortcode = emoji . shortcode;
269252
270- protected Gtk .FlowBox create_emoji_box () {
271- return new Gtk .FlowBox () {
272- homogeneous = true ,
273- column_spacing = 6 ,
274- row_spacing = 6 ,
275- max_children_per_line = 6 ,
276- min_children_per_line = 6 ,
277- selection_mode = Gtk . SelectionMode . NONE
278- };
279- }
253+ this . child = new Widgets .Emoji (emoji. url, emoji. shortcode) {
254+ icon_size = Gtk . IconSize . LARGE
255+ };
256+ this . clicked. connect (on_custom_emoji_picked);
257+ }
280258
281- protected Gtk .Label create_category_label (string label ) {
282- return new Gtk .Label (label) {
283- wrap = true ,
284- wrap_mode = Pango . WrapMode . WORD_CHAR ,
285- halign = Gtk . Align . START ,
286- margin_top = 3
287- };
259+ private void on_custom_emoji_picked () {
260+ emoji_selected (shortcode);
261+ }
262+ }
263+
264+ public string label {
265+ get { return title_label. label; }
266+ set { title_label. label = value ; }
267+ }
268+
269+ Gtk . Label title_label;
270+ Gtk . FlowBox emoji_box;
271+ construct {
272+ this . orientation = Gtk . Orientation . VERTICAL ;
273+ this . spacing = 6 ;
274+
275+ title_label = new Gtk .Label (" " ) {
276+ wrap = true ,
277+ wrap_mode = Pango . WrapMode . WORD_CHAR ,
278+ halign = Gtk . Align . START ,
279+ margin_top = 3
280+ };
281+
282+ emoji_box = new Gtk .FlowBox () {
283+ homogeneous = true ,
284+ column_spacing = 6 ,
285+ row_spacing = 6 ,
286+ max_children_per_line = 6 ,
287+ min_children_per_line = 6 ,
288+ selection_mode = Gtk . SelectionMode . NONE
289+ };
290+
291+ this . append (title_label);
292+ this . append (emoji_box);
293+ }
294+
295+ public EmojiCategory (string title ) {
296+ title_label. label = title;
297+ }
298+
299+ public void add_emojis (Gee .ArrayList<API . Emoji > emojis ) {
300+ emojis. foreach (add_emoji);
301+ }
302+
303+ public bool add_emoji (owned API .Emoji emoji ) {
304+ var emoji_btn = new EmojiButton (emoji);
305+ emoji_btn. emoji_selected. connect (on_custom_emoji_picked);
306+
307+ emoji_box. append (new Gtk .FlowBoxChild () {
308+ child = emoji_btn,
309+ focusable = false
310+ });
311+
312+ return true ;
313+ }
314+
315+ public void remove_all () {
316+ emoji_box. remove_all ();
317+ }
318+
319+ private void on_custom_emoji_picked (string shortcode ) {
320+ emoji_selected (shortcode);
321+ }
288322 }
289323}
0 commit comments