Compare commits
16 Commits
font_from_
...
53ae3f8ce5
Author | SHA1 | Date | |
---|---|---|---|
53ae3f8ce5 | |||
b5e90528f0 | |||
22071b60e6 | |||
5283df7b98 | |||
21243ea979 | |||
1d212c5fab | |||
37239f1c25 | |||
780e1e06d4 | |||
7c227457cd | |||
5544adf345 | |||
6d3ef742b5 | |||
cba3282dce | |||
5c5e830f0f | |||
e08dbba940 | |||
752f2ebe2c | |||
a47d607a8d |
4
.github/workflows/cd.yml
vendored
4
.github/workflows/cd.yml
vendored
@ -153,7 +153,7 @@ jobs:
|
||||
git pull
|
||||
|
||||
- name: Install Dependencies
|
||||
run: vcpkg install libsodium:x64-windows-static pthreads:x64-windows-static pkgconf:x64-windows
|
||||
run: vcpkg install pkgconf:x64-windows libsodium:x64-windows-static pthreads:x64-windows-static opus:x64-windows-static libvpx:x64-windows-static
|
||||
|
||||
# setup vs env
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
@ -212,7 +212,7 @@ jobs:
|
||||
git pull
|
||||
|
||||
- name: Install Dependencies
|
||||
run: vcpkg install libsodium:x64-windows-static pthreads:x64-windows-static pkgconf:x64-windows
|
||||
run: vcpkg install pkgconf:x64-windows libsodium:x64-windows-static pthreads:x64-windows-static opus:x64-windows-static libvpx:x64-windows-static
|
||||
|
||||
# setup vs env
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
|
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -129,7 +129,7 @@ jobs:
|
||||
git pull
|
||||
|
||||
- name: Install Dependencies
|
||||
run: vcpkg install libsodium:x64-windows-static pthreads:x64-windows-static pkgconf:x64-windows
|
||||
run: vcpkg install pkgconf:x64-windows libsodium:x64-windows-static pthreads:x64-windows-static opus:x64-windows-static libvpx:x64-windows-static
|
||||
|
||||
# setup vs env
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
|
@ -96,14 +96,11 @@
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||
</intent-filter>
|
||||
<!-- Drop file event -->
|
||||
<!--
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="*/*" />
|
||||
</intent-filter>
|
||||
-->
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
2
external/solanaceae_contact
vendored
2
external/solanaceae_contact
vendored
Submodule external/solanaceae_contact updated: e8b069c803...2401079c1d
2
external/solanaceae_object_store
vendored
2
external/solanaceae_object_store
vendored
Submodule external/solanaceae_object_store updated: be24b3815b...bccf7680e6
2
external/solanaceae_util
vendored
2
external/solanaceae_util
vendored
Submodule external/solanaceae_util updated: 4bda751f76...17d2baf736
6
flake.lock
generated
6
flake.lock
generated
@ -20,11 +20,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1718111384,
|
||||
"narHash": "sha256-7tSst0S5FOmcgvNtfy6cjZX5w8CabCVAfAeCkhY4OVg=",
|
||||
"lastModified": 1720691131,
|
||||
"narHash": "sha256-CWT+KN8aTPyMIx8P303gsVxUnkinIz0a/Cmasz1jyIM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a508a44af0c1b1b57785c34d8b54783536273eeb",
|
||||
"rev": "a046c1202e11b62cbede5385ba64908feb7bfac4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -75,11 +75,16 @@
|
||||
#(libsodium.override { stdenv = pkgs.pkgsStatic.stdenv; })
|
||||
#pkgsStatic.libsodium
|
||||
libsodium
|
||||
libopus
|
||||
libvpx
|
||||
] ++ self.packages.${system}.default.dlopenBuildInputs;
|
||||
|
||||
cmakeFlags = [
|
||||
"-DTOMATO_ASAN=OFF"
|
||||
"-DCMAKE_BUILD_TYPE=RelWithDebInfo"
|
||||
#"-DCMAKE_BUILD_TYPE=Debug"
|
||||
#"-DCMAKE_C_FLAGS:STRING=-Og"
|
||||
#"-DCMAKE_CXX_FLAGS:STRING=-Og"
|
||||
|
||||
"-DFETCHCONTENT_SOURCE_DIR_JSON=${nlohmann-json}" # we care about the version
|
||||
# TODO: use package instead
|
||||
|
@ -67,6 +67,16 @@ target_sources(tomato PUBLIC
|
||||
|
||||
./chat_gui/theme.hpp
|
||||
./chat_gui/theme.cpp
|
||||
./chat_gui/icons/direct.hpp
|
||||
./chat_gui/icons/direct.cpp
|
||||
./chat_gui/icons/cloud.hpp
|
||||
./chat_gui/icons/cloud.cpp
|
||||
./chat_gui/icons/mail.hpp
|
||||
./chat_gui/icons/mail.cpp
|
||||
./chat_gui/icons/person.hpp
|
||||
./chat_gui/icons/person.cpp
|
||||
./chat_gui/icons/group.hpp
|
||||
./chat_gui/icons/group.cpp
|
||||
./chat_gui/contact_list.hpp
|
||||
./chat_gui/contact_list.cpp
|
||||
./chat_gui/file_selector.hpp
|
||||
|
@ -1,139 +1,16 @@
|
||||
#include "./contact_list.hpp"
|
||||
|
||||
#include <solanaceae/contact/components.hpp>
|
||||
#include <solanaceae/util/utils.hpp>
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
//#include <imgui/imgui_internal.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
static void drawIconDirectLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
// arrow 1
|
||||
// (3,1) -> (9,7)
|
||||
PLINE(0.3f, 0.1f, 0.9f, 0.7f)
|
||||
// (9,7) -> (9,5)
|
||||
PLINE(0.9f, 0.7f, 0.9f, 0.5f)
|
||||
// (9,7) -> (7,7)
|
||||
PLINE(0.9f, 0.7f, 0.7f, 0.7f)
|
||||
|
||||
// arrow 2
|
||||
// (7,9) -> (1,3)
|
||||
PLINE(0.7f, 0.9f, 0.1f, 0.3f)
|
||||
// (1,3) -> (3,3)
|
||||
PLINE(0.1f, 0.3f, 0.3f, 0.3f)
|
||||
// (1,3) -> (1,5)
|
||||
PLINE(0.1f, 0.3f, 0.1f, 0.5f)
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
static void drawIconDirect(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
drawIconDirectLines(p0, p1_o, col_back, 4.0f);
|
||||
drawIconDirectLines(p0, p1_o, col_main, 1.5f);
|
||||
}
|
||||
|
||||
static void drawIconCloud(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
std::array<ImVec2, 19> points {{
|
||||
{0.2f, 0.9f},
|
||||
{0.8f, 0.9f},
|
||||
{0.9f, 0.8f},
|
||||
{0.9f, 0.7f},
|
||||
{0.7f, 0.7f},
|
||||
{0.9f, 0.5f},
|
||||
{0.9f, 0.4f},
|
||||
{0.8f, 0.2f},
|
||||
{0.6f, 0.2f},
|
||||
{0.5f, 0.3f},
|
||||
{0.5f, 0.5f},
|
||||
{0.4f, 0.4f},
|
||||
{0.3f, 0.4f},
|
||||
{0.2f, 0.5f},
|
||||
{0.2f, 0.6f},
|
||||
{0.3f, 0.7f},
|
||||
{0.1f, 0.7f},
|
||||
{0.1f, 0.8f},
|
||||
{0.2f, 0.9f},
|
||||
}};
|
||||
for (auto& v : points) {
|
||||
v.y -= 0.1f;
|
||||
v = {p0.x + p1_o.x*v.x, p0.y + p1_o.y*v.y};
|
||||
}
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
ImGui::GetWindowDrawList()->AddPolyline(points.data(), points.size(), col_back, ImDrawFlags_None, 4.f);
|
||||
ImGui::GetWindowDrawList()->AddPolyline(points.data(), points.size(), col_main, ImDrawFlags_None, 1.5f);
|
||||
}
|
||||
|
||||
static void drawIconMailLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
// quad
|
||||
// (1,2) -> (1,8)
|
||||
PLINE(0.1f, 0.2f, 0.1f, 0.8f)
|
||||
// (1,8) -> (9,8)
|
||||
PLINE(0.1f, 0.8f, 0.9f, 0.8f)
|
||||
// (9,8) -> (9,2)
|
||||
PLINE(0.9f, 0.8f, 0.9f, 0.2f)
|
||||
// (9,2) -> (1,2)
|
||||
PLINE(0.9f, 0.2f, 0.1f, 0.2f)
|
||||
|
||||
// lip
|
||||
// (1,2) -> (5,5)
|
||||
PLINE(0.1f, 0.2f, 0.5f, 0.5f)
|
||||
// (5,5) -> (9,2)
|
||||
PLINE(0.5f, 0.5f, 0.9f, 0.2f)
|
||||
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
static void drawIconMail(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
drawIconMailLines(p0, p1_o, col_back, 4.0f);
|
||||
drawIconMailLines(p0, p1_o, col_main, 1.5f);
|
||||
}
|
||||
#include "./icons/direct.hpp"
|
||||
#include "./icons/cloud.hpp"
|
||||
#include "./icons/mail.hpp"
|
||||
#include "./icons/person.hpp"
|
||||
#include "./icons/group.hpp"
|
||||
|
||||
void renderAvatar(
|
||||
const Theme& th,
|
||||
@ -220,6 +97,11 @@ bool renderContactBig(
|
||||
|
||||
const auto* cstate = c.try_get<Contact::Components::ConnectionState>();
|
||||
if (ImGui::BeginItemTooltip()) {
|
||||
if (c.all_of<Contact::Components::ID>()) {
|
||||
const auto id_str = bin2hex(c.get<Contact::Components::ID>().data);
|
||||
ImGui::Text("ID: %s", id_str.c_str());
|
||||
}
|
||||
|
||||
if (cstate != nullptr) {
|
||||
ImGui::Text("Connection state: %s",
|
||||
(cstate->state == Contact::Components::ConnectionState::disconnected)
|
||||
@ -264,6 +146,9 @@ bool renderContactBig(
|
||||
ImGui::SameLine(0.f, same_line_spacing);
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
const bool is_group = c.all_of<Contact::Components::TagGroup>();
|
||||
const bool is_private = c.all_of<Contact::Components::TagPrivate>();
|
||||
|
||||
{ // line 1
|
||||
if (line_height == 1 && cstate != nullptr) {
|
||||
// icon pos
|
||||
@ -271,6 +156,8 @@ bool renderContactBig(
|
||||
p0.y += ImGui::GetStyle().FramePadding.y;
|
||||
ImVec2 p1_o = {img_y, img_y}; // img_y is 1 line_height in this case
|
||||
|
||||
ImGui::Dummy(p1_o);
|
||||
if (ImGui::IsItemVisible()) {
|
||||
const ImU32 col_back = ImGui::GetColorU32(th.getColor<ThemeCol_Contact::icon_backdrop>());
|
||||
if (cstate->state == Contact::Components::ConnectionState::direct) { // direct icon
|
||||
drawIconDirect(
|
||||
@ -287,7 +174,34 @@ bool renderContactBig(
|
||||
col_back
|
||||
);
|
||||
}
|
||||
}
|
||||
ImGui::SameLine(0.f, same_line_spacing);
|
||||
}
|
||||
|
||||
// we dont render group/private in 1lh mode
|
||||
if (line_height != 1 && (is_private || is_group)) {
|
||||
// icon pos
|
||||
auto p0 = ImGui::GetCursorScreenPos();
|
||||
p0.y += ImGui::GetStyle().FramePadding.y;
|
||||
const float box_hight = TEXT_BASE_HEIGHT - ImGui::GetStyle().FramePadding.y*2;
|
||||
ImVec2 p1_o = {box_hight, box_hight};
|
||||
|
||||
ImGui::Dummy(p1_o);
|
||||
if (ImGui::IsItemVisible()) {
|
||||
if (is_private) {
|
||||
drawIconPerson(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_Text))
|
||||
);
|
||||
} else if (is_group) {
|
||||
drawIconGroup(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_Text))
|
||||
);
|
||||
}
|
||||
}
|
||||
ImGui::SameLine(0.f, same_line_spacing);
|
||||
}
|
||||
|
||||
@ -327,6 +241,8 @@ bool renderContactBig(
|
||||
const float box_hight = TEXT_BASE_HEIGHT - ImGui::GetStyle().FramePadding.y*2;
|
||||
ImVec2 p1_o = {box_hight, box_hight};
|
||||
|
||||
ImGui::Dummy(p1_o);
|
||||
if (ImGui::IsItemVisible()) {
|
||||
const ImU32 col_back = ImGui::GetColorU32(th.getColor<ThemeCol_Contact::icon_backdrop>());
|
||||
if (cstate->state == Contact::Components::ConnectionState::direct) { // direct icon
|
||||
drawIconDirect(
|
||||
@ -343,7 +259,7 @@ bool renderContactBig(
|
||||
col_back
|
||||
);
|
||||
}
|
||||
ImGui::Dummy(p1_o);
|
||||
}
|
||||
ImGui::SameLine(0.f, same_line_spacing);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
void FileSelector::reset(void) {
|
||||
_is_valid = [](auto){ return true; };
|
||||
|
41
src/chat_gui/icons/cloud.cpp
Normal file
41
src/chat_gui/icons/cloud.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include "./cloud.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
void drawIconCloud(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
std::array<ImVec2, 19> points {{
|
||||
{0.2f, 0.9f},
|
||||
{0.8f, 0.9f},
|
||||
{0.9f, 0.8f},
|
||||
{0.9f, 0.7f},
|
||||
{0.7f, 0.7f},
|
||||
{0.9f, 0.5f},
|
||||
{0.9f, 0.4f},
|
||||
{0.8f, 0.2f},
|
||||
{0.6f, 0.2f},
|
||||
{0.5f, 0.3f},
|
||||
{0.5f, 0.5f},
|
||||
{0.4f, 0.4f},
|
||||
{0.3f, 0.4f},
|
||||
{0.2f, 0.5f},
|
||||
{0.2f, 0.6f},
|
||||
{0.3f, 0.7f},
|
||||
{0.1f, 0.7f},
|
||||
{0.1f, 0.8f},
|
||||
{0.2f, 0.9f},
|
||||
}};
|
||||
for (auto& v : points) {
|
||||
v.y -= 0.1f;
|
||||
v = {p0.x + p1_o.x*v.x, p0.y + p1_o.y*v.y};
|
||||
}
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
ImGui::GetWindowDrawList()->AddPolyline(points.data(), points.size(), col_back, ImDrawFlags_None, 4.f);
|
||||
ImGui::GetWindowDrawList()->AddPolyline(points.data(), points.size(), col_main, ImDrawFlags_None, 1.5f);
|
||||
}
|
||||
|
11
src/chat_gui/icons/cloud.hpp
Normal file
11
src/chat_gui/icons/cloud.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
void drawIconCloud(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
);
|
||||
|
49
src/chat_gui/icons/direct.cpp
Normal file
49
src/chat_gui/icons/direct.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "./direct.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
static void drawIconDirectLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
// arrow 1
|
||||
// (3,1) -> (9,7)
|
||||
PLINE(0.3f, 0.1f, 0.9f, 0.7f)
|
||||
// (9,7) -> (9,5)
|
||||
PLINE(0.9f, 0.7f, 0.9f, 0.5f)
|
||||
// (9,7) -> (7,7)
|
||||
PLINE(0.9f, 0.7f, 0.7f, 0.7f)
|
||||
|
||||
// arrow 2
|
||||
// (7,9) -> (1,3)
|
||||
PLINE(0.7f, 0.9f, 0.1f, 0.3f)
|
||||
// (1,3) -> (3,3)
|
||||
PLINE(0.1f, 0.3f, 0.3f, 0.3f)
|
||||
// (1,3) -> (1,5)
|
||||
PLINE(0.1f, 0.3f, 0.1f, 0.5f)
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
void drawIconDirect(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
drawIconDirectLines(p0, p1_o, col_back, 4.0f);
|
||||
drawIconDirectLines(p0, p1_o, col_main, 1.5f);
|
||||
}
|
||||
|
10
src/chat_gui/icons/direct.hpp
Normal file
10
src/chat_gui/icons/direct.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
void drawIconDirect(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
);
|
139
src/chat_gui/icons/group.cpp
Normal file
139
src/chat_gui/icons/group.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
#include "./group.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
static void drawIconGroupLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
// person front
|
||||
// x y
|
||||
PLINE(
|
||||
0.1f, 0.9f,
|
||||
0.6f, 0.9f
|
||||
)
|
||||
PLINE(
|
||||
0.6f, 0.9f,
|
||||
0.6f, 0.7f
|
||||
)
|
||||
PLINE(
|
||||
0.6f, 0.7f,
|
||||
0.5f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.5f, 0.6f,
|
||||
0.4f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.4f, 0.6f,
|
||||
0.5f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.5f, 0.5f,
|
||||
0.5f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.5f, 0.4f,
|
||||
0.4f, 0.3f
|
||||
)
|
||||
PLINE(
|
||||
0.4f, 0.3f,
|
||||
0.3f, 0.3f
|
||||
)
|
||||
PLINE(
|
||||
0.3f, 0.3f,
|
||||
0.2f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.2f, 0.4f,
|
||||
0.2f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.2f, 0.5f,
|
||||
0.3f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.3f, 0.6f,
|
||||
0.2f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.2f, 0.6f,
|
||||
0.1f, 0.7f
|
||||
)
|
||||
PLINE(
|
||||
0.1f, 0.7f,
|
||||
0.1f, 0.9f
|
||||
)
|
||||
|
||||
// person back
|
||||
// x y
|
||||
PLINE(
|
||||
0.7f, 0.7f,
|
||||
0.9f, 0.7f
|
||||
)
|
||||
PLINE(
|
||||
0.9f, 0.7f,
|
||||
0.9f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.9f, 0.5f,
|
||||
0.8f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.8f, 0.4f,
|
||||
0.7f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.7f, 0.4f,
|
||||
0.8f, 0.3f
|
||||
)
|
||||
PLINE(
|
||||
0.8f, 0.3f,
|
||||
0.8f, 0.2f
|
||||
)
|
||||
PLINE(
|
||||
0.8f, 0.2f,
|
||||
0.7f, 0.1f
|
||||
)
|
||||
PLINE(
|
||||
0.7f, 0.1f,
|
||||
0.6f, 0.1f
|
||||
)
|
||||
PLINE(
|
||||
0.6f, 0.1f,
|
||||
0.5f, 0.2f
|
||||
)
|
||||
PLINE(
|
||||
0.5f, 0.2f,
|
||||
0.5f, 0.3f
|
||||
)
|
||||
PLINE(
|
||||
0.5f, 0.3f,
|
||||
0.6f, 0.4f
|
||||
)
|
||||
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
void drawIconGroup(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
//drawIconGroupLines(p0, p1_o, col_back, 3.5f);
|
||||
drawIconGroupLines(p0, p1_o, col_main, 1.0f);
|
||||
}
|
||||
|
10
src/chat_gui/icons/group.hpp
Normal file
10
src/chat_gui/icons/group.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
void drawIconGroup(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main
|
||||
);
|
||||
|
50
src/chat_gui/icons/mail.cpp
Normal file
50
src/chat_gui/icons/mail.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "./mail.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
static void drawIconMailLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
// quad
|
||||
// (1,2) -> (1,8)
|
||||
PLINE(0.1f, 0.2f, 0.1f, 0.8f)
|
||||
// (1,8) -> (9,8)
|
||||
PLINE(0.1f, 0.8f, 0.9f, 0.8f)
|
||||
// (9,8) -> (9,2)
|
||||
PLINE(0.9f, 0.8f, 0.9f, 0.2f)
|
||||
// (9,2) -> (1,2)
|
||||
PLINE(0.9f, 0.2f, 0.1f, 0.2f)
|
||||
|
||||
// lip
|
||||
// (1,2) -> (5,5)
|
||||
PLINE(0.1f, 0.2f, 0.5f, 0.5f)
|
||||
// (5,5) -> (9,2)
|
||||
PLINE(0.5f, 0.5f, 0.9f, 0.2f)
|
||||
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
void drawIconMail(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
drawIconMailLines(p0, p1_o, col_back, 4.0f);
|
||||
drawIconMailLines(p0, p1_o, col_main, 1.5f);
|
||||
}
|
||||
|
11
src/chat_gui/icons/mail.hpp
Normal file
11
src/chat_gui/icons/mail.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
void drawIconMail(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
);
|
||||
|
101
src/chat_gui/icons/person.cpp
Normal file
101
src/chat_gui/icons/person.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include "./person.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
static void drawIconPersonLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
//// quad
|
||||
//// (1,2) -> (1,8)
|
||||
//PLINE(0.1f, 0.2f, 0.1f, 0.8f)
|
||||
//// (1,8) -> (9,8)
|
||||
//PLINE(0.1f, 0.8f, 0.9f, 0.8f)
|
||||
//// (9,8) -> (9,2)
|
||||
//PLINE(0.9f, 0.8f, 0.9f, 0.2f)
|
||||
//// (9,2) -> (1,2)
|
||||
//PLINE(0.9f, 0.2f, 0.1f, 0.2f)
|
||||
|
||||
// x y
|
||||
PLINE(
|
||||
0.2f, 0.8f,
|
||||
0.8f, 0.8f
|
||||
)
|
||||
PLINE(
|
||||
0.8f, 0.8f,
|
||||
0.8f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.8f, 0.6f,
|
||||
0.7f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.7f, 0.5f,
|
||||
0.6f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.6f, 0.5f,
|
||||
0.7f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.7f, 0.4f,
|
||||
0.7f, 0.2f
|
||||
)
|
||||
PLINE(
|
||||
0.7f, 0.2f,
|
||||
0.6f, 0.1f
|
||||
)
|
||||
PLINE(
|
||||
0.6f, 0.1f,
|
||||
0.4f, 0.1f
|
||||
)
|
||||
PLINE(
|
||||
0.4f, 0.1f,
|
||||
0.3f, 0.2f
|
||||
)
|
||||
PLINE(
|
||||
0.3f, 0.2f,
|
||||
0.3f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.3f, 0.4f,
|
||||
0.4f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.4f, 0.5f,
|
||||
0.3f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.3f, 0.5f,
|
||||
0.2f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.2f, 0.6f,
|
||||
0.2f, 0.8f
|
||||
)
|
||||
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
void drawIconPerson(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
//drawIconPersonLines(p0, p1_o, col_back, 3.5f);
|
||||
drawIconPersonLines(p0, p1_o, col_main, 1.0f);
|
||||
}
|
||||
|
10
src/chat_gui/icons/person.hpp
Normal file
10
src/chat_gui/icons/person.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
void drawIconPerson(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main
|
||||
);
|
||||
|
@ -63,6 +63,28 @@ static constexpr float lerp(float a, float b, float t) {
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
// returns divider and places static suffix string into suffix_out
|
||||
static int64_t sizeToHumanReadable(int64_t file_size, const char*& suffix_out) {
|
||||
static const char* suffix_arr[] {
|
||||
"bytes",
|
||||
"KiB",
|
||||
"MiB",
|
||||
"GiB",
|
||||
"TiB",
|
||||
"PiB",
|
||||
// TODO: fix upper bound behaviour
|
||||
};
|
||||
int64_t divider = 1024;
|
||||
for (size_t ij = 0; ij < std::size(suffix_arr); ij++, divider *= 1024) {
|
||||
if (file_size < divider) {
|
||||
suffix_out = suffix_arr[ij];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (divider > 1024) ? (divider / 1024) : 1;
|
||||
}
|
||||
|
||||
static std::string file_path_url_escape(const std::string&& value) {
|
||||
std::ostringstream escaped;
|
||||
|
||||
@ -817,6 +839,7 @@ void ChatGui4::sendFilePath(const char* file_path) {
|
||||
void ChatGui4::renderMessageBodyText(Message3Registry& reg, const Message3 e) {
|
||||
const auto& msgtext = reg.get<Message::Components::MessageText>(e).text;
|
||||
|
||||
#if 0
|
||||
// TODO: set word wrap
|
||||
ImVec2 text_size = ImGui::CalcTextSize(msgtext.c_str(), msgtext.c_str()+msgtext.size());
|
||||
text_size.x = -FLT_MIN; // fill width (suppresses label)
|
||||
@ -849,11 +872,70 @@ void ChatGui4::renderMessageBodyText(Message3Registry& reg, const Message3 e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ImGui::MenuItem("copy")) {
|
||||
ImGui::SetClipboardText(msgtext.c_str());
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
#else
|
||||
|
||||
ImGui::PushTextWrapPos(0.0f);
|
||||
std::string_view msgtext_sv{msgtext};
|
||||
size_t pos_prev {0};
|
||||
size_t pos_next {msgtext_sv.find_first_of('\n')};
|
||||
do {
|
||||
const auto current_line = msgtext_sv.substr(pos_prev, pos_next - pos_prev);
|
||||
if (current_line.front() == '>') {
|
||||
// TODO: theming
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, {0.3f, 0.9f, 0.1f, 1.f});
|
||||
ImGui::TextUnformatted(current_line.data(), current_line.data()+current_line.size());
|
||||
ImGui::PopStyleColor();
|
||||
} else {
|
||||
ImGui::TextUnformatted(current_line.data(), current_line.data()+current_line.size());
|
||||
}
|
||||
|
||||
if (pos_next != msgtext_sv.npos) {
|
||||
pos_next += 1; // skip past
|
||||
if (pos_next < msgtext_sv.size()) {
|
||||
pos_prev = pos_next; // old end is new start
|
||||
pos_next = msgtext_sv.find_first_of('\n', pos_next);
|
||||
} else {
|
||||
pos_prev = msgtext_sv.npos;
|
||||
pos_next = msgtext_sv.npos;
|
||||
}
|
||||
} else {
|
||||
pos_prev = msgtext_sv.npos;
|
||||
}
|
||||
} while (pos_prev != msgtext_sv.npos);
|
||||
|
||||
ImGui::PopTextWrapPos();
|
||||
|
||||
if (ImGui::BeginPopupContextItem("##text")) {
|
||||
if (ImGui::MenuItem("quote")) {
|
||||
//text_buffer.insert(0, (_cr.all_of<Contact::Components::Name>(c) ? _cr.get<Contact::Components::Name>(c).name : "<unk>") + ": ");
|
||||
if (!_text_input_buffer.empty()) {
|
||||
_text_input_buffer += "\n";
|
||||
}
|
||||
|
||||
_text_input_buffer += "> ";
|
||||
|
||||
for (const char c : msgtext) {
|
||||
_text_input_buffer += c;
|
||||
|
||||
if (c == '\n') {
|
||||
_text_input_buffer += "> ";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ImGui::MenuItem("copy")) {
|
||||
ImGui::SetClipboardText(msgtext.c_str());
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
|
||||
@ -995,8 +1077,16 @@ void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
|
||||
for (size_t i = 0; i < file_list.size(); i++) {
|
||||
ImGui::PushID(i);
|
||||
|
||||
const char* byte_suffix = "???";
|
||||
int64_t byte_divider = sizeToHumanReadable(file_list[i].file_size, byte_suffix);
|
||||
|
||||
// TODO: selectable text widget ?
|
||||
ImGui::Bullet(); ImGui::Text("%s (%lu)", file_list[i].file_name.c_str(), file_list[i].file_size);
|
||||
ImGui::Bullet(); ImGui::Text("%s (%.2lf %s)", file_list[i].file_name.c_str(), double(file_list[i].file_size)/byte_divider, byte_suffix);
|
||||
if (ImGui::BeginItemTooltip()) {
|
||||
ImGui::Text("TODO: file path?");
|
||||
ImGui::Text("%lu bytes", file_list[i].file_size);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
if (reg.all_of<Message::Components::Transfer::FileInfoLocal>(e)) {
|
||||
const auto& local_info = reg.get<Message::Components::Transfer::FileInfoLocal>(e);
|
||||
|
@ -51,7 +51,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
// more RAII
|
||||
std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> window {
|
||||
SDL_CreateWindow("tomato", 1280, 720, SDL_WINDOW_RESIZABLE),
|
||||
SDL_CreateWindow("tomato", 1280, 720, SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY),
|
||||
&SDL_DestroyWindow
|
||||
};
|
||||
|
||||
|
@ -50,6 +50,12 @@ StartScreen::StartScreen(const std::vector<std::string_view>& args, SDL_Renderer
|
||||
}
|
||||
}
|
||||
|
||||
{ // seed tox save path
|
||||
if (_conf.has_string("tox", "save_file_path")) {
|
||||
_tox_profile_path = _conf.get_string("tox", "save_file_path").value();
|
||||
}
|
||||
}
|
||||
|
||||
float display_scale = SDL_GetWindowDisplayScale(SDL_GetRenderWindow(renderer));
|
||||
if (display_scale < 0.001f) {
|
||||
// error?
|
||||
@ -134,6 +140,9 @@ StartScreen::StartScreen(const std::vector<std::string_view>& args, SDL_Renderer
|
||||
}
|
||||
|
||||
Screen* StartScreen::render(float, bool&) {
|
||||
const float TEXT_LOAD_WIDTH = ImGui::CalcTextSize("load").x;
|
||||
const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing();
|
||||
|
||||
|
||||
// TODO: imgui tox profile selector?
|
||||
|
||||
@ -246,7 +255,7 @@ Screen* StartScreen::render(float, bool&) {
|
||||
// load but file missing
|
||||
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::Button("load", {60, 25});
|
||||
ImGui::Button("load", {TEXT_LOAD_WIDTH*1.5f, TEXT_BASE_HEIGHT*1.5f});
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||
@ -256,14 +265,14 @@ Screen* StartScreen::render(float, bool&) {
|
||||
// new but file exists
|
||||
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::Button("load", {60, 25});
|
||||
ImGui::Button("load", {TEXT_LOAD_WIDTH*1.5f, TEXT_BASE_HEIGHT*1.5f});
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||
ImGui::SetTooltip("file already exists");
|
||||
}
|
||||
} else {
|
||||
if (ImGui::Button("load", {60, 25})) {
|
||||
if (ImGui::Button("load", {TEXT_LOAD_WIDTH*1.5f, TEXT_BASE_HEIGHT*1.5f})) {
|
||||
|
||||
auto new_screen = std::make_unique<MainScreen>(std::move(_conf), _renderer, _theme, _tox_profile_path, _password, _user_name, queued_plugin_paths);
|
||||
return new_screen.release();
|
||||
|
@ -29,6 +29,9 @@ void ToxUIUtils::render(void) {
|
||||
if (ImGui::MenuItem("add Friend by ID")) {
|
||||
_show_add_friend_window = true;
|
||||
}
|
||||
if (ImGui::MenuItem("copy own ToxID")) {
|
||||
ImGui::SetClipboardText(_tc.toxSelfGetAddressStr().c_str());
|
||||
}
|
||||
if (ImGui::MenuItem("join Group by ID (ngc)")) {
|
||||
_show_add_group_window = true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user