aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-04-28 11:52:04 +0200
committerdec05eba <dec05eba@protonmail.com>2018-04-28 11:53:18 +0200
commit3b03f87070d91f63f0dc3c7152723727781dcccf (patch)
tree7b06163f34248d1e632c032cfaf306787675e585
parentb0bfb8b8d1479502bd5adf17e6a1b94ec00c63ca (diff)
Add commands, users side panel, improve image download
start using odhtdb
-rw-r--r--.kdev4/dchat.kdev43
m---------depends/odhtdb0
-rw-r--r--include/Cache.hpp1
-rw-r--r--include/Channel.hpp2
-rw-r--r--include/ChannelSidePanel.hpp12
-rw-r--r--include/Chatbar.hpp6
-rw-r--r--include/Command.hpp17
-rw-r--r--include/MessageBoard.hpp2
-rw-r--r--include/StringView.hpp10
-rw-r--r--include/UsersSidePanel.hpp15
-rw-r--r--include/env.hpp14
-rw-r--r--src/Cache.cpp22
-rw-r--r--src/Channel.cpp10
-rw-r--r--src/ChannelSidePanel.cpp22
-rw-r--r--src/Chatbar.cpp135
-rw-r--r--src/Command.cpp37
-rw-r--r--src/MessageBoard.cpp12
-rw-r--r--src/UsersSidePanel.cpp47
-rw-r--r--src/main.cpp165
19 files changed, 481 insertions, 51 deletions
diff --git a/.kdev4/dchat.kdev4 b/.kdev4/dchat.kdev4
index d4eb7c2..78720b2 100644
--- a/.kdev4/dchat.kdev4
+++ b/.kdev4/dchat.kdev4
@@ -13,6 +13,9 @@ Name=Clang
[CustomDefinesAndIncludes][ProjectPath0][Includes]
1=/home/dec05eba/.sibs/lib/tiny-process/2.0.0
2=/home/dec05eba/git/dchat/depends/odhtdb/include
+3=/home/dec05eba/.sibs/lib/sibs-serializer/0.2.0
+4=/home/dec05eba/.sibs/lib/ntpclient/0.2.0/include
+5=/home/dec05eba/.sibs/lib/fmt/4.1.0
[Project]
VersionControlSupport=kdevgit
diff --git a/depends/odhtdb b/depends/odhtdb
-Subproject 13718f15767db6774dbf562b6798838ad905898
+Subproject 54d8ae4c335c21290dc41e5ba4701b3c19bba60
diff --git a/include/Cache.hpp b/include/Cache.hpp
index 0314e7e..d78324c 100644
--- a/include/Cache.hpp
+++ b/include/Cache.hpp
@@ -61,6 +61,7 @@ namespace dchat
std::thread downloadWaitThread;
std::vector<ImageDownloadInfo> imageDownloadProcesses;
+ std::vector<ImageDownloadInfo> imageDownloadProcessesQueue;
std::mutex imageDownloadMutex;
};
}
diff --git a/include/Channel.hpp b/include/Channel.hpp
index 4d1f528..4bdb4b5 100644
--- a/include/Channel.hpp
+++ b/include/Channel.hpp
@@ -18,7 +18,7 @@ namespace dchat
const std::string& getName() const;
void processEvent(const sf::Event &event);
- void draw(sf::RenderWindow &window, const sf::Vector2f &position, Cache &cache);
+ void draw(sf::RenderWindow &window, Cache &cache);
private:
MessageBoard messageBoard;
Chatbar chatbar;
diff --git a/include/ChannelSidePanel.hpp b/include/ChannelSidePanel.hpp
index 8331787..c1ed5d6 100644
--- a/include/ChannelSidePanel.hpp
+++ b/include/ChannelSidePanel.hpp
@@ -1,6 +1,5 @@
#pragma once
-#include <vector>
#include <SFML/Graphics/RenderWindow.hpp>
namespace dchat
@@ -10,13 +9,8 @@ namespace dchat
class ChannelSidePanel
{
public:
- ChannelSidePanel(float width);
- void addChannel(Channel *channel);
-
- void draw(sf::RenderWindow &window);
-
- float width;
- private:
- std::vector<Channel*> channels;
+ static void addChannel(Channel *channel);
+ static void draw(sf::RenderWindow &window);
+ static float getWidth();
};
}
diff --git a/include/Chatbar.hpp b/include/Chatbar.hpp
index c98db48..a9871f6 100644
--- a/include/Chatbar.hpp
+++ b/include/Chatbar.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "StringView.hpp"
#include <SFML/Graphics/Text.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
@@ -16,6 +17,7 @@ namespace dchat
Chatbar();
void addChar(sf::Uint32 codePoint);
+ void addString(const std::string &strToAdd);
const sf::String& getString() const;
void removePreviousChar();
void removeNextChar();
@@ -27,7 +29,9 @@ namespace dchat
bool isFocused() const;
void processEvent(const sf::Event &event, Channel *channel);
- void draw(sf::RenderWindow &window, const sf::Vector2f &position);
+ void draw(sf::RenderWindow &window);
+ private:
+ void processChatCommand(const StringView &cmd);
private:
sf::Text text;
sf::RectangleShape background;
diff --git a/include/Command.hpp b/include/Command.hpp
new file mode 100644
index 0000000..fe8a947
--- /dev/null
+++ b/include/Command.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <vector>
+#include <string>
+#include <functional>
+
+namespace dchat
+{
+ using CommandHandlerFunc = std::function<void(const std::vector<std::string> &args)>;
+
+ class Command
+ {
+ public:
+ static bool add(const std::string &cmd, CommandHandlerFunc handlerFunc);
+ static bool call(const std::string &cmd, const std::vector<std::string> &args);
+ };
+}
diff --git a/include/MessageBoard.hpp b/include/MessageBoard.hpp
index 523fb16..ca1405f 100644
--- a/include/MessageBoard.hpp
+++ b/include/MessageBoard.hpp
@@ -20,7 +20,7 @@ namespace dchat
void addMessage(Message *message);
void processEvent(const sf::Event &event);
- void draw(sf::RenderWindow &window, const sf::Vector2f &position, Cache &cache);
+ void draw(sf::RenderWindow &window, Cache &cache);
private:
sf::RenderTexture staticContentTexture;
bool dirty;
diff --git a/include/StringView.hpp b/include/StringView.hpp
index 9eea387..45d0f5b 100644
--- a/include/StringView.hpp
+++ b/include/StringView.hpp
@@ -52,6 +52,16 @@ namespace dchat
return memcmp(data, other.data, size * sizeof(CharType)) == 0;
}
+ bool operator == (const BasicStringView<CharType> &other) const
+ {
+ return equals(other);
+ }
+
+ bool operator != (const BasicStringView<CharType> &other) const
+ {
+ return !equals(other);
+ }
+
CharType operator [] (usize index) const
{
assert(index < size);
diff --git a/include/UsersSidePanel.hpp b/include/UsersSidePanel.hpp
new file mode 100644
index 0000000..aebdb34
--- /dev/null
+++ b/include/UsersSidePanel.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "User.hpp"
+#include <SFML/Graphics/RenderWindow.hpp>
+
+namespace dchat
+{
+ class UsersSidePanel
+ {
+ public:
+ static void addUser(User *user);
+ static void draw(sf::RenderWindow &window);
+ static float getWidth();
+ };
+}
diff --git a/include/env.hpp b/include/env.hpp
index e0a5b03..abaedd8 100644
--- a/include/env.hpp
+++ b/include/env.hpp
@@ -8,9 +8,9 @@
#if defined(_WIN32) || defined(_WIN64)
#if defined(_WIN64)
- #define OS_ENV_64BIT
+ #define SYS_ENV_64BIT
#else
- #define OS_ENV_32BIT
+ #define SYS_ENV_32BIT
#endif
#define OS_FAMILY OS_FAMILY_WINDOWS
#define OS_TYPE OS_TYPE_WINDOWS
@@ -40,13 +40,13 @@
#if defined(__GNUC__)
#if defined(__x86_64__) || defined(__pc64__)
- #define OS_ENV_64BIT
+ #define SYS_ENV_64BIT
#else
- #define OS_ENV_32BIT
+ #define SYS_ENV_32BIT
#endif
#endif
-#if !defined(OS_ENV_32BIT) && !defined(OS_ENV_64BIT)
+#if !defined(SYS_ENV_32BIT) && !defined(SYS_ENV_64BIT)
#error "System is not detected as either 32-bit or 64-bit"
#endif
@@ -57,7 +57,3 @@
#if !defined(OS_TYPE)
#error "System not supported. Only Windows and linux systems supported right now"
#endif
-
-#if !defined(DEBUG) && !defined(NDEBUG)
-#define DEBUG
-#endif
diff --git a/src/Cache.cpp b/src/Cache.cpp
index accd0c4..abfa1dd 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -80,6 +80,7 @@ namespace dchat
texture->generateMipmap();
return { texture, ImageByUrlResult::Type::CACHED };
}
+ delete texture;
delete fileContent.data;
}
}
@@ -100,7 +101,6 @@ namespace dchat
{
while(true)
{
- imageDownloadMutex.lock();
for(vector<ImageDownloadInfo>::iterator it = imageDownloadProcesses.begin(); it != imageDownloadProcesses.end();)
{
int exitStatus;
@@ -114,7 +114,9 @@ namespace dchat
filepath /= urlHash.toString();
ImageByUrlResult imageByUrlResult = loadImageFromFile(filepath);
+ imageDownloadMutex.lock();
imageUrlCache[it->url] = imageByUrlResult;
+ imageDownloadMutex.unlock();
switch(imageByUrlResult.type)
{
case ImageByUrlResult::Type::CACHED:
@@ -130,11 +132,21 @@ namespace dchat
else
++it;
}
- imageDownloadMutex.unlock();
- while(imageDownloadProcesses.empty())
+ while(imageDownloadProcesses.empty() && imageDownloadProcessesQueue.empty())
this_thread::sleep_for(chrono::milliseconds(20));
+ if(!imageDownloadProcessesQueue.empty())
+ {
+ imageDownloadMutex.lock();
+ for(auto imageDownloadInfo : imageDownloadProcessesQueue)
+ {
+ imageDownloadProcesses.push_back(imageDownloadInfo);
+ }
+ imageDownloadProcessesQueue.clear();
+ imageDownloadMutex.unlock();
+ }
+
this_thread::sleep_for(chrono::milliseconds(20));
}
});
@@ -169,10 +181,10 @@ namespace dchat
Process::string_type cmd = "curl -L --silent -o '";
cmd += filepath.native();
cmd += "' --max-filesize " + downloadLimitBytesStr + " --range 0-" + downloadLimitBytesStr + " --url '" + url + "'";
- // certutil.exe -urlcache -split -f "https://url/to/file" path/and/name/to/save/as/file
+ // TODO: Use this instead of curl on windows: certutil.exe -urlcache -split -f "https://url/to/file" path/and/name/to/save/as/file
Process *process = new Process(cmd, "", nullptr, nullptr, false);
ImageDownloadInfo imageDownloadInfo { process, url };
- imageDownloadProcesses.emplace_back(imageDownloadInfo);
+ imageDownloadProcessesQueue.emplace_back(imageDownloadInfo);
return result;
}
}
diff --git a/src/Channel.cpp b/src/Channel.cpp
index d7d6dc5..f02b97a 100644
--- a/src/Channel.cpp
+++ b/src/Channel.cpp
@@ -1,4 +1,6 @@
#include "../include/Channel.hpp"
+#include "../include/UsersSidePanel.hpp"
+#include "../include/ChannelSidePanel.hpp"
#include <cstring>
using namespace std;
@@ -72,9 +74,11 @@ namespace dchat
messageBoard.processEvent(event);
}
- void Channel::draw(sf::RenderWindow &window, const sf::Vector2f &position, Cache &cache)
+ void Channel::draw(sf::RenderWindow &window, Cache &cache)
{
- messageBoard.draw(window, position, cache);
- chatbar.draw(window, position);
+ ChannelSidePanel::draw(window);
+ messageBoard.draw(window, cache);
+ chatbar.draw(window);
+ UsersSidePanel::draw(window);
}
}
diff --git a/src/ChannelSidePanel.cpp b/src/ChannelSidePanel.cpp
index 3958376..a85dbdc 100644
--- a/src/ChannelSidePanel.cpp
+++ b/src/ChannelSidePanel.cpp
@@ -4,15 +4,16 @@
#include "../include/Channel.hpp"
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/Text.hpp>
+#include <vector>
#include <cmath>
+using namespace std;
+
namespace dchat
{
- ChannelSidePanel::ChannelSidePanel(float _width) :
- width(floor(_width))
- {
-
- }
+ vector<Channel*> channels;
+ const float width = 200.0f;
+ const unsigned int FONT_SIZE = 20;
void ChannelSidePanel::addChannel(Channel *channel)
{
@@ -27,16 +28,21 @@ namespace dchat
window.draw(rect);
const sf::Font &font = ResourceCache::getFont("fonts/Roboto-Regular.ttf");
- sf::Vector2f position;
+ sf::Vector2f position(10.0f, 10.0f);
for(Channel *channel : channels)
{
// TODO: Remove this shit
sf::String str = "# ";
str += sf::String::fromUtf8(channel->getName().begin(), channel->getName().end());
- sf::Text text(str, font, 24 * Settings::getScaling());
+ sf::Text text(str, font, FONT_SIZE * Settings::getScaling());
text.setPosition(position);
window.draw(text);
- position.y += font.getLineSpacing(24 * Settings::getScaling());
+ position.y += font.getLineSpacing(FONT_SIZE * Settings::getScaling());
}
}
+
+ float ChannelSidePanel::getWidth()
+ {
+ return width;
+ }
}
diff --git a/src/Chatbar.cpp b/src/Chatbar.cpp
index fcfec36..51ab9f5 100644
--- a/src/Chatbar.cpp
+++ b/src/Chatbar.cpp
@@ -2,8 +2,12 @@
#include "../include/ResourceCache.hpp"
#include "../include/Settings.hpp"
#include "../include/Channel.hpp"
+#include "../include/ChannelSidePanel.hpp"
+#include "../include/UsersSidePanel.hpp"
+#include "../include/Command.hpp"
#include <cmath>
#include <cstring>
+#include <process.hpp>
using namespace std;
@@ -14,6 +18,7 @@ namespace dchat
const float BOX_PADDING_Y = 5.0f;
const int BLINK_TIME_VISIBLE_MS = 500;
const int BLINK_TIME_INVISIBLE_MS = 500;
+ const float PADDING_SIDE = 20.0f;
Chatbar::Chatbar() :
text("", ResourceCache::getFont("fonts/Roboto-Regular.ttf"), FONT_SIZE * Settings::getScaling()),
@@ -34,6 +39,17 @@ namespace dchat
blinkTimer.restart();
}
+ void Chatbar::addString(const string &strToAdd)
+ {
+ if(strToAdd.empty()) return;
+ auto str = text.getString();
+ str.insert(caretIndex, sf::String::fromUtf8(strToAdd.begin(), strToAdd.end()));
+ text.setString(str);
+ caretIndex += strToAdd.size();
+ caretOffset = text.findCharacterPos(caretIndex) - text.getPosition();
+ blinkTimer.restart();
+ }
+
const sf::String& Chatbar::getString() const
{
return text.getString();
@@ -92,6 +108,108 @@ namespace dchat
return focused;
}
+ class ArgParseException : public std::runtime_error
+ {
+ public:
+ ArgParseException(const string &errMsg) : std::runtime_error(errMsg) {}
+ };
+
+ string stringRemoveQuotes(const StringView &str)
+ {
+ string result;
+ result.reserve(str.size);
+ for(usize i = 0; i < str.size; ++i)
+ {
+ char c = str[i];
+ if(c != '\'' && c != '"')
+ result += c;
+ }
+ return result;
+ }
+
+ vector<string> splitCommandArgs(const StringView &str)
+ {
+ vector<string> result;
+ ssize offset = 0;
+ char quoteChar = '\0';
+
+ for(ssize i = 0; i < str.size; ++i)
+ {
+ char c = str[i];
+ if(c == '\'' || c == '"')
+ {
+ if(c == quoteChar)
+ quoteChar = '\0';
+ else
+ quoteChar = c;
+ }
+ else if(quoteChar == '\0' && c == ' ')
+ {
+ ssize substrLength = i - offset;
+ if(substrLength > 0)
+ {
+ StringView substrView(str.data + offset, substrLength);
+ string substr = stringRemoveQuotes(substrView);
+ if(!substr.empty())
+ result.emplace_back(move(substr));
+ }
+ offset = i + 1;
+ }
+ }
+
+ if(quoteChar != '\0')
+ {
+ string errMsg = "Reached end of command before end of quote (";
+ errMsg += quoteChar;
+ errMsg += ")";
+ throw ArgParseException(errMsg);
+ }
+
+ ssize strLeft = str.size - offset;
+ if(strLeft > 0)
+ {
+ StringView substrView(str.data + offset, strLeft);
+ string substr = stringRemoveQuotes(substrView);
+ if(!substr.empty())
+ result.emplace_back(move(substr));
+ }
+ return result;
+ }
+
+ void Chatbar::processChatCommand(const StringView &cmd)
+ {
+ vector<string> args;
+ try
+ {
+ args = splitCommandArgs(cmd);
+ }
+ catch(ArgParseException &e)
+ {
+ fprintf(stderr, "Failed to parse command arguments, reason: %s\n", e.what());
+ return;
+ }
+
+ if(!args.empty())
+ {
+ string command = args.front();
+ args.erase(args.begin());
+ if(!Command::call(command, args))
+ fprintf(stderr, "No such command: %s\n", command.c_str());
+ }
+ }
+
+ string getClipboard()
+ {
+ string result;
+ TinyProcessLib::Process process("xsel -o -b", "", [&result](const char *bytes, size_t n)
+ {
+ result.append(bytes, n);
+ });
+ if(process.get_exit_status() != 0)
+ fprintf(stderr, "Failed to get clipboard content\n");
+ return result;
+ }
+
void Chatbar::processEvent(const sf::Event &event, Channel *channel)
{
if(!focused) return;
@@ -114,7 +232,10 @@ namespace dchat
string msg;
msg.resize(chatbarMsgUtf8.size());
memcpy(&msg[0], chatbarMsgUtf8.data(), chatbarMsgUtf8.size());
- channel->getMessageBoard().addMessage(new Message(channel->getLocalUser(), msg));
+ if(msg[0] == '/')
+ processChatCommand(StringView(msg.data() + 1, msg.size() - 1));
+ else
+ channel->getMessageBoard().addMessage(new Message(channel->getLocalUser(), msg));
clear();
}
}
@@ -123,6 +244,12 @@ namespace dchat
{
removeNextChar();
}
+ else if(event.text.unicode == 22) // ctrl+v
+ {
+ // TODO: Instead of calling external xsel, use sfml clipboard functionality (in new sfml version)
+ string clipboard = getClipboard();
+ addString(clipboard);
+ }
else
{
addChar(event.text.unicode);
@@ -137,12 +264,12 @@ namespace dchat
}
}
- void Chatbar::draw(sf::RenderWindow &window, const sf::Vector2f &position)
+ void Chatbar::draw(sf::RenderWindow &window)
{
auto windowSize = window.getSize();
- sf::Vector2f backgroundSize(floor(windowSize.x * 0.7f), floor(text.getCharacterSize() * 1.7f + BOX_PADDING_Y * 2.0f));
- sf::Vector2f backgroundPos(floor(position.x), floor(position.y + windowSize.y - backgroundSize.y - 20.0f));
+ sf::Vector2f backgroundSize(floor(windowSize.x - ChannelSidePanel::getWidth() - UsersSidePanel::getWidth() - PADDING_SIDE * 2.0f), floor(text.getCharacterSize() * 1.7f + BOX_PADDING_Y * 2.0f));
+ sf::Vector2f backgroundPos(floor(ChannelSidePanel::getWidth() + PADDING_SIDE), floor(windowSize.y - backgroundSize.y - 20.0f));
background.setSize(backgroundSize);
background.setPosition(backgroundPos);
text.setPosition(floor(backgroundPos.x + BOX_PADDING_X), floor(backgroundPos.y + backgroundSize.y * 0.5f - text.getCharacterSize() * 0.5f));
diff --git a/src/Command.cpp b/src/Command.cpp
new file mode 100644
index 0000000..a074930
--- /dev/null
+++ b/src/Command.cpp
@@ -0,0 +1,37 @@
+#include "../include/Command.hpp"
+#include <unordered_map>
+
+using namespace std;
+
+namespace dchat
+{
+ unordered_map<string, CommandHandlerFunc> commandHandlerFuncs;
+
+ bool Command::add(const string &cmd, CommandHandlerFunc handlerFunc)
+ {
+ auto it = commandHandlerFuncs.find(cmd);
+ if(it != commandHandlerFuncs.end())
+ return false;
+
+ commandHandlerFuncs[cmd] = handlerFunc;
+ return true;
+ }
+
+ bool Command::call(const string &cmd, const vector<string> &args)
+ {
+ auto it = commandHandlerFuncs.find(cmd);
+ if(it != commandHandlerFuncs.end())
+ {
+ try
+ {
+ it->second(args);
+ }
+ catch(exception &e)
+ {
+ fprintf(stderr, "Failed while executing command %s, reason: %s\n", cmd.c_str(), e.what());
+ }
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/src/MessageBoard.cpp b/src/MessageBoard.cpp
index 4cab31d..a0d1ab2 100644
--- a/src/MessageBoard.cpp
+++ b/src/MessageBoard.cpp
@@ -2,6 +2,8 @@
#include "../include/Settings.hpp"
#include "../include/ResourceCache.hpp"
#include "../include/Gif.hpp"
+#include "../include/ChannelSidePanel.hpp"
+#include "../include/UsersSidePanel.hpp"
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Window/Mouse.hpp>
@@ -17,6 +19,8 @@ namespace dchat
const float USERNAME_PADDING_BOTTOM = 0.0f;
const float MESSAGE_PADDING_BOTTOM = 20.0f;
+ const float PADDING_SIDE = 20.0f;
+
MessageBoard::MessageBoard(const sf::Vector2u &size) :
selectingText(false),
leftMouseButtonPressed(false),
@@ -93,10 +97,10 @@ namespace dchat
}
}
- void MessageBoard::draw(sf::RenderWindow &window, const sf::Vector2f &pos, Cache &cache)
+ void MessageBoard::draw(sf::RenderWindow &window, Cache &cache)
{
auto windowSize = window.getSize();
- sf::Vector2u backgroundSize(floor(windowSize.x - pos.x * 2.0f), floor(windowSize.y));
+ sf::Vector2u backgroundSize(floor(windowSize.x - ChannelSidePanel::getWidth() - UsersSidePanel::getWidth() - PADDING_SIDE * 2.0f), floor(windowSize.y));
//if(backgroundSize != staticContentTexture.getSize())
// updateStaticContentTexture(backgroundSize);
@@ -116,8 +120,8 @@ namespace dchat
if(dirty)
{
- sf::Vector2f position = pos;
- position.x += 20.0f;
+ sf::Vector2f position;
+ position.x = ChannelSidePanel::getWidth() + PADDING_SIDE;
position.y += scroll;
for(Message *message : messages)
{
diff --git a/src/UsersSidePanel.cpp b/src/UsersSidePanel.cpp
new file mode 100644
index 0000000..5af01bc
--- /dev/null
+++ b/src/UsersSidePanel.cpp
@@ -0,0 +1,47 @@
+#include "../include/UsersSidePanel.hpp"
+#include "../include/ResourceCache.hpp"
+#include "../include/Settings.hpp"
+#include <SFML/Graphics/RectangleShape.hpp>
+#include <SFML/Graphics/Text.hpp>
+#include <vector>
+#include <cmath>
+
+using namespace std;
+
+namespace dchat
+{
+ vector<User*> users;
+ const float width = 200.0f;
+ const unsigned int FONT_SIZE = 20;
+
+ void UsersSidePanel::addUser(User *user)
+ {
+ users.push_back(user);
+ }
+
+ void UsersSidePanel::draw(sf::RenderWindow &window)
+ {
+ auto windowSize = window.getSize();
+ sf::RectangleShape rect(sf::Vector2f(width, windowSize.y));
+ rect.setFillColor(sf::Color(30, 30, 30));
+ rect.setPosition(windowSize.x - width, 0.0f);
+ window.draw(rect);
+
+ const sf::Font &font = ResourceCache::getFont("fonts/Roboto-Regular.ttf");
+ sf::Vector2f position(rect.getPosition().x + 10.0f, 10.0f);
+ for(User *user : users)
+ {
+ // TODO: Remove this shit
+ sf::String str = sf::String::fromUtf8(user->getName().begin(), user->getName().end());
+ sf::Text text(str, font, FONT_SIZE * Settings::getScaling());
+ text.setPosition(position);
+ window.draw(text);
+ position.y += font.getLineSpacing(FONT_SIZE * Settings::getScaling());
+ }
+ }
+
+ float UsersSidePanel::getWidth()
+ {
+ return width;
+ }
+}
diff --git a/src/main.cpp b/src/main.cpp
index 3cebfe7..52a19b9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,18 +1,48 @@
#include "../include/Channel.hpp"
#include "../include/ChannelSidePanel.hpp"
+#include "../include/UsersSidePanel.hpp"
#include "../include/Cache.hpp"
#include "../include/ResourceCache.hpp"
#include "../include/Video.hpp"
+#include "../include/Command.hpp"
#include <string>
#include <SFML/Graphics.hpp>
#include <cstring>
-#include <X11/Xlib.h>
#include <boost/filesystem/path.hpp>
+#include <odhtdb/Database.hpp>
+#include <odhtdb/Signature.hpp>
+#include <odhtdb/bin2hex.hpp>
+#include <odhtdb/hex2bin.hpp>
+#include <X11/Xlib.h>
using namespace std;
using namespace dchat;
using namespace TinyProcessLib;
+string createChannelJoinKey(const unique_ptr<odhtdb::DatabaseCreateResponse> &databaseCreateResponse)
+{
+ string result;
+ result += databaseCreateResponse->getRequestHash()->toString();
+ result += "&";
+ result += odhtdb::bin2hex((const char*)databaseCreateResponse->getNodeEncryptionKey()->data, databaseCreateResponse->getNodeEncryptionKey()->size);
+ return result;
+}
+
+odhtdb::DatabaseNode createDatabaseNodeFromJoinKey(const string &joinKey)
+{
+ odhtdb::DatabaseNode result;
+
+ string nodeHashStr = odhtdb::hex2bin(joinKey.c_str(), 64);
+ memcpy(result.getRequestHash()->getData(), nodeHashStr.data(), nodeHashStr.size());
+
+ string nodeEncryptionKeyStr = odhtdb::hex2bin(joinKey.c_str() + 65, 64);
+ char *nodeEncryptionKeyRaw = new char[nodeEncryptionKeyStr.size()];
+ result.getNodeEncryptionKey()->data = nodeEncryptionKeyRaw;
+ result.getNodeEncryptionKey()->size = nodeEncryptionKeyStr.size();
+
+ return result;
+}
+
int main(int argc, char **argv)
{
/*
@@ -27,14 +57,138 @@ int main(int argc, char **argv)
window.setVerticalSyncEnabled(false);
window.setFramerateLimit(60);
- //odhtdb::Database database("bootstrap.ring.cx", 4222, Cache::getDchatDir());
+ odhtdb::Database database("bootstrap.ring.cx", 4222, Cache::getDchatDir());
+
+ database.setOnCreateNodeCallback([](const odhtdb::DatabaseCreateNodeRequest &request)
+ {
+
+ });
+
+ database.setOnAddNodeCallback([](const odhtdb::DatabaseAddNodeRequest &request)
+ {
+
+ });
+
+ database.setOnAddUserCallback([](const odhtdb::DatabaseAddUserRequest &request)
+ {
+
+ });
//Video video(500, 500, "https://www.youtube.com/watch?v=bs0-EX9mJmg");
Cache cache;
Channel channel("latenightshiendjs");
- ChannelSidePanel channelSidePanel(300.0f);
- channelSidePanel.addChannel(&channel);
+ ChannelSidePanel::addChannel(&channel);
+ UsersSidePanel::addUser(channel.getLocalUser());
+
+ odhtdb::Signature::KeyPair *currentUserKeyPair = nullptr;
+ vector<odhtdb::NodeLocalUser> localNodeUsers;
+ string currentUserName;
+ string currentUserPassword;
+
+ Command::add("login", [&currentUserKeyPair, &currentUserName, &currentUserPassword, &localNodeUsers, &database](const vector<string> &args)
+ {
+ if(args.size() != 2)
+ {
+ fprintf(stderr, "Expected 2 arguments for command login (username and password), got %u argument(s)\n", args.size());
+ return;
+ }
+
+ try
+ {
+ odhtdb::Signature::KeyPair keyPair = database.getStorage().decryptLocalEncryptedUser(args[0], args[1]);
+ localNodeUsers = database.getStorage().getLocalNodeUsers(keyPair);
+
+ for(auto localNodeUser : localNodeUsers)
+ {
+ //const odhtdb::DatabaseStorageObjectList *nodeStorage = database.getStorage().getStorage(localNodeUser.nodeHash);
+ //Channel *channel = new Channel()
+ }
+
+ printf("Successfully logged into user %s\n", args[0].c_str());
+ if(currentUserKeyPair)
+ delete currentUserKeyPair;
+ currentUserKeyPair = new odhtdb::Signature::KeyPair(keyPair);
+
+ currentUserName = args[0];
+ currentUserPassword = args[1];
+ }
+ catch(odhtdb::DatabaseStorageException &e)
+ {
+ fprintf(stderr, "Failed to login, reason: %s\n", e.what());
+ }
+ });
+
+ Command::add("register", [&currentUserKeyPair, &currentUserName, &currentUserPassword, &database](const vector<string> &args)
+ {
+ if(args.size() != 2)
+ {
+ fprintf(stderr, "Expected 2 arguments for command register (username and password), got %u argument(s)\n", args.size());
+ return;
+ }
+
+ odhtdb::Signature::KeyPair keyPair;
+ if(!database.getStorage().storeLocalUser(args[0], keyPair, args[1]))
+ {
+ fprintf(stderr, "User with name %s already exists in storage\n", args[0].c_str());
+ return;
+ }
+
+ printf("Registered user %s, public key: %s, private key: %s\n", args[0].c_str(), keyPair.getPublicKey().toString().c_str(), keyPair.getPrivateKey().toString().c_str());
+ printf("Successfully logged into user %s\n", args[0].c_str());
+
+ if(currentUserKeyPair)
+ delete currentUserKeyPair;
+ currentUserKeyPair = new odhtdb::Signature::KeyPair(keyPair);
+
+ currentUserName = args[0];
+ currentUserPassword = args[1];
+ });
+
+ Command::add("cc", [&currentUserKeyPair, &currentUserName, &database](const vector<string> &args)
+ {
+ if(args.size() != 1)
+ {
+ fprintf(stderr, "Expected 1 argument for command cc (channel name), got %u argument(s)\n", args.size());
+ return;
+ }
+
+ if(!currentUserKeyPair)
+ {
+ fprintf(stderr, "You are not logged in. Please login before creating a channel\n");
+ return;
+ }
+
+ auto createResponse = database.create(currentUserName, *currentUserKeyPair, args[0]);
+ database.commit();
+ odhtdb::DatabaseNode databaseNode(createResponse->getNodeEncryptionKey(), createResponse->getRequestHash());
+ database.seed(databaseNode);
+ printf("Created database '%s', join key: '%s'\n", args[0].c_str(), createChannelJoinKey(createResponse).c_str());
+ });
+
+ Command::add("jc", [&currentUserKeyPair, &database](const vector<string> &args)
+ {
+ if(args.size() != 1)
+ {
+ fprintf(stderr, "Expected 1 argument for command jc (channel join key), got %u argument(s)\n", args.size());
+ return;
+ }
+
+ if(args[0].size() != 129)
+ {
+ fprintf(stderr, "Expected join key to be 129 characters, was %u character(s)\n", args[0].size());
+ return;
+ }
+
+ if(!currentUserKeyPair)
+ {
+ fprintf(stderr, "You are not logged in. Please login before joining a channel\n");
+ return;
+ }
+
+ odhtdb::DatabaseNode databaseNode = createDatabaseNodeFromJoinKey(args[0]);
+ database.seed(databaseNode);
+ });
sf::Event event;
while (window.isOpen())
@@ -60,8 +214,7 @@ int main(int argc, char **argv)
}
window.clear(sf::Color(40, 40, 40));
- channel.draw(window, sf::Vector2f(channelSidePanel.width, 0.0f), cache);
- channelSidePanel.draw(window);
+ channel.draw(window, cache);
//video.draw(window);
window.display();
}