1using Gee;
2using Gtk;
3
4using Dino.Entities;
5using Xmpp;
6
7namespace Dino.Ui {
8
9[GtkTemplate (ui = "/im/dino/Dino/add_conversation/select_jid_fragment.ui")]
10public class SelectJidFragment : Gtk.Box {
11
12    public signal void add_jid();
13    public signal void remove_jid(ListRow row);
14    public bool done {
15        get { return filterable_list.get_selected_row() != null; }
16        private set {}
17    }
18
19    [GtkChild] private Entry entry;
20    [GtkChild] private Box box;
21    [GtkChild] private Button add_button;
22    [GtkChild] private Button remove_button;
23
24    private StreamInteractor stream_interactor;
25    private FilterableList filterable_list;
26    private Gee.List<Account> accounts;
27
28    private ArrayList<AddListRow> added_rows = new ArrayList<AddListRow>();
29
30    public SelectJidFragment(StreamInteractor stream_interactor, FilterableList filterable_list, Gee.List<Account> accounts) {
31        this.stream_interactor = stream_interactor;
32        this.filterable_list = filterable_list;
33        this.accounts = accounts;
34
35        filterable_list.visible = true;
36        filterable_list.activate_on_single_click = false;
37        filterable_list.vexpand = true;
38        box.add(filterable_list);
39
40        filterable_list.set_sort_func(sort);
41        filterable_list.row_selected.connect(check_buttons_active);
42        filterable_list.row_selected.connect(() => { done = true; }); // just for notifying
43        entry.changed.connect(() => { set_filter(entry.text); });
44        add_button.clicked.connect(() => { add_jid(); });
45        remove_button.clicked.connect(() => { remove_jid(filterable_list.get_selected_row() as ListRow); });
46    }
47
48    public void set_filter(string str) {
49        if (entry.text != str) entry.text = str;
50
51        foreach (AddListRow row in added_rows) row.destroy();
52        added_rows.clear();
53
54        string[] ? values = str == "" ? null : str.split(" ");
55        filterable_list.set_filter_values(values);
56        try {
57            Jid parsed_jid = new Jid(str);
58            if (parsed_jid != null && parsed_jid.localpart != null) {
59                foreach (Account account in accounts) {
60                    AddListRow row = new AddListRow(stream_interactor, parsed_jid, account);
61                    filterable_list.add(row);
62                    added_rows.add(row);
63                }
64            }
65        } catch (InvalidJidError ignored) {
66            // Ignore
67        }
68    }
69
70    private void check_buttons_active() {
71        ListBoxRow? row = filterable_list.get_selected_row();
72        bool active = row != null && !row.get_type().is_a(typeof(AddListRow));
73        remove_button.sensitive = active;
74    }
75
76    private int sort(ListBoxRow row1, ListBoxRow row2) {
77        AddListRow al1 = (row1 as AddListRow);
78        AddListRow al2 = (row2 as AddListRow);
79        if (al1 != null && al2 == null) {
80            return -1;
81        } else if (al2 != null && al1 == null) {
82            return 1;
83        }
84        return filterable_list.sort(row1, row2);
85    }
86
87    private class AddListRow : ListRow {
88
89        public AddListRow(StreamInteractor stream_interactor, Jid jid, Account account) {
90            this.account = account;
91            this.jid = jid;
92
93            name_label.label = jid.to_string();
94            if (stream_interactor.get_accounts().size > 1) {
95                via_label.label = account.bare_jid.to_string();
96            } else {
97                via_label.visible = false;
98            }
99            image.set_text("?");
100        }
101    }
102}
103
104public abstract class FilterableList : Gtk.ListBox {
105    public string[]? filter_values;
106
107    public void set_filter_values(string[] values) {
108        if (filter_values == values) return;
109        filter_values = values;
110        invalidate_filter();
111    }
112
113    public abstract int sort(ListBoxRow row1, ListBoxRow row2);
114}
115
116}
117