diff options
-rw-r--r-- | .github/workflows/ci.yml | 54 | ||||
-rw-r--r-- | ci/msys-deps.txt | 57 | ||||
-rw-r--r-- | src/abaddon.cpp | 38 | ||||
-rw-r--r-- | src/components/channelscellrenderer.cpp | 2 | ||||
-rw-r--r-- | src/components/chatinputindicator.cpp | 14 | ||||
-rw-r--r-- | src/components/chatwindow.cpp | 2 | ||||
-rw-r--r-- | src/components/chatwindow.hpp | 4 | ||||
-rw-r--r-- | src/discord/activity.hpp | 2 | ||||
-rw-r--r-- | src/discord/ban.hpp | 2 | ||||
-rw-r--r-- | src/discord/interactions.hpp | 8 | ||||
-rw-r--r-- | src/discord/relationship.hpp | 16 | ||||
-rw-r--r-- | src/discord/snowflake.cpp | 11 | ||||
-rw-r--r-- | src/discord/snowflake.hpp | 2 | ||||
-rw-r--r-- | src/discord/store.cpp | 10 | ||||
-rw-r--r-- | src/discord/usersettings.hpp | 20 | ||||
-rw-r--r-- | src/http.cpp | 2 | ||||
-rw-r--r-- | src/platform.cpp | 18 | ||||
-rw-r--r-- | src/platform.hpp | 2 | ||||
-rw-r--r-- | src/util.cpp | 9 | ||||
m--------- | subprojects/ixwebsocket | 0 |
20 files changed, 210 insertions, 63 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce93f43..a8ea5ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,60 @@ name: Abaddon CI on: [push, pull_request] jobs: + msys2: + name: msys2-mingw64 + runs-on: windows-latest + strategy: + matrix: + buildtype: [Debug, RelWithDebInfo, MinSizeRel] + defaults: + run: + shell: msys2 {0} + steps: + - uses: actions/checkout@v1 + with: + submodules: true + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: mingw64 + update: true + install: >- + git + make + mingw-w64-x86_64-toolchain + mingw-w64-x86_64-cmake + mingw-w64-x86_64-ninja + mingw-w64-x86_64-sqlite3 + mingw-w64-x86_64-nlohmann-json + mingw-w64-x86_64-curl + mingw-w64-x86_64-zlib + mingw-w64-x86_64-gtkmm3 + + - name: Build + run: | + cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=${{ matrix.buildtype }} + cmake --build build + + - name: Setup Artifact + run: | + mkdir -p build/artifactdir/bin build/artifactdir/ssl/certs build/artifactdir/lib build/artifactdir/share/glib-2.0/schemas + cd build + cp *.exe artifactdir/bin + cd .. + cp /mingw64/ssl/certs/ca-bundle.crt build/artifactdir/ssl/certs + cp -r /mingw64/lib/gdk-pixbuf-2.0 build/artifactdir/lib + cp -r res/css res/res res/fonts build/artifactdir/bin + cp /mingw64/share/glib-2.0/schemas/gschemas.compiled build/artifactdir/share/glib-2.0/schemas + cat "ci/msys-deps.txt" | sed 's/\r$//' | xargs -I % cp /mingw64% build/artifactdir/bin + + - name: Upload build + uses: actions/upload-artifact@v2 + with: + name: build-windows-msys2-${{ matrix.buildtype }} + path: build/artifactdir + windows: name: windows-${{ matrix.buildtype }} runs-on: windows-2019 diff --git a/ci/msys-deps.txt b/ci/msys-deps.txt new file mode 100644 index 0000000..ab98a15 --- /dev/null +++ b/ci/msys-deps.txt @@ -0,0 +1,57 @@ +/bin/gdbus.exe +/bin/gspawn-win64-helper-console.exe +/bin/libatk-1.0-0.dll +/bin/libatkmm-1.6-1.dll +/bin/libbrotlicommon.dll +/bin/libbrotlidec.dll +/bin/libbz2-1.dll +/bin/libcairo-2.dll +/bin/libcairo-gobject-2.dll +/bin/libcairomm-1.0-1.dll +/bin/libcrypto-1_1-x64.dll +/bin/libcurl-4.dll +/bin/libdatrie-1.dll +/bin/libdeflate.dll +/bin/libepoxy-0.dll +/bin/libexpat-1.dll +/bin/libffi-7.dll +/bin/libfontconfig-1.dll +/bin/libfreetype-6.dll +/bin/libfribidi-0.dll +/bin/libgcc_s_seh-1.dll +/bin/libgdk-3-0.dll +/bin/libgdk_pixbuf-2.0-0.dll +/bin/libgdkmm-3.0-1.dll +/bin/libgio-2.0-0.dll +/bin/libgiomm-2.4-1.dll +/bin/libglib-2.0-0.dll +/bin/libglibmm-2.4-1.dll +/bin/libgmodule-2.0-0.dll +/bin/libgobject-2.0-0.dll +/bin/libgraphite2.dll +/bin/libgtk-3-0.dll +/bin/libgtkmm-3.0-1.dll +/bin/libharfbuzz-0.dll +/bin/libiconv-2.dll +/bin/libidn2-0.dll +/bin/libintl-8.dll +/bin/libnghttp2-14.dll +/bin/libpango-1.0-0.dll +/bin/libpangocairo-1.0-0.dll +/bin/libpangoft2-1.0-0.dll +/bin/libpangomm-1.4-1.dll +/bin/libpangowin32-1.0-0.dll +/bin/libpcre-1.dll +/bin/libpixman-1-0.dll +/bin/libpng16-16.dll +/bin/libpsl-5.dll +/bin/libsigc-2.0-0.dll +/bin/libsqlite3-0.dll +/bin/libssh2-1.dll +/bin/libssl-1_1-x64.dll +/bin/libstdc++-6.dll +/bin/libthai-0.dll +/bin/libunistring-2.dll +/bin/libwinpthread-1.dll +/bin/libzstd.dll +/bin/zlib1.dll diff --git a/src/abaddon.cpp b/src/abaddon.cpp index 55c6ee9..1ab6f8c 100644 --- a/src/abaddon.cpp +++ b/src/abaddon.cpp @@ -64,18 +64,41 @@ int Abaddon::StartGTK() { m_css_provider = Gtk::CssProvider::create(); m_css_provider->signal_parsing_error().connect([this](const Glib::RefPtr<const Gtk::CssSection> §ion, const Glib::Error &error) { - Gtk::MessageDialog dlg(*m_main_window, "css failed parsing (" + error.what() + ")", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + Gtk::MessageDialog dlg("css failed parsing (" + error.what() + ")", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); dlg.set_position(Gtk::WIN_POS_CENTER); dlg.run(); }); m_css_low_provider = Gtk::CssProvider::create(); m_css_low_provider->signal_parsing_error().connect([this](const Glib::RefPtr<const Gtk::CssSection> §ion, const Glib::Error &error) { - Gtk::MessageDialog dlg(*m_main_window, "low-priority css failed parsing (" + error.what() + ")", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + Gtk::MessageDialog dlg("low-priority css failed parsing (" + error.what() + ")", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); dlg.set_position(Gtk::WIN_POS_CENTER); dlg.run(); }); +#ifdef _WIN32 + bool png_found = false; + bool gif_found = false; + for (const auto &fmt : Gdk::Pixbuf::get_formats()) { + if (fmt.get_name() == "png") + png_found = true; + else if (fmt.get_name() == "gif") + gif_found = true; + } + + if (!png_found) { + Gtk::MessageDialog dlg("The PNG pixbufloader wasn't detected. Abaddon may not work as a result.", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + dlg.set_position(Gtk::WIN_POS_CENTER); + dlg.run(); + } + + if (!gif_found) { + Gtk::MessageDialog dlg("The GIF pixbufloader wasn't detected. Animations may not display as a result.", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); + dlg.set_position(Gtk::WIN_POS_CENTER); + dlg.run(); + } +#endif + m_main_window = std::make_unique<MainWindow>(); m_main_window->set_title(APP_TITLE); m_main_window->set_position(Gtk::WIN_POS_CENTER); @@ -754,6 +777,17 @@ EmojiResource &Abaddon::GetEmojis() { int main(int argc, char **argv) { if (std::getenv("ABADDON_NO_FC") == nullptr) Platform::SetupFonts(); + + char *systemLocale = std::setlocale(LC_ALL, ""); + try { + std::locale::global(std::locale(systemLocale)); + } catch (...) { + try { + std::locale::global(std::locale::classic()); + std::setlocale(LC_ALL, systemLocale); + } catch (...) {} + } + #if defined(_WIN32) && defined(_MSC_VER) TCHAR buf[2] { 0 }; GetEnvironmentVariableA("GTK_CSD", buf, sizeof(buf)); diff --git a/src/components/channelscellrenderer.cpp b/src/components/channelscellrenderer.cpp index e657ed3..141556a 100644 --- a/src/components/channelscellrenderer.cpp +++ b/src/components/channelscellrenderer.cpp @@ -642,7 +642,7 @@ void CellRendererChannels::cairo_path_rounded_rect(const Cairo::RefPtr<Cairo::Co void CellRendererChannels::unread_render_mentions(const Cairo::RefPtr<Cairo::Context> &cr, Gtk::Widget &widget, int mentions, int edge, const Gdk::Rectangle &cell_area) { Pango::FontDescription font; font.set_family("sans 14"); - //font.set_weight(Pango::WEIGHT_BOLD); + // font.set_weight(Pango::WEIGHT_BOLD); auto layout = widget.create_pango_layout(std::to_string(mentions)); layout->set_font_description(font); diff --git a/src/components/chatinputindicator.cpp b/src/components/chatinputindicator.cpp index 9b063b2..ba794f3 100644 --- a/src/components/chatinputindicator.cpp +++ b/src/components/chatinputindicator.cpp @@ -25,16 +25,16 @@ ChatInputIndicator::ChatInputIndicator() if (!std::filesystem::exists(path)) return; auto gif_data = ReadWholeFile(path); auto loader = Gdk::PixbufLoader::create(); - loader->signal_size_prepared().connect([&](int inw, int inh) { - int w, h; - GetImageDimensions(inw, inh, w, h, 20, 10); - loader->set_size(w, h); - }); - loader->write(gif_data.data(), gif_data.size()); try { + loader->signal_size_prepared().connect([&](int inw, int inh) { + int w, h; + GetImageDimensions(inw, inh, w, h, 20, 10); + loader->set_size(w, h); + }); + loader->write(gif_data.data(), gif_data.size()); loader->close(); m_img.property_pixbuf_animation() = loader->get_animation(); - } catch (const std::exception &) {} + } catch (...) {} } void ChatInputIndicator::AddUser(Snowflake channel_id, const UserData &user, int timeout) { diff --git a/src/components/chatwindow.cpp b/src/components/chatwindow.cpp index 9b34dfd..df2b6b8 100644 --- a/src/components/chatwindow.cpp +++ b/src/components/chatwindow.cpp @@ -88,7 +88,7 @@ ChatWindow::ChatWindow() { m_meta->add(*m_input_indicator); m_meta->add(*m_rate_limit_indicator); - //m_scroll->add(*m_list); + // m_scroll->add(*m_list); m_main->add(m_topic); m_main->add(*m_chat); m_main->add(m_completer); diff --git a/src/components/chatwindow.hpp b/src/components/chatwindow.hpp index de55b0a..db0bfc4 100644 --- a/src/components/chatwindow.hpp +++ b/src/components/chatwindow.hpp @@ -47,8 +47,8 @@ protected: void OnMessageSendFail(const std::string &nonce, float retry_after); Gtk::Box *m_main; - //Gtk::ListBox *m_list; - //Gtk::ScrolledWindow *m_scroll; + // Gtk::ListBox *m_list; + // Gtk::ScrolledWindow *m_scroll; Gtk::EventBox m_topic; // todo probably make everything else go on the stack Gtk::Label m_topic_text; diff --git a/src/discord/activity.hpp b/src/discord/activity.hpp index 6b8e944..4382ac0 100644 --- a/src/discord/activity.hpp +++ b/src/discord/activity.hpp @@ -26,7 +26,7 @@ constexpr inline const char *GetPresenceString(PresenceStatus s) { return ""; } -constexpr inline const char* GetPresenceDisplayString(PresenceStatus s) { +constexpr inline const char *GetPresenceDisplayString(PresenceStatus s) { switch (s) { case PresenceStatus::Online: return "Online"; diff --git a/src/discord/ban.hpp b/src/discord/ban.hpp index d417ce3..7ab3d33 100644 --- a/src/discord/ban.hpp +++ b/src/discord/ban.hpp @@ -4,7 +4,7 @@ struct BanData { std::string Reason; // null - UserData User; // access id + UserData User; // access id friend void from_json(const nlohmann::json &j, BanData &m); }; diff --git a/src/discord/interactions.hpp b/src/discord/interactions.hpp index c076145..782c491 100644 --- a/src/discord/interactions.hpp +++ b/src/discord/interactions.hpp @@ -14,10 +14,10 @@ enum class InteractionType { }; struct MessageInteractionData { - Snowflake ID; // id of the interaction - InteractionType Type; // the type of interaction - std::string Name; // the name of the ApplicationCommand - UserData User; // the user who invoked the interaction + Snowflake ID; // id of the interaction + InteractionType Type; // the type of interaction + std::string Name; // the name of the ApplicationCommand + UserData User; // the user who invoked the interaction // undocumented??? std::optional<GuildMember> Member; // the member who invoked the interaction (in a guild) diff --git a/src/discord/relationship.hpp b/src/discord/relationship.hpp index d492bd3..1595502 100644 --- a/src/discord/relationship.hpp +++ b/src/discord/relationship.hpp @@ -3,19 +3,19 @@ #include "user.hpp" enum class RelationshipType { - None = 0, - Friend = 1, - Blocked = 2, - PendingIncoming = 3, - PendingOutgoing = 4, - Implicit = 5, + None = 0, + Friend = 1, + Blocked = 2, + PendingIncoming = 3, + PendingOutgoing = 4, + Implicit = 5, }; struct RelationshipData { // Snowflake UserID; this is the same as ID apparently but it looks new so i wont touch it RelationshipType Type; Snowflake ID; - // Unknown Nickname; // null + // Unknown Nickname; // null - friend void from_json(const nlohmann::json &j, RelationshipData &m); + friend void from_json(const nlohmann::json &j, RelationshipData &m); }; diff --git a/src/discord/snowflake.cpp b/src/discord/snowflake.cpp index 8f470a7..3624c01 100644 --- a/src/discord/snowflake.cpp +++ b/src/discord/snowflake.cpp @@ -2,6 +2,7 @@ #include "util.hpp" #include <chrono> #include <ctime> +#include <glibmm.h> #include <iomanip> constexpr static uint64_t DiscordEpochSeconds = 1420070400; @@ -53,14 +54,12 @@ bool Snowflake::IsValid() const { return m_num != Invalid; } -std::string Snowflake::GetLocalTimestamp() const { +Glib::ustring Snowflake::GetLocalTimestamp() const { const time_t secs_since_epoch = (m_num / SecondsInterval) + DiscordEpochSeconds; const std::tm tm = *localtime(&secs_since_epoch); - std::stringstream ss; - const static std::locale locale(""); - ss.imbue(locale); - ss << std::put_time(&tm, "%X %x"); - return ss.str(); + std::array<char, 256> tmp; + std::strftime(tmp.data(), sizeof(tmp), "%X %x", &tm); + return tmp.data(); } void from_json(const nlohmann::json &j, Snowflake &s) { diff --git a/src/discord/snowflake.hpp b/src/discord/snowflake.hpp index f2da5d1..e83317a 100644 --- a/src/discord/snowflake.hpp +++ b/src/discord/snowflake.hpp @@ -13,7 +13,7 @@ struct Snowflake { static Snowflake FromISO8601(std::string_view ts); bool IsValid() const; - std::string GetLocalTimestamp() const; + Glib::ustring GetLocalTimestamp() const; bool operator==(const Snowflake &s) const noexcept { return m_num == s.m_num; diff --git a/src/discord/store.cpp b/src/discord/store.cpp index 8eb3613..ede6364 100644 --- a/src/discord/store.cpp +++ b/src/discord/store.cpp @@ -818,8 +818,8 @@ std::optional<GuildMember> Store::GetGuildMember(Snowflake guild_id, Snowflake u s->Get(2, r.Nickname); s->Get(3, r.JoinedAt); s->Get(4, r.PremiumSince); - //s->Get(5, r.IsDeafened); - //s->Get(6, r.IsMuted); + // s->Get(5, r.IsDeafened); + // s->Get(6, r.IsMuted); s->Get(7, r.Avatar); s->Get(8, r.IsPending); @@ -879,8 +879,8 @@ Message Store::GetMessageBound(std::unique_ptr<Statement> &s) const { s->Get(4, r.Content); s->Get(5, r.Timestamp); s->Get(6, r.EditedTimestamp); - //s->Get(7, r.IsTTS); - //s->Get(8, r.DoesMentionEveryone); + // s->Get(7, r.IsTTS); + // s->Get(8, r.DoesMentionEveryone); s->GetJSON(9, r.Embeds); s->Get(10, r.IsPinned); s->Get(11, r.WebhookID); @@ -1005,7 +1005,7 @@ RoleData Store::GetRoleBound(std::unique_ptr<Statement> &s) const { RoleData r; s->Get(0, r.ID); - //s->Get(1, guild id); + // s->Get(1, guild id); s->Get(2, r.Name); s->Get(3, r.Color); s->Get(4, r.IsHoisted); diff --git a/src/discord/usersettings.hpp b/src/discord/usersettings.hpp index 6d37b3c..2baf61e 100644 --- a/src/discord/usersettings.hpp +++ b/src/discord/usersettings.hpp @@ -6,7 +6,7 @@ struct UserSettingsGuildFoldersEntry { int Color = -1; // null std::vector<Snowflake> GuildIDs; - Snowflake ID; // null (this can be a snowflake as a string or an int that isnt a snowflake lol) + Snowflake ID; // null (this can be a snowflake as a string or an int that isnt a snowflake lol) std::string Name; // null friend void from_json(const nlohmann::json &j, UserSettingsGuildFoldersEntry &m); @@ -19,16 +19,16 @@ struct UserSettings { std::string Status; // bool ShouldShowCurrentGame; // // std::vector<Unknown> RestrictedGuilds; // - bool ShouldRenderReactions; // - bool ShouldRenderEmbeds; // - bool IsNativePhoneIntegrationEnabled; // - bool ShouldMessageDisplayCompact; // - std::string Locale; // - bool ShouldInlineEmbedMedia; // - bool ShouldInlineAttachmentMedia; // - std::vector<Snowflake> GuildPositions; // deprecated? + bool ShouldRenderReactions; // + bool ShouldRenderEmbeds; // + bool IsNativePhoneIntegrationEnabled; // + bool ShouldMessageDisplayCompact; // + std::string Locale; // + bool ShouldInlineEmbedMedia; // + bool ShouldInlineAttachmentMedia; // + std::vector<Snowflake> GuildPositions; // deprecated? std::vector<UserSettingsGuildFoldersEntry> GuildFolders; // - bool ShouldGIFAutoplay; // + bool ShouldGIFAutoplay; // // Unknown FriendSourceFlags; // int ExplicitContentFilter; // bool IsTTSCommandEnabled; // diff --git a/src/http.cpp b/src/http.cpp index 790add7..877970a 100644 --- a/src/http.cpp +++ b/src/http.cpp @@ -99,7 +99,7 @@ void request::prepare() { namespace detail { size_t curl_write_data_callback(void *ptr, size_t size, size_t nmemb, void *userdata) { const size_t n = size * nmemb; - static_cast<std::string*>(userdata)->append(static_cast<char*>(ptr), n); + static_cast<std::string *>(userdata)->append(static_cast<char *>(ptr), n); return n; } diff --git a/src/platform.cpp b/src/platform.cpp index dc64a26..8eff19d 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -7,10 +7,14 @@ using namespace std::literals::string_literals; -#if defined(_WIN32) && defined(_MSC_VER) +#if defined(_WIN32) #include <pango/pangocairo.h> #include <pango/pangofc-fontmap.h> - #include <ShlObj_core.h> + #if defined(_MSC_VER) + #include <ShlObj_core.h> + #else + #include <shlobj.h> + #endif #include <Shlwapi.h> #include <Windows.h> #pragma comment(lib, "Shlwapi.lib") @@ -22,8 +26,8 @@ bool Platform::SetupFonts() { { // thanks @WorkingRobot for da help :^)) - std::ifstream template_stream(buf + "\\fonts\\fonts.template.conf"s); - std::ofstream conf_stream(buf + "\\fonts\\fonts.conf"s); + std::ifstream template_stream(buf + R"(\fonts\fonts.template.conf)"s); + std::ofstream conf_stream(buf + R"(\fonts\fonts.conf)"s); if (!template_stream.good()) { printf("can't open fonts/fonts.template.conf\n"); return false; @@ -36,7 +40,7 @@ bool Platform::SetupFonts() { std::string line; while (std::getline(template_stream, line)) { if (line == "<!--(CONFD)-->") - conf_stream << "<include ignore_missing=\"no\">" << (buf + "\\fonts\\conf.d"s) << "</include>"; + conf_stream << "<include ignore_missing=\"no\">" << (buf + R"(\fonts\conf.d)"s) << "</include>"; else conf_stream << line; conf_stream << '\n'; @@ -45,11 +49,11 @@ bool Platform::SetupFonts() { auto fc = FcConfigCreate(); FcConfigSetCurrent(fc); - FcConfigParseAndLoad(fc, const_cast<FcChar8 *>(reinterpret_cast<const FcChar8 *>((buf + "\\fonts\\fonts.conf"s).c_str())), true); + FcConfigParseAndLoad(fc, const_cast<FcChar8 *>(reinterpret_cast<const FcChar8 *>((buf + R"(\fonts\fonts.conf)"s).c_str())), true); FcConfigAppFontAddDir(fc, const_cast<FcChar8 *>(reinterpret_cast<const FcChar8 *>((buf + "\\fonts"s).c_str()))); char fonts_path[MAX_PATH]; - if (SHGetFolderPathA(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, fonts_path) == S_OK) { + if (SHGetFolderPathA(nullptr, CSIDL_FONTS, nullptr, SHGFP_TYPE_CURRENT, fonts_path) == S_OK) { FcConfigAppFontAddDir(fc, reinterpret_cast<FcChar8 *>(fonts_path)); } diff --git a/src/platform.hpp b/src/platform.hpp index e321d4e..8083a5a 100644 --- a/src/platform.hpp +++ b/src/platform.hpp @@ -6,4 +6,4 @@ bool SetupFonts(); std::string FindResourceFolder(); std::string FindConfigFile(); std::string FindStateCacheFolder(); -} +} // namespace Platform diff --git a/src/util.cpp b/src/util.cpp index 6796a3f..0ebe73e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,6 +1,7 @@ #include "util.hpp" #include <array> #include <filesystem> +#include <array> Semaphore::Semaphore(int count) : m_count(count) {} @@ -94,11 +95,9 @@ std::string FormatISO8601(const std::string &in, int extra_offset, const std::st int offset = GetTimezoneOffset(); tm.tm_sec += offset + extra_offset; mktime(&tm); - std::stringstream ss; - const static std::locale locale(""); - ss.imbue(locale); - ss << std::put_time(&tm, fmt.c_str()); - return ss.str(); + std::array<char, 512> tmp; + std::strftime(tmp.data(), sizeof(tmp), fmt.c_str(), &tm); + return tmp.data(); } void ScrollListBoxToSelected(Gtk::ListBox &list) { diff --git a/subprojects/ixwebsocket b/subprojects/ixwebsocket -Subproject 2fac4bd9ef58c3be3e370222410b8694a4ef0d2 +Subproject e66437b56089be46886084ff3930f352b6d3d90 |