feat: add countdown for slow mode and timeouts (#6782)
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
## Unversioned
|
## Unversioned
|
||||||
|
|
||||||
|
- Minor: Added a countdown timer to the input box to show when you can chat again during slow mode or after a timeout. This feature is disabled by default, and can be enabled with the "Show countdown on slow mode or when timed out" setting. (#6782)
|
||||||
- Minor: Add search engine selection for context menu search action. (#6743, #6770)
|
- Minor: Add search engine selection for context menu search action. (#6743, #6770)
|
||||||
- Minor: Add a separate highlight option for watchstreak notifications. (#6571, #6581)
|
- Minor: Add a separate highlight option for watchstreak notifications. (#6571, #6581)
|
||||||
- Minor: Badges now link to their home page like emotes in the context menu. (#6437)
|
- Minor: Badges now link to their home page like emotes in the context menu. (#6437)
|
||||||
|
|||||||
@@ -222,7 +222,9 @@ std::optional<ClearChatMessage> parseClearChatMessage(
|
|||||||
calculateMessageTime(message))
|
calculateMessageTime(message))
|
||||||
.release();
|
.release();
|
||||||
|
|
||||||
return ClearChatMessage{.message = timeoutMsg, .disableAllMessages = false};
|
return ClearChatMessage{.message = timeoutMsg,
|
||||||
|
.disableAllMessages = false,
|
||||||
|
.username = username};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -403,6 +405,22 @@ void IrcMessageHandler::parsePrivMessageInto(
|
|||||||
channel->setVIP(parsedBadges.contains("vip"));
|
channel->setVIP(parsedBadges.contains("vip"));
|
||||||
channel->setStaff(parsedBadges.contains("staff"));
|
channel->setStaff(parsedBadges.contains("staff"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!channel->isLoadingRecentMessages())
|
||||||
|
{
|
||||||
|
// Clear the send wait timer when we are able to send a message
|
||||||
|
channel->setSendWait(0);
|
||||||
|
|
||||||
|
// Update send wait timer with slow mode timeout if this user is not a mod or vip.
|
||||||
|
if (!channel->hasHighRateLimit())
|
||||||
|
{
|
||||||
|
auto roomModes = *channel->accessRoomModes();
|
||||||
|
if (roomModes.slowMode > 0)
|
||||||
|
{
|
||||||
|
channel->setSendWait(roomModes.slowMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IrcMessageHandler::addMessage(
|
IrcMessageHandler::addMessage(
|
||||||
@@ -510,6 +528,25 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Set send wait timer when the user is timed out
|
||||||
|
const auto currentUsername =
|
||||||
|
getApp()->getAccounts()->twitch.getCurrent()->getUserName();
|
||||||
|
if (currentUsername == clearChat.username)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int remainingTime =
|
||||||
|
message->tags().value("ban-duration").toInt(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
auto *tc = dynamic_cast<TwitchChannel *>(chan.get());
|
||||||
|
assert(tc != nullptr);
|
||||||
|
if (tc != nullptr)
|
||||||
|
{
|
||||||
|
tc->setSendWait(remainingTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
chan->addOrReplaceTimeout(std::move(clearChat.message), time);
|
chan->addOrReplaceTimeout(std::move(clearChat.message), time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,6 +654,13 @@ void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message)
|
|||||||
tc->setMod(modTag == "1");
|
tc->setMod(modTag == "1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When a user is updated to mod or vip status, any previous
|
||||||
|
// slow mode or timeout timers are no longer in effect.
|
||||||
|
if (tc->hasHighRateLimit())
|
||||||
|
{
|
||||||
|
tc->setSendWait(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -979,6 +1023,33 @@ void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message)
|
|||||||
{
|
{
|
||||||
channel->addMessage(msg, MessageContext::Original);
|
channel->addMessage(msg, MessageContext::Original);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto handleSendWait = [&channel](const QString &remaining) {
|
||||||
|
bool ok = false;
|
||||||
|
int seconds = remaining.toInt(&ok);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
|
||||||
|
assert(tc != nullptr);
|
||||||
|
if (tc != nullptr)
|
||||||
|
{
|
||||||
|
tc->setSendWait(seconds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (tags == "msg_slowmode")
|
||||||
|
{
|
||||||
|
// Notice received when the user sends a message too quickly during slow mode.
|
||||||
|
// @msg-id=msg_slowmode :tmi.twitch.tv NOTICE #channel :This room is in slow mode and you are sending messages too quickly. You will be able to talk again in 10 seconds.
|
||||||
|
handleSendWait(message->content().split(u' ').value(21));
|
||||||
|
}
|
||||||
|
else if (tags == "msg_timedout")
|
||||||
|
{
|
||||||
|
// Notice received when the user sends a message while timed out.
|
||||||
|
// @msg-id=msg_timedout :tmi.twitch.tv NOTICE #twitch :You are timed out for 3600 more seconds.
|
||||||
|
handleSendWait(message->content().split(u' ').value(5));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcMessageHandler::handleJoinMessage(Communi::IrcMessage *message)
|
void IrcMessageHandler::handleJoinMessage(Communi::IrcMessage *message)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class MessageSink;
|
|||||||
struct ClearChatMessage {
|
struct ClearChatMessage {
|
||||||
MessagePtr message;
|
MessagePtr message;
|
||||||
bool disableAllMessages;
|
bool disableAllMessages;
|
||||||
|
std::optional<QString> username;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IrcMessageHandler
|
class IrcMessageHandler
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
#include "singletons/StreamerMode.hpp"
|
#include "singletons/StreamerMode.hpp"
|
||||||
#include "singletons/Toasts.hpp"
|
#include "singletons/Toasts.hpp"
|
||||||
#include "singletons/WindowManager.hpp"
|
#include "singletons/WindowManager.hpp"
|
||||||
|
#include "util/FormatTime.hpp"
|
||||||
#include "util/Helpers.hpp"
|
#include "util/Helpers.hpp"
|
||||||
#include "util/PostToThread.hpp"
|
#include "util/PostToThread.hpp"
|
||||||
#include "util/QStringHash.hpp"
|
#include "util/QStringHash.hpp"
|
||||||
@@ -65,6 +66,7 @@
|
|||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
using namespace literals;
|
using namespace literals;
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
@@ -212,6 +214,11 @@ TwitchChannel::TwitchChannel(const QString &name)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QObject::connect(&this->sendWaitTimer_, &QTimer::timeout,
|
||||||
|
&this->lifetimeGuard_, [this] {
|
||||||
|
this->syncSendWaitTimer();
|
||||||
|
});
|
||||||
|
|
||||||
// debugging
|
// debugging
|
||||||
#if 0
|
#if 0
|
||||||
for (int i = 0; i < 1000; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
@@ -997,6 +1004,12 @@ void TwitchChannel::setRoomModes(const RoomModes &newRoomModes)
|
|||||||
{
|
{
|
||||||
this->roomModes = newRoomModes;
|
this->roomModes = newRoomModes;
|
||||||
|
|
||||||
|
// Clear send wait timer when slow mode is disabled
|
||||||
|
if (newRoomModes.slowMode == 0)
|
||||||
|
{
|
||||||
|
this->setSendWait(newRoomModes.slowMode);
|
||||||
|
}
|
||||||
|
|
||||||
this->roomModesChanged.invoke();
|
this->roomModesChanged.invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2342,4 +2355,48 @@ void TwitchChannel::listenSevenTVCosmetics() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TwitchChannel::syncSendWaitTimer()
|
||||||
|
{
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
const auto remaining =
|
||||||
|
this->sendWaitEnd_.has_value()
|
||||||
|
? std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
|
this->sendWaitEnd_.value() - now)
|
||||||
|
: 0s;
|
||||||
|
if (remaining <= 0s)
|
||||||
|
{
|
||||||
|
this->sendWaitTimer_.stop();
|
||||||
|
this->sendWaitUpdate.invoke("");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->sendWaitUpdate.invoke(formatTime(remaining, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchChannel::setSendWait(int seconds)
|
||||||
|
{
|
||||||
|
if (seconds <= 0)
|
||||||
|
{
|
||||||
|
if (this->sendWaitEnd_.has_value())
|
||||||
|
{
|
||||||
|
this->sendWaitEnd_ = std::nullopt;
|
||||||
|
this->syncSendWaitTimer();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->sendWaitEnd_ =
|
||||||
|
std::chrono::steady_clock::now() + std::chrono::seconds(seconds);
|
||||||
|
if (!this->sendWaitTimer_.isActive())
|
||||||
|
{
|
||||||
|
this->sendWaitTimer_.start(1s);
|
||||||
|
this->syncSendWaitTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TwitchChannel::isLoadingRecentMessages() const
|
||||||
|
{
|
||||||
|
return this->loadingRecentMessages_.test();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -338,6 +338,8 @@ public:
|
|||||||
|
|
||||||
pajlada::Signals::NoArgSignal destroyed;
|
pajlada::Signals::NoArgSignal destroyed;
|
||||||
|
|
||||||
|
pajlada::Signals::Signal<const QString &> sendWaitUpdate;
|
||||||
|
|
||||||
// Channel point rewards
|
// Channel point rewards
|
||||||
void addQueuedRedemption(const QString &rewardId,
|
void addQueuedRedemption(const QString &rewardId,
|
||||||
const QString &originalContent,
|
const QString &originalContent,
|
||||||
@@ -368,6 +370,21 @@ public:
|
|||||||
const QString &getDisplayName() const override;
|
const QString &getDisplayName() const override;
|
||||||
void updateDisplayName(const QString &displayName);
|
void updateDisplayName(const QString &displayName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync the text of the send wait timer to the actual time remaining.
|
||||||
|
*/
|
||||||
|
void syncSendWaitTimer();
|
||||||
|
/**
|
||||||
|
* Set the send wait timer to given number of seconds
|
||||||
|
*
|
||||||
|
* When a channel is in slow mode or the user is timed out, calling
|
||||||
|
* this function sets the timer to show how long the user will need
|
||||||
|
* to wait before they can send again.
|
||||||
|
*/
|
||||||
|
void setSendWait(int seconds);
|
||||||
|
|
||||||
|
bool isLoadingRecentMessages() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct NameOptions {
|
struct NameOptions {
|
||||||
// displayName is the non-CJK-display name for this user
|
// displayName is the non-CJK-display name for this user
|
||||||
@@ -572,6 +589,10 @@ private:
|
|||||||
friend class Commands_E2E_Test;
|
friend class Commands_E2E_Test;
|
||||||
friend class ::TestIrcMessageHandlerP;
|
friend class ::TestIrcMessageHandlerP;
|
||||||
friend class ::TestEventSubMessagesP;
|
friend class ::TestEventSubMessagesP;
|
||||||
|
|
||||||
|
QTimer sendWaitTimer_;
|
||||||
|
// Timepoint at which the user can send messages again
|
||||||
|
std::optional<std::chrono::steady_clock::time_point> sendWaitEnd_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -170,6 +170,8 @@ public:
|
|||||||
BoolSetting showEmptyInput = {"/appearance/showEmptyInputBox", true};
|
BoolSetting showEmptyInput = {"/appearance/showEmptyInputBox", true};
|
||||||
BoolSetting showMessageLength = {"/appearance/messages/showMessageLength",
|
BoolSetting showMessageLength = {"/appearance/messages/showMessageLength",
|
||||||
false};
|
false};
|
||||||
|
BoolSetting showSendWaitTimer = {"/appearance/messages/showSendWaitTimer",
|
||||||
|
false};
|
||||||
EnumSetting<MessageOverflow> messageOverflow = {
|
EnumSetting<MessageOverflow> messageOverflow = {
|
||||||
"/appearance/messages/messageOverflow", MessageOverflow::Highlight};
|
"/appearance/messages/messageOverflow", MessageOverflow::Highlight};
|
||||||
BoolSetting separateMessages = {"/appearance/messages/separateMessages",
|
BoolSetting separateMessages = {"/appearance/messages/separateMessages",
|
||||||
|
|||||||
+19
-13
@@ -125,7 +125,7 @@ BalancedDuration durationBetween(const QDateTime &a, const QDateTime &b)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
QString formatTime(int totalSeconds)
|
QString formatTime(int totalSeconds, int components)
|
||||||
{
|
{
|
||||||
QString res;
|
QString res;
|
||||||
|
|
||||||
@@ -135,46 +135,52 @@ QString formatTime(int totalSeconds)
|
|||||||
int timeoutHours = timeoutMinutes / 60;
|
int timeoutHours = timeoutMinutes / 60;
|
||||||
int hours = timeoutHours % 24;
|
int hours = timeoutHours % 24;
|
||||||
int days = timeoutHours / 24;
|
int days = timeoutHours / 24;
|
||||||
if (days > 0)
|
if (days > 0 && components > 0)
|
||||||
{
|
{
|
||||||
appendShortDuration(days, 'd', res);
|
appendShortDuration(days, 'd', res);
|
||||||
|
components--;
|
||||||
}
|
}
|
||||||
if (hours > 0)
|
if (hours > 0 && components > 0)
|
||||||
{
|
{
|
||||||
appendShortDuration(hours, 'h', res);
|
appendShortDuration(hours, 'h', res);
|
||||||
|
components--;
|
||||||
}
|
}
|
||||||
if (minutes > 0)
|
if (minutes > 0 && components > 0)
|
||||||
{
|
{
|
||||||
appendShortDuration(minutes, 'm', res);
|
appendShortDuration(minutes, 'm', res);
|
||||||
|
components--;
|
||||||
}
|
}
|
||||||
if (seconds > 0)
|
if (seconds > 0 && components > 0)
|
||||||
{
|
{
|
||||||
appendShortDuration(seconds, 's', res);
|
appendShortDuration(seconds, 's', res);
|
||||||
|
components--;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString formatTime(const QString &totalSecondsString)
|
QString formatTime(const QString &totalSecondsString, int components)
|
||||||
{
|
{
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
int totalSeconds(totalSecondsString.toInt(&ok));
|
int totalSeconds(totalSecondsString.toInt(&ok));
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
return formatTime(totalSeconds);
|
return formatTime(totalSeconds, components);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "n/a";
|
return "n/a";
|
||||||
}
|
}
|
||||||
|
|
||||||
QString formatTime(std::chrono::seconds totalSeconds)
|
QString formatTime(std::chrono::seconds totalSeconds, int components)
|
||||||
{
|
{
|
||||||
auto count = totalSeconds.count();
|
auto count = totalSeconds.count();
|
||||||
|
|
||||||
return formatTime(static_cast<int>(std::clamp(
|
return formatTime(
|
||||||
count,
|
static_cast<int>(std::clamp(count,
|
||||||
static_cast<std::chrono::seconds::rep>(std::numeric_limits<int>::min()),
|
static_cast<std::chrono::seconds::rep>(
|
||||||
static_cast<std::chrono::seconds::rep>(
|
std::numeric_limits<int>::min()),
|
||||||
std::numeric_limits<int>::max()))));
|
static_cast<std::chrono::seconds::rep>(
|
||||||
|
std::numeric_limits<int>::max()))),
|
||||||
|
components);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString formatLongFriendlyDuration(const QDateTime &from, const QDateTime &to)
|
QString formatLongFriendlyDuration(const QDateTime &from, const QDateTime &to)
|
||||||
|
|||||||
@@ -12,9 +12,10 @@
|
|||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
// format: 1h 23m 42s
|
// format: 1h 23m 42s
|
||||||
QString formatTime(int totalSeconds);
|
// 'components' controls how many most significant components the formatted time will have
|
||||||
QString formatTime(const QString &totalSecondsString);
|
QString formatTime(int totalSeconds, int components = 4);
|
||||||
QString formatTime(std::chrono::seconds totalSeconds);
|
QString formatTime(const QString &totalSecondsString, int components = 4);
|
||||||
|
QString formatTime(std::chrono::seconds totalSeconds, int components = 4);
|
||||||
|
|
||||||
/// Formats a duration that's expected to be long (sevreal months or years) like
|
/// Formats a duration that's expected to be long (sevreal months or years) like
|
||||||
/// "4 years, 5 days and 8 hours".
|
/// "4 years, 5 days and 8 hours".
|
||||||
|
|||||||
@@ -381,6 +381,14 @@ void GeneralPage::initLayout(GeneralPageView &layout)
|
|||||||
"limit, or a lower limit enforced by a moderation bot")
|
"limit, or a lower limit enforced by a moderation bot")
|
||||||
->addTo(layout);
|
->addTo(layout);
|
||||||
|
|
||||||
|
SettingWidget::checkbox("Show countdown on slow mode or when timed out",
|
||||||
|
s.showSendWaitTimer)
|
||||||
|
->setTooltip("Show how long you may need to wait before being able to "
|
||||||
|
"send in a Twitch channel again if the channel is in slow "
|
||||||
|
"mode or if you have been timed out")
|
||||||
|
->addKeywords({"slowmode", "timeout"})
|
||||||
|
->addTo(layout);
|
||||||
|
|
||||||
SettingWidget::checkbox("Allow sending duplicate messages",
|
SettingWidget::checkbox("Allow sending duplicate messages",
|
||||||
s.allowDuplicateMessages)
|
s.allowDuplicateMessages)
|
||||||
->setTooltip(
|
->setTooltip(
|
||||||
|
|||||||
@@ -847,6 +847,11 @@ void Split::setChannel(IndirectChannel newChannel)
|
|||||||
this->roomModeChangedConnection_ = tc->roomModesChanged.connect([this] {
|
this->roomModeChangedConnection_ = tc->roomModesChanged.connect([this] {
|
||||||
this->header_->updateRoomModes();
|
this->header_->updateRoomModes();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this->channelSignalHolder_.managedConnect(
|
||||||
|
tc->sendWaitUpdate, [this](const QString &text) {
|
||||||
|
this->getInput().setSendWaitStatus(text);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this->indirectChannelChangedConnection_ =
|
this->indirectChannelChangedConnection_ =
|
||||||
|
|||||||
@@ -211,10 +211,16 @@ void SplitInput::initLayout()
|
|||||||
auto box = hboxLayout.emplace<QVBoxLayout>().withoutMargin();
|
auto box = hboxLayout.emplace<QVBoxLayout>().withoutMargin();
|
||||||
box->setSpacing(0);
|
box->setSpacing(0);
|
||||||
{
|
{
|
||||||
|
auto hbox = box.emplace<QHBoxLayout>().withoutMargin();
|
||||||
this->ui_.textEditLength = new QLabel();
|
this->ui_.textEditLength = new QLabel();
|
||||||
// Right-align the labels contents
|
// Right-align the labels contents
|
||||||
this->ui_.textEditLength->setAlignment(Qt::AlignRight);
|
this->ui_.textEditLength->setAlignment(Qt::AlignRight);
|
||||||
box->addWidget(this->ui_.textEditLength);
|
hbox->addWidget(this->ui_.textEditLength);
|
||||||
|
|
||||||
|
this->ui_.sendWaitStatus = new QLabel();
|
||||||
|
this->ui_.sendWaitStatus->setAlignment(Qt::AlignRight);
|
||||||
|
this->ui_.sendWaitStatus->setHidden(true);
|
||||||
|
hbox->addWidget(this->ui_.sendWaitStatus);
|
||||||
|
|
||||||
this->ui_.emoteButton = new SvgButton(
|
this->ui_.emoteButton = new SvgButton(
|
||||||
{
|
{
|
||||||
@@ -266,6 +272,16 @@ void SplitInput::initLayout()
|
|||||||
this->editTextChanged();
|
this->editTextChanged();
|
||||||
},
|
},
|
||||||
this->managedConnections_);
|
this->managedConnections_);
|
||||||
|
|
||||||
|
// sendWaitStatus visibility
|
||||||
|
getSettings()->showSendWaitTimer.connect(
|
||||||
|
[this](bool value, const auto &) {
|
||||||
|
if (!this->ui_.sendWaitStatus->text().isEmpty())
|
||||||
|
{
|
||||||
|
this->ui_.sendWaitStatus->setHidden(!value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
this->managedConnections_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplitInput::triggerSelfMessageReceived()
|
void SplitInput::triggerSelfMessageReceived()
|
||||||
@@ -1427,4 +1443,17 @@ void SplitInput::updateFonts()
|
|||||||
app->getFonts()->getFont(FontStyle::ChatMediumBold, this->scale()));
|
app->getFonts()->getFont(FontStyle::ChatMediumBold, this->scale()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SplitInput::setSendWaitStatus(const QString &text) const
|
||||||
|
{
|
||||||
|
this->ui_.sendWaitStatus->setText(text);
|
||||||
|
if (text.isEmpty())
|
||||||
|
{
|
||||||
|
this->ui_.sendWaitStatus->setHidden(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->ui_.sendWaitStatus->setHidden(!getSettings()->showSendWaitTimer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|||||||
@@ -82,6 +82,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setInputText(const QString &newInputText);
|
void setInputText(const QString &newInputText);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets a formatted time to sendWaitStatus
|
||||||
|
*
|
||||||
|
* This method is used to update the text of the timeout and slow mode timer
|
||||||
|
*/
|
||||||
|
void setSendWaitStatus(const QString &text) const;
|
||||||
|
|
||||||
void triggerSelfMessageReceived();
|
void triggerSelfMessageReceived();
|
||||||
|
|
||||||
std::optional<bool> checkSpellingOverride() const;
|
std::optional<bool> checkSpellingOverride() const;
|
||||||
@@ -161,6 +168,7 @@ protected:
|
|||||||
ResizingTextEdit *textEdit;
|
ResizingTextEdit *textEdit;
|
||||||
QLabel *textEditLength;
|
QLabel *textEditLength;
|
||||||
LabelButton *sendButton;
|
LabelButton *sendButton;
|
||||||
|
QLabel *sendWaitStatus;
|
||||||
SvgButton *emoteButton;
|
SvgButton *emoteButton;
|
||||||
} ui_;
|
} ui_;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user