Ring Daemon 16.0.0
Loading...
Searching...
No Matches
typers.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2004-2025 Savoir-faire Linux Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#include "typers.h"
19#include "manager.h"
20#include "jamidht/jamiaccount.h"
21
22static constexpr std::chrono::steady_clock::duration COMPOSING_TIMEOUT {std::chrono::seconds(12)};
23
24namespace jami {
25
26Typers::Typers(const std::shared_ptr<JamiAccount>& acc, const std::string& convId)
27 : ioContext_(Manager::instance().ioContext())
28 , acc_(acc)
29 , accountId_(acc->getAccountID())
30 , convId_(convId)
31 , selfUri_(acc->getUsername())
32{
33
34}
35
37{
38 for (auto& watcher : watcher_) {
39 watcher.second.cancel();
40 }
41 watcher_.clear();
42}
43
44std::string
45getIsComposing(const std::string& conversationId, bool isWriting)
46{
47 // implementing https://tools.ietf.org/rfc/rfc3994.txt
48 return fmt::format("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
49 "<isComposing><state>{}</state>{}</isComposing>",
50 isWriting ? "active"sv : "idle"sv,
51 conversationId.empty()
52 ? ""
53 : "<conversation>" + conversationId + "</conversation>");
54}
55
56void
57Typers::addTyper(const std::string &typer, bool sendMessage)
58{
59 auto acc = acc_.lock();
60 if (!acc || !acc->isComposingEnabled())
61 return;
62 auto [it, res] = watcher_.emplace(typer, asio::steady_timer {*ioContext_});
63 if (res) {
64 auto& watcher = it->second;
65 // Check next member
66 watcher.expires_at(std::chrono::steady_clock::now() + COMPOSING_TIMEOUT);
67 watcher.async_wait(
68 std::bind(&Typers::onTyperTimeout,
70 std::placeholders::_1,
71 typer));
72
73 if (typer != selfUri_)
75 convId_,
76 typer,
77 1);
78 }
79 if (sendMessage) {
80 // In this case we should emit for remote to update the timer
81 acc->sendInstantMessage(convId_,
82 {{MIME_TYPE_IM_COMPOSING, getIsComposing(convId_, true)}});
83 }
84}
85
86void
87Typers::removeTyper(const std::string &typer, bool sendMessage)
88{
89 auto acc = acc_.lock();
90 if (!acc || !acc->isComposingEnabled())
91 return;
92 if (watcher_.erase(typer)) {
93 if (sendMessage) {
94 acc->sendInstantMessage(convId_,
95 {{MIME_TYPE_IM_COMPOSING, getIsComposing(convId_, false)}});
96 }
97 if (typer != selfUri_) {
99 convId_,
100 typer,
101 0);
102 }
103 }
104}
105
106void
107Typers::onTyperTimeout(const asio::error_code& ec, const std::string &typer)
108{
109 if (ec == asio::error::operation_aborted)
110 return;
112}
113
114} // namespace jami
Manager (controller) of daemon.
Definition manager.h:67
void removeTyper(const std::string &typer, bool sendMessage=false)
Definition typers.cpp:87
void addTyper(const std::string &typer, bool sendMessage=false)
Add typer to the list of typers.
Definition typers.cpp:57
Typers(const std::shared_ptr< JamiAccount > &acc, const std::string &convId)
Definition typers.cpp:26
void emitSignal(Args... args)
Definition ring_signal.h:64
static constexpr const char MIME_TYPE_IM_COMPOSING[]
Definition jamiaccount.h:90
std::string getIsComposing(const std::string &conversationId, bool isWriting)
Definition typers.cpp:45
static constexpr std::chrono::steady_clock::duration COMPOSING_TIMEOUT
Definition typers.cpp:22