mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Emotes and emojis in webview (cheers not yet), rewriting of some code
This commit is contained in:
parent
bfaf08745e
commit
b00f0fcfb7
14 changed files with 178 additions and 353 deletions
|
@ -53,7 +53,6 @@ SOURCES += \
|
||||||
src/messages/link.cpp \
|
src/messages/link.cpp \
|
||||||
src/messages/message.cpp \
|
src/messages/message.cpp \
|
||||||
src/messages/word.cpp \
|
src/messages/word.cpp \
|
||||||
src/messages/wordpart.cpp \
|
|
||||||
src/resources.cpp \
|
src/resources.cpp \
|
||||||
src/widgets/chatwidget.cpp \
|
src/widgets/chatwidget.cpp \
|
||||||
src/widgets/chatwidgetheader.cpp \
|
src/widgets/chatwidgetheader.cpp \
|
||||||
|
@ -69,7 +68,6 @@ SOURCES += \
|
||||||
src/widgets/settingsdialog.cpp \
|
src/widgets/settingsdialog.cpp \
|
||||||
src/widgets/settingsdialogtab.cpp \
|
src/widgets/settingsdialogtab.cpp \
|
||||||
src/widgets/textinputdialog.cpp \
|
src/widgets/textinputdialog.cpp \
|
||||||
src/messages/messageref.cpp \
|
|
||||||
src/logging/loggingmanager.cpp \
|
src/logging/loggingmanager.cpp \
|
||||||
src/logging/loggingchannel.cpp \
|
src/logging/loggingchannel.cpp \
|
||||||
src/windowmanager.cpp \
|
src/windowmanager.cpp \
|
||||||
|
@ -109,7 +107,6 @@ HEADERS += \
|
||||||
src/messages/link.hpp \
|
src/messages/link.hpp \
|
||||||
src/messages/message.hpp \
|
src/messages/message.hpp \
|
||||||
src/messages/word.hpp \
|
src/messages/word.hpp \
|
||||||
src/messages/wordpart.hpp \
|
|
||||||
src/resources.hpp \
|
src/resources.hpp \
|
||||||
src/setting.hpp \
|
src/setting.hpp \
|
||||||
src/twitch/emotevalue.hpp \
|
src/twitch/emotevalue.hpp \
|
||||||
|
@ -132,7 +129,6 @@ HEADERS += \
|
||||||
src/settingssnapshot.hpp \
|
src/settingssnapshot.hpp \
|
||||||
src/messages/limitedqueue.hpp \
|
src/messages/limitedqueue.hpp \
|
||||||
src/messages/limitedqueuesnapshot.hpp \
|
src/messages/limitedqueuesnapshot.hpp \
|
||||||
src/messages/messageref.hpp \
|
|
||||||
src/logging/loggingmanager.hpp \
|
src/logging/loggingmanager.hpp \
|
||||||
src/logging/loggingchannel.hpp \
|
src/logging/loggingchannel.hpp \
|
||||||
src/channelmanager.hpp \
|
src/channelmanager.hpp \
|
||||||
|
|
|
@ -46,11 +46,6 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/html" id="messageTemplate">
|
|
||||||
<div class="chat-element chat-textual">
|
|
||||||
<span style="color: blue;" class="chat-username">{{username}}</span>:
|
|
||||||
</div>
|
|
||||||
</script>
|
|
||||||
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
||||||
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>
|
<script src="https://code.jquery.com/jquery-3.2.1.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
@ -62,14 +57,13 @@
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
function addMessage(username, color, ...parts) {
|
function addMessage(...parts) {
|
||||||
let main = $('<div>');
|
let main = $('<div>');
|
||||||
let tmpl = $('#messageTemplate').html();
|
|
||||||
main.html(tmpl);
|
|
||||||
|
|
||||||
for (let part of parts) {
|
for (let part of parts) {
|
||||||
if (part.type === 'text') {
|
if (part.type === 'text') {
|
||||||
let msg = $('<div class="chat-element chat-textual"></div>');
|
let msg = $('<div class="chat-element chat-textual"></div>');
|
||||||
|
msg.css('color', part.color);
|
||||||
msg.html(part.data);
|
msg.html(part.data);
|
||||||
main.append(msg);
|
main.append(msg);
|
||||||
} else if (part.type === 'emote') {
|
} else if (part.type === 'emote') {
|
||||||
|
@ -82,6 +76,10 @@
|
||||||
window.scrollTo(0, document.body.scrollHeight);
|
window.scrollTo(0, document.body.scrollHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearMessages() {
|
||||||
|
$('#chat').empty();
|
||||||
|
}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
if (CHANNEL) CHANNEL.objects.test.testMethod();
|
if (CHANNEL) CHANNEL.objects.test.testMethod();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ using namespace chatterino::messages;
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
Channel::Channel()
|
Channel::Channel()
|
||||||
// , loggingChannel(logging::get(name))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,10 +36,6 @@ void Channel::addMessage(std::shared_ptr<Message> message)
|
||||||
{
|
{
|
||||||
std::shared_ptr<Message> deleted;
|
std::shared_ptr<Message> deleted;
|
||||||
|
|
||||||
// if (_loggingChannel.get() != nullptr) {
|
|
||||||
// _loggingChannel->append(message);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (this->messages.appendItem(message, deleted)) {
|
if (this->messages.appendItem(message, deleted)) {
|
||||||
messageRemovedFromStart(deleted);
|
messageRemovedFromStart(deleted);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#define TWITCH_EMOTE_TEMPLATE "https://static-cdn.jtvnw.net/emoticons/v1/{id}/{scale}.0"
|
#define TWITCH_EMOTE_TEMPLATE "https://static-cdn.jtvnw.net/emoticons/v1/%1/%2.0"
|
||||||
|
|
||||||
using namespace chatterino::messages;
|
using namespace chatterino::messages;
|
||||||
|
|
||||||
|
@ -67,13 +67,9 @@ void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName, std::weak
|
||||||
|
|
||||||
QString link = linkTemplate;
|
QString link = linkTemplate;
|
||||||
link.detach();
|
link.detach();
|
||||||
|
link.replace("{{id}}", id).replace("{{image}}", "1x");
|
||||||
|
|
||||||
link = link.replace("{{id}}", id).replace("{{image}}", "1x");
|
Emote emote(code, link, channelName);
|
||||||
|
|
||||||
auto emote = this->getBTTVChannelEmoteFromCaches().getOrAdd(id, [this, &code, &link] {
|
|
||||||
return EmoteData(new LazyLoadedImage(*this, this->windowManager, link, 1, code,
|
|
||||||
code + "\nChannel BTTV Emote"));
|
|
||||||
});
|
|
||||||
|
|
||||||
this->bttvChannelEmotes.insert(code, emote);
|
this->bttvChannelEmotes.insert(code, emote);
|
||||||
map->insert(code, emote);
|
map->insert(code, emote);
|
||||||
|
@ -115,11 +111,7 @@ void EmoteManager::reloadFFZChannelEmotes(const QString &channelName, std::weak_
|
||||||
QJsonObject urls = emoteObject.value("urls").toObject();
|
QJsonObject urls = emoteObject.value("urls").toObject();
|
||||||
QString url1 = "http:" + urls.value("1").toString();
|
QString url1 = "http:" + urls.value("1").toString();
|
||||||
|
|
||||||
auto emote =
|
Emote emote(code, url1, channelName);
|
||||||
this->getFFZChannelEmoteFromCaches().getOrAdd(id, [this, &code, &url1] {
|
|
||||||
return EmoteData(new LazyLoadedImage(*this, this->windowManager, url1, 1,
|
|
||||||
code, code + "\nGlobal FFZ Emote"));
|
|
||||||
});
|
|
||||||
|
|
||||||
this->ffzChannelEmotes.insert(code, emote);
|
this->ffzChannelEmotes.insert(code, emote);
|
||||||
map->insert(code, emote);
|
map->insert(code, emote);
|
||||||
|
@ -146,26 +138,11 @@ EmoteMap &EmoteManager::getChatterinoEmotes()
|
||||||
return _chatterinoEmotes;
|
return _chatterinoEmotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmoteMap &EmoteManager::getBTTVChannelEmoteFromCaches()
|
|
||||||
{
|
|
||||||
return _bttvChannelEmoteFromCaches;
|
|
||||||
}
|
|
||||||
|
|
||||||
EmoteMap &EmoteManager::getEmojis()
|
EmoteMap &EmoteManager::getEmojis()
|
||||||
{
|
{
|
||||||
return this->emojis;
|
return this->emojis;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentMap<int, EmoteData> &EmoteManager::getFFZChannelEmoteFromCaches()
|
|
||||||
{
|
|
||||||
return _ffzChannelEmoteFromCaches;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConcurrentMap<long, EmoteData> &EmoteManager::getTwitchEmoteFromCache()
|
|
||||||
{
|
|
||||||
return _twitchEmoteFromCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmoteManager::loadEmojis()
|
void EmoteManager::loadEmojis()
|
||||||
{
|
{
|
||||||
QFile file(":/emojidata.txt");
|
QFile file(":/emojidata.txt");
|
||||||
|
@ -203,9 +180,9 @@ void EmoteManager::loadEmojis()
|
||||||
}
|
}
|
||||||
|
|
||||||
EmojiData emojiData{
|
EmojiData emojiData{
|
||||||
QString::fromUcs4(unicodeBytes, numUnicodeBytes), //
|
QString::fromUcs4(unicodeBytes, numUnicodeBytes),
|
||||||
code, //
|
code,
|
||||||
shortCode, //
|
shortCode,
|
||||||
};
|
};
|
||||||
|
|
||||||
this->emojiShortCodeToEmoji.insert(shortCode, emojiData);
|
this->emojiShortCodeToEmoji.insert(shortCode, emojiData);
|
||||||
|
@ -217,16 +194,15 @@ void EmoteManager::loadEmojis()
|
||||||
"emojione/2.2.6/assets/png/" +
|
"emojione/2.2.6/assets/png/" +
|
||||||
code + ".png";
|
code + ".png";
|
||||||
|
|
||||||
this->emojis.insert(code,
|
this->emojis.insert(code, Emote(code, url));
|
||||||
EmoteData(new LazyLoadedImage(*this, this->windowManager, url, 0.35)));
|
|
||||||
|
|
||||||
// TODO(pajlada): The vectors in emojiFirstByte need to be sorted by
|
// TODO(pajlada): The vectors in emojiFirstByte need to be sorted by
|
||||||
// emojiData.code.length()
|
// emojiData.code.length()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmoteManager::parseEmojis(std::vector<std::tuple<EmoteData, QString>> &parsedWords,
|
void EmoteManager::parseEmojis(
|
||||||
const QString &text)
|
std::vector<std::tuple<std::unique_ptr<Emote>, QString>> &parsedWords, const QString &text)
|
||||||
{
|
{
|
||||||
int lastParsedEmojiEndIndex = 0;
|
int lastParsedEmojiEndIndex = 0;
|
||||||
|
|
||||||
|
@ -286,8 +262,9 @@ void EmoteManager::parseEmojis(std::vector<std::tuple<EmoteData, QString>> &pars
|
||||||
|
|
||||||
if (charactersFromLastParsedEmoji > 0) {
|
if (charactersFromLastParsedEmoji > 0) {
|
||||||
// Add characters inbetween emojis
|
// Add characters inbetween emojis
|
||||||
parsedWords.push_back(std::tuple<messages::LazyLoadedImage *, QString>(
|
parsedWords.push_back(std::tuple<std::unique_ptr<Emote>, QString>(
|
||||||
nullptr, text.mid(lastParsedEmojiEndIndex, charactersFromLastParsedEmoji)));
|
std::unique_ptr<Emote>(nullptr),
|
||||||
|
text.mid(lastParsedEmojiEndIndex, charactersFromLastParsedEmoji)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString url = "https://cdnjs.cloudflare.com/ajax/libs/"
|
QString url = "https://cdnjs.cloudflare.com/ajax/libs/"
|
||||||
|
@ -295,12 +272,11 @@ void EmoteManager::parseEmojis(std::vector<std::tuple<EmoteData, QString>> &pars
|
||||||
matchedEmoji.code + ".png";
|
matchedEmoji.code + ".png";
|
||||||
|
|
||||||
// Create or fetch cached emoji image
|
// Create or fetch cached emoji image
|
||||||
auto emojiImage = this->emojiCache.getOrAdd(url, [this, &url] {
|
Emote *emojiImage = new Emote(url, "");
|
||||||
return EmoteData(new LazyLoadedImage(*this, this->windowManager, url, 0.35)); //
|
|
||||||
});
|
|
||||||
|
|
||||||
// Push the emoji as a word to parsedWords
|
// Push the emoji as a word to parsedWords
|
||||||
parsedWords.push_back(std::tuple<EmoteData, QString>(emojiImage, QString()));
|
parsedWords.push_back(std::tuple<std::unique_ptr<Emote>, QString>(
|
||||||
|
std::unique_ptr<Emote>(emojiImage), QString()));
|
||||||
|
|
||||||
lastParsedEmojiEndIndex = currentParsedEmojiEndIndex;
|
lastParsedEmojiEndIndex = currentParsedEmojiEndIndex;
|
||||||
|
|
||||||
|
@ -309,8 +285,8 @@ void EmoteManager::parseEmojis(std::vector<std::tuple<EmoteData, QString>> &pars
|
||||||
|
|
||||||
if (lastParsedEmojiEndIndex < text.length()) {
|
if (lastParsedEmojiEndIndex < text.length()) {
|
||||||
// Add remaining characters
|
// Add remaining characters
|
||||||
parsedWords.push_back(std::tuple<messages::LazyLoadedImage *, QString>(
|
parsedWords.push_back(std::tuple<std::unique_ptr<Emote>, QString>(
|
||||||
nullptr, text.mid(lastParsedEmojiEndIndex)));
|
std::unique_ptr<Emote>(nullptr), text.mid(lastParsedEmojiEndIndex)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,15 +396,12 @@ void EmoteManager::loadBTTVEmotes()
|
||||||
for (const QJsonValue &emote : emotes) {
|
for (const QJsonValue &emote : emotes) {
|
||||||
QString id = emote.toObject().value("id").toString();
|
QString id = emote.toObject().value("id").toString();
|
||||||
QString code = emote.toObject().value("code").toString();
|
QString code = emote.toObject().value("code").toString();
|
||||||
// emote.value("imageType").toString();
|
|
||||||
|
|
||||||
QString tmp = linkTemplate;
|
QString url = linkTemplate;
|
||||||
tmp.detach();
|
url.detach();
|
||||||
QString url = tmp.replace("{{id}}", id).replace("{{image}}", "1x");
|
url.replace("{{id}}", id).replace("{{image}}", "1x");
|
||||||
|
|
||||||
this->bttvGlobalEmotes.insert(
|
this->bttvGlobalEmotes.insert(code, Emote(code, url));
|
||||||
code, new LazyLoadedImage(*this, this->windowManager, url, 1, code,
|
|
||||||
code + "\nGlobal BTTV Emote"));
|
|
||||||
codes.push_back(code.toStdString());
|
codes.push_back(code.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,9 +445,7 @@ void EmoteManager::loadFFZEmotes()
|
||||||
QJsonObject urls = object.value("urls").toObject();
|
QJsonObject urls = object.value("urls").toObject();
|
||||||
QString url1 = "http:" + urls.value("1").toString();
|
QString url1 = "http:" + urls.value("1").toString();
|
||||||
|
|
||||||
this->ffzGlobalEmotes.insert(
|
this->ffzGlobalEmotes.insert(code, Emote(code, url1));
|
||||||
code, new LazyLoadedImage(*this, this->windowManager, url1, 1, code,
|
|
||||||
code + "\nGlobal FFZ Emote"));
|
|
||||||
codes.push_back(code.toStdString());
|
codes.push_back(code.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,32 +460,34 @@ void EmoteManager::loadFFZEmotes()
|
||||||
|
|
||||||
// id is used for lookup
|
// id is used for lookup
|
||||||
// emoteName is used for giving a name to the emote in case it doesn't exist
|
// emoteName is used for giving a name to the emote in case it doesn't exist
|
||||||
EmoteData EmoteManager::getTwitchEmoteById(long id, const QString &emoteName)
|
Emote EmoteManager::getTwitchEmoteById(long id, const QString &emoteName)
|
||||||
{
|
{
|
||||||
return _twitchEmoteFromCache.getOrAdd(id, [this, &emoteName, &id] {
|
qreal scale;
|
||||||
qDebug() << "added twitch emote: " << id;
|
QString url = getTwitchEmoteLink(id, scale);
|
||||||
qreal scale;
|
return Emote(emoteName, url);
|
||||||
QString url = getTwitchEmoteLink(id, scale);
|
|
||||||
return new LazyLoadedImage(*this, this->windowManager, url, scale, emoteName,
|
|
||||||
emoteName + "\nTwitch Emote");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString EmoteManager::getTwitchEmoteLink(long id, qreal &scale)
|
QString EmoteManager::getTwitchEmoteLink(long id, qreal &scale)
|
||||||
{
|
{
|
||||||
scale = .5;
|
scale = .5;
|
||||||
|
|
||||||
QString value = TWITCH_EMOTE_TEMPLATE;
|
QString value(TWITCH_EMOTE_TEMPLATE);
|
||||||
|
|
||||||
value.detach();
|
return value.arg(QString::number(id), "1");
|
||||||
|
|
||||||
return value.replace("{id}", QString::number(id)).replace("{scale}", "2");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EmoteData EmoteManager::getCheerImage(long long amount, bool animated)
|
Emote EmoteManager::getCheerImage(long long amount, bool animated)
|
||||||
|
{
|
||||||
|
// TODO: Implement cheers
|
||||||
|
}
|
||||||
|
|
||||||
|
Emote::Emote(const QString &emoteName, const QString &emoteUrl, const QString &emoteChannel,
|
||||||
|
const QString &emoteCreator)
|
||||||
|
: name(emoteName)
|
||||||
|
, url(emoteUrl)
|
||||||
|
, channel(emoteChannel)
|
||||||
|
, creator(emoteCreator)
|
||||||
{
|
{
|
||||||
// TODO: fix this xD
|
|
||||||
return EmoteData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -19,20 +19,26 @@ namespace chatterino {
|
||||||
|
|
||||||
class WindowManager;
|
class WindowManager;
|
||||||
|
|
||||||
struct EmoteData {
|
class Emote
|
||||||
EmoteData()
|
{
|
||||||
{
|
public:
|
||||||
}
|
Emote() = default;
|
||||||
|
|
||||||
EmoteData(messages::LazyLoadedImage *_image)
|
/**
|
||||||
: image(_image)
|
* @param emoteName name of the emote (what chatter writes in chat)
|
||||||
{
|
* @param emoteChannel name of the channel which possesses this emote
|
||||||
}
|
* @param emoteCreator name of the user (FFZ / BTTV) who made this emote
|
||||||
|
*/
|
||||||
|
Emote(const QString &emoteName, const QString &emoteUrl, const QString &emoteChannel = "",
|
||||||
|
const QString &emoteCreator = "");
|
||||||
|
|
||||||
messages::LazyLoadedImage *image = nullptr;
|
QString name;
|
||||||
|
QString url;
|
||||||
|
QString channel;
|
||||||
|
QString creator;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ConcurrentMap<QString, EmoteData> EmoteMap;
|
typedef ConcurrentMap<QString, Emote> EmoteMap;
|
||||||
|
|
||||||
class EmoteManager
|
class EmoteManager
|
||||||
{
|
{
|
||||||
|
@ -49,14 +55,11 @@ public:
|
||||||
ConcurrentMap<QString, twitch::EmoteValue *> &getTwitchEmotes();
|
ConcurrentMap<QString, twitch::EmoteValue *> &getTwitchEmotes();
|
||||||
EmoteMap &getFFZEmotes();
|
EmoteMap &getFFZEmotes();
|
||||||
EmoteMap &getChatterinoEmotes();
|
EmoteMap &getChatterinoEmotes();
|
||||||
EmoteMap &getBTTVChannelEmoteFromCaches();
|
|
||||||
EmoteMap &getEmojis();
|
EmoteMap &getEmojis();
|
||||||
ConcurrentMap<int, EmoteData> &getFFZChannelEmoteFromCaches();
|
|
||||||
ConcurrentMap<long, EmoteData> &getTwitchEmoteFromCache();
|
|
||||||
|
|
||||||
EmoteData getCheerImage(long long int amount, bool animated);
|
Emote getCheerImage(long long int amount, bool animated);
|
||||||
|
|
||||||
EmoteData getTwitchEmoteById(long int id, const QString &emoteName);
|
Emote getTwitchEmoteById(long int id, const QString &emoteName);
|
||||||
|
|
||||||
int getGeneration()
|
int getGeneration()
|
||||||
{
|
{
|
||||||
|
@ -90,7 +93,8 @@ private:
|
||||||
void loadEmojis();
|
void loadEmojis();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void parseEmojis(std::vector<std::tuple<EmoteData, QString>> &parsedWords, const QString &text);
|
void parseEmojis(std::vector<std::tuple<std::unique_ptr<Emote>, QString>> &parsedWords,
|
||||||
|
const QString &text);
|
||||||
|
|
||||||
QString replaceShortCodes(const QString &text);
|
QString replaceShortCodes(const QString &text);
|
||||||
|
|
||||||
|
@ -119,9 +123,6 @@ private:
|
||||||
// emote code
|
// emote code
|
||||||
ConcurrentMap<QString, twitch::EmoteValue *> _twitchEmotes;
|
ConcurrentMap<QString, twitch::EmoteValue *> _twitchEmotes;
|
||||||
|
|
||||||
// emote id
|
|
||||||
ConcurrentMap<long, EmoteData> _twitchEmoteFromCache;
|
|
||||||
|
|
||||||
/// BTTV emotes
|
/// BTTV emotes
|
||||||
EmoteMap bttvChannelEmotes;
|
EmoteMap bttvChannelEmotes;
|
||||||
|
|
||||||
|
@ -146,8 +147,6 @@ public:
|
||||||
std::map<std::string, SignalVector<std::string>> ffzChannelEmoteCodes;
|
std::map<std::string, SignalVector<std::string>> ffzChannelEmoteCodes;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConcurrentMap<int, EmoteData> _ffzChannelEmoteFromCaches;
|
|
||||||
|
|
||||||
void loadFFZEmotes();
|
void loadFFZEmotes();
|
||||||
|
|
||||||
/// Chatterino emotes
|
/// Chatterino emotes
|
||||||
|
|
|
@ -42,13 +42,13 @@ void MessageBuilder::appendTimestamp(time_t time)
|
||||||
strftime(timeStampBuffer, 69, "%H:%M", localtime(&time));
|
strftime(timeStampBuffer, 69, "%H:%M", localtime(&time));
|
||||||
QString timestampNoSeconds(timeStampBuffer);
|
QString timestampNoSeconds(timeStampBuffer);
|
||||||
this->appendWord(Word(timestampNoSeconds, Word::TimestampNoSeconds,
|
this->appendWord(Word(timestampNoSeconds, Word::TimestampNoSeconds,
|
||||||
MessageColor(MessageColor::System), QString(), QString()));
|
MessageColor(MessageColor::System), QString()));
|
||||||
|
|
||||||
// Add word for timestamp with seconds
|
// Add word for timestamp with seconds
|
||||||
strftime(timeStampBuffer, 69, "%H:%M:%S", localtime(&time));
|
strftime(timeStampBuffer, 69, "%H:%M:%S", localtime(&time));
|
||||||
QString timestampWithSeconds(timeStampBuffer);
|
QString timestampWithSeconds(timeStampBuffer);
|
||||||
this->appendWord(Word(timestampWithSeconds, Word::TimestampWithSeconds,
|
this->appendWord(Word(timestampWithSeconds, Word::TimestampWithSeconds,
|
||||||
MessageColor(MessageColor::System), QString(), QString()));
|
MessageColor(MessageColor::System), QString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MessageBuilder::matchLink(const QString &string)
|
QString MessageBuilder::matchLink(const QString &string)
|
||||||
|
|
|
@ -4,35 +4,30 @@ namespace chatterino {
|
||||||
namespace messages {
|
namespace messages {
|
||||||
|
|
||||||
// Image word
|
// Image word
|
||||||
Word::Word(LazyLoadedImage *image, Type type, const QString ©text, const QString &tooltip,
|
Word::Word(const QString &imageURL, Type type, const QString &tooltip, const Link &link)
|
||||||
const Link &link)
|
: imageURL(imageURL)
|
||||||
: image(image)
|
|
||||||
, _isImage(true)
|
, _isImage(true)
|
||||||
, type(type)
|
, type(type)
|
||||||
, copyText(copytext)
|
|
||||||
, tooltip(tooltip)
|
, tooltip(tooltip)
|
||||||
, link(link)
|
, link(link)
|
||||||
{
|
{
|
||||||
image->getWidth(); // professional segfault test
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text word
|
// Text word
|
||||||
Word::Word(const QString &text, Type type, const MessageColor &color, const QString ©text,
|
Word::Word(const QString &text, Type type, const MessageColor &color, const QString &tooltip,
|
||||||
const QString &tooltip, const Link &link)
|
const Link &link)
|
||||||
: image(nullptr)
|
: text(text)
|
||||||
, text(text)
|
|
||||||
, color(color)
|
, color(color)
|
||||||
, _isImage(false)
|
, _isImage(false)
|
||||||
, type(type)
|
, type(type)
|
||||||
, copyText(copytext)
|
|
||||||
, tooltip(tooltip)
|
, tooltip(tooltip)
|
||||||
, link(link)
|
, link(link)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyLoadedImage &Word::getImage() const
|
const QString &Word::getImageURL() const
|
||||||
{
|
{
|
||||||
return *this->image;
|
return this->imageURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString &Word::getText() const
|
const QString &Word::getText() const
|
||||||
|
@ -40,22 +35,6 @@ const QString &Word::getText() const
|
||||||
return this->text;
|
return this->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Word::getWidth() const
|
|
||||||
{
|
|
||||||
return this->width;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Word::getHeight() const
|
|
||||||
{
|
|
||||||
return this->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Word::setSize(int width, int height)
|
|
||||||
{
|
|
||||||
this->width = width;
|
|
||||||
this->height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Word::isImage() const
|
bool Word::isImage() const
|
||||||
{
|
{
|
||||||
return this->_isImage;
|
return this->_isImage;
|
||||||
|
@ -71,21 +50,6 @@ const QString &Word::getCopyText() const
|
||||||
return this->copyText;
|
return this->copyText;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Word::hasTrailingSpace() const
|
|
||||||
{
|
|
||||||
return this->_hasTrailingSpace;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFont &Word::getFont() const
|
|
||||||
{
|
|
||||||
return FontManager::getInstance().getFont(this->font);
|
|
||||||
}
|
|
||||||
|
|
||||||
QFontMetrics &Word::getFontMetrics() const
|
|
||||||
{
|
|
||||||
return FontManager::getInstance().getFontMetrics(this->font);
|
|
||||||
}
|
|
||||||
|
|
||||||
Word::Type Word::getType() const
|
Word::Type Word::getType() const
|
||||||
{
|
{
|
||||||
return this->type;
|
return this->type;
|
||||||
|
@ -106,46 +70,5 @@ const Link &Word::getLink() const
|
||||||
return this->link;
|
return this->link;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Word::getXOffset() const
|
|
||||||
{
|
|
||||||
return this->xOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Word::getYOffset() const
|
|
||||||
{
|
|
||||||
return this->yOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Word::setOffset(int xOffset, int yOffset)
|
|
||||||
{
|
|
||||||
this->xOffset = std::max(0, xOffset);
|
|
||||||
this->yOffset = std::max(0, yOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Word::getCharacterLength() const
|
|
||||||
{
|
|
||||||
return this->isImage() ? 2 : this->getText().length() + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &Word::getEmoteURL() const
|
|
||||||
{
|
|
||||||
return emoteURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<short> &Word::getCharacterWidthCache() const
|
|
||||||
{
|
|
||||||
// lock not required because there is only one gui thread
|
|
||||||
// std::lock_guard<std::mutex> lock(this->charWidthCacheMutex);
|
|
||||||
|
|
||||||
if (this->charWidthCache.size() == 0 && this->isText()) {
|
|
||||||
for (int i = 0; i < this->getText().length(); i++) {
|
|
||||||
this->charWidthCache.push_back(this->getFontMetrics().charWidth(this->getText(), i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: on font change
|
|
||||||
return this->charWidthCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace messages
|
} // namespace messages
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -89,56 +89,32 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit Word(LazyLoadedImage *_image, Type getType, const QString ©text,
|
explicit Word(const QString &imageURL, Type getType, const QString &getTooltip,
|
||||||
const QString &getTooltip, const Link &getLink = Link());
|
const Link &getLink = Link());
|
||||||
explicit Word(const QString &_text, Type getType, const MessageColor &getColor,
|
explicit Word(const QString &_text, Type getType, const MessageColor &getColor,
|
||||||
const QString ©text, const QString &getTooltip, const Link &getLink = Link());
|
const QString &getTooltip, const Link &getLink = Link());
|
||||||
|
|
||||||
LazyLoadedImage &getImage() const;
|
const QString &getImageURL() const;
|
||||||
const QString &getText() const;
|
const QString &getText() const;
|
||||||
int getWidth() const;
|
|
||||||
int getHeight() const;
|
|
||||||
void setSize(int _width, int _height);
|
|
||||||
|
|
||||||
bool isImage() const;
|
bool isImage() const;
|
||||||
bool isText() const;
|
bool isText() const;
|
||||||
const QString &getCopyText() const;
|
const QString &getCopyText() const;
|
||||||
bool hasTrailingSpace() const;
|
|
||||||
QFont &getFont() const;
|
|
||||||
QFontMetrics &getFontMetrics() const;
|
|
||||||
Type getType() const;
|
Type getType() const;
|
||||||
const QString &getTooltip() const;
|
const QString &getTooltip() const;
|
||||||
const MessageColor &getColor() const;
|
const MessageColor &getColor() const;
|
||||||
const Link &getLink() const;
|
const Link &getLink() const;
|
||||||
int getXOffset() const;
|
|
||||||
int getYOffset() const;
|
|
||||||
void setOffset(int _xOffset, int _yOffset);
|
|
||||||
int getCharacterLength() const;
|
|
||||||
const QString &getEmoteURL() const;
|
|
||||||
|
|
||||||
std::vector<short> &getCharacterWidthCache() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LazyLoadedImage *image;
|
QString imageURL;
|
||||||
QString text;
|
QString text;
|
||||||
MessageColor color;
|
MessageColor color;
|
||||||
bool _isImage;
|
bool _isImage;
|
||||||
QString emoteURL;
|
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
QString copyText;
|
QString copyText;
|
||||||
QString tooltip;
|
QString tooltip;
|
||||||
|
|
||||||
int width = 16;
|
|
||||||
int height = 16;
|
|
||||||
int xOffset = 0;
|
|
||||||
int yOffset = 0;
|
|
||||||
|
|
||||||
bool _hasTrailingSpace = true;
|
|
||||||
FontManager::Type font = FontManager::Medium;
|
|
||||||
Link link;
|
Link link;
|
||||||
|
|
||||||
mutable std::vector<short> charWidthCache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace messages
|
} // namespace messages
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "twitch/twitchmessagebuilder.hpp"
|
#include "twitch/twitchmessagebuilder.hpp"
|
||||||
#include "colorscheme.hpp"
|
#include "colorscheme.hpp"
|
||||||
#include "debug/log.hpp"
|
#include "debug/log.hpp"
|
||||||
#include "emotemanager.hpp"
|
#include "emotemanager.hpp"
|
||||||
|
@ -52,9 +52,11 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
|
|
||||||
this->appendModerationButtons();
|
this->appendModerationButtons();
|
||||||
|
|
||||||
|
/*
|
||||||
this->parseTwitchBadges();
|
this->parseTwitchBadges();
|
||||||
|
|
||||||
this->parseChatterinoBadges();
|
this->parseChatterinoBadges();
|
||||||
|
*/
|
||||||
|
|
||||||
if (this->args.includeChannelName) {
|
if (this->args.includeChannelName) {
|
||||||
this->parseChannelName();
|
this->parseChannelName();
|
||||||
|
@ -76,7 +78,7 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
// twitch emotes
|
// twitch emotes
|
||||||
std::vector<std::pair<long, EmoteData>> twitchEmotes;
|
std::vector<std::pair<long, Emote>> twitchEmotes;
|
||||||
|
|
||||||
iterator = this->tags.find("emotes");
|
iterator = this->tags.find("emotes");
|
||||||
if (iterator != this->tags.end()) {
|
if (iterator != this->tags.end()) {
|
||||||
|
@ -87,8 +89,7 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool operator()(const std::pair<long, EmoteData> &lhs,
|
bool operator()(const std::pair<long, Emote> &lhs, const std::pair<long, Emote> &rhs)
|
||||||
const std::pair<long, EmoteData> &rhs)
|
|
||||||
{
|
{
|
||||||
return lhs.first < rhs.first;
|
return lhs.first < rhs.first;
|
||||||
}
|
}
|
||||||
|
@ -111,14 +112,10 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
|
|
||||||
// twitch emote
|
// twitch emote
|
||||||
if (currentTwitchEmote != twitchEmotes.end() && currentTwitchEmote->first == i) {
|
if (currentTwitchEmote != twitchEmotes.end() && currentTwitchEmote->first == i) {
|
||||||
this->appendWord(
|
this->appendWord(Word(currentTwitchEmote->second.url, Word::TwitchEmoteImage,
|
||||||
Word(currentTwitchEmote->second.image, Word::TwitchEmoteImage,
|
currentTwitchEmote->second.name));
|
||||||
currentTwitchEmote->second.image->getName(),
|
/*this->appendWord(Word(currentTwitchEmote->second.url, Word::TwitchEmoteText,
|
||||||
currentTwitchEmote->second.image->getName() + QString("\nTwitch Emote")));
|
textColor, currentTwitchEmote->second.name));*/
|
||||||
this->appendWord(
|
|
||||||
Word(currentTwitchEmote->second.image->getName(), Word::TwitchEmoteText, textColor,
|
|
||||||
currentTwitchEmote->second.image->getName(),
|
|
||||||
currentTwitchEmote->second.image->getName() + QString("\nTwitch Emote")));
|
|
||||||
|
|
||||||
i += split.length() + 1;
|
i += split.length() + 1;
|
||||||
currentTwitchEmote = std::next(currentTwitchEmote);
|
currentTwitchEmote = std::next(currentTwitchEmote);
|
||||||
|
@ -127,15 +124,15 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
// split words
|
// split words
|
||||||
std::vector<std::tuple<EmoteData, QString>> parsed;
|
std::vector<std::tuple<std::unique_ptr<Emote>, QString>> parsed;
|
||||||
|
|
||||||
// Parse emojis and take all non-emojis and put them in parsed as full text-words
|
// Parse emojis and take all non-emojis and put them in parsed as full text-words
|
||||||
emoteManager.parseEmojis(parsed, split);
|
emoteManager.parseEmojis(parsed, split);
|
||||||
|
|
||||||
for (const auto &tuple : parsed) {
|
for (const std::tuple<std::unique_ptr<Emote>, QString> &tuple : parsed) {
|
||||||
const EmoteData &emoteData = std::get<0>(tuple);
|
Emote *emote = std::get<0>(tuple).get();
|
||||||
|
|
||||||
if (emoteData.image == nullptr) { // is text
|
if (emote == nullptr) { // is text
|
||||||
QString string = std::get<1>(tuple);
|
QString string = std::get<1>(tuple);
|
||||||
|
|
||||||
static QRegularExpression cheerRegex("cheer[1-9][0-9]*");
|
static QRegularExpression cheerRegex("cheer[1-9][0-9]*");
|
||||||
|
@ -170,31 +167,20 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
QString bitsLink =
|
QString bitsLink =
|
||||||
QString("http://static-cdn.jtvnw.net/bits/dark/static/" + color + "/1");
|
QString("http://static-cdn.jtvnw.net/bits/dark/static/" + color + "/1");
|
||||||
|
|
||||||
LazyLoadedImage *imageAnimated = emoteManager.miscImageCache.getOrAdd(
|
this->appendWord(Word(bitsLinkAnimated, Word::BitsAnimated,
|
||||||
bitsLinkAnimated, [this, &bitsLinkAnimated] {
|
|
||||||
return new LazyLoadedImage(this->emoteManager, this->windowManager,
|
|
||||||
bitsLinkAnimated);
|
|
||||||
});
|
|
||||||
LazyLoadedImage *image =
|
|
||||||
emoteManager.miscImageCache.getOrAdd(bitsLink, [this, &bitsLink] {
|
|
||||||
return new LazyLoadedImage(this->emoteManager, this->windowManager,
|
|
||||||
bitsLink);
|
|
||||||
});
|
|
||||||
|
|
||||||
this->appendWord(Word(imageAnimated, Word::BitsAnimated, QString("cheer"),
|
|
||||||
QString("Twitch Cheer"),
|
QString("Twitch Cheer"),
|
||||||
Link(Link::Url, QString("https://blog.twitch.tv/"
|
Link(Link::Url, QString("https://blog.twitch.tv/"
|
||||||
"introducing-cheering-celebrate-"
|
"introducing-cheering-celebrate-"
|
||||||
"together-da62af41fac6"))));
|
"together-da62af41fac6"))));
|
||||||
this->appendWord(Word(
|
this->appendWord(Word(
|
||||||
image, Word::BitsStatic, QString("cheer"), QString("Twitch Cheer"),
|
bitsLink, Word::BitsStatic, QString("Twitch Cheer"),
|
||||||
Link(Link::Url,
|
Link(Link::Url,
|
||||||
QString("https://blog.twitch.tv/"
|
QString("https://blog.twitch.tv/"
|
||||||
"introducing-cheering-celebrate-together-da62af41fac6"))));
|
"introducing-cheering-celebrate-together-da62af41fac6"))));
|
||||||
|
|
||||||
this->appendWord(Word(
|
this->appendWord(Word(
|
||||||
QString("x" + string.mid(5)), Word::BitsAmount, MessageColor(bitsColor),
|
QString("x" + string.mid(5)), Word::BitsAmount, MessageColor(bitsColor),
|
||||||
QString(string.mid(5)), QString("Twitch Cheer"),
|
QString("Twitch Cheer"),
|
||||||
Link(Link::Url,
|
Link(Link::Url,
|
||||||
QString("https://blog.twitch.tv/"
|
QString("https://blog.twitch.tv/"
|
||||||
"introducing-cheering-celebrate-together-da62af41fac6"))));
|
"introducing-cheering-celebrate-together-da62af41fac6"))));
|
||||||
|
@ -224,14 +210,13 @@ SharedMessage TwitchMessageBuilder::parse()
|
||||||
textColor = MessageColor(MessageColor::Link);
|
textColor = MessageColor(MessageColor::Link);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->appendWord(Word(string, Word::Text, textColor, string, QString(), link));
|
this->appendWord(Word(string, Word::Text, textColor, string, link));
|
||||||
} else { // is emoji
|
} else { // is emoji
|
||||||
static QString emojiTooltip("Emoji");
|
static QString emojiTooltip("Emoji");
|
||||||
|
|
||||||
this->appendWord(Word(emoteData.image, Word::EmojiImage, emoteData.image->getName(),
|
this->appendWord(Word(emote->url, Word::EmojiImage, emojiTooltip));
|
||||||
emojiTooltip));
|
/*Word(emoteData.image->getName(), Word::EmojiText, textColor,
|
||||||
Word(emoteData.image->getName(), Word::EmojiText, textColor,
|
emoteData.image->getName(), emojiTooltip);*/
|
||||||
emoteData.image->getName(), emojiTooltip);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +260,7 @@ void TwitchMessageBuilder::parseChannelName()
|
||||||
{
|
{
|
||||||
QString channelName("#" + this->channel->name);
|
QString channelName("#" + this->channel->name);
|
||||||
this->appendWord(Word(channelName, Word::Misc, MessageColor(MessageColor::System),
|
this->appendWord(Word(channelName, Word::Misc, MessageColor(MessageColor::System),
|
||||||
QString(channelName), QString(),
|
QString(channelName),
|
||||||
Link(Link::Url, this->channel->name + "\n" + this->messageID)));
|
Link(Link::Url, this->channel->name + "\n" + this->messageID)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +341,7 @@ void TwitchMessageBuilder::appendUsername()
|
||||||
}
|
}
|
||||||
|
|
||||||
this->appendWord(Word(usernameString, Word::Username, MessageColor(this->usernameColor),
|
this->appendWord(Word(usernameString, Word::Username, MessageColor(this->usernameColor),
|
||||||
usernameString, QString(), Link(Link::UserInfo, this->userName)));
|
usernameString, Link(Link::UserInfo, this->userName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwitchMessageBuilder::parseHighlights()
|
void TwitchMessageBuilder::parseHighlights()
|
||||||
|
@ -450,18 +435,22 @@ void TwitchMessageBuilder::parseHighlights()
|
||||||
void TwitchMessageBuilder::appendModerationButtons()
|
void TwitchMessageBuilder::appendModerationButtons()
|
||||||
{
|
{
|
||||||
// mod buttons
|
// mod buttons
|
||||||
|
|
||||||
static QString buttonBanTooltip("Ban user");
|
static QString buttonBanTooltip("Ban user");
|
||||||
static QString buttonTimeoutTooltip("Timeout user");
|
static QString buttonTimeoutTooltip("Timeout user");
|
||||||
|
|
||||||
this->appendWord(Word(this->resources.buttonBan, Word::ButtonBan, QString(), buttonBanTooltip,
|
// TODO: Implement ban buttons
|
||||||
Link(Link::UserBan, ircMessage->account())));
|
/*
|
||||||
this->appendWord(Word(this->resources.buttonTimeout, Word::ButtonTimeout, QString(),
|
this->appendWord(Word(this->resources.buttonBan->getUrl(), Word::ButtonBan, QString(),
|
||||||
buttonTimeoutTooltip, Link(Link::UserTimeout, ircMessage->account())));
|
buttonBanTooltip, Link(Link::UserBan, ircMessage->account())));
|
||||||
|
this->appendWord(Word(this->resources.buttonTimeout->getUrl(), Word::ButtonTimeout,
|
||||||
|
QString(), buttonTimeoutTooltip, Link(Link::UserTimeout, ircMessage->account())));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwitchMessageBuilder::appendTwitchEmote(const Communi::IrcPrivateMessage *ircMessage,
|
void TwitchMessageBuilder::appendTwitchEmote(const Communi::IrcPrivateMessage *ircMessage,
|
||||||
const QString &emote,
|
const QString &emote,
|
||||||
std::vector<std::pair<long int, EmoteData>> &vec,
|
std::vector<std::pair<long, Emote>> &vec,
|
||||||
EmoteManager &emoteManager)
|
EmoteManager &emoteManager)
|
||||||
{
|
{
|
||||||
if (!emote.contains(':')) {
|
if (!emote.contains(':')) {
|
||||||
|
@ -494,45 +483,43 @@ void TwitchMessageBuilder::appendTwitchEmote(const Communi::IrcPrivateMessage *i
|
||||||
|
|
||||||
QString name = ircMessage->content().mid(start, end - start + 1);
|
QString name = ircMessage->content().mid(start, end - start + 1);
|
||||||
|
|
||||||
vec.push_back(
|
vec.push_back(std::pair<long, Emote>(start, emoteManager.getTwitchEmoteById(id, name)));
|
||||||
std::pair<long int, EmoteData>(start, emoteManager.getTwitchEmoteById(id, name)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TwitchMessageBuilder::tryAppendEmote(QString &emoteString)
|
bool TwitchMessageBuilder::tryAppendEmote(QString &emoteString)
|
||||||
{
|
{
|
||||||
EmoteData emoteData;
|
Emote emote;
|
||||||
|
|
||||||
if (emoteManager.bttvGlobalEmotes.tryGet(emoteString, emoteData)) {
|
if (emoteManager.bttvGlobalEmotes.tryGet(emoteString, emote)) {
|
||||||
// BTTV Global Emote
|
// BTTV Global Emote
|
||||||
return this->appendEmote(emoteData);
|
return this->appendEmote(emote);
|
||||||
} else if (this->twitchChannel->bttvChannelEmotes->tryGet(emoteString, emoteData)) {
|
} else if (this->twitchChannel->bttvChannelEmotes->tryGet(emoteString, emote)) {
|
||||||
// BTTV Channel Emote
|
// BTTV Channel Emote
|
||||||
return this->appendEmote(emoteData);
|
return this->appendEmote(emote);
|
||||||
} else if (emoteManager.ffzGlobalEmotes.tryGet(emoteString, emoteData)) {
|
} else if (emoteManager.ffzGlobalEmotes.tryGet(emoteString, emote)) {
|
||||||
// FFZ Global Emote
|
// FFZ Global Emote
|
||||||
return this->appendEmote(emoteData);
|
return this->appendEmote(emote);
|
||||||
} else if (this->twitchChannel->ffzChannelEmotes->tryGet(emoteString, emoteData)) {
|
} else if (this->twitchChannel->ffzChannelEmotes->tryGet(emoteString, emote)) {
|
||||||
// FFZ Channel Emote
|
// FFZ Channel Emote
|
||||||
return this->appendEmote(emoteData);
|
return this->appendEmote(emote);
|
||||||
} else if (emoteManager.getChatterinoEmotes().tryGet(emoteString, emoteData)) {
|
} else if (emoteManager.getChatterinoEmotes().tryGet(emoteString, emote)) {
|
||||||
// Chatterino Emote
|
// Chatterino Emote
|
||||||
return this->appendEmote(emoteData);
|
return this->appendEmote(emote);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TwitchMessageBuilder::appendEmote(EmoteData &emoteData)
|
bool TwitchMessageBuilder::appendEmote(Emote &emote)
|
||||||
{
|
{
|
||||||
this->appendWord(Word(emoteData.image, Word::BttvEmoteImage, emoteData.image->getName(),
|
this->appendWord(Word(emote.url, Word::EmoteImages, emote.name, Link(Link::Url, emote.url)));
|
||||||
emoteData.image->getTooltip(),
|
|
||||||
Link(Link::Url, emoteData.image->getUrl())));
|
|
||||||
|
|
||||||
// Perhaps check for ignored emotes here?
|
// Perhaps check for ignored emotes here?
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void TwitchMessageBuilder::parseTwitchBadges()
|
void TwitchMessageBuilder::parseTwitchBadges()
|
||||||
{
|
{
|
||||||
const auto &channelResources = this->resources.channels[this->roomID];
|
const auto &channelResources = this->resources.channels[this->roomID];
|
||||||
|
@ -567,7 +554,7 @@ void TwitchMessageBuilder::parseTwitchBadges()
|
||||||
auto &badgeVersion = badgeSet.versions.at(versionKey);
|
auto &badgeVersion = badgeSet.versions.at(versionKey);
|
||||||
|
|
||||||
appendWord(
|
appendWord(
|
||||||
Word(badgeVersion.badgeImage1x, Word::BadgeVanity, QString(),
|
Word(badgeVersion.badgeImage1x, Word::BadgeVanity,
|
||||||
QString("Twitch " + QString::fromStdString(badgeVersion.title))));
|
QString("Twitch " + QString::fromStdString(badgeVersion.title))));
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
debug::Log("Exception caught: {} when trying to fetch badge version {}",
|
debug::Log("Exception caught: {} when trying to fetch badge version {}",
|
||||||
|
@ -577,34 +564,34 @@ void TwitchMessageBuilder::parseTwitchBadges()
|
||||||
debug::Log("No badge set with key bits. Exception: {}", e.what());
|
debug::Log("No badge set with key bits. Exception: {}", e.what());
|
||||||
}
|
}
|
||||||
} else if (badge == "staff/1") {
|
} else if (badge == "staff/1") {
|
||||||
appendWord(Word(this->resources.badgeStaff, Word::BadgeGlobalAuthority, QString(),
|
appendWord(Word(this->resources.badgeStaff, Word::BadgeGlobalAuthority,
|
||||||
QString("Twitch Staff")));
|
QString("Twitch Staff")));
|
||||||
} else if (badge == "admin/1") {
|
} else if (badge == "admin/1") {
|
||||||
appendWord(Word(this->resources.badgeAdmin, Word::BadgeGlobalAuthority, QString(),
|
appendWord(Word(this->resources.badgeAdmin, Word::BadgeGlobalAuthority,
|
||||||
QString("Twitch Admin")));
|
QString("Twitch Admin")));
|
||||||
} else if (badge == "global_mod/1") {
|
} else if (badge == "global_mod/1") {
|
||||||
appendWord(Word(this->resources.badgeGlobalModerator, Word::BadgeGlobalAuthority,
|
appendWord(Word(this->resources.badgeGlobalModerator, Word::BadgeGlobalAuthority,
|
||||||
QString(), QString("Global Moderator")));
|
QString("Global Moderator")));
|
||||||
} else if (badge == "moderator/1") {
|
} else if (badge == "moderator/1") {
|
||||||
// TODO: Implement custom FFZ moderator badge
|
// TODO: Implement custom FFZ moderator badge
|
||||||
appendWord(Word(this->resources.badgeModerator, Word::BadgeChannelAuthority, QString(),
|
appendWord(Word(this->resources.badgeModerator, Word::BadgeChannelAuthority,
|
||||||
QString("Channel Moderator"))); // custom badge
|
QString("Channel Moderator"))); // custom badge
|
||||||
} else if (badge == "turbo/1") {
|
} else if (badge == "turbo/1") {
|
||||||
appendWord(Word(this->resources.badgeTurbo, Word::BadgeVanity, QString(),
|
appendWord(
|
||||||
QString("Turbo Subscriber")));
|
Word(this->resources.badgeTurbo, Word::BadgeVanity, QString("Turbo Subscriber")));
|
||||||
} else if (badge == "broadcaster/1") {
|
} else if (badge == "broadcaster/1") {
|
||||||
appendWord(Word(this->resources.badgeBroadcaster, Word::BadgeChannelAuthority,
|
appendWord(Word(this->resources.badgeBroadcaster, Word::BadgeChannelAuthority,
|
||||||
QString(), QString("Channel Broadcaster")));
|
QString("Channel Broadcaster")));
|
||||||
} else if (badge == "premium/1") {
|
} else if (badge == "premium/1") {
|
||||||
appendWord(Word(this->resources.badgePremium, Word::BadgeVanity, QString(),
|
appendWord(Word(this->resources.badgePremium, Word::BadgeVanity),
|
||||||
QString("Twitch Prime")));
|
QString("Twitch Prime")));
|
||||||
|
|
||||||
} else if (badge.startsWith("partner/")) {
|
} else if (badge.startsWith("partner/")) {
|
||||||
int index = badge.midRef(8).toInt();
|
int index = badge.midRef(8).toInt();
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 1: {
|
case 1: {
|
||||||
appendWord(Word(this->resources.badgeVerified, Word::BadgeVanity, QString(),
|
appendWord(
|
||||||
"Twitch Verified"));
|
Word(this->resources.badgeVerified, Word::BadgeVanity, "Twitch Verified"));
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
printf("[TwitchMessageBuilder] Unhandled partner badge index: %d\n", index);
|
printf("[TwitchMessageBuilder] Unhandled partner badge index: %d\n", index);
|
||||||
|
@ -625,7 +612,7 @@ void TwitchMessageBuilder::parseTwitchBadges()
|
||||||
auto &badgeVersion = badgeSet.versions.at(versionKey);
|
auto &badgeVersion = badgeSet.versions.at(versionKey);
|
||||||
|
|
||||||
appendWord(
|
appendWord(
|
||||||
Word(badgeVersion.badgeImage1x, Word::Type::BadgeSubscription, QString(),
|
Word(badgeVersion.badgeImage1x, Word::Type::BadgeSubscription,
|
||||||
QString("Twitch " + QString::fromStdString(badgeVersion.title))));
|
QString("Twitch " + QString::fromStdString(badgeVersion.title))));
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
qDebug() << "Exception caught:" << e.what()
|
qDebug() << "Exception caught:" << e.what()
|
||||||
|
@ -673,7 +660,9 @@ void TwitchMessageBuilder::parseTwitchBadges()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
void TwitchMessageBuilder::parseChatterinoBadges()
|
void TwitchMessageBuilder::parseChatterinoBadges()
|
||||||
{
|
{
|
||||||
auto &badges = this->resources.chatterinoBadges;
|
auto &badges = this->resources.chatterinoBadges;
|
||||||
|
@ -687,6 +676,7 @@ void TwitchMessageBuilder::parseChatterinoBadges()
|
||||||
|
|
||||||
this->appendWord(Word(badge->image, Word::BadgeChatterino, QString(), badge->tooltip.c_str()));
|
this->appendWord(Word(badge->image, Word::BadgeChatterino, QString(), badge->tooltip.c_str()));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// bool
|
// bool
|
||||||
// sortTwitchEmotes(const std::pair<long int, LazyLoadedImage *> &a,
|
// sortTwitchEmotes(const std::pair<long int, LazyLoadedImage *> &a,
|
||||||
|
|
|
@ -66,13 +66,14 @@ private:
|
||||||
|
|
||||||
void appendModerationButtons();
|
void appendModerationButtons();
|
||||||
void appendTwitchEmote(const Communi::IrcPrivateMessage *ircMessage, const QString &emote,
|
void appendTwitchEmote(const Communi::IrcPrivateMessage *ircMessage, const QString &emote,
|
||||||
std::vector<std::pair<long, EmoteData>> &vec,
|
std::vector<std::pair<long, Emote>> &vec, EmoteManager &emoteManager);
|
||||||
EmoteManager &emoteManager);
|
|
||||||
bool tryAppendEmote(QString &emoteString);
|
bool tryAppendEmote(QString &emoteString);
|
||||||
bool appendEmote(EmoteData &emoteData);
|
bool appendEmote(Emote &emote);
|
||||||
|
|
||||||
|
/* TODO: Implement badges
|
||||||
void parseTwitchBadges();
|
void parseTwitchBadges();
|
||||||
void parseChatterinoBadges();
|
void parseChatterinoBadges();
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace twitch
|
} // namespace twitch
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
#include "colorscheme.hpp"
|
#include "colorscheme.hpp"
|
||||||
#include "messages/limitedqueuesnapshot.hpp"
|
#include "messages/limitedqueuesnapshot.hpp"
|
||||||
#include "messages/message.hpp"
|
#include "messages/message.hpp"
|
||||||
#include "messages/messageref.hpp"
|
|
||||||
#include "settingsmanager.hpp"
|
#include "settingsmanager.hpp"
|
||||||
#include "ui_accountpopupform.h"
|
#include "ui_accountpopupform.h"
|
||||||
#include "util/distancebetweenpoints.hpp"
|
#include "util/distancebetweenpoints.hpp"
|
||||||
#include "widgets/chatwidget.hpp"
|
#include "widgets/chatwidget.hpp"
|
||||||
#include "windowmanager.hpp"
|
#include "windowmanager.hpp"
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QGraphicsBlurEffect>
|
#include <QGraphicsBlurEffect>
|
||||||
|
@ -45,12 +45,32 @@ ChannelView::~ChannelView()
|
||||||
|
|
||||||
void ChannelView::clearMessages()
|
void ChannelView::clearMessages()
|
||||||
{
|
{
|
||||||
this->messages.clear();
|
web.page()->runJavaScript("clearMessages()");
|
||||||
}
|
}
|
||||||
|
|
||||||
messages::LimitedQueueSnapshot<SharedMessageRef> ChannelView::getMessagesSnapshot()
|
void ChannelView::addMessage(SharedMessage &message)
|
||||||
{
|
{
|
||||||
return this->messages.getSnapshot();
|
auto command = QString("addMessage(");
|
||||||
|
for (int i = 0; i < message->getWords().size(); i++) {
|
||||||
|
auto word = message->getWords()[i];
|
||||||
|
if (word.isText()) {
|
||||||
|
if (i != 0)
|
||||||
|
command += ",";
|
||||||
|
command += QString("{type:'text', data:'%1', color: '%2'}")
|
||||||
|
.arg(word.getText(), word.getColor().getColor(this->colorScheme).name());
|
||||||
|
} else {
|
||||||
|
if (word.getType() == messages::Word::Type::Badges) {
|
||||||
|
// command += "{type:'emote', data:'" + word.+ "'}";
|
||||||
|
} else if (word.getType() | messages::Word::Type::EmoteImages) {
|
||||||
|
if (i != 0)
|
||||||
|
command += ",";
|
||||||
|
command += "{type:'emote', data:'" + word.getImageURL() + "'}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
command += ");";
|
||||||
|
qDebug() << command;
|
||||||
|
web.page()->runJavaScript(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelView::setChannel(std::shared_ptr<Channel> channel)
|
void ChannelView::setChannel(std::shared_ptr<Channel> channel)
|
||||||
|
@ -58,49 +78,11 @@ void ChannelView::setChannel(std::shared_ptr<Channel> channel)
|
||||||
if (this->channel) {
|
if (this->channel) {
|
||||||
this->detachChannel();
|
this->detachChannel();
|
||||||
}
|
}
|
||||||
this->messages.clear();
|
this->clearMessages();
|
||||||
|
|
||||||
// on new message
|
// on new message
|
||||||
this->messageAppendedConnection =
|
this->messageAppendedConnection = channel->messageAppended.connect(boost::bind(
|
||||||
channel->messageAppended.connect([this](SharedMessage &message) {
|
&ChannelView::addMessage, this, _1)); // Has to use boost::bind for some reason.
|
||||||
// SharedMessageRef deleted;
|
|
||||||
|
|
||||||
auto command = QString("addMessage('%1','%2'").arg("", "");
|
|
||||||
for (const auto &word : message->getWords()) {
|
|
||||||
command += ",";
|
|
||||||
if (word.isText()) {
|
|
||||||
command += "{type:'text', data:'" + word.getText() + "'}";
|
|
||||||
} else {
|
|
||||||
command += "{type:'emote', data:'" + word.getEmoteURL() + "'}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
command += ");";
|
|
||||||
qDebug() << command;
|
|
||||||
web.page()->runJavaScript(command);
|
|
||||||
|
|
||||||
/*if (this->messages.appendItem(SharedMessageRef(messageRef), deleted)) {
|
|
||||||
qreal value = std::max(0.0, this->getScrollBar().getDesiredValue() - 1);
|
|
||||||
|
|
||||||
this->getScrollBar().setDesiredValue(value, false);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// layoutMessages();
|
|
||||||
// update();
|
|
||||||
});
|
|
||||||
|
|
||||||
// on message removed
|
|
||||||
this->messageRemovedConnection =
|
|
||||||
channel->messageRemovedFromStart.connect([](SharedMessage &) {});
|
|
||||||
|
|
||||||
auto snapshot = channel->getMessageSnapshot();
|
|
||||||
|
|
||||||
for (size_t i = 0; i < snapshot.getLength(); i++) {
|
|
||||||
SharedMessageRef deleted;
|
|
||||||
|
|
||||||
auto messageRef = new MessageRef(snapshot[i]);
|
|
||||||
|
|
||||||
this->messages.appendItem(SharedMessageRef(messageRef), deleted);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->channel = channel;
|
this->channel = channel;
|
||||||
|
|
||||||
|
@ -111,9 +93,6 @@ void ChannelView::detachChannel()
|
||||||
{
|
{
|
||||||
// on message added
|
// on message added
|
||||||
this->messageAppendedConnection.disconnect();
|
this->messageAppendedConnection.disconnect();
|
||||||
|
|
||||||
// on message removed
|
|
||||||
this->messageRemovedConnection.disconnect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace widgets
|
} // namespace widgets
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include "channel.hpp"
|
#include "channel.hpp"
|
||||||
#include "messages/lazyloadedimage.hpp"
|
#include "messages/lazyloadedimage.hpp"
|
||||||
#include "messages/limitedqueuesnapshot.hpp"
|
#include "messages/limitedqueuesnapshot.hpp"
|
||||||
#include "messages/messageref.hpp"
|
|
||||||
#include "messages/word.hpp"
|
#include "messages/word.hpp"
|
||||||
#include "widgets/accountpopup.hpp"
|
#include "widgets/accountpopup.hpp"
|
||||||
#include "widgets/basewidget.hpp"
|
#include "widgets/basewidget.hpp"
|
||||||
|
@ -30,7 +29,7 @@ public:
|
||||||
~ChannelView();
|
~ChannelView();
|
||||||
|
|
||||||
void setChannel(std::shared_ptr<Channel> channel);
|
void setChannel(std::shared_ptr<Channel> channel);
|
||||||
messages::LimitedQueueSnapshot<messages::SharedMessageRef> getMessagesSnapshot();
|
void addMessage(messages::SharedMessage &message);
|
||||||
|
|
||||||
void clearMessages();
|
void clearMessages();
|
||||||
|
|
||||||
|
@ -50,10 +49,7 @@ private:
|
||||||
|
|
||||||
AccountPopupWidget userPopupWidget;
|
AccountPopupWidget userPopupWidget;
|
||||||
|
|
||||||
messages::LimitedQueue<messages::SharedMessageRef> messages;
|
|
||||||
|
|
||||||
boost::signals2::connection messageAppendedConnection;
|
boost::signals2::connection messageAppendedConnection;
|
||||||
boost::signals2::connection messageRemovedConnection;
|
|
||||||
QWebEngineView web;
|
QWebEngineView web;
|
||||||
QVBoxLayout vbox;
|
QVBoxLayout vbox;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
|
|
||||||
#include "channel.hpp"
|
#include "channel.hpp"
|
||||||
#include "messages/limitedqueuesnapshot.hpp"
|
#include "messages/limitedqueuesnapshot.hpp"
|
||||||
#include "messages/messageref.hpp"
|
|
||||||
#include "messages/word.hpp"
|
#include "messages/word.hpp"
|
||||||
#include "messages/wordpart.hpp"
|
|
||||||
#include "widgets/basewidget.hpp"
|
#include "widgets/basewidget.hpp"
|
||||||
#include "widgets/channelview.hpp"
|
#include "widgets/channelview.hpp"
|
||||||
#include "widgets/chatwidgetheader.hpp"
|
#include "widgets/chatwidgetheader.hpp"
|
||||||
|
|
|
@ -41,7 +41,7 @@ void EmotePopup::loadChannel(std::shared_ptr<Channel> _channel)
|
||||||
messages::MessageBuilder builder1;
|
messages::MessageBuilder builder1;
|
||||||
|
|
||||||
builder1.appendWord(
|
builder1.appendWord(
|
||||||
Word(title, Word::Type::Text, MessageColor(MessageColor::Text), QString(), QString()));
|
Word(title, Word::Type::Text, MessageColor(MessageColor::Text), QString()));
|
||||||
|
|
||||||
builder1.getMessage()->centered = true;
|
builder1.getMessage()->centered = true;
|
||||||
emoteChannel->addMessage(builder1.getMessage());
|
emoteChannel->addMessage(builder1.getMessage());
|
||||||
|
@ -50,11 +50,12 @@ void EmotePopup::loadChannel(std::shared_ptr<Channel> _channel)
|
||||||
messages::MessageBuilder builder2;
|
messages::MessageBuilder builder2;
|
||||||
builder2.getMessage()->centered = true;
|
builder2.getMessage()->centered = true;
|
||||||
|
|
||||||
map.each([&](const QString &key, const EmoteData &value) {
|
/*
|
||||||
builder2.appendWord(Word(value.image, Word::Type::AlwaysShow, key, emoteDesc,
|
map.each([&](const QString &key, const QString &value) {
|
||||||
|
builder2.appendWord(Word(value, Word::Type::AlwaysShow, key, emoteDesc,
|
||||||
Link(Link::Type::InsertText, key)));
|
Link(Link::Type::InsertText, key)));
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
emoteChannel->addMessage(builder2.getMessage());
|
emoteChannel->addMessage(builder2.getMessage());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue