#include "../include/UsersSidePanel.hpp" #include "../include/RoomTopPanel.hpp" #include "../include/RoomSidePanel.hpp" #include "../include/ResourceCache.hpp" #include "../include/StaticImage.hpp" #include "../include/Gif.hpp" #include "../include/Settings.hpp" #include "../include/ColorScheme.hpp" #include "../include/Room.hpp" #include #include #include #include #include #include #include #include using namespace std; namespace dchat { const float WIDTH = 250.0f; const unsigned int FONT_SIZE = 20; const float AVATAR_DIAMETER = 40.0f; const float AVATAR_PADDING_SIDE = 10.0f; const float PADDING_BOTTOM = 20.0f; const i64 USER_TIMEOUT_SEC = 25; static void renderUser(Cache *cache, const User *user, sf::Shader *circleShader, sf::RenderWindow &window, sf::Vector2f &position, const sf::Font *font, const float textHeight, bool isUserOnline) { if(position.y + AVATAR_DIAMETER > 0.0f && position.y < window.getSize().y) { // Max avatar size = 1mb const ContentByUrlResult avatarResult = cache->getContentByUrl(user->avatarUrl, 1024 * 1024); if(avatarResult.type == ContentByUrlResult::Type::CACHED) { circleShader->setUniform("texture", sf::Shader::CurrentTexture); if(avatarResult.cachedType == ContentByUrlResult::CachedType::STATIC_IMAGE) { auto *staticImage = static_cast(avatarResult.staticImage); // TODO: Store this sprite somewhere, might not be efficient to create a new sprite object every frame sf::Sprite sprite(staticImage->texture); auto textureSize = staticImage->texture.getSize(); sprite.setPosition(sf::Vector2f(floor(position.x), floor(position.y))); sprite.setScale(sf::Vector2f(AVATAR_DIAMETER * Settings::getScaling() / (float)textureSize.x, AVATAR_DIAMETER * Settings::getScaling() / (float)textureSize.y)); sprite.setColor(isUserOnline ? sf::Color::White : sf::Color(255, 255, 255, 100)); window.draw(sprite, circleShader); } else if(avatarResult.cachedType == ContentByUrlResult::CachedType::GIF) { auto *gif = static_cast(avatarResult.gif); gif->update(); auto gifSize = gif->getSize(); sf::Sprite sprite(gif->texture); sprite.setPosition(sf::Vector2f(floor(position.x), floor(position.y))); sprite.setScale(sf::Vector2f(AVATAR_DIAMETER * Settings::getScaling() / (float)gifSize.x, AVATAR_DIAMETER * Settings::getScaling() / (float)gifSize.y)); sprite.setColor(isUserOnline ? sf::Color::White : sf::Color(255, 255, 255, 100)); window.draw(sprite, circleShader); } } else { sf::CircleShape avatarCircle(AVATAR_DIAMETER * 0.5f * Settings::getScaling(), 60 * Settings::getScaling()); avatarCircle.setPosition(sf::Vector2f(floor(position.x), floor(position.y))); avatarCircle.setFillColor(isUserOnline ? ColorScheme::getBackgroundColor() + sf::Color(30, 30, 30) : ColorScheme::getBackgroundColor() * sf::Color(255, 255, 255, 100)); window.draw(avatarCircle); } // TODO: Remove this shit sf::String str = sf::String::fromUtf8(user->nickname.begin(), user->nickname.end()); sf::Text text(str, *font, FONT_SIZE * Settings::getScaling()); text.setPosition(floor(position.x + (AVATAR_DIAMETER + AVATAR_PADDING_SIDE) * Settings::getScaling()), floor(position.y + AVATAR_DIAMETER * 0.5f - textHeight * 0.5f)); text.setFillColor(isUserOnline ? sf::Color(15, 192, 252) : sf::Color(15, 192, 252, 100)); window.draw(text); } position.y += ((AVATAR_DIAMETER + PADDING_BOTTOM) * Settings::getScaling()); } void UsersSidePanel::draw(sf::RenderWindow &window, Cache *cache) { auto windowSize = window.getSize(); float posY = std::min((windowSize.y - RoomTopPanel::getHeight()) * 0.5f, RoomSidePanel::getHeight()); std::shared_ptr currentRoom = getCurrentRoom(); if(!currentRoom) return; const sf::Font *font = ResourceCache::getFont("fonts/Nunito-Regular.ttf"); sf::Vector2f position(10.0f, posY); const float textHeight = font->getLineSpacing(FONT_SIZE * Settings::getScaling()); //i64 timestampSec = currentRoom->getSyncedTimestampUtcInSec(); auto &channelUsers = currentRoom->getUsers(); // auto currentChannelUsers = sibs::makeFunction(channelUsers.data(), channelUsers.data() + channelUsers.size()); // for(BridgeService *bridgeService : currentRoom->getBridgeServices()) // { // auto &bridgeServiceUsers = bridgeService->getUsers(); // currentChannelUsers.merge(sibs::makeFunction(bridgeServiceUsers.data(), bridgeServiceUsers.data() + bridgeServiceUsers.size())); // } u32 numOnlineUsers = 0; u32 numOfflineUsers = 0; for(auto &it : channelUsers) { const User *user = it.second.get(); // TODO: Fix this //if(user->isConnected(timestampSec)) // ++numOnlineUsers; //else // ++numOfflineUsers; } // TODO: Remove this shit sf::String str = "Online - "; str += to_string(numOnlineUsers); sf::Text text(str, *font, FONT_SIZE * Settings::getScaling()); text.setPosition(position); text.setFillColor(ColorScheme::getTextRegularColor() * sf::Color(255, 255, 255, 100)); window.draw(text); position.y += floor(font->getLineSpacing(text.getCharacterSize())); position.y += PADDING_BOTTOM * Settings::getScaling() * 0.5f; sf::Shader *circleShader = ResourceCache::getShader("shaders/circleMask.glsl", sf::Shader::Fragment); for(auto &it : channelUsers) { const User *user = it.second.get(); // TODO: Fix this //if(user->isConnected(timestampSec)) renderUser(cache, user, circleShader, window, position, font, textHeight, true); } if(numOfflineUsers == 0) return; position.y += PADDING_BOTTOM * Settings::getScaling(); // TODO: Remove this shit str = "Offline - "; str += to_string(numOfflineUsers); text.setString(str); text.setPosition(position); text.setFillColor(ColorScheme::getTextRegularColor() * sf::Color(255, 255, 255, 100)); window.draw(text); position.y += floor(font->getLineSpacing(text.getCharacterSize())); position.y += PADDING_BOTTOM * Settings::getScaling() * 0.5f; // TODO: Fix this //for(const User *user : channelUsers) //{ // const User *user = it.second.get(); // TODO: Fix this //if(!user->isConnected(timestampSec)) // renderUser(cache, user, circleShader, window, position, font, textHeight, false); // } } float UsersSidePanel::getWidth() { return floor(WIDTH * Settings::getScaling()); } }