diff --git a/src/Application.cpp b/src/Application.cpp index 332272246..bfa03bfe2 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -70,8 +70,6 @@ Application::Application(Settings &_settings, Paths &_paths) this->fonts->fontChanged.connect( [this]() { this->windows->layoutChannelViews(); }); - Irc::getInstance().load(); - this->twitch.server = this->twitch2; this->twitch.pubsub = this->twitch2->pubsub; } @@ -100,6 +98,7 @@ int Application::run(QApplication &qtApp) assert(isAppInitialized); this->twitch.server->connect(); + Irc::getInstance().load(); this->windows->getMainWindow().show(); diff --git a/src/common/Credentials.cpp b/src/common/Credentials.cpp index f66658cd1..fb5e5f983 100644 --- a/src/common/Credentials.cpp +++ b/src/common/Credentials.cpp @@ -85,8 +85,8 @@ Credentials::Credentials() { } -QString Credentials::get(const QString &provider, const QString &name_, - std::function &&onLoaded) +void Credentials::get(const QString &provider, const QString &name_, + std::function &&onLoaded) { assertInGuiThread(); @@ -100,16 +100,15 @@ QString Credentials::get(const QString &provider, const QString &name_, QObject::connect(job, &QKeychain::Job::finished, qApp, [job, onLoaded = std::move(onLoaded)](auto) mutable { onLoaded(job->textData()); - }); + }, + Qt::DirectConnection); job->start(); - - return job->textData(); } else { auto &instance = insecureInstance(); - return instance.object().find(name).value().toString(); + onLoaded(instance.object().find(name).value().toString()); } } diff --git a/src/common/Credentials.hpp b/src/common/Credentials.hpp index 95ae27afb..d8dd9098b 100644 --- a/src/common/Credentials.hpp +++ b/src/common/Credentials.hpp @@ -10,8 +10,8 @@ class Credentials public: static Credentials &getInstance(); - QString get(const QString &provider, const QString &name, - std::function &&onLoaded); + void get(const QString &provider, const QString &name, + std::function &&onLoaded); void set(const QString &provider, const QString &name, const QString &credential); void erase(const QString &provider, const QString &name); diff --git a/src/providers/irc/Irc2.cpp b/src/providers/irc/Irc2.cpp index f79b79bdc..39e1bb9cc 100644 --- a/src/providers/irc/Irc2.cpp +++ b/src/providers/irc/Irc2.cpp @@ -9,6 +9,7 @@ #include "util/StandardItemHelper.hpp" #include +#include namespace chatterino { @@ -22,7 +23,7 @@ namespace { { public: Model(QObject *parent) - : SignalVectorModel(8, parent) + : SignalVectorModel(6, parent) { } @@ -30,8 +31,6 @@ namespace { IrcServerData getItemFromRow(std::vector &row, const IrcServerData &original) { - qDebug() << row[2]->data(Qt::CheckStateRole).toBool(); - return IrcServerData{ row[0]->data(Qt::EditRole).toString(), // host row[1]->data(Qt::EditRole).toInt(), // port @@ -39,7 +38,8 @@ namespace { row[3]->data(Qt::EditRole).toString(), // user row[4]->data(Qt::EditRole).toString(), // nick row[5]->data(Qt::EditRole).toString(), // real - row[6]->data(Qt::EditRole).toString(), // password + original.password, // password + original.connectCommands, // connectCommands original.id, // id }; } @@ -54,30 +54,21 @@ namespace { setStringItem(row[3], item.user); setStringItem(row[4], item.nick); setStringItem(row[5], item.real); - setStringItem(row[6], item.password); } }; } // namespace -//inline QString escape(QString str) -//{ -// return str.replace(":", "::"); -//} +inline QString escape(QString str) +{ + return str.replace(":", "::"); +} -//inline QString getCredentialName(const IrcConnection_ &conn) -//{ -// //return escape(conn.host) + escape(conn. -//} - -//QString IrcConnection_::getPassword() -//{ -// return -//} - -//void IrcConnection_::setPassword(const QString &str) -//{ -// //Credentials::set("irc", -//} +// This returns a unique id for every server which is understandeable in the systems credential manager. +inline QString getCredentialName(const IrcServerData &data) +{ + return escape(QString::number(data.id)) + ":" + escape(data.user) + "@" + + escape(data.host); +} Irc::Irc() { @@ -85,6 +76,7 @@ Irc::Irc() // make sure only one id can only exist for one server assert(this->servers_.find(args.item.id) == this->servers_.end()); + // add new server if (auto ab = this->abandonedChannels_.find(args.item.id); ab != this->abandonedChannels_.end()) { @@ -107,6 +99,10 @@ Irc::Irc() this->servers_.emplace(args.item.id, std::make_unique(args.item)); } + + // store password + Credentials::getInstance().set("irc", getCredentialName(args.item), + args.item.password); }); this->connections.itemRemoved.connect([this](auto &&args) { @@ -125,6 +121,10 @@ Irc::Irc() this->abandonedChannels_[args.item.id] = abandoned; this->servers_.erase(server); + + // delete password + Credentials::getInstance().erase("irc", + getCredentialName(args.item)); } }); @@ -146,7 +146,11 @@ ChannelPtr Irc::getOrAddChannel(int id, QString name) } else { - return Channel::getEmpty(); + auto channel = std::make_shared(name, nullptr); + + this->abandonedChannels_[id].push_back(channel); + + return std::move(channel); } } @@ -187,7 +191,8 @@ void Irc::save() obj.insert("username", conn.user); obj.insert("nickname", conn.nick); obj.insert("realname", conn.real); - //obj.insert("password", conn.password); + obj.insert("connectCommands", + QJsonArray::fromStringList(conn.connectCommands)); obj.insert("id", conn.id); servers.append(obj); } @@ -210,29 +215,36 @@ void Irc::load() QString config = configPath(); QFile file(configPath()); file.open(QIODevice::ReadOnly); - auto doc = QJsonDocument::fromJson(file.readAll()); + auto object = QJsonDocument::fromJson(file.readAll()).object(); - auto object = doc.object(); - std::unordered_set ids; - - for (auto server : doc.object().value("servers").toArray()) + // load servers + for (auto server : object.value("servers").toArray()) { auto obj = server.toObject(); - IrcServerData conn; - conn.host = obj.value("host").toString(conn.host); - conn.port = obj.value("port").toInt(conn.port); - conn.ssl = obj.value("ssl").toBool(conn.ssl); - conn.user = obj.value("username").toString(conn.user); - conn.nick = obj.value("nickname").toString(conn.nick); - conn.real = obj.value("realname").toString(conn.real); - // conn.password = obj.value("password").toString(conn.password); - conn.id = obj.value("id").toInt(conn.id); + IrcServerData data; + data.host = obj.value("host").toString(data.host); + data.port = obj.value("port").toInt(data.port); + data.ssl = obj.value("ssl").toBool(data.ssl); + data.user = obj.value("username").toString(data.user); + data.nick = obj.value("nickname").toString(data.nick); + data.real = obj.value("realname").toString(data.real); + data.connectCommands = + obj.value("connectCommands").toVariant().toStringList(); + data.id = obj.value("id").toInt(data.id); // duplicate id's are not allowed :( - if (ids.find(conn.id) == ids.end()) + if (this->abandonedChannels_.find(data.id) == + this->abandonedChannels_.end()) { - this->connections.appendItem(conn); - ids.insert(conn.id); + // insert element + this->abandonedChannels_[data.id]; + + Credentials::getInstance().get( + "irc", getCredentialName(data), + [=](const QString &password) mutable { + data.password = password; + this->connections.appendItem(data); + }); } } } diff --git a/src/providers/irc/Irc2.hpp b/src/providers/irc/Irc2.hpp index 9ff678558..a256f47d8 100644 --- a/src/providers/irc/Irc2.hpp +++ b/src/providers/irc/Irc2.hpp @@ -23,6 +23,7 @@ struct IrcServerData { // IrcAuthType authType = Anonymous; QString password; + QStringList connectCommands; int id; }; @@ -44,9 +45,6 @@ public: int uniqueId(); -signals: - void connectionUpdated(int id); - private: int currentId_{}; bool loaded_{}; diff --git a/src/providers/irc/IrcChannel2.hpp b/src/providers/irc/IrcChannel2.hpp index 4b07be155..2dd1b6622 100644 --- a/src/providers/irc/IrcChannel2.hpp +++ b/src/providers/irc/IrcChannel2.hpp @@ -14,6 +14,7 @@ public: void sendMessage(const QString &message) override; + // server may be nullptr IrcServer *server(); private: diff --git a/src/providers/irc/IrcServer.cpp b/src/providers/irc/IrcServer.cpp index d942d18f3..ac8e0f88f 100644 --- a/src/providers/irc/IrcServer.cpp +++ b/src/providers/irc/IrcServer.cpp @@ -80,6 +80,11 @@ void IrcServer::onReadConnected(IrcConnection *connection) std::lock_guard lock(this->channelMutex); + for (auto &&command : this->data_->connectCommands) + { + connection->sendRaw(command + "\r\n"); + } + for (auto &&weak : this->channels) { if (auto channel = weak.lock()) diff --git a/src/singletons/WindowManager.cpp b/src/singletons/WindowManager.cpp index 4adb08e74..f59f7985c 100644 --- a/src/singletons/WindowManager.cpp +++ b/src/singletons/WindowManager.cpp @@ -621,7 +621,10 @@ void WindowManager::encodeChannel(IndirectChannel channel, QJsonObject &obj) dynamic_cast(channel.get().get())) { obj.insert("type", "irc"); - obj.insert("server", ircChannel->server()->id()); + if (ircChannel->server()) + { + obj.insert("server", ircChannel->server()->id()); + } obj.insert("channel", ircChannel->getName()); } } diff --git a/src/widgets/dialogs/IrcConnectionEditor.cpp b/src/widgets/dialogs/IrcConnectionEditor.cpp index 624d13a09..dfa13dad8 100644 --- a/src/widgets/dialogs/IrcConnectionEditor.cpp +++ b/src/widgets/dialogs/IrcConnectionEditor.cpp @@ -26,7 +26,13 @@ IrcConnectionEditor::IrcConnectionEditor(const IrcServerData &data, bool isAdd, this->ui_->userNameLineEdit->setText(data.user); this->ui_->nickNameLineEdit->setText(data.nick); this->ui_->realNameLineEdit->setText(data.real); + this->ui_->connectCommandsEditor->setPlainText( + data.connectCommands.join('\n')); this->ui_->passwordLineEdit->setText(data.password); + + QFont font("Monospace"); + font.setStyleHint(QFont::TypeWriter); + this->ui_->connectCommandsEditor->setFont(font); } // namespace chatterino IrcConnectionEditor::~IrcConnectionEditor() @@ -43,6 +49,8 @@ IrcServerData IrcConnectionEditor::data() data.user = this->ui_->userNameLineEdit->text(); data.nick = this->ui_->nickNameLineEdit->text(); data.real = this->ui_->realNameLineEdit->text(); + data.connectCommands = + this->ui_->connectCommandsEditor->toPlainText().split('\n'); data.password = this->ui_->passwordLineEdit->text(); return data; } diff --git a/src/widgets/dialogs/IrcConnectionEditor.ui b/src/widgets/dialogs/IrcConnectionEditor.ui index 7fc356943..df79f6d31 100644 --- a/src/widgets/dialogs/IrcConnectionEditor.ui +++ b/src/widgets/dialogs/IrcConnectionEditor.ui @@ -7,7 +7,7 @@ 0 0 264 - 350 + 414 @@ -155,21 +155,38 @@ + + + + <html><head/><body><p>Send IRC commands</p><p>on connect:</p></body></html> + + + + + + + + 0 + 1 + + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + - - - - Qt::Vertical - - - - 20 - 20 - - - - diff --git a/src/widgets/dialogs/SelectChannelDialog.cpp b/src/widgets/dialogs/SelectChannelDialog.cpp index 123484efc..1333e86e6 100644 --- a/src/widgets/dialogs/SelectChannelDialog.cpp +++ b/src/widgets/dialogs/SelectChannelDialog.cpp @@ -130,7 +130,7 @@ SelectChannelDialog::SelectChannelDialog(QWidget *parent) // irc { LayoutCreator obj(new QWidget()); - auto outerBox = obj.setLayoutType(); + auto outerBox = obj.setLayoutType(); // outerBox.emplace("Connection:"); { @@ -140,16 +140,11 @@ SelectChannelDialog::SelectChannelDialog(QWidget *parent) view->setTitles({"host", "port", "ssl", "user", "nick", "real", "password", "login command"}); view->getTableView()->horizontalHeader()->resizeSection(0, 140); - view->getTableView()->horizontalHeader()->resizeSection(1, 40); - view->getTableView()->horizontalHeader()->resizeSection(2, 30); - //view->getTableView()->horizontalHeader()->setVisible(false); view->getTableView()->horizontalHeader()->setSectionHidden(1, true); view->getTableView()->horizontalHeader()->setSectionHidden(2, true); view->getTableView()->horizontalHeader()->setSectionHidden(4, true); view->getTableView()->horizontalHeader()->setSectionHidden(5, true); - view->getTableView()->horizontalHeader()->setSectionHidden(6, true); - view->getTableView()->horizontalHeader()->setSectionHidden(7, true); view->addButtonPressed.connect([] { auto unique = IrcServerData{}; @@ -158,7 +153,7 @@ SelectChannelDialog::SelectChannelDialog(QWidget *parent) auto editor = new IrcConnectionEditor(unique); if (editor->exec() == QDialog::Accepted) { - Irc::getInstance().connections.appendItem(unique); + Irc::getInstance().connections.appendItem(editor->data()); } }); @@ -188,14 +183,10 @@ SelectChannelDialog::SelectChannelDialog(QWidget *parent) } }); - outerBox->addWidget(view); + outerBox->addRow("Server:", view); } - { - auto box = outerBox.emplace().withoutMargin(); - box.emplace("Channel:"); - this->ui_.irc.channel = box.emplace().getElement(); - } + outerBox->addRow("Channel:", this->ui_.irc.channel = new QLineEdit); auto tab = notebook->addPage(obj.getElement()); tab->setCustomTitle("Irc");