ChatWidgetView -> ChannelView, added Emote Picker

This commit is contained in:
fourtf 2017-09-16 00:05:06 +02:00
parent 84c23a5d00
commit c7b3480aaf
37 changed files with 532 additions and 407 deletions

View file

@ -62,7 +62,6 @@ SOURCES += \
src/widgets/chatwidgetheader.cpp \
src/widgets/chatwidgetheaderbutton.cpp \
src/widgets/chatwidgetinput.cpp \
src/widgets/chatwidgetview.cpp \
src/widgets/mainwindow.cpp \
src/widgets/notebook.cpp \
src/widgets/notebookbutton.cpp \
@ -97,7 +96,9 @@ SOURCES += \
src/completionmanager.cpp \
src/widgets/logindialog.cpp \
src/widgets/qualitypopup.cpp \
src/widgets/emotepopup.cpp
src/widgets/emotepopup.cpp \
src/widgets/channelview.cpp \
src/twitch/twitchchannel.cpp
HEADERS += \
src/asyncexec.hpp \
@ -118,7 +119,6 @@ HEADERS += \
src/widgets/chatwidgetheader.hpp \
src/widgets/chatwidgetheaderbutton.hpp \
src/widgets/chatwidgetinput.hpp \
src/widgets/chatwidgetview.hpp \
src/widgets/mainwindow.hpp \
src/widgets/notebook.hpp \
src/widgets/notebookbutton.hpp \
@ -159,7 +159,9 @@ HEADERS += \
src/widgets/basewidget.hpp \
src/completionmanager.hpp \
src/widgets/qualitypopup.h \
src/widgets/emotepopup.h
src/widgets/emotepopup.h \
src/widgets/channelview.hpp \
src/twitch/twitchchannel.hpp
PRECOMPILED_HEADER =

View file

@ -18,55 +18,14 @@ using namespace chatterino::messages;
namespace chatterino {
Channel::Channel(WindowManager &_windowManager, EmoteManager &_emoteManager,
IrcManager &_ircManager, const QString &channelName, bool isSpecial)
: windowManager(_windowManager)
, emoteManager(_emoteManager)
, ircManager(_ircManager)
, name(channelName)
, bttvChannelEmotes(this->emoteManager.bttvChannels[channelName])
, ffzChannelEmotes(this->emoteManager.ffzChannels[channelName])
, _subLink("https://www.twitch.tv/" + name + "/subscribe?ref=in_chat_subscriber_link")
, _channelLink("https://twitch.tv/" + name)
, _popoutPlayerLink("https://player.twitch.tv/?channel=" + name)
, isLive(false)
Channel::Channel()
// , _loggingChannel(logging::get(_name))
{
qDebug() << "Open channel:" << this->name;
if (!isSpecial) {
this->reloadChannelEmotes();
}
}
//
// properties
//
bool Channel::isEmpty() const
{
return name.isEmpty();
}
const QString &Channel::getSubLink() const
{
return _subLink;
}
const QString &Channel::getChannelLink() const
{
return _channelLink;
}
const QString &Channel::getPopoutPlayerLink() const
{
return _popoutPlayerLink;
}
void Channel::setRoomID(std::string id)
{
this->roomID = id;
this->roomIDchanged();
return false;
}
messages::LimitedQueueSnapshot<messages::SharedMessage> Channel::getMessageSnapshot()
@ -74,9 +33,6 @@ messages::LimitedQueueSnapshot<messages::SharedMessage> Channel::getMessageSnaps
return _messages.getSnapshot();
}
//
// methods
//
void Channel::addMessage(std::shared_ptr<Message> message)
{
std::shared_ptr<Message> deleted;
@ -90,26 +46,15 @@ void Channel::addMessage(std::shared_ptr<Message> message)
}
this->messageAppended(message);
this->windowManager.repaintVisibleChatWidgets(this);
}
// private methods
void Channel::reloadChannelEmotes()
bool Channel::canSendMessage() const
{
printf("[Channel:%s] Reloading channel emotes\n", qPrintable(this->name));
this->emoteManager.reloadBTTVChannelEmotes(this->name);
this->emoteManager.reloadFFZChannelEmotes(this->name);
return false;
}
void Channel::sendMessage(const QString &message)
{
qDebug() << "Channel send message: " << message;
// Do last message processing
QString parsedMessage = this->emoteManager.replaceShortCodes(message);
this->ircManager.sendMessage(name, parsedMessage);
}
} // namespace chatterino

View file

@ -19,58 +19,30 @@ namespace messages {
class Message;
}
class WindowManager;
class IrcManager;
class Channel
{
WindowManager &windowManager;
EmoteManager &emoteManager;
IrcManager &ircManager;
public:
explicit Channel(WindowManager &_windowManager, EmoteManager &_emoteManager,
IrcManager &_ircManager, const QString &channelName, bool isSpecial = false);
explicit Channel();
boost::signals2::signal<void(messages::SharedMessage &)> messageRemovedFromStart;
boost::signals2::signal<void(messages::SharedMessage &)> messageAppended;
bool isEmpty() const;
const QString &getSubLink() const;
const QString &getChannelLink() const;
const QString &getPopoutPlayerLink() const;
virtual bool isEmpty() const;
messages::LimitedQueueSnapshot<messages::SharedMessage> getMessageSnapshot();
// methods
void addMessage(messages::SharedMessage message);
void reloadChannelEmotes();
QString name;
void sendMessage(const QString &message);
std::string roomID;
const QString name;
bool isLive;
QString streamViewerCount;
QString streamStatus;
QString streamGame;
QString streamUptime;
void setRoomID(std::string id);
boost::signals2::signal<void()> roomIDchanged;
virtual bool canSendMessage() const;
virtual void sendMessage(const QString &message);
private:
// variables
messages::LimitedQueue<messages::SharedMessage> _messages;
public:
const EmoteManager::EmoteMap &bttvChannelEmotes;
const EmoteManager::EmoteMap &ffzChannelEmotes;
private:
QString _subLink;
QString _channelLink;
QString _popoutPlayerLink;
// std::shared_ptr<logging::Channel> _loggingChannel;
};

View file

@ -1,6 +1,8 @@
#include "channelmanager.hpp"
#include "ircmanager.hpp"
using namespace chatterino::twitch;
namespace chatterino {
ChannelManager::ChannelManager(WindowManager &_windowManager, EmoteManager &_emoteManager,
@ -8,9 +10,9 @@ ChannelManager::ChannelManager(WindowManager &_windowManager, EmoteManager &_emo
: windowManager(_windowManager)
, emoteManager(_emoteManager)
, ircManager(_ircManager)
, whispersChannel(new Channel(_windowManager, _emoteManager, _ircManager, "/whispers", true))
, mentionsChannel(new Channel(_windowManager, _emoteManager, _ircManager, "/mentions", true))
, emptyChannel(new Channel(_windowManager, _emoteManager, _ircManager, "", true))
, whispersChannel(new TwitchChannel(_emoteManager, _ircManager, "/whispers", true))
, mentionsChannel(new TwitchChannel(_emoteManager, _ircManager, "/mentions", true))
, emptyChannel(new TwitchChannel(_emoteManager, _ircManager, "", true))
{
}
@ -20,19 +22,19 @@ const std::vector<std::shared_ptr<Channel>> ChannelManager::getItems()
std::vector<std::shared_ptr<Channel>> items;
for (auto &item : this->channels.values()) {
for (auto &item : this->twitchChannels.values()) {
items.push_back(std::get<0>(item));
}
return items;
}
std::shared_ptr<Channel> ChannelManager::addChannel(const QString &rawChannelName)
std::shared_ptr<TwitchChannel> ChannelManager::addTwitchChannel(const QString &rawChannelName)
{
QString channelName = rawChannelName.toLower();
if (channelName.length() > 1 && channelName.at(0) == '/') {
return this->getChannel(channelName);
return this->getTwitchChannel(channelName);
}
if (channelName.length() > 0 && channelName.at(0) == '#') {
@ -41,12 +43,13 @@ std::shared_ptr<Channel> ChannelManager::addChannel(const QString &rawChannelNam
QMutexLocker locker(&this->channelsMutex);
auto it = this->channels.find(channelName);
auto it = this->twitchChannels.find(channelName);
if (it == this->channels.end()) {
auto channel = std::make_shared<Channel>(this->windowManager, this->emoteManager,
this->ircManager, channelName);
this->channels.insert(channelName, std::make_tuple(channel, 1));
if (it == this->twitchChannels.end()) {
auto channel =
std::make_shared<TwitchChannel>(this->emoteManager, this->ircManager, channelName);
this->twitchChannels.insert(channelName, std::make_tuple(channel, 1));
this->ircManager.joinChannel(channelName);
@ -58,7 +61,7 @@ std::shared_ptr<Channel> ChannelManager::addChannel(const QString &rawChannelNam
return std::get<0>(it.value());
}
std::shared_ptr<Channel> ChannelManager::getChannel(const QString &channel)
std::shared_ptr<TwitchChannel> ChannelManager::getTwitchChannel(const QString &channel)
{
QMutexLocker locker(&this->channelsMutex);
@ -76,16 +79,16 @@ std::shared_ptr<Channel> ChannelManager::getChannel(const QString &channel)
return emptyChannel;
}
auto a = this->channels.find(c);
auto a = this->twitchChannels.find(c);
if (a == this->channels.end()) {
if (a == this->twitchChannels.end()) {
return emptyChannel;
}
return std::get<0>(a.value());
}
void ChannelManager::removeChannel(const QString &channel)
void ChannelManager::removeTwitchChannel(const QString &channel)
{
QMutexLocker locker(&this->channelsMutex);
@ -95,9 +98,9 @@ void ChannelManager::removeChannel(const QString &channel)
QString c = channel.toLower();
auto a = this->channels.find(c);
auto a = this->twitchChannels.find(c);
if (a == this->channels.end()) {
if (a == this->twitchChannels.end()) {
return;
}
@ -105,7 +108,7 @@ void ChannelManager::removeChannel(const QString &channel)
if (std::get<1>(a.value()) == 0) {
this->ircManager.partChannel(c);
this->channels.remove(c);
this->twitchChannels.remove(c);
}
}
@ -123,4 +126,9 @@ const std::string &ChannelManager::getUserID(const std::string &username)
return temporary;
}
EmoteManager &ChannelManager::getEmoteManager()
{
return this->emoteManager;
}
} // namespace chatterino

View file

@ -2,6 +2,7 @@
#include "channel.hpp"
#include "channeldata.hpp"
#include "twitch/twitchchannel.hpp"
#include <map>
@ -23,23 +24,24 @@ public:
const std::vector<std::shared_ptr<Channel>> getItems();
std::shared_ptr<Channel> addChannel(const QString &channel);
std::shared_ptr<Channel> getChannel(const QString &channel);
void removeChannel(const QString &channel);
std::shared_ptr<twitch::TwitchChannel> addTwitchChannel(const QString &channel);
std::shared_ptr<twitch::TwitchChannel> getTwitchChannel(const QString &channel);
void removeTwitchChannel(const QString &channel);
const std::string &getUserID(const std::string &username);
EmoteManager &getEmoteManager();
// Special channels
const std::shared_ptr<Channel> whispersChannel;
const std::shared_ptr<Channel> mentionsChannel;
const std::shared_ptr<Channel> emptyChannel;
const std::shared_ptr<twitch::TwitchChannel> whispersChannel;
const std::shared_ptr<twitch::TwitchChannel> mentionsChannel;
const std::shared_ptr<twitch::TwitchChannel> emptyChannel;
private:
std::map<std::string, std::string> usernameToID;
std::map<std::string, ChannelData> channelDatas;
QMutex channelsMutex;
QMap<QString, std::tuple<std::shared_ptr<Channel>, int>> channels;
QMap<QString, std::tuple<std::shared_ptr<twitch::TwitchChannel>, int>> twitchChannels;
};
} // namespace chatterino

View file

@ -20,7 +20,7 @@ public:
bool tryGet(const TKey &name, TValue &value) const
{
QMutexLocker lock(this->mutex.get());
QMutexLocker lock(&this->mutex);
auto a = this->data.find(name);
if (a == this->data.end()) {
@ -34,7 +34,7 @@ public:
TValue getOrAdd(const TKey &name, std::function<TValue()> addLambda)
{
QMutexLocker lock(this->mutex.get());
QMutexLocker lock(&this->mutex);
auto a = this->data.find(name);
if (a == this->data.end()) {
@ -48,42 +48,28 @@ public:
TValue &operator[](const TKey &name)
{
QMutexLocker lock(this->mutex.get());
QMutexLocker lock(&this->mutex);
return this->data[name];
}
ConcurrentMap(const ConcurrentMap &o)
: mutex(std::move(o.mutex))
, data(std::move(o.data))
{
}
ConcurrentMap &operator=(const ConcurrentMap &rhs)
{
this->mutex = std::move(rhs.mutex);
this->data = std::move(rhs.data);
return *this;
}
void clear()
{
QMutexLocker lock(this->mutex.get());
QMutexLocker lock(&this->mutex);
this->data.clear();
}
void insert(const TKey &name, const TValue &value)
{
QMutexLocker lock(this->mutex.get());
QMutexLocker lock(&this->mutex);
this->data.insert(name, value);
}
void each(std::function<void(const TKey &name, const TValue &value)> &func) const
void each(std::function<void(const TKey &name, const TValue &value)> func) const
{
QMutexLocker lock(this->mutex.get());
QMutexLocker lock(&this->mutex);
QMapIterator<TKey, TValue> it(this->data);
@ -94,66 +80,7 @@ public:
}
private:
mutable std::unique_ptr<QMutex> mutex;
mutable QMutex mutex;
QMap<TKey, TValue> data;
};
template <typename TKey, typename TValue>
class ConcurrentStdMap
{
public:
bool tryGet(const TKey &name, TValue &value) const
{
QMutexLocker lock(&_mutex);
auto a = _map.find(name);
if (a == _map.end()) {
return false;
}
value = a.value();
return true;
}
TValue getOrAdd(const TKey &name, std::function<TValue()> addLambda)
{
QMutexLocker lock(&_mutex);
auto a = _map.find(name);
if (a == _map.end()) {
TValue value = addLambda();
_map.insert(name, value);
return value;
}
return a.value();
}
TValue &operator[](const TKey &name)
{
QMutexLocker lock(&_mutex);
return this->_map[name];
}
void clear()
{
QMutexLocker lock(&_mutex);
_map.clear();
}
void insert(const TKey &name, const TValue &value)
{
QMutexLocker lock(&_mutex);
_map.insert(name, value);
}
private:
mutable QMutex _mutex;
std::map<TKey, TValue> _map;
};
} // namespace chatterino

View file

@ -39,15 +39,19 @@ void EmoteManager::loadGlobalEmotes()
this->loadFFZEmotes();
}
void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName)
void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName, std::weak_ptr<EmoteMap> _map)
{
printf("[EmoteManager] Reload BTTV Channel Emotes for channel %s\n", qPrintable(channelName));
QString url("https://api.betterttv.net/2/channels/" + channelName);
util::urlFetchJSON(url, [this, channelName](QJsonObject &rootNode) {
EmoteMap &channelEmoteMap = this->bttvChannels[channelName];
util::urlFetchJSON(url, [this, channelName, _map](QJsonObject &rootNode) {
auto map = _map.lock();
channelEmoteMap.clear();
if (_map.expired()) {
return;
}
map->clear();
auto emotesNode = rootNode.value("emotes").toArray();
@ -72,7 +76,7 @@ void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName)
});
this->bttvChannelEmotes.insert(code, emote);
channelEmoteMap.insert(code, emote);
map->insert(code, emote);
codes.push_back(code.toStdString());
}
@ -80,16 +84,20 @@ void EmoteManager::reloadBTTVChannelEmotes(const QString &channelName)
});
}
void EmoteManager::reloadFFZChannelEmotes(const QString &channelName)
void EmoteManager::reloadFFZChannelEmotes(const QString &channelName, std::weak_ptr<EmoteMap> _map)
{
printf("[EmoteManager] Reload FFZ Channel Emotes for channel %s\n", qPrintable(channelName));
QString url("http://api.frankerfacez.com/v1/room/" + channelName);
util::urlFetchJSON(url, [this, channelName](QJsonObject &rootNode) {
EmoteMap &channelEmoteMap = this->ffzChannels[channelName];
util::urlFetchJSON(url, [this, channelName, _map](QJsonObject &rootNode) {
auto map = _map.lock();
channelEmoteMap.clear();
if (_map.expired()) {
return;
}
map->clear();
auto setsNode = rootNode.value("sets").toObject();
@ -114,7 +122,7 @@ void EmoteManager::reloadFFZChannelEmotes(const QString &channelName)
});
this->ffzChannelEmotes.insert(code, emote);
channelEmoteMap.insert(code, emote);
map->insert(code, emote);
codes.push_back(code.toStdString());
}
@ -128,17 +136,17 @@ ConcurrentMap<QString, twitch::EmoteValue *> &EmoteManager::getTwitchEmotes()
return _twitchEmotes;
}
EmoteManager::EmoteMap &EmoteManager::getFFZEmotes()
EmoteMap &EmoteManager::getFFZEmotes()
{
return ffzGlobalEmotes;
}
EmoteManager::EmoteMap &EmoteManager::getChatterinoEmotes()
EmoteMap &EmoteManager::getChatterinoEmotes()
{
return _chatterinoEmotes;
}
EmoteManager::EmoteMap &EmoteManager::getBTTVChannelEmoteFromCaches()
EmoteMap &EmoteManager::getBTTVChannelEmoteFromCaches()
{
return _bttvChannelEmoteFromCaches;
}

View file

@ -32,17 +32,19 @@ struct EmoteData {
messages::LazyLoadedImage *image = nullptr;
};
typedef ConcurrentMap<QString, EmoteData> EmoteMap;
class EmoteManager
{
public:
using EmoteMap = ConcurrentMap<QString, EmoteData>;
explicit EmoteManager(WindowManager &_windowManager);
void loadGlobalEmotes();
void reloadBTTVChannelEmotes(const QString &channelName);
void reloadFFZChannelEmotes(const QString &channelName);
void reloadBTTVChannelEmotes(const QString &channelName,
std::weak_ptr<EmoteMap> channelEmoteMap);
void reloadFFZChannelEmotes(const QString &channelName,
std::weak_ptr<EmoteMap> channelEmoteMap);
ConcurrentMap<QString, twitch::EmoteValue *> &getTwitchEmotes();
EmoteMap &getFFZEmotes();

View file

@ -237,7 +237,7 @@ void IrcManager::partChannel(const QString &channelName)
void IrcManager::privateMessageReceived(Communi::IrcPrivateMessage *message)
{
this->onPrivateMessage.invoke(message);
auto c = this->channelManager.getChannel(message->target().mid(1));
auto c = this->channelManager.getTwitchChannel(message->target().mid(1));
if (!c) {
return;
@ -283,7 +283,7 @@ void IrcManager::handleRoomStateMessage(Communi::IrcMessage *message)
std::string roomID = iterator.value().toString().toStdString();
auto channel = QString(message->toData()).split("#").at(1);
channelManager.getChannel(channel)->setRoomID(roomID);
channelManager.getTwitchChannel(channel)->setRoomID(roomID);
this->resources.loadChannelData(roomID);
}

View file

@ -24,7 +24,7 @@ class Message
{
public:
// explicit Message(const QString &text);
//explicit Message(const QString &text, const std::vector<messages::Word> &words,
// explicit Message(const QString &text, const std::vector<messages::Word> &words,
// const bool &highlight);
bool getCanHighlightTab() const;
@ -39,6 +39,7 @@ public:
const QString &getId() const;
const QString text;
bool centered = false;
private:
static LazyLoadedImage *badgeStaff;

View file

@ -12,7 +12,7 @@ MessageBuilder::MessageBuilder()
_parseTime = std::chrono::system_clock::now();
}
SharedMessage MessageBuilder::build()
SharedMessage MessageBuilder::getMessage()
{
return this->message;
}

View file

@ -14,7 +14,7 @@ class MessageBuilder
public:
MessageBuilder();
SharedMessage build();
SharedMessage getMessage();
void appendWord(const Word &&word);
void appendTimestamp();

View file

@ -129,7 +129,7 @@ bool MessageRef::layout(int width, bool enableEmoteMargins)
// word wrapping
if (word.isText() && word.getWidth() + MARGIN_LEFT > right) {
alignWordParts(lineStart, lineHeight);
alignWordParts(lineStart, lineHeight, width);
y += lineHeight;
@ -183,7 +183,7 @@ bool MessageRef::layout(int width, bool enableEmoteMargins)
first = false;
} else {
// doesn't fit in the line
alignWordParts(lineStart, lineHeight);
alignWordParts(lineStart, lineHeight, width);
y += lineHeight;
@ -201,7 +201,7 @@ bool MessageRef::layout(int width, bool enableEmoteMargins)
}
}
alignWordParts(lineStart, lineHeight);
alignWordParts(lineStart, lineHeight, width);
if (_height != y + lineHeight) {
sizeChanged = true;
@ -224,12 +224,18 @@ const std::vector<WordPart> &MessageRef::getWordParts() const
return _wordParts;
}
void MessageRef::alignWordParts(int lineStart, int lineHeight)
void MessageRef::alignWordParts(int lineStart, int lineHeight, int width)
{
for (size_t i = lineStart; i < _wordParts.size(); i++) {
WordPart &wordPart2 = _wordParts.at(i);
int xOffset = 0;
wordPart2.setY(wordPart2.getY() + lineHeight);
if (this->_message->centered && _wordParts.size() > 0) {
xOffset = (width - this->_wordParts.at(_wordParts.size() - 1).getRight()) / 2;
}
for (size_t i = lineStart; i < this->_wordParts.size(); i++) {
WordPart &wordPart2 = this->_wordParts.at(i);
wordPart2.setPosition(wordPart2.getX() + xOffset, wordPart2.getY() + lineHeight);
}
}

View file

@ -47,7 +47,7 @@ private:
Word::Type _currentWordTypes = Word::None;
// methods
void alignWordParts(int lineStart, int lineHeight);
void alignWordParts(int lineStart, int lineHeight, int width);
};
} // namespace messages

View file

@ -77,9 +77,11 @@ public:
EmojiImage = (1 << 23),
EmojiText = (1 << 24),
AlwaysShow = (1 << 25),
Default = TimestampNoSeconds | Badges | Username | BitsStatic | FfzEmoteImage |
BttvEmoteImage | BttvGifEmoteImage | TwitchEmoteImage | BitsAmount | Text |
ButtonBan | ButtonTimeout
ButtonBan | ButtonTimeout | AlwaysShow
};
Word()

View file

@ -146,6 +146,8 @@ void SettingsManager::updateWordTypeMask()
newMaskUint |= Word::Username;
newMaskUint |= Word::AlwaysShow;
Word::Type newMask = static_cast<Word::Type>(newMaskUint);
if (newMask != _wordTypeMask) {

View file

@ -0,0 +1,80 @@
#include "twitchchannel.hpp"
#include "emotemanager.hpp"
#include <QDebug>
namespace chatterino {
namespace twitch {
TwitchChannel::TwitchChannel(EmoteManager &emoteManager, IrcManager &ircManager,
const QString &channelName, bool isSpecial)
: emoteManager(emoteManager)
, ircManager(ircManager)
// , name(channelName)
, bttvChannelEmotes(new EmoteMap)
, ffzChannelEmotes(new EmoteMap)
, subLink("https://www.twitch.tv/" + name + "/subscribe?ref=in_chat_subscriber_link")
, channelLink("https://twitch.tv/" + name)
, popoutPlayerLink("https://player.twitch.tv/?channel=" + name)
, isLive(false)
, isSpecial(isSpecial)
{
this->name = channelName;
qDebug() << "Open twitch channel:" << this->name;
if (!isSpecial) {
this->reloadChannelEmotes();
}
}
bool TwitchChannel::isEmpty() const
{
return this->name.isEmpty();
}
const QString &TwitchChannel::getSubLink() const
{
return this->subLink;
}
bool TwitchChannel::canSendMessage() const
{
return !this->isEmpty() && !this->isSpecial;
}
const QString &TwitchChannel::getChannelLink() const
{
return this->channelLink;
}
const QString &TwitchChannel::getPopoutPlayerLink() const
{
return this->popoutPlayerLink;
}
void TwitchChannel::setRoomID(std::string id)
{
this->roomID = id;
this->roomIDchanged();
}
void TwitchChannel::reloadChannelEmotes()
{
printf("[TwitchChannel:%s] Reloading channel emotes\n", qPrintable(this->name));
this->emoteManager.reloadBTTVChannelEmotes(this->name, this->bttvChannelEmotes);
this->emoteManager.reloadFFZChannelEmotes(this->name, this->ffzChannelEmotes);
}
void TwitchChannel::sendMessage(const QString &message)
{
qDebug() << "TwitchChannel send message: " << message;
// Do last message processing
QString parsedMessage = this->emoteManager.replaceShortCodes(message);
this->ircManager.sendMessage(this->name, parsedMessage);
}
}
}

View file

@ -0,0 +1,49 @@
#pragma once
#include "channel.hpp"
#include "concurrentmap.hpp"
#include "ircmanager.hpp"
namespace chatterino {
namespace twitch {
class TwitchChannel : public Channel
{
public:
explicit TwitchChannel(EmoteManager &emoteManager, IrcManager &ircManager,
const QString &channelName, bool isSpecial = false);
void reloadChannelEmotes();
bool isEmpty() const override;
bool canSendMessage() const override;
void sendMessage(const QString &message) override;
const QString &getSubLink() const;
const QString &getChannelLink() const;
const QString &getPopoutPlayerLink() const;
void setRoomID(std::string id);
boost::signals2::signal<void()> roomIDchanged;
std::string roomID;
bool isLive;
QString streamViewerCount;
QString streamStatus;
QString streamGame;
QString streamUptime;
const std::shared_ptr<EmoteMap> bttvChannelEmotes;
const std::shared_ptr<EmoteMap> ffzChannelEmotes;
private:
EmoteManager &emoteManager;
IrcManager &ircManager;
QString subLink;
QString channelLink;
QString popoutPlayerLink;
bool isSpecial;
};
}
}

View file

@ -15,12 +15,13 @@ using namespace chatterino::messages;
namespace chatterino {
namespace twitch {
TwitchMessageBuilder::TwitchMessageBuilder(Channel *_channel, Resources &_resources,
TwitchMessageBuilder::TwitchMessageBuilder(TwitchChannel *_channel, Resources &_resources,
EmoteManager &_emoteManager,
WindowManager &_windowManager,
const Communi::IrcPrivateMessage *_ircMessage,
const messages::MessageParseArgs &_args)
: channel(_channel)
, twitchChannel(_channel)
, resources(_resources)
, windowManager(_windowManager)
, colorScheme(this->windowManager.colorScheme)
@ -249,7 +250,7 @@ SharedMessage TwitchMessageBuilder::parse()
// HighlightTab = false;
// }
return this->build();
return this->getMessage();
}
void TwitchMessageBuilder::parseMessageID()
@ -264,11 +265,12 @@ void TwitchMessageBuilder::parseMessageID()
void TwitchMessageBuilder::parseRoomID()
{
auto iterator = this->tags.find("room-id");
if (iterator != std::end(this->tags)) {
this->roomID = iterator.value().toString().toStdString();
if (this->channel->roomID.empty()) {
this->channel->roomID = this->roomID;
if (this->twitchChannel->roomID.empty()) {
this->twitchChannel->roomID = this->roomID;
}
}
}
@ -503,13 +505,13 @@ bool TwitchMessageBuilder::tryAppendEmote(QString &emoteString)
if (emoteManager.bttvGlobalEmotes.tryGet(emoteString, emoteData)) {
// BTTV Global Emote
return this->appendEmote(emoteData);
} else if (this->channel->bttvChannelEmotes.tryGet(emoteString, emoteData)) {
} else if (this->twitchChannel->bttvChannelEmotes->tryGet(emoteString, emoteData)) {
// BTTV Channel Emote
return this->appendEmote(emoteData);
} else if (emoteManager.ffzGlobalEmotes.tryGet(emoteString, emoteData)) {
// FFZ Global Emote
return this->appendEmote(emoteData);
} else if (this->channel->ffzChannelEmotes.tryGet(emoteString, emoteData)) {
} else if (this->twitchChannel->ffzChannelEmotes->tryGet(emoteString, emoteData)) {
// FFZ Channel Emote
return this->appendEmote(emoteData);
} else if (emoteManager.getChatterinoEmotes().tryGet(emoteString, emoteData)) {

View file

@ -3,6 +3,7 @@
#include "emotemanager.hpp"
#include "messages/messagebuilder.hpp"
#include "resources.hpp"
#include "twitch/twitchchannel.hpp"
#include <QString>
#include <QVariant>
@ -26,12 +27,13 @@ public:
TwitchMessageBuilder() = delete;
explicit TwitchMessageBuilder(Channel *_channel, Resources &_resources,
explicit TwitchMessageBuilder(TwitchChannel *_channel, Resources &_resources,
EmoteManager &_emoteManager, WindowManager &_windowManager,
const Communi::IrcPrivateMessage *_ircMessage,
const messages::MessageParseArgs &_args);
Channel *channel;
TwitchChannel *twitchChannel;
Resources &resources;
WindowManager &windowManager;
ColorScheme &colorScheme;

View file

@ -1,4 +1,4 @@
#include "widgets/chatwidgetview.hpp"
#include "widgets/channelview.hpp"
#include "channelmanager.hpp"
#include "colorscheme.hpp"
#include "messages/limitedqueuesnapshot.hpp"
@ -20,14 +20,15 @@
#include <functional>
#include <memory>
using namespace chatterino::messages;
namespace chatterino {
namespace widgets {
ChatWidgetView::ChatWidgetView(ChatWidget *_chatWidget)
: BaseWidget(_chatWidget)
, chatWidget(_chatWidget)
ChannelView::ChannelView(BaseWidget *parent)
: BaseWidget(parent)
, scrollBar(this)
, userPopupWidget(_chatWidget->getChannelRef())
, userPopupWidget(std::shared_ptr<Channel>())
{
#ifndef Q_OS_MAC
// this->setAttribute(Qt::WA_OpaquePaintEvent);
@ -35,7 +36,7 @@ ChatWidgetView::ChatWidgetView(ChatWidget *_chatWidget)
this->setMouseTracking(true);
QObject::connect(&SettingsManager::getInstance(), &SettingsManager::wordTypeMaskChanged, this,
&ChatWidgetView::wordTypeMaskChanged);
&ChannelView::wordTypeMaskChanged);
this->scrollBar.getCurrentValueChanged().connect([this] {
// Whenever the scrollbar value has been changed, re-render the ChatWidgetView
@ -45,15 +46,15 @@ ChatWidgetView::ChatWidgetView(ChatWidget *_chatWidget)
});
}
ChatWidgetView::~ChatWidgetView()
ChannelView::~ChannelView()
{
QObject::disconnect(&SettingsManager::getInstance(), &SettingsManager::wordTypeMaskChanged,
this, &ChatWidgetView::wordTypeMaskChanged);
this, &ChannelView::wordTypeMaskChanged);
}
bool ChatWidgetView::layoutMessages()
bool ChannelView::layoutMessages()
{
auto messages = this->chatWidget->getMessagesSnapshot();
auto messages = this->getMessagesSnapshot();
if (messages.getLength() == 0) {
this->scrollBar.setVisible(false);
@ -130,21 +131,30 @@ bool ChatWidgetView::layoutMessages()
return redraw;
}
void ChatWidgetView::updateGifEmotes()
void ChannelView::clearMessages()
{
// Clear all stored messages in this chat widget
this->messages.clear();
// Layout chat widget messages, and force an update regardless if there are no messages
this->layoutMessages();
this->update();
}
void ChannelView::updateGifEmotes()
{
this->onlyUpdateEmotes = true;
this->update();
}
ScrollBar &ChatWidgetView::getScrollBar()
ScrollBar &ChannelView::getScrollBar()
{
return this->scrollBar;
}
QString ChatWidgetView::getSelectedText() const
QString ChannelView::getSelectedText()
{
messages::LimitedQueueSnapshot<messages::SharedMessageRef> messages =
this->chatWidget->getMessagesSnapshot();
LimitedQueueSnapshot<SharedMessageRef> messages = this->getMessagesSnapshot();
QString text;
bool isSingleMessage = this->selection.isSingleMessage();
@ -232,7 +242,72 @@ QString ChatWidgetView::getSelectedText() const
return text;
}
void ChatWidgetView::resizeEvent(QResizeEvent *)
messages::LimitedQueueSnapshot<SharedMessageRef> ChannelView::getMessagesSnapshot()
{
return this->messages.getSnapshot();
}
void ChannelView::setChannel(std::shared_ptr<Channel> channel)
{
if (this->channel) {
this->detachChannel();
}
this->messages.clear();
// on new message
this->messageAppendedConnection =
channel->messageAppended.connect([this](SharedMessage &message) {
SharedMessageRef deleted;
auto messageRef = new MessageRef(message);
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([this](SharedMessage &) {
this->selection.min.messageIndex--;
this->selection.max.messageIndex--;
this->selection.start.messageIndex--;
this->selection.end.messageIndex--;
layoutMessages();
update();
});
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->userPopupWidget.setChannel(channel);
}
void ChannelView::detachChannel()
{
// on message added
this->messageAppendedConnection.disconnect();
// on message removed
this->messageRemovedConnection.disconnect();
}
void ChannelView::resizeEvent(QResizeEvent *)
{
this->scrollBar.resize(this->scrollBar.width(), height());
this->scrollBar.move(width() - this->scrollBar.width(), 0);
@ -242,7 +317,7 @@ void ChatWidgetView::resizeEvent(QResizeEvent *)
this->update();
}
void ChatWidgetView::setSelection(const SelectionItem &start, const SelectionItem &end)
void ChannelView::setSelection(const SelectionItem &start, const SelectionItem &end)
{
// selections
this->selection = Selection(start, end);
@ -251,7 +326,7 @@ void ChatWidgetView::setSelection(const SelectionItem &start, const SelectionIte
// << max.charIndex;
}
void ChatWidgetView::paintEvent(QPaintEvent * /*event*/)
void ChannelView::paintEvent(QPaintEvent * /*event*/)
{
QPainter painter(this);
@ -288,9 +363,9 @@ void ChatWidgetView::paintEvent(QPaintEvent * /*event*/)
}
}
void ChatWidgetView::drawMessages(QPainter &painter)
void ChannelView::drawMessages(QPainter &painter)
{
auto messages = this->chatWidget->getMessagesSnapshot();
auto messages = this->getMessagesSnapshot();
size_t start = this->scrollBar.getCurrentValue();
@ -341,7 +416,9 @@ void ChatWidgetView::drawMessages(QPainter &painter)
messageRef->buffer = bufferPtr;
// if (buffer != nullptr) {
painter.drawPixmap(0, y, *buffer);
// }
y += messageRef->getHeight();
@ -351,8 +428,8 @@ void ChatWidgetView::drawMessages(QPainter &painter)
}
}
void ChatWidgetView::updateMessageBuffer(messages::MessageRef *messageRef, QPixmap *buffer,
int messageIndex)
void ChannelView::updateMessageBuffer(messages::MessageRef *messageRef, QPixmap *buffer,
int messageIndex)
{
QPainter painter(buffer);
@ -403,8 +480,8 @@ void ChatWidgetView::updateMessageBuffer(messages::MessageRef *messageRef, QPixm
messageRef->updateBuffer = false;
}
void ChatWidgetView::drawMessageSelection(QPainter &painter, messages::MessageRef *messageRef,
int messageIndex, int bufferHeight)
void ChannelView::drawMessageSelection(QPainter &painter, messages::MessageRef *messageRef,
int messageIndex, int bufferHeight)
{
if (this->selection.min.messageIndex > messageIndex ||
this->selection.max.messageIndex < messageIndex) {
@ -552,7 +629,7 @@ void ChatWidgetView::drawMessageSelection(QPainter &painter, messages::MessageRe
painter.fillRect(rect, selectionColor);
}
void ChatWidgetView::wheelEvent(QWheelEvent *event)
void ChannelView::wheelEvent(QWheelEvent *event)
{
if (this->scrollBar.isVisible()) {
auto mouseMultiplier = SettingsManager::getInstance().mouseScrollMultiplier.get();
@ -562,7 +639,7 @@ void ChatWidgetView::wheelEvent(QWheelEvent *event)
}
}
void ChatWidgetView::mouseMoveEvent(QMouseEvent *event)
void ChannelView::mouseMoveEvent(QMouseEvent *event)
{
std::shared_ptr<messages::MessageRef> message;
QPoint relativePos;
@ -594,10 +671,8 @@ void ChatWidgetView::mouseMoveEvent(QMouseEvent *event)
}
}
void ChatWidgetView::mousePressEvent(QMouseEvent *event)
void ChannelView::mousePressEvent(QMouseEvent *event)
{
this->chatWidget->giveFocus(Qt::MouseFocusReason);
this->isMouseDown = true;
this->lastPressPosition = event->screenPos();
@ -621,7 +696,7 @@ void ChatWidgetView::mousePressEvent(QMouseEvent *event)
this->repaint();
}
void ChatWidgetView::mouseReleaseEvent(QMouseEvent *event)
void ChannelView::mouseReleaseEvent(QMouseEvent *event)
{
if (!this->isMouseDown) {
// We didn't grab the mouse press, so we shouldn't be handling the mouse
@ -682,10 +757,10 @@ void ChatWidgetView::mouseReleaseEvent(QMouseEvent *event)
}
}
bool ChatWidgetView::tryGetMessageAt(QPoint p, std::shared_ptr<messages::MessageRef> &_message,
QPoint &relativePos, int &index)
bool ChannelView::tryGetMessageAt(QPoint p, std::shared_ptr<messages::MessageRef> &_message,
QPoint &relativePos, int &index)
{
auto messages = this->chatWidget->getMessagesSnapshot();
auto messages = this->getMessagesSnapshot();
size_t start = this->scrollBar.getCurrentValue();

View file

@ -2,6 +2,7 @@
#include "channel.hpp"
#include "messages/lazyloadedimage.hpp"
#include "messages/limitedqueuesnapshot.hpp"
#include "messages/messageref.hpp"
#include "messages/word.hpp"
#include "widgets/accountpopup.hpp"
@ -13,6 +14,8 @@
#include <QWheelEvent>
#include <QWidget>
#include <boost/signals2.hpp>
namespace chatterino {
namespace widgets {
@ -75,21 +78,23 @@ struct Selection {
}
};
class ChatWidget;
class ChatWidgetView : public BaseWidget
class ChannelView : public BaseWidget
{
friend class ChatWidget;
Q_OBJECT
public:
explicit ChatWidgetView(ChatWidget *_chatWidget);
~ChatWidgetView();
bool layoutMessages();
explicit ChannelView(BaseWidget *parent = 0);
~ChannelView();
void updateGifEmotes();
ScrollBar &getScrollBar();
QString getSelectedText() const;
QString getSelectedText();
void setChannel(std::shared_ptr<Channel> channel);
messages::LimitedQueueSnapshot<messages::SharedMessageRef> getMessagesSnapshot();
bool layoutMessages();
void clearMessages();
protected:
virtual void resizeEvent(QResizeEvent *) override;
@ -110,15 +115,17 @@ private:
QRect rect;
};
void detachChannel();
void drawMessages(QPainter &painter);
void updateMessageBuffer(messages::MessageRef *messageRef, QPixmap *buffer, int messageIndex);
void drawMessageSelection(QPainter &painter, messages::MessageRef *messageRef, int messageIndex,
int bufferHeight);
void setSelection(const SelectionItem &start, const SelectionItem &end);
std::vector<GifEmoteData> gifEmotes;
std::shared_ptr<Channel> channel;
ChatWidget *const chatWidget;
std::vector<GifEmoteData> gifEmotes;
ScrollBar scrollBar;
@ -136,6 +143,11 @@ private:
Selection selection;
bool selecting = false;
messages::LimitedQueue<messages::SharedMessageRef> messages;
boost::signals2::connection messageAppendedConnection;
boost::signals2::connection messageRemovedConnection;
private slots:
void wordTypeMaskChanged()
{

View file

@ -18,6 +18,7 @@
#include <QPainter>
#include <QProcess>
#include <QShortcut>
#include <QTimer>
#include <QVBoxLayout>
#include <boost/signals2.hpp>
@ -52,7 +53,7 @@ ChatWidget::ChatWidget(ChannelManager &_channelManager, NotebookPage *parent)
, vbox(this)
, header(this)
, view(this)
, input(this)
, input(this, _channelManager.getEmoteManager())
{
this->vbox.setSpacing(0);
this->vbox.setMargin(1);
@ -80,11 +81,15 @@ ChatWidget::ChatWidget(ChannelManager &_channelManager, NotebookPage *parent)
this->channelNameUpdated(this->channelName.getValue());
this->input.textInput.installEventFilter(parent);
connect(&view, &this->view.mousePressEvent, this, [&](QMouseEvent *) {
QTimer::singleShot(10, [this] { this->giveFocus(Qt::MouseFocusReason); });
});
}
ChatWidget::~ChatWidget()
{
this->detachChannel();
channelNameUpdated("");
}
std::shared_ptr<Channel> ChatWidget::getChannel() const
@ -99,82 +104,33 @@ std::shared_ptr<Channel> &ChatWidget::getChannelRef()
void ChatWidget::setChannel(std::shared_ptr<Channel> _newChannel)
{
this->view.setChannel(_newChannel);
this->channel = _newChannel;
this->channel->roomIDchanged.connect([this]() { this->header.checkLive(); });
this->view.userPopupWidget.setChannel(_newChannel);
// on new message
this->messageAppendedConnection =
this->channel->messageAppended.connect([this](SharedMessage &message) {
SharedMessageRef deleted;
auto messageRef = new MessageRef(message);
if (this->messages.appendItem(SharedMessageRef(messageRef), deleted)) {
qreal value = std::max(0.0, this->view.getScrollBar().getDesiredValue() - 1);
this->view.getScrollBar().setDesiredValue(value, false);
}
});
// on message removed
this->messageRemovedConnection =
this->channel->messageRemovedFromStart.connect([this](SharedMessage &) {
this->view.selection.min.messageIndex--;
this->view.selection.max.messageIndex--;
this->view.selection.start.messageIndex--;
this->view.selection.end.messageIndex--;
});
auto snapshot = this->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);
twitch::TwitchChannel *twitchChannel = dynamic_cast<twitch::TwitchChannel *>(_newChannel.get());
if (twitchChannel != nullptr) {
twitchChannel->roomIDchanged.connect([this]() { this->header.checkLive(); });
}
}
void ChatWidget::detachChannel()
{
// on message added
this->messageAppendedConnection.disconnect();
// on message removed
this->messageRemovedConnection.disconnect();
}
void ChatWidget::channelNameUpdated(const std::string &newChannelName)
{
// remove current channel
if (!this->channel->isEmpty()) {
this->channelManager.removeChannel(this->channel->name);
this->detachChannel();
this->channelManager.removeTwitchChannel(this->channel->name);
}
// update messages
this->messages.clear();
if (newChannelName.empty()) {
this->channel = this->channelManager.emptyChannel;
this->setChannel(this->channelManager.emptyChannel);
} else {
this->setChannel(this->channelManager.addChannel(QString::fromStdString(newChannelName)));
this->setChannel(
this->channelManager.addTwitchChannel(QString::fromStdString(newChannelName)));
}
// update header
this->header.updateChannelText();
// update view
this->layoutMessages(true);
}
LimitedQueueSnapshot<SharedMessageRef> ChatWidget::getMessagesSnapshot()
{
return this->messages.getSnapshot();
}
bool ChatWidget::showChangeChannelPopup(const char *dialogTitle, bool empty)
@ -202,9 +158,12 @@ bool ChatWidget::showChangeChannelPopup(const char *dialogTitle, bool empty)
void ChatWidget::layoutMessages(bool forceUpdate)
{
if (this->view.layoutMessages() || forceUpdate) {
this->view.update();
}
this->view.layoutMessages();
this->view.update();
// if (this->view.layoutMessages() || forceUpdate) {
// this->view.update();
// }
}
void ChatWidget::updateGifEmotes()
@ -285,11 +244,7 @@ void ChatWidget::doPopup()
void ChatWidget::doClearChat()
{
// Clear all stored messages in this chat widget
this->messages.clear();
// Layout chat widget messages, and force an update regardless if there are no messages
this->layoutMessages(true);
view.clearMessages();
}
void ChatWidget::doOpenChannel()

View file

@ -6,9 +6,9 @@
#include "messages/word.hpp"
#include "messages/wordpart.hpp"
#include "widgets/basewidget.hpp"
#include "widgets/channelview.hpp"
#include "widgets/chatwidgetheader.hpp"
#include "widgets/chatwidgetinput.hpp"
#include "widgets/chatwidgetview.hpp"
#include <QFont>
#include <QShortcut>
@ -49,13 +49,13 @@ public:
std::shared_ptr<Channel> &getChannelRef();
bool showChangeChannelPopup(const char *dialogTitle, bool empty = false);
messages::LimitedQueueSnapshot<messages::SharedMessageRef> getMessagesSnapshot();
void layoutMessages(bool forceUpdate = false);
void updateGifEmotes();
void giveFocus(Qt::FocusReason reason);
bool hasFocus() const;
void layoutMessages(bool forceUpdate = false);
void updateGifEmotes();
protected:
virtual void paintEvent(QPaintEvent *) override;
@ -67,24 +67,20 @@ public:
private:
void setChannel(std::shared_ptr<Channel> newChannel);
void detachChannel();
void doOpenAccountPopupWidget(AccountPopupWidget *widget, QString user);
void channelNameUpdated(const std::string &newChannelName);
NotebookPage &parentPage;
messages::LimitedQueue<messages::SharedMessageRef> messages;
std::shared_ptr<Channel> channel;
QVBoxLayout vbox;
ChatWidgetHeader header;
ChatWidgetView view;
ChannelView view;
ChatWidgetInput input;
boost::signals2::connection messageAppendedConnection;
boost::signals2::connection messageRemovedConnection;
boost::signals2::connection channelIDChangedConnection;
public:
void load(const boost::property_tree::ptree &tree);

View file

@ -1,5 +1,6 @@
#include "widgets/chatwidgetheader.hpp"
#include "colorscheme.hpp"
#include "twitch/twitchchannel.hpp"
#include "util/urlfetch.hpp"
#include "widgets/chatwidget.hpp"
#include "widgets/notebookpage.hpp"
@ -81,16 +82,22 @@ void ChatWidgetHeader::updateChannelText()
if (channelName.empty()) {
this->channelNameLabel.setText("<no channel>");
} else {
if (this->chatWidget->getChannelRef()->isLive) {
auto channel = this->chatWidget->getChannelRef();
auto channel = this->chatWidget->getChannel();
twitch::TwitchChannel *twitchChannel = dynamic_cast<twitch::TwitchChannel *>(channel.get());
if (channel->isEmpty()) {
this->channelNameLabel.setText(QString::fromStdString(channelName) + " (live)");
this->setToolTip(
"<style>.center { text-align: center; }</style>"
"<p class = \"center\">" +
channel->streamStatus + "<br><br>" + channel->streamGame + "<br>"
"Live for " +
channel->streamUptime + " with " + channel->streamViewerCount + " viewers"
"</p>");
if (twitchChannel != nullptr) {
this->setToolTip("<style>.center { text-align: center; }</style>"
"<p class = \"center\">" +
twitchChannel->streamStatus + "<br><br>" +
twitchChannel->streamGame + "<br>"
"Live for " +
twitchChannel->streamUptime + " with " +
twitchChannel->streamViewerCount + " viewers"
"</p>");
}
} else {
this->channelNameLabel.setText(QString::fromStdString(channelName));
this->setToolTip("");
@ -157,7 +164,7 @@ void ChatWidgetHeader::mouseDoubleClickEvent(QMouseEvent *event)
void ChatWidgetHeader::leftButtonClicked()
{
QTimer::singleShot(100, [&] {
QTimer::singleShot(80, [&] {
this->leftMenu.move(this->leftLabel.mapToGlobal(QPoint(0, this->leftLabel.height())));
this->leftMenu.show();
});
@ -193,10 +200,18 @@ void ChatWidgetHeader::menuShowChangelog()
{
}
// TODO: this needs to be moved out of here
void ChatWidgetHeader::checkLive()
{
auto channel = this->chatWidget->getChannelRef();
twitch::TwitchChannel *channel =
dynamic_cast<twitch::TwitchChannel *>(this->chatWidget->getChannel().get());
if (channel == nullptr) {
return;
}
auto id = QString::fromStdString(channel->roomID);
util::twitch::get("https://api.twitch.tv/kraken/streams/" + id, [=](QJsonObject obj) {
if (obj.value("stream").isNull()) {
channel->isLive = false;

View file

@ -23,12 +23,12 @@ ChatWidgetHeaderButton::ChatWidgetHeaderButton(BaseWidget *parent, int spacing)
this->setMouseEffectColor(QColor(255, 255, 255, 63));
}
void ChatWidgetHeaderButton::paintEvent(QPaintEvent *)
{
QPainter painter(this);
// void ChatWidgetHeaderButton::paintEvent(QPaintEvent *)
//{
// QPainter painter(this);
this->fancyPaint(painter);
}
// this->fancyPaint(painter);
//}
} // namespace widgets
} // namespace chatterino

View file

@ -28,7 +28,7 @@ public:
}
protected:
virtual void paintEvent(QPaintEvent *) override;
// virtual void paintEvent(QPaintEvent *) override;
private:
struct {

View file

@ -13,9 +13,10 @@
namespace chatterino {
namespace widgets {
ChatWidgetInput::ChatWidgetInput(ChatWidget *_chatWidget)
ChatWidgetInput::ChatWidgetInput(ChatWidget *_chatWidget, EmoteManager &emoteManager)
: BaseWidget(_chatWidget)
, chatWidget(_chatWidget)
, emoteManager(emoteManager)
, emotesLabel(this)
{
this->setMaximumHeight(150);
@ -46,10 +47,12 @@ ChatWidgetInput::ChatWidgetInput(ChatWidget *_chatWidget)
connect(&this->emotesLabel, &ChatWidgetHeaderButton::clicked, [this] {
if (this->emotePopup == nullptr) {
this->emotePopup = new EmotePopup();
this->emotePopup = new EmotePopup(this->colorScheme, this->emoteManager);
}
this->emotePopup->show(); //
this->emotePopup->resize(300, 500);
this->emotePopup->loadChannel(this->chatWidget->getChannel());
this->emotePopup->show();
});
connect(&textInput, &ResizingTextEdit::textChanged, this, &ChatWidgetInput::editTextChanged);

View file

@ -1,5 +1,6 @@
#pragma once
#include "emotemanager.hpp"
#include "resizingtextedit.hpp"
#include "widgets/basewidget.hpp"
#include "widgets/chatwidgetheaderbutton.hpp"
@ -25,7 +26,7 @@ class ChatWidgetInput : public BaseWidget
Q_OBJECT
public:
ChatWidgetInput(ChatWidget *_chatWidget);
ChatWidgetInput(ChatWidget *_chatWidget, EmoteManager &);
~ChatWidgetInput();
protected:
@ -37,6 +38,7 @@ protected:
private:
ChatWidget *const chatWidget;
EmotePopup *emotePopup = nullptr;
EmoteManager &emoteManager;
boost::signals2::connection textLengthVisibleChangedConnection;
QHBoxLayout hbox;

View file

@ -1,18 +1,70 @@
#include "emotepopup.h"
#include <QHBoxLayout>
#include "messages/messagebuilder.hpp"
#include "twitch/twitchchannel.hpp"
using namespace chatterino::twitch;
using namespace chatterino::messages;
namespace chatterino {
namespace widgets {
EmotePopup::EmotePopup(QWidget *parent)
: QWidget(parent)
EmotePopup::EmotePopup(ColorScheme &colorScheme, EmoteManager &emoteManager)
: BaseWidget(colorScheme, 0)
, emoteManager(emoteManager)
{
QHBoxLayout *layout = new QHBoxLayout(this);
this->setLayout(layout);
layout->setMargin(0);
view = new ChannelView(this);
layout->addWidget(view);
}
void EmotePopup::loadChannel(std::shared_ptr<Channel> channel)
void EmotePopup::loadChannel(std::shared_ptr<Channel> _channel)
{
// channel->bttvChannelEmotes.each([](const QString &key, const EmoteData &value) {
TwitchChannel *channel = dynamic_cast<TwitchChannel *>(_channel.get());
// //
// });
if (channel == nullptr) {
return;
}
std::shared_ptr<Channel> emoteChannel(new Channel);
auto addEmotes = [&](EmoteMap &map, const QString &title, const QString &emoteDesc) {
// TITLE
messages::MessageBuilder builder1;
builder1.appendWord(
Word(title, Word::Type::Text, QColor(255, 255, 255), QString(), QString()));
builder1.getMessage()->centered = true;
emoteChannel->addMessage(builder1.getMessage());
// EMOTES
messages::MessageBuilder builder2;
builder2.getMessage()->centered = true;
map.each([&](const QString &key, const EmoteData &value) {
builder2.appendWord(Word(value.image, Word::Type::AlwaysShow, key, emoteDesc,
Link(Link::Type::InsertText, key)));
});
emoteChannel->addMessage(builder2.getMessage());
};
addEmotes(this->emoteManager.bttvGlobalEmotes, "BetterTTV Global Emotes",
"BetterTTV Global Emote");
addEmotes(*channel->bttvChannelEmotes.get(), "BetterTTV Channel Emotes",
"BetterTTV Channel Emote");
addEmotes(this->emoteManager.ffzGlobalEmotes, "FrankerFaceZ Global Emotes",
"FrankerFaceZ Global Emote");
addEmotes(*channel->ffzChannelEmotes.get(), "FrankerFaceZ Channel Emotes",
"FrankerFaceZ Channel Emote");
view->setChannel(emoteChannel);
}
}
}

View file

@ -1,18 +1,23 @@
#pragma once
#include <QWidget>
#include "channel.hpp"
#include "emotemanager.hpp"
#include "widgets/basewidget.hpp"
#include "widgets/channelview.hpp"
namespace chatterino {
namespace widgets {
class EmotePopup : public QWidget
class EmotePopup : public BaseWidget
{
public:
explicit EmotePopup(QWidget *parent = 0);
explicit EmotePopup(ColorScheme &, EmoteManager &);
void loadChannel(std::shared_ptr<Channel> channel);
private:
ChannelView *view;
EmoteManager &emoteManager;
};
}
}

View file

@ -23,7 +23,7 @@ void FancyButton::setMouseEffectColor(QColor color)
void FancyButton::paintEvent(QPaintEvent *)
{
QPainter painter;
QPainter painter(this);
this->fancyPaint(painter);
}

View file

@ -212,7 +212,7 @@ void Notebook::resizeEvent(QResizeEvent *)
void Notebook::settingsButtonClicked()
{
QTimer::singleShot(100, [this] { SettingsDialog::showDialog(); });
QTimer::singleShot(80, [this] { SettingsDialog::showDialog(); });
}
void Notebook::usersButtonClicked()
@ -221,7 +221,7 @@ void Notebook::usersButtonClicked()
void Notebook::addPageButtonClicked()
{
QTimer::singleShot(100, [this] { this->addPage(true); });
QTimer::singleShot(80, [this] { this->addPage(true); });
}
void Notebook::load(const boost::property_tree::ptree &tree)

View file

@ -1,6 +1,6 @@
#include "widgets/scrollbar.hpp"
#include "colorscheme.hpp"
#include "widgets/chatwidgetview.hpp"
#include "widgets/channelview.hpp"
#include <QDebug>
#include <QMouseEvent>
@ -11,7 +11,7 @@
namespace chatterino {
namespace widgets {
ScrollBar::ScrollBar(ChatWidgetView *parent)
ScrollBar::ScrollBar(ChannelView *parent)
: BaseWidget(parent)
, _currentValueAnimation(this, "_currentValue")
, _highlights(nullptr)

View file

@ -14,14 +14,14 @@ class ColorScheme;
namespace widgets {
class ChatWidgetView;
class ChannelView;
class ScrollBar : public BaseWidget
{
Q_OBJECT
public:
ScrollBar(ChatWidgetView *parent = 0);
ScrollBar(ChannelView *parent = 0);
~ScrollBar();
void removeHighlightsWhere(std::function<bool(ScrollBarHighlight &)> func);

View file

@ -46,12 +46,12 @@ void WindowManager::repaintGifEmotes()
}
}
void WindowManager::updateAll()
{
if (this->mainWindow != nullptr) {
this->mainWindow->update();
}
}
// void WindowManager::updateAll()
//{
// if (this->mainWindow != nullptr) {
// this->mainWindow->update();
// }
//}
widgets::MainWindow &WindowManager::getMainWindow()
{

View file

@ -23,7 +23,7 @@ public:
void layoutVisibleChatWidgets(Channel *channel = nullptr);
void repaintVisibleChatWidgets(Channel *channel = nullptr);
void repaintGifEmotes();
void updateAll();
// void updateAll();
widgets::MainWindow &getMainWindow();