aboutsummaryrefslogtreecommitdiff
path: root/main/src/ui/conversation_content_view/chat_state_populator.vala
blob: 2f02c63530d3113c73d4b8342ca68a5e86e3f764 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
using Gee;
using Gtk;

using Dino.Entities;
using Xmpp;

namespace Dino.Ui.ConversationSummary {

class ChatStatePopulator : Plugins.ConversationItemPopulator, Plugins.ConversationAdditionPopulator, Object {

    public string id { get { return "chat_state"; } }

    private StreamInteractor? stream_interactor;
    private Conversation? current_conversation;
    private Plugins.ConversationItemCollection? item_collection;

    private MetaChatStateItem? meta_item;

    public ChatStatePopulator(StreamInteractor stream_interactor) {
        this.stream_interactor = stream_interactor;

        stream_interactor.get_module(CounterpartInteractionManager.IDENTITY).received_state.connect((conversation, state) => {
            if (current_conversation != null && current_conversation.equals(conversation)) {
                update_chat_state();
            }
        });
        stream_interactor.get_module(MessageProcessor.IDENTITY).message_sent.connect((message, conversation) => {
            if (conversation.equals(current_conversation)) {
                update_chat_state();
            }
        });
    }

    public void init(Conversation conversation, Plugins.ConversationItemCollection item_collection, Plugins.WidgetType type) {
        current_conversation = conversation;
        this.item_collection = item_collection;
        this.meta_item = null;

        update_chat_state();
    }

    public void close(Conversation conversation) { }

    public void populate_timespan(Conversation conversation, DateTime from, DateTime to) { }

    private void update_chat_state() {
        Gee.List<Jid>? typing_jids = stream_interactor.get_module(CounterpartInteractionManager.IDENTITY).get_typing_jids(current_conversation);

        if (meta_item != null && typing_jids == null) {
            // Remove state (stoped typing)
            item_collection.remove_item(meta_item);
            meta_item = null;
        } else if (meta_item != null && typing_jids != null) {
            // Update state (other people typing in MUC)
            meta_item.set_new(typing_jids);
        } else if (typing_jids != null) {
            // New state (started typing)
            meta_item = new MetaChatStateItem(stream_interactor, current_conversation, typing_jids);
            item_collection.insert_item(meta_item);
        }
    }
}

private class MetaChatStateItem : Plugins.MetaConversationItem {
    public override DateTime time { get; set; default=new DateTime.now_utc().add_years(10); }

    private StreamInteractor stream_interactor;
    private Conversation conversation;
    private Gee.List<Jid> jids = new ArrayList<Jid>();
    private Label label;
    private AvatarPicture picture;

    public MetaChatStateItem(StreamInteractor stream_interactor, Conversation conversation, Gee.List<Jid> jids) {
        this.stream_interactor = stream_interactor;
        this.conversation = conversation;
        this.jids = jids;
    }

    public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType widget_type) {
        label = new Label("") { xalign=0, vexpand=true };
        label.add_css_class("dim-label");
        picture = new AvatarPicture() { margin_top=2, valign=Align.START };

        Box image_content_box = new Box(Orientation.HORIZONTAL, 8);
        image_content_box.append(picture);
        image_content_box.append(label);

        update();
        return image_content_box;
    }

    public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { return null; }

    public void set_new(Gee.List<Jid> jids) {
        this.jids = jids;
        update();
    }

    private void update() {
        if (picture == null || label == null) return;

        Gee.List<string> display_names = new ArrayList<string>();
        foreach (Jid jid in jids) {
            display_names.add(Util.get_participant_display_name(stream_interactor, conversation, jid));
        }
        string new_text = "";
        if (jids.size > 3) {
            new_text = _("%s, %s and %i others are typing…").printf(display_names[0], display_names[1], jids.size - 2);
            picture.model = new ViewModel.CompatAvatarPictureModel(stream_interactor)
                    .add_participant(conversation, jids[0])
                    .add_participant(conversation, jids[1])
                    .add_participant(conversation, jids[2])
                    .add("+");
        } else if (jids.size == 3) {
            new_text = _("%s, %s and %s are typing…").printf(display_names[0], display_names[1], display_names[2]);
            picture.model = new ViewModel.CompatAvatarPictureModel(stream_interactor)
                    .add_participant(conversation, jids[0])
                    .add_participant(conversation, jids[1])
                    .add_participant(conversation, jids[2]);
        } else if (jids.size == 2) {
            new_text =_("%s and %s are typing…").printf(display_names[0], display_names[1]);
            picture.model = new ViewModel.CompatAvatarPictureModel(stream_interactor)
                    .add_participant(conversation, jids[0])
                    .add_participant(conversation, jids[1]);
        } else {
            new_text = _("%s is typing…").printf(display_names[0]);
            picture.model = new ViewModel.CompatAvatarPictureModel(stream_interactor)
                    .add_participant(conversation, jids[0]);
        }

        label.label = new_text;
    }
}

}