mirror of
https://github.com/celisej567/abaddon.git
synced 2026-09-19 20:11:59 +03:00
Restructure source and resource files (#46)
importantly, res is now res/res and css is now res/css
This commit is contained in:
committed by
GitHub
parent
d88079000a
commit
a51a54bc59
58
src/windows/profile/mutualfriendspane.cpp
Normal file
58
src/windows/profile/mutualfriendspane.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "mutualfriendspane.hpp"
|
||||
#include "abaddon.hpp"
|
||||
|
||||
MutualFriendItem::MutualFriendItem(const UserData &user)
|
||||
: Gtk::Box(Gtk::ORIENTATION_HORIZONTAL) {
|
||||
get_style_context()->add_class("mutual-friend-item");
|
||||
m_name.get_style_context()->add_class("mutual-friend-item-name");
|
||||
m_avatar.get_style_context()->add_class("mutual-friend-item-avatar");
|
||||
|
||||
m_avatar.set_margin_end(10);
|
||||
|
||||
const auto show_animations = Abaddon::Get().GetSettings().GetShowAnimations();
|
||||
auto &img = Abaddon::Get().GetImageManager();
|
||||
m_avatar.property_pixbuf() = img.GetPlaceholder(24);
|
||||
if (user.HasAnimatedAvatar() && show_animations) {
|
||||
auto cb = [this](const Glib::RefPtr<Gdk::PixbufAnimation> &pb) {
|
||||
m_avatar.property_pixbuf_animation() = pb;
|
||||
};
|
||||
img.LoadAnimationFromURL(user.GetAvatarURL("gif", "32"), 24, 24, sigc::track_obj(cb, *this));
|
||||
} else {
|
||||
auto cb = [this](const Glib::RefPtr<Gdk::Pixbuf> &pb) {
|
||||
m_avatar.property_pixbuf() = pb->scale_simple(24, 24, Gdk::INTERP_BILINEAR);
|
||||
};
|
||||
img.LoadFromURL(user.GetAvatarURL("png", "32"), sigc::track_obj(cb, *this));
|
||||
}
|
||||
|
||||
m_name.set_markup(user.GetEscapedBoldString<false>());
|
||||
|
||||
m_name.set_valign(Gtk::ALIGN_CENTER);
|
||||
add(m_avatar);
|
||||
add(m_name);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
MutualFriendsPane::MutualFriendsPane(Snowflake id)
|
||||
: UserID(id) {
|
||||
signal_map().connect(sigc::mem_fun(*this, &MutualFriendsPane::OnMap));
|
||||
add(m_list);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
void MutualFriendsPane::OnFetchRelationships(const std::vector<UserData> &users) {
|
||||
for (auto child : m_list.get_children())
|
||||
delete child;
|
||||
|
||||
for (const auto &user : users) {
|
||||
auto *item = Gtk::manage(new MutualFriendItem(user));
|
||||
item->show();
|
||||
m_list.add(*item);
|
||||
}
|
||||
}
|
||||
|
||||
void MutualFriendsPane::OnMap() {
|
||||
if (m_requested) return;
|
||||
m_requested = true;
|
||||
|
||||
Abaddon::Get().GetDiscordClient().FetchUserRelationships(UserID, sigc::mem_fun(*this, &MutualFriendsPane::OnFetchRelationships));
|
||||
}
|
||||
28
src/windows/profile/mutualfriendspane.hpp
Normal file
28
src/windows/profile/mutualfriendspane.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include <gtkmm.h>
|
||||
#include "discord/objects.hpp"
|
||||
|
||||
class MutualFriendItem : public Gtk::Box {
|
||||
public:
|
||||
MutualFriendItem(const UserData &user);
|
||||
|
||||
private:
|
||||
Gtk::Image m_avatar;
|
||||
Gtk::Label m_name;
|
||||
};
|
||||
|
||||
class MutualFriendsPane : public Gtk::ScrolledWindow {
|
||||
public:
|
||||
MutualFriendsPane(Snowflake id);
|
||||
|
||||
Snowflake UserID;
|
||||
|
||||
private:
|
||||
void OnMap();
|
||||
|
||||
bool m_requested = false;
|
||||
|
||||
void OnFetchRelationships(const std::vector<UserData> &users);
|
||||
|
||||
Gtk::ListBox m_list;
|
||||
};
|
||||
73
src/windows/profile/mutualguildspane.cpp
Normal file
73
src/windows/profile/mutualguildspane.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#include "mutualguildspane.hpp"
|
||||
#include "abaddon.hpp"
|
||||
|
||||
MutualGuildItem::MutualGuildItem(const MutualGuildData &guild)
|
||||
: Gtk::Box(Gtk::ORIENTATION_HORIZONTAL)
|
||||
, m_box(Gtk::ORIENTATION_VERTICAL) {
|
||||
get_style_context()->add_class("mutual-guild-item");
|
||||
m_name.get_style_context()->add_class("mutual-guild-item-name");
|
||||
m_icon.get_style_context()->add_class("mutual-guild-item-icon");
|
||||
|
||||
m_icon.set_margin_end(10);
|
||||
|
||||
// discord will return info (id + nick) for "deleted" guilds from this endpoint. strange !
|
||||
const auto data = Abaddon::Get().GetDiscordClient().GetGuild(guild.ID);
|
||||
if (data.has_value()) {
|
||||
const auto show_animations = Abaddon::Get().GetSettings().GetShowAnimations();
|
||||
auto &img = Abaddon::Get().GetImageManager();
|
||||
m_icon.property_pixbuf() = img.GetPlaceholder(24);
|
||||
if (data->HasIcon()) {
|
||||
if (data->HasAnimatedIcon() && show_animations) {
|
||||
auto cb = [this](const Glib::RefPtr<Gdk::PixbufAnimation> &pb) {
|
||||
m_icon.property_pixbuf_animation() = pb;
|
||||
};
|
||||
img.LoadAnimationFromURL(data->GetIconURL("gif", "32"), 24, 24, sigc::track_obj(cb, *this));
|
||||
} else {
|
||||
auto cb = [this](const Glib::RefPtr<Gdk::Pixbuf> &pb) {
|
||||
m_icon.property_pixbuf() = pb->scale_simple(24, 24, Gdk::INTERP_BILINEAR);
|
||||
};
|
||||
img.LoadFromURL(data->GetIconURL("png", "32"), sigc::track_obj(cb, *this));
|
||||
}
|
||||
}
|
||||
|
||||
m_name.set_markup("<b>" + Glib::Markup::escape_text(data->Name) + "</b>");
|
||||
} else {
|
||||
m_icon.property_pixbuf() = Abaddon::Get().GetImageManager().GetPlaceholder(24);
|
||||
m_name.set_markup("<b>Unknown server</b>");
|
||||
}
|
||||
|
||||
if (guild.Nick.has_value()) {
|
||||
m_nick = Gtk::manage(new Gtk::Label(*guild.Nick));
|
||||
m_nick->get_style_context()->add_class("mutual-guild-item-nick");
|
||||
m_nick->set_margin_start(5);
|
||||
m_nick->set_halign(Gtk::ALIGN_START);
|
||||
m_nick->set_single_line_mode(true);
|
||||
m_nick->set_ellipsize(Pango::ELLIPSIZE_END);
|
||||
}
|
||||
|
||||
m_box.set_valign(Gtk::ALIGN_CENTER);
|
||||
|
||||
m_box.add(m_name);
|
||||
if (m_nick != nullptr)
|
||||
m_box.add(*m_nick);
|
||||
add(m_icon);
|
||||
add(m_box);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
UserMutualGuildsPane::UserMutualGuildsPane(Snowflake id)
|
||||
: UserID(id) {
|
||||
add(m_list);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
void UserMutualGuildsPane::SetMutualGuilds(const std::vector<MutualGuildData> &guilds) {
|
||||
for (auto child : m_list.get_children())
|
||||
delete child;
|
||||
|
||||
for (const auto &guild : guilds) {
|
||||
auto *item = Gtk::manage(new MutualGuildItem(guild));
|
||||
item->show();
|
||||
m_list.add(*item);
|
||||
}
|
||||
}
|
||||
26
src/windows/profile/mutualguildspane.hpp
Normal file
26
src/windows/profile/mutualguildspane.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <gtkmm.h>
|
||||
#include "discord/objects.hpp"
|
||||
|
||||
class MutualGuildItem : public Gtk::Box {
|
||||
public:
|
||||
MutualGuildItem(const MutualGuildData &guild);
|
||||
|
||||
private:
|
||||
Gtk::Image m_icon;
|
||||
Gtk::Box m_box;
|
||||
Gtk::Label m_name;
|
||||
Gtk::Label *m_nick = nullptr;
|
||||
};
|
||||
|
||||
class UserMutualGuildsPane : public Gtk::ScrolledWindow {
|
||||
public:
|
||||
UserMutualGuildsPane(Snowflake id);
|
||||
|
||||
void SetMutualGuilds(const std::vector<MutualGuildData> &guilds);
|
||||
|
||||
Snowflake UserID;
|
||||
|
||||
private:
|
||||
Gtk::ListBox m_list;
|
||||
};
|
||||
236
src/windows/profile/userinfopane.cpp
Normal file
236
src/windows/profile/userinfopane.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
#include "userinfopane.hpp"
|
||||
#include <unordered_set>
|
||||
#include "abaddon.hpp"
|
||||
|
||||
ConnectionItem::ConnectionItem(const ConnectionData &conn)
|
||||
: m_box(Gtk::ORIENTATION_HORIZONTAL)
|
||||
, m_name(conn.Name) {
|
||||
Glib::RefPtr<Gdk::Pixbuf> pixbuf;
|
||||
try {
|
||||
pixbuf = Gdk::Pixbuf::create_from_file(Abaddon::GetResPath("/" + conn.Type + ".png"), 32, 32);
|
||||
} catch (const Glib::Exception &e) {}
|
||||
std::string url;
|
||||
if (conn.Type == "github")
|
||||
url = "https://github.com/" + conn.Name;
|
||||
else if (conn.Type == "steam")
|
||||
url = "https://steamcommunity.com/profiles/" + conn.ID;
|
||||
else if (conn.Type == "twitch")
|
||||
url = "https://twitch.tv/" + conn.Name;
|
||||
else if (conn.Type == "twitter")
|
||||
url = "https://twitter.com/i/user/" + conn.ID;
|
||||
else if (conn.Type == "spotify")
|
||||
url = "https://open.spotify.com/user/" + conn.ID;
|
||||
else if (conn.Type == "reddit")
|
||||
url = "https://reddit.com/u/" + conn.Name;
|
||||
else if (conn.Type == "youtube")
|
||||
url = "https://www.youtube.com/channel/" + conn.ID;
|
||||
else if (conn.Type == "facebook")
|
||||
url = "https://www.facebook.com/" + conn.ID;
|
||||
if (pixbuf) {
|
||||
m_image = Gtk::manage(new Gtk::Image(pixbuf));
|
||||
m_image->get_style_context()->add_class("profile-connection-image");
|
||||
m_box.add(*m_image);
|
||||
}
|
||||
m_box.set_halign(Gtk::ALIGN_START);
|
||||
m_box.set_size_request(200, -1);
|
||||
m_box.get_style_context()->add_class("profile-connection");
|
||||
m_name.get_style_context()->add_class("profile-connection-label");
|
||||
m_name.set_valign(Gtk::ALIGN_CENTER);
|
||||
m_name.set_single_line_mode(true);
|
||||
m_name.set_ellipsize(Pango::ELLIPSIZE_END);
|
||||
m_box.add(m_name);
|
||||
if (url != "") {
|
||||
auto cb = [this, url](GdkEventButton *event) -> bool {
|
||||
if (event->type == GDK_BUTTON_PRESS && event->button == GDK_BUTTON_PRIMARY) {
|
||||
LaunchBrowser(url);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
signal_button_press_event().connect(sigc::track_obj(cb, *this));
|
||||
AddPointerCursor(*this);
|
||||
}
|
||||
m_overlay.add(m_box);
|
||||
if (conn.IsVerified) {
|
||||
try {
|
||||
const static auto checkmarks_path = Abaddon::GetResPath("/checkmark.png");
|
||||
static auto pb = Gdk::Pixbuf::create_from_file(checkmarks_path, 24, 24);
|
||||
m_check = Gtk::manage(new Gtk::Image(pb));
|
||||
m_check->get_style_context()->add_class("profile-connection-check");
|
||||
m_check->set_margin_end(25);
|
||||
m_check->set_valign(Gtk::ALIGN_CENTER);
|
||||
m_check->set_halign(Gtk::ALIGN_END);
|
||||
m_check->show();
|
||||
m_overlay.add_overlay(*m_check);
|
||||
} catch (const Glib::Exception &e) {}
|
||||
}
|
||||
m_overlay.set_hexpand(false);
|
||||
m_overlay.set_halign(Gtk::ALIGN_START);
|
||||
add(m_overlay);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
ConnectionsContainer::ConnectionsContainer() {
|
||||
get_style_context()->add_class("profile-connections");
|
||||
set_column_homogeneous(true);
|
||||
set_row_spacing(10);
|
||||
set_column_spacing(10);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
void ConnectionsContainer::SetConnections(const std::vector<ConnectionData> &connections) {
|
||||
for (auto child : get_children())
|
||||
delete child;
|
||||
|
||||
static const std::unordered_set<std::string> supported_services = {
|
||||
"battlenet",
|
||||
"github",
|
||||
"leagueoflegends",
|
||||
"reddit",
|
||||
"skype",
|
||||
"spotify",
|
||||
"steam",
|
||||
"twitch",
|
||||
"twitter",
|
||||
"xbox",
|
||||
"youtube",
|
||||
"facebook"
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < connections.size(); i++) {
|
||||
const auto &conn = connections[i];
|
||||
if (supported_services.find(conn.Type) == supported_services.end()) continue;
|
||||
auto widget = Gtk::manage(new ConnectionItem(conn));
|
||||
widget->show();
|
||||
attach(*widget, i % 2, i / 2, 1, 1);
|
||||
}
|
||||
|
||||
set_halign(Gtk::ALIGN_FILL);
|
||||
set_hexpand(true);
|
||||
}
|
||||
|
||||
NotesContainer::NotesContainer()
|
||||
: Gtk::Box(Gtk::ORIENTATION_VERTICAL) {
|
||||
get_style_context()->add_class("profile-notes");
|
||||
m_label.get_style_context()->add_class("profile-notes-label");
|
||||
m_note.get_style_context()->add_class("profile-notes-text");
|
||||
|
||||
m_label.set_markup("<b>NOTE</b>");
|
||||
m_label.set_halign(Gtk::ALIGN_START);
|
||||
|
||||
m_note.set_wrap_mode(Gtk::WRAP_WORD_CHAR);
|
||||
m_note.signal_key_press_event().connect(sigc::mem_fun(*this, &NotesContainer::OnNoteKeyPress), false);
|
||||
|
||||
add(m_label);
|
||||
add(m_note);
|
||||
show_all_children();
|
||||
}
|
||||
|
||||
void NotesContainer::SetNote(const std::string ¬e) {
|
||||
m_note.get_buffer()->set_text(note);
|
||||
}
|
||||
|
||||
void NotesContainer::UpdateNote() {
|
||||
auto text = m_note.get_buffer()->get_text();
|
||||
if (text.size() > 256)
|
||||
text = text.substr(0, 256);
|
||||
m_signal_update_note.emit(text);
|
||||
}
|
||||
|
||||
bool NotesContainer::OnNoteKeyPress(GdkEventKey *event) {
|
||||
if (event->type != GDK_KEY_PRESS) return false;
|
||||
const auto text = m_note.get_buffer()->get_text();
|
||||
if (event->keyval == GDK_KEY_Return) {
|
||||
if (event->state & GDK_SHIFT_MASK) {
|
||||
int newlines = 0;
|
||||
for (const auto c : text)
|
||||
if (c == '\n') newlines++;
|
||||
return newlines >= 5;
|
||||
} else {
|
||||
UpdateNote();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NotesContainer::type_signal_update_note NotesContainer::signal_update_note() {
|
||||
return m_signal_update_note;
|
||||
}
|
||||
|
||||
BioContainer::BioContainer()
|
||||
: Gtk::Box(Gtk::ORIENTATION_VERTICAL) {
|
||||
m_label.set_markup("<b>ABOUT ME</b>");
|
||||
m_label.set_halign(Gtk::ALIGN_START);
|
||||
m_bio.set_halign(Gtk::ALIGN_START);
|
||||
m_bio.set_line_wrap(true);
|
||||
m_bio.set_line_wrap_mode(Pango::WRAP_WORD_CHAR);
|
||||
|
||||
m_label.show();
|
||||
m_bio.show();
|
||||
|
||||
add(m_label);
|
||||
add(m_bio);
|
||||
}
|
||||
|
||||
void BioContainer::SetBio(const std::string &bio) {
|
||||
m_bio.set_text(bio);
|
||||
}
|
||||
|
||||
ProfileUserInfoPane::ProfileUserInfoPane(Snowflake ID)
|
||||
: Gtk::Box(Gtk::ORIENTATION_VERTICAL)
|
||||
, UserID(ID) {
|
||||
get_style_context()->add_class("profile-info-pane");
|
||||
m_created.get_style_context()->add_class("profile-info-created");
|
||||
|
||||
m_note.signal_update_note().connect([this](const Glib::ustring ¬e) {
|
||||
auto cb = [this](DiscordError code) {
|
||||
if (code != DiscordError::NONE) {
|
||||
Gtk::MessageDialog dlg("Failed to set note", false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||
dlg.set_position(Gtk::WIN_POS_CENTER);
|
||||
dlg.run();
|
||||
}
|
||||
};
|
||||
Abaddon::Get().GetDiscordClient().SetUserNote(UserID, note, sigc::track_obj(cb, *this));
|
||||
});
|
||||
|
||||
auto &discord = Abaddon::Get().GetDiscordClient();
|
||||
auto note_update_cb = [this](Snowflake id, std::string note) {
|
||||
if (id == UserID)
|
||||
m_note.SetNote(note);
|
||||
};
|
||||
discord.signal_note_update().connect(sigc::track_obj(note_update_cb, m_note));
|
||||
|
||||
auto fetch_note_cb = [this](const std::string ¬e) {
|
||||
m_note.SetNote(note);
|
||||
};
|
||||
discord.FetchUserNote(UserID, sigc::track_obj(fetch_note_cb, *this));
|
||||
|
||||
m_created.set_halign(Gtk::ALIGN_START);
|
||||
m_created.set_margin_top(5);
|
||||
m_created.set_text("Account created: " + ID.GetLocalTimestamp());
|
||||
|
||||
m_conns.set_halign(Gtk::ALIGN_START);
|
||||
m_conns.set_hexpand(true);
|
||||
|
||||
m_created.show();
|
||||
m_note.show();
|
||||
m_conns.show();
|
||||
|
||||
add(m_created);
|
||||
add(m_bio);
|
||||
add(m_note);
|
||||
add(m_conns);
|
||||
}
|
||||
|
||||
void ProfileUserInfoPane::SetProfile(const UserProfileData &data) {
|
||||
if (data.User.Bio.has_value() && *data.User.Bio != "") {
|
||||
m_bio.SetBio(*data.User.Bio);
|
||||
m_bio.show();
|
||||
} else {
|
||||
m_bio.hide();
|
||||
}
|
||||
|
||||
m_conns.SetConnections(data.ConnectedAccounts);
|
||||
}
|
||||
65
src/windows/profile/userinfopane.hpp
Normal file
65
src/windows/profile/userinfopane.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
#include <gtkmm.h>
|
||||
#include "discord/objects.hpp"
|
||||
|
||||
class ConnectionItem : public Gtk::EventBox {
|
||||
public:
|
||||
ConnectionItem(const ConnectionData &connection);
|
||||
|
||||
private:
|
||||
Gtk::Overlay m_overlay;
|
||||
Gtk::Box m_box;
|
||||
Gtk::Label m_name;
|
||||
Gtk::Image *m_image = nullptr;
|
||||
Gtk::Image *m_check = nullptr;
|
||||
};
|
||||
|
||||
class ConnectionsContainer : public Gtk::Grid {
|
||||
public:
|
||||
ConnectionsContainer();
|
||||
void SetConnections(const std::vector<ConnectionData> &connections);
|
||||
};
|
||||
|
||||
class NotesContainer : public Gtk::Box {
|
||||
public:
|
||||
NotesContainer();
|
||||
void SetNote(const std::string ¬e);
|
||||
|
||||
private:
|
||||
void UpdateNote();
|
||||
bool OnNoteKeyPress(GdkEventKey *event);
|
||||
|
||||
Gtk::Label m_label;
|
||||
Gtk::TextView m_note;
|
||||
|
||||
typedef sigc::signal<void, Glib::ustring> type_signal_update_note;
|
||||
type_signal_update_note m_signal_update_note;
|
||||
|
||||
public:
|
||||
type_signal_update_note signal_update_note();
|
||||
};
|
||||
|
||||
class BioContainer : public Gtk::Box {
|
||||
public:
|
||||
BioContainer();
|
||||
void SetBio(const std::string &bio);
|
||||
|
||||
private:
|
||||
Gtk::Label m_label;
|
||||
Gtk::Label m_bio;
|
||||
};
|
||||
|
||||
class ProfileUserInfoPane : public Gtk::Box {
|
||||
public:
|
||||
ProfileUserInfoPane(Snowflake ID);
|
||||
void SetProfile(const UserProfileData &data);
|
||||
|
||||
Snowflake UserID;
|
||||
|
||||
private:
|
||||
Gtk::Label m_created;
|
||||
|
||||
BioContainer m_bio;
|
||||
NotesContainer m_note;
|
||||
ConnectionsContainer m_conns;
|
||||
};
|
||||
Reference in New Issue
Block a user