mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Merge remote-tracking branch 'origin/master' into zneix/enhancement/login-overhaul
This commit is contained in:
commit
4141f683b6
13 changed files with 97 additions and 22 deletions
|
@ -8,6 +8,7 @@
|
||||||
- Minor: Received IRC messages use `time` message tag for timestamp if it's available. (#3021)
|
- Minor: Received IRC messages use `time` message tag for timestamp if it's available. (#3021)
|
||||||
- Minor: Added informative messages for recent-messages API's errors. (#3029)
|
- Minor: Added informative messages for recent-messages API's errors. (#3029)
|
||||||
- Bugfix: Fixed "smiley" emotes being unable to be "Tabbed" with autocompletion, introduced in v2.3.3. (#3010)
|
- Bugfix: Fixed "smiley" emotes being unable to be "Tabbed" with autocompletion, introduced in v2.3.3. (#3010)
|
||||||
|
- Bugfix: Fixed comma appended to username completion when not at the beginning of the message. (#3060)
|
||||||
- Dev: Ubuntu packages are now available (#2936)
|
- Dev: Ubuntu packages are now available (#2936)
|
||||||
|
|
||||||
## 2.3.3
|
## 2.3.3
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "providers/twitch/TwitchIrcServer.hpp"
|
#include "providers/twitch/TwitchIrcServer.hpp"
|
||||||
#include "singletons/Emotes.hpp"
|
#include "singletons/Emotes.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
|
#include "util/Helpers.hpp"
|
||||||
#include "util/QStringHash.hpp"
|
#include "util/QStringHash.hpp"
|
||||||
|
|
||||||
#include <QtAlgorithms>
|
#include <QtAlgorithms>
|
||||||
|
@ -150,9 +151,6 @@ void CompletionModel::refresh(const QString &prefix, bool isFirstWord)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usernames
|
// Usernames
|
||||||
QString usernamePostfix =
|
|
||||||
isFirstWord && getSettings()->mentionUsersWithComma ? "," : QString();
|
|
||||||
|
|
||||||
if (prefix.startsWith("@"))
|
if (prefix.startsWith("@"))
|
||||||
{
|
{
|
||||||
QString usernamePrefix = prefix;
|
QString usernamePrefix = prefix;
|
||||||
|
@ -162,8 +160,10 @@ void CompletionModel::refresh(const QString &prefix, bool isFirstWord)
|
||||||
|
|
||||||
for (const auto &name : chatters)
|
for (const auto &name : chatters)
|
||||||
{
|
{
|
||||||
addString("@" + name + usernamePostfix,
|
addString(
|
||||||
TaggedString::Type::Username);
|
"@" + formatUserMention(name, isFirstWord,
|
||||||
|
getSettings()->mentionUsersWithComma),
|
||||||
|
TaggedString::Type::Username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!getSettings()->userCompletionOnlyWithAt)
|
else if (!getSettings()->userCompletionOnlyWithAt)
|
||||||
|
@ -172,7 +172,9 @@ void CompletionModel::refresh(const QString &prefix, bool isFirstWord)
|
||||||
|
|
||||||
for (const auto &name : chatters)
|
for (const auto &name : chatters)
|
||||||
{
|
{
|
||||||
addString(name + usernamePostfix, TaggedString::Type::Username);
|
addString(formatUserMention(name, isFirstWord,
|
||||||
|
getSettings()->mentionUsersWithComma),
|
||||||
|
TaggedString::Type::Username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,4 +68,17 @@ QColor getRandomColor(const QString &userId)
|
||||||
return TWITCH_USERNAME_COLORS[colorIndex];
|
return TWITCH_USERNAME_COLORS[colorIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString formatUserMention(const QString &userName, bool isFirstWord,
|
||||||
|
bool mentionUsersWithComma)
|
||||||
|
{
|
||||||
|
QString result = userName;
|
||||||
|
|
||||||
|
if (isFirstWord && mentionUsersWithComma)
|
||||||
|
{
|
||||||
|
result += ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -20,4 +20,14 @@ QString kFormatNumbers(const int &number);
|
||||||
|
|
||||||
QColor getRandomColor(const QString &userId);
|
QColor getRandomColor(const QString &userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Takes a user's name and some formatting parameter and spits out the standardized way to format it
|
||||||
|
*
|
||||||
|
* @param userName a user's name
|
||||||
|
* @param isFirstWord signifies whether this mention would be the first word in a message
|
||||||
|
* @param mentionUsersWithComma postfix mentions with a comma. generally powered by getSettings()->mentionUsersWithComma
|
||||||
|
**/
|
||||||
|
QString formatUserMention(const QString &userName, bool isFirstWord,
|
||||||
|
bool mentionUsersWithComma);
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "singletons/WindowManager.hpp"
|
#include "singletons/WindowManager.hpp"
|
||||||
#include "util/Clipboard.hpp"
|
#include "util/Clipboard.hpp"
|
||||||
#include "util/DistanceBetweenPoints.hpp"
|
#include "util/DistanceBetweenPoints.hpp"
|
||||||
|
#include "util/Helpers.hpp"
|
||||||
#include "util/IncognitoBrowser.hpp"
|
#include "util/IncognitoBrowser.hpp"
|
||||||
#include "util/StreamerMode.hpp"
|
#include "util/StreamerMode.hpp"
|
||||||
#include "util/Twitch.hpp"
|
#include "util/Twitch.hpp"
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
#include "widgets/helper/EffectLabel.hpp"
|
#include "widgets/helper/EffectLabel.hpp"
|
||||||
#include "widgets/helper/SearchPopup.hpp"
|
#include "widgets/helper/SearchPopup.hpp"
|
||||||
#include "widgets/splits/Split.hpp"
|
#include "widgets/splits/Split.hpp"
|
||||||
|
#include "widgets/splits/SplitInput.hpp"
|
||||||
|
|
||||||
#define DRAW_WIDTH (this->width())
|
#define DRAW_WIDTH (this->width())
|
||||||
#define SELECTION_RESUME_SCROLLING_MSG_THRESHOLD 3
|
#define SELECTION_RESUME_SCROLLING_MSG_THRESHOLD 3
|
||||||
|
@ -1804,8 +1806,9 @@ void ChannelView::handleMouseClick(QMouseEvent *event,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Qt::RightButton: {
|
case Qt::RightButton: {
|
||||||
|
auto split = dynamic_cast<Split *>(this->parentWidget());
|
||||||
auto insertText = [=](QString text) {
|
auto insertText = [=](QString text) {
|
||||||
if (auto split = dynamic_cast<Split *>(this->parentWidget()))
|
if (split)
|
||||||
{
|
{
|
||||||
split->insertTextToInput(text);
|
split->insertTextToInput(text);
|
||||||
}
|
}
|
||||||
|
@ -1815,7 +1818,11 @@ void ChannelView::handleMouseClick(QMouseEvent *event,
|
||||||
if (link.type == Link::UserInfo)
|
if (link.type == Link::UserInfo)
|
||||||
{
|
{
|
||||||
const bool commaMention = getSettings()->mentionUsersWithComma;
|
const bool commaMention = getSettings()->mentionUsersWithComma;
|
||||||
insertText("@" + link.value + (commaMention ? ", " : " "));
|
const bool isFirstWord =
|
||||||
|
split && split->getInput().isEditFirstWord();
|
||||||
|
auto userMention =
|
||||||
|
formatUserMention(link.value, isFirstWord, commaMention);
|
||||||
|
insertText("@" + userMention + " ");
|
||||||
}
|
}
|
||||||
else if (link.type == Link::UserWhisper)
|
else if (link.type == Link::UserWhisper)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,19 @@ bool ResizingTextEdit::hasHeightForWidth() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ResizingTextEdit::isFirstWord() const
|
||||||
|
{
|
||||||
|
QString plainText = this->toPlainText();
|
||||||
|
for (int i = this->textCursor().position(); i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (plainText[i] == ' ')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
int ResizingTextEdit::heightForWidth(int) const
|
int ResizingTextEdit::heightForWidth(int) const
|
||||||
{
|
{
|
||||||
auto margins = this->contentsMargins();
|
auto margins = this->contentsMargins();
|
||||||
|
@ -108,17 +121,6 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event)
|
||||||
}
|
}
|
||||||
|
|
||||||
QString currentCompletionPrefix = this->textUnderCursor();
|
QString currentCompletionPrefix = this->textUnderCursor();
|
||||||
bool isFirstWord = [&] {
|
|
||||||
QString plainText = this->toPlainText();
|
|
||||||
for (int i = this->textCursor().position(); i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (plainText[i] == ' ')
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
|
|
||||||
// check if there is something to complete
|
// check if there is something to complete
|
||||||
if (currentCompletionPrefix.size() <= 1)
|
if (currentCompletionPrefix.size() <= 1)
|
||||||
|
@ -134,7 +136,8 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event)
|
||||||
// First type pressing tab after modifying a message, we refresh our
|
// First type pressing tab after modifying a message, we refresh our
|
||||||
// completion model
|
// completion model
|
||||||
this->completer_->setModel(completionModel);
|
this->completer_->setModel(completionModel);
|
||||||
completionModel->refresh(currentCompletionPrefix, isFirstWord);
|
completionModel->refresh(currentCompletionPrefix,
|
||||||
|
this->isFirstWord());
|
||||||
this->completionInProgress_ = true;
|
this->completionInProgress_ = true;
|
||||||
this->completer_->setCompletionPrefix(currentCompletionPrefix);
|
this->completer_->setCompletionPrefix(currentCompletionPrefix);
|
||||||
this->completer_->complete();
|
this->completer_->complete();
|
||||||
|
|
|
@ -15,6 +15,7 @@ public:
|
||||||
QSize sizeHint() const override;
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
bool hasHeightForWidth() const override;
|
bool hasHeightForWidth() const override;
|
||||||
|
bool isFirstWord() const;
|
||||||
|
|
||||||
pajlada::Signals::Signal<QKeyEvent *> keyPressed;
|
pajlada::Signals::Signal<QKeyEvent *> keyPressed;
|
||||||
pajlada::Signals::NoArgSignal focused;
|
pajlada::Signals::NoArgSignal focused;
|
||||||
|
|
|
@ -306,6 +306,11 @@ ChannelView &Split::getChannelView()
|
||||||
return *this->view_;
|
return *this->view_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SplitInput &Split::getInput()
|
||||||
|
{
|
||||||
|
return *this->input_;
|
||||||
|
}
|
||||||
|
|
||||||
void Split::updateInputPlaceholder()
|
void Split::updateInputPlaceholder()
|
||||||
{
|
{
|
||||||
if (!this->getChannel()->isTwitchChannel())
|
if (!this->getChannel()->isTwitchChannel())
|
||||||
|
|
|
@ -47,6 +47,7 @@ public:
|
||||||
pajlada::Signals::NoArgSignal focusLost;
|
pajlada::Signals::NoArgSignal focusLost;
|
||||||
|
|
||||||
ChannelView &getChannelView();
|
ChannelView &getChannelView();
|
||||||
|
SplitInput &getInput();
|
||||||
|
|
||||||
IndirectChannel getIndirectChannel();
|
IndirectChannel getIndirectChannel();
|
||||||
ChannelPtr getChannel();
|
ChannelPtr getChannel();
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
#include "singletons/Theme.hpp"
|
#include "singletons/Theme.hpp"
|
||||||
#include "util/Clamp.hpp"
|
#include "util/Clamp.hpp"
|
||||||
|
#include "util/Helpers.hpp"
|
||||||
#include "util/LayoutCreator.hpp"
|
#include "util/LayoutCreator.hpp"
|
||||||
#include "widgets/Notebook.hpp"
|
#include "widgets/Notebook.hpp"
|
||||||
#include "widgets/Scrollbar.hpp"
|
#include "widgets/Scrollbar.hpp"
|
||||||
|
@ -568,8 +569,10 @@ void SplitInput::insertCompletionText(const QString &input_)
|
||||||
}
|
}
|
||||||
else if (text[i] == '@')
|
else if (text[i] == '@')
|
||||||
{
|
{
|
||||||
input = "@" + input_ +
|
const auto userMention =
|
||||||
(getSettings()->mentionUsersWithComma ? ", " : " ");
|
formatUserMention(input_, edit.isFirstWord(),
|
||||||
|
getSettings()->mentionUsersWithComma);
|
||||||
|
input = "@" + userMention + " ";
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,6 +598,11 @@ void SplitInput::clearSelection()
|
||||||
this->ui_.textEdit->setTextCursor(c);
|
this->ui_.textEdit->setTextCursor(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SplitInput::isEditFirstWord() const
|
||||||
|
{
|
||||||
|
return this->ui_.textEdit->isFirstWord();
|
||||||
|
}
|
||||||
|
|
||||||
QString SplitInput::getInputText() const
|
QString SplitInput::getInputText() const
|
||||||
{
|
{
|
||||||
return this->ui_.textEdit->toPlainText();
|
return this->ui_.textEdit->toPlainText();
|
||||||
|
|
|
@ -28,6 +28,7 @@ public:
|
||||||
SplitInput(Split *_chatWidget);
|
SplitInput(Split *_chatWidget);
|
||||||
|
|
||||||
void clearSelection();
|
void clearSelection();
|
||||||
|
bool isEditFirstWord() const;
|
||||||
QString getInputText() const;
|
QString getInputText() const;
|
||||||
void insertText(const QString &text);
|
void insertText(const QString &text);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ set(test_SOURCES
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/Emojis.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/Emojis.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/ExponentialBackoff.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/ExponentialBackoff.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/TwitchAccount.cpp
|
${CMAKE_CURRENT_LIST_DIR}/src/TwitchAccount.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/Helpers.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${test_SOURCES})
|
add_executable(${PROJECT_NAME} ${test_SOURCES})
|
||||||
|
|
22
tests/src/Helpers.cpp
Normal file
22
tests/src/Helpers.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include "util/Helpers.hpp"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
using namespace chatterino;
|
||||||
|
|
||||||
|
TEST(Helpers, formatUserMention)
|
||||||
|
{
|
||||||
|
const auto userName = "pajlada";
|
||||||
|
|
||||||
|
// A user mention that is the first word, that has 'mention with comma' enabled should have a comma appended at the end.
|
||||||
|
EXPECT_EQ(formatUserMention(userName, true, true), "pajlada,");
|
||||||
|
|
||||||
|
// A user mention that is not the first word, but has 'mention with comma' enabled should not have a comma appended at the end.
|
||||||
|
EXPECT_EQ(formatUserMention(userName, false, true), "pajlada");
|
||||||
|
|
||||||
|
// A user mention that is the first word, but has 'mention with comma' disabled should not have a comma appended at the end.
|
||||||
|
EXPECT_EQ(formatUserMention(userName, true, false), "pajlada");
|
||||||
|
|
||||||
|
// A user mention that is neither the first word, nor has 'mention with comma' enabled should not have a comma appended at the end.
|
||||||
|
EXPECT_EQ(formatUserMention(userName, false, false), "pajlada");
|
||||||
|
}
|
Loading…
Reference in a new issue