diff --git a/src/main_screen.cpp b/src/main_screen.cpp index af3f450..8bd2113 100644 --- a/src/main_screen.cpp +++ b/src/main_screen.cpp @@ -33,14 +33,14 @@ static std::unique_ptr constructSystemTray(SimpleConfigModel& conf, } } -MainScreen::MainScreen(SimpleConfigModel&& conf_, SDL_Renderer* renderer_, Theme& theme_, std::string save_path, std::string save_password, std::string new_username, std::vector plugins) : +MainScreen::MainScreen(const SimpleConfigModel& conf_, SDL_Renderer* renderer_, Theme& theme_, std::string save_path, std::string save_password, std::string new_username, std::vector plugins) : renderer(renderer_), - conf(std::move(conf_)), + conf(conf_), rmm(cr), msnj{cr, os, {}, {}}, mts(rmm), sm(os), - tc(save_path, save_password), + tc(conf, save_path, save_password), tel(tc, std::cout), tpi(tc.getTox()), ad(tc), diff --git a/src/main_screen.hpp b/src/main_screen.hpp index fedb66a..64ab280 100644 --- a/src/main_screen.hpp +++ b/src/main_screen.hpp @@ -119,7 +119,7 @@ struct MainScreen final : public Screen { std::vector _dopped_files; - MainScreen(SimpleConfigModel&& conf_, SDL_Renderer* renderer_, Theme& theme_, std::string save_path, std::string save_password, std::string new_username, std::vector plugins); + MainScreen(const SimpleConfigModel& conf_, SDL_Renderer* renderer_, Theme& theme_, std::string save_path, std::string save_password, std::string new_username, std::vector plugins); ~MainScreen(void); bool handleEvent(SDL_Event& e) override; diff --git a/src/start_screen.cpp b/src/start_screen.cpp index d5d30f1..788384d 100644 --- a/src/start_screen.cpp +++ b/src/start_screen.cpp @@ -173,111 +173,221 @@ Screen* StartScreen::render(float, bool&) { const float TEXT_PROCEED_WIDTH = ImGui::CalcTextSize("proceed").x; const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing(); + ImGui::SetNextWindowSize({656,334}, ImGuiCond_FirstUseEver); + ImGui::Begin("start screen"); // TODO: imgui tox profile selector? // +---------------------------- - // | |*tox profile*| plugins | + // | |*tox profile*| plugins | toxcore config | // | +------+ +-------- // | | ICON | | fileselector/dropdown? // | | | | password input // | +------+ +-------- + // | [proceed] // +---------------------------- - if (ImGui::BeginTabBar("view")) { - if (ImGui::BeginTabItem("load profile")) { - _new_save = false; + if (ImGui::BeginChild("conf", {0, ImGui::GetContentRegionAvail().y - TEXT_BASE_HEIGHT*2.f})) { + if (ImGui::BeginTabBar("view")) { + if (ImGui::BeginTabItem("load profile")) { + _new_save = false; - ImGui::TextUnformatted("profile :"); - ImGui::SameLine(); - if (ImGui::Button("select")) { - _fss.requestFile( - [](const auto& path) -> bool { return std::filesystem::is_regular_file(path); }, - [this](const auto& path) { - _tox_profile_path = path.string(); - }, - [](){} - ); + ImGui::TextUnformatted("profile :"); + ImGui::SameLine(); + if (ImGui::Button("select")) { + _fss.requestFile( + [](const auto& path) -> bool { return std::filesystem::is_regular_file(path); }, + [this](const auto& path) { + _tox_profile_path = path.string(); + }, + [](){} + ); + } + ImGui::SameLine(); + ImGui::TextUnformatted(_tox_profile_path.c_str()); + + ImGui::TextUnformatted("password:"); + ImGui::SameLine(); + if (_show_password) { + ImGui::InputText("##password", &_password); + } else { + ImGui::InputText("##password", &_password, ImGuiInputTextFlags_Password); + } + ImGui::SameLine(); + ImGui::Checkbox("show password", &_show_password); + + ImGui::EndTabItem(); } - ImGui::SameLine(); - ImGui::TextUnformatted(_tox_profile_path.c_str()); + if (ImGui::BeginTabItem("create profile")) { + _new_save = true; - ImGui::TextUnformatted("password:"); - ImGui::SameLine(); - if (_show_password) { - ImGui::InputText("##password", &_password); - } else { - ImGui::InputText("##password", &_password, ImGuiInputTextFlags_Password); + ImGui::TextUnformatted("username:"); + ImGui::SameLine(); + if (ImGui::InputText("##user_name", &_user_name)) { + std::string tmp_copy = _user_name; + for (auto& c : tmp_copy) { + if (!std::isalnum(static_cast(c)) && c != '-' && c != '.') { + c = '_'; + } + } + + if (tmp_copy.empty()) { + tmp_copy = "unnamed-tomato"; + } + + _tox_profile_path = tmp_copy + ".tox"; + } + + ImGui::TextUnformatted("password:"); + ImGui::SameLine(); + if (_show_password) { + ImGui::InputText("##password", &_password); + } else { + ImGui::InputText("##password", &_password, ImGuiInputTextFlags_Password); + } + ImGui::SameLine(); + ImGui::Checkbox("show password", &_show_password); + + ImGui::TextUnformatted("TODO: profile path (current path for now)"); + + ImGui::EndTabItem(); } - ImGui::SameLine(); - ImGui::Checkbox("show password", &_show_password); + if (ImGui::BeginTabItem("plugins")) { + // list of selected plugins (in order) + for (auto it = queued_plugin_paths.begin(); it != queued_plugin_paths.end();) { + ImGui::PushID(it->c_str()); + if (ImGui::SmallButton("-")) { + it = queued_plugin_paths.erase(it); + ImGui::PopID(); + continue; + } + ImGui::SameLine(); + ImGui::TextUnformatted(it->c_str()); - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("create profile")) { - _new_save = true; + ImGui::PopID(); + it++; + } - ImGui::TextUnformatted("username:"); - ImGui::SameLine(); - if (ImGui::InputText("##user_name", &_user_name)) { - std::string tmp_copy = _user_name; - for (auto& c : tmp_copy) { - if (!std::isalnum(static_cast(c)) && c != '-' && c != '.') { - c = '_'; + if (ImGui::Button("+")) { + _fss.requestFile( + [](const auto& path) -> bool { return std::filesystem::is_regular_file(path); }, + [this](const auto& path) { + queued_plugin_paths.push_back(path.string()); + }, + [](){} + ); + } + + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("toxcore")) { + ImGui::TextDisabled("Be advised that no settings are written to disk.\nUse a config file if you don't want to set these values every start."); + + ImGui::SeparatorText("DNS"); + + { + static bool value {true}; + if (ImGui::Checkbox("DNS lookups", &value)) { + _conf.set("tox", "dns", value); + } + ImGui::SetItemTooltip("Allow toxcore to use your systems name resolver."); + } + + ImGui::SeparatorText("Proxy"); + + static int proxy_type {0}; + if (ImGui::Combo("proxy type", &proxy_type, "NONE\0HTTP\0SOCKS5\0")) { + if (proxy_type == 0) { + _conf.set("tox", "proxy_type", std::string_view{"NONE"}); + } else if (proxy_type == 1) { + _conf.set("tox", "proxy_type", std::string_view{"HTTP"}); + } else if (proxy_type == 2) { + _conf.set("tox", "proxy_type", std::string_view{"SOCKS5"}); } } - if (tmp_copy.empty()) { - tmp_copy = "unnamed-tomato"; + ImGui::BeginDisabled(proxy_type == 0); + { + { + static std::string value; + if (ImGui::InputText("host", &value)) { + _conf.set("tox", "proxy_host", value); + } + ImGui::SetItemTooltip("toxcore does not currently support authentication."); + } + + { + static uint16_t value {0}; + if (ImGui::InputScalar("port", ImGuiDataType_U16, &value)) { + _conf.set("tox", "proxy_port", int64_t(value)); + } + } + } + ImGui::EndDisabled(); + + ImGui::SeparatorText("IP connectivity"); + + { + static bool value {true}; + if (ImGui::Checkbox("ipv6", &value)) { + _conf.set("tox", "ipv6_enabled", value); + } } - _tox_profile_path = tmp_copy + ".tox"; - } - - ImGui::TextUnformatted("password:"); - ImGui::SameLine(); - if (_show_password) { - ImGui::InputText("##password", &_password); - } else { - ImGui::InputText("##password", &_password, ImGuiInputTextFlags_Password); - } - ImGui::SameLine(); - ImGui::Checkbox("show password", &_show_password); - - ImGui::TextUnformatted("TODO: profile path (current path for now)"); - - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("plugins")) { - // list of selected plugins (in order) - for (auto it = queued_plugin_paths.begin(); it != queued_plugin_paths.end();) { - ImGui::PushID(it->c_str()); - if (ImGui::SmallButton("-")) { - it = queued_plugin_paths.erase(it); - ImGui::PopID(); - continue; + { + static bool value {true}; + if (ImGui::Checkbox("udp", &value)) { + _conf.set("tox", "udp_enabled", value); + } } - ImGui::SameLine(); - ImGui::TextUnformatted(it->c_str()); - ImGui::PopID(); - it++; + { + static bool value {true}; + if (ImGui::Checkbox("hole punching", &value)) { + _conf.set("tox", "hole_punching_enabled", value); + } + ImGui::SetItemTooltip("Perform NAT hole punching.\nOnly meaningful if udp is enabled."); + } + + { + static uint16_t value {0}; + if (ImGui::InputScalar("start port", ImGuiDataType_U16, &value)) { + _conf.set("tox", "start_port", int64_t(value)); + } + ImGui::SetItemTooltip("The range in which toxcore finds a free port.\nOnly meaningful if udp is enabled."); + } + { + static uint16_t value {0}; + if (ImGui::InputScalar("end port", ImGuiDataType_U16, &value)) { + _conf.set("tox", "end_port", int64_t(value)); + } + ImGui::SetItemTooltip("The range in which toxcore finds a free port.\nOnly meaningful if udp is enabled."); + } + + ImGui::SeparatorText("local discovery"); + { + static bool value {true}; + if (ImGui::Checkbox("local discovery", &value)) { + _conf.set("tox", "local_discovery_enabled", value); + } + ImGui::SetItemTooltip("Perform broadcasts in your local networks to fine other peers.\nOnly meaningful if udp is enabled."); + } + + ImGui::SeparatorText("tcp relay server"); + { + static uint16_t value {0}; + if (ImGui::InputScalar("server port", ImGuiDataType_U16, &value)) { + _conf.set("tox", "tcp_port", int64_t(value)); + } + ImGui::SetItemTooltip("Run a tcp relay server in your client, aiding the network with another relay node.\n!! Check local juristiction and law to not get in trouble.\n0 is disabled"); + } + + ImGui::EndTabItem(); } - - if (ImGui::Button("+")) { - _fss.requestFile( - [](const auto& path) -> bool { return std::filesystem::is_regular_file(path); }, - [this](const auto& path) { - queued_plugin_paths.push_back(path.string()); - }, - [](){} - ); - } - - ImGui::EndTabItem(); + ImGui::EndTabBar(); } - ImGui::EndTabBar(); } + ImGui::EndChild(); ImGui::Separator(); @@ -306,10 +416,11 @@ Screen* StartScreen::render(float, bool&) { _error_string.clear(); try { - auto new_screen = std::make_unique(std::move(_conf), _renderer, _theme, _tox_profile_path, _password, _user_name, queued_plugin_paths); + auto new_screen = std::make_unique(_conf, _renderer, _theme, _tox_profile_path, _password, _user_name, queued_plugin_paths); if (!new_screen) { throw std::runtime_error("failed to init main screen."); } + ImGui::End(); // start screen return new_screen.release(); } catch (const std::exception& e) { _error_string = std::string{"ToxCore/MainScreen creation failed with: "} + e.what(); @@ -319,10 +430,13 @@ Screen* StartScreen::render(float, bool&) { } if (!_error_string.empty()) { + ImGui::SameLine(); ImGui::TextColored({1.f, 0.5f, 0.5f, 1.f}, "%s", _error_string.c_str()); } } + ImGui::End(); // start screen + _fss.render(); // TODO: dont check every frame diff --git a/src/tox_client.cpp b/src/tox_client.cpp index 48e2ed4..a3ea924 100644 --- a/src/tox_client.cpp +++ b/src/tox_client.cpp @@ -2,6 +2,7 @@ // meh, change this #include +#include #include #include @@ -18,12 +19,13 @@ static void eee(std::string& mod) { } } -ToxClient::ToxClient(std::string_view save_path, std::string_view save_password) : +ToxClient::ToxClient(ConfigModelI& conf, std::string_view save_path, std::string_view save_password) : _tox_profile_path(save_path), _tox_profile_password(save_password) { TOX_ERR_OPTIONS_NEW err_opt_new; - Tox_Options* options = tox_options_new(&err_opt_new); + std::unique_ptr options {tox_options_new(&err_opt_new), &tox_options_free}; assert(err_opt_new == TOX_ERR_OPTIONS_NEW::TOX_ERR_OPTIONS_NEW_OK); + std::string tmp_proxy_host; // the string needs to survive until options is freed std::vector profile_data{}; if (!_tox_profile_path.empty()) { @@ -59,19 +61,55 @@ ToxClient::ToxClient(std::string_view save_path, std::string_view save_password) } eee(_tox_profile_password); } - tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); - tox_options_set_savedata_data(options, profile_data.data(), profile_data.size()); + tox_options_set_savedata_type(options.get(), TOX_SAVEDATA_TYPE_TOX_SAVE); + tox_options_set_savedata_data(options.get(), profile_data.data(), profile_data.size()); } ifile.close(); // do i need this? } } - tox_options_set_experimental_groups_persistence(options, true); + tox_options_set_ipv6_enabled(options.get(), conf.get_bool("tox", "ipv6_enabled").value_or(true)); + tox_options_set_udp_enabled(options.get(), conf.get_bool("tox", "udp_enabled").value_or(true)); + tox_options_set_local_discovery_enabled(options.get(), conf.get_bool("tox", "local_discovery_enabled").value_or(true)); + //tox_options_set_dht_announcements_enabled(options.get(), conf.get_bool("tox", "dht_announcements_enabled").value_or(true)); + tox_options_set_dht_announcements_enabled(options.get(), true); // dont harm the network + + const size_t proxy_conf_sum = conf.has_string("tox", "proxy_type") + + conf.has_string("tox", "proxy_host") + + conf.has_int("tox", "proxy_port") + ; + // if all proxy parts defined + if (proxy_conf_sum == 3) { + const std::string_view proxy_type_str = conf.get_string("tox", "proxy_type").value(); + if (proxy_type_str == "HTTP") { + tox_options_set_proxy_type(options.get(), Tox_Proxy_Type::TOX_PROXY_TYPE_HTTP); + } else if (proxy_type_str == "SOCKS5") { + tox_options_set_proxy_type(options.get(), Tox_Proxy_Type::TOX_PROXY_TYPE_SOCKS5); + } else { + throw std::runtime_error("invalid proxy type in config"); + } + + tmp_proxy_host = conf.get_string("tox", "proxy_host").value(); + tox_options_set_proxy_host(options.get(), tmp_proxy_host.c_str()); + + tox_options_set_proxy_port(options.get(), conf.get_int("tox", "proxy_port").value()); + } else if (proxy_conf_sum > 0) { + throw std::runtime_error("config only partly specified proxy"); + } + + tox_options_set_start_port(options.get(), conf.get_int("tox", "start_port").value_or(0)); + tox_options_set_end_port(options.get(), conf.get_int("tox", "end_port").value_or(0)); + tox_options_set_tcp_port(options.get(), conf.get_int("tox", "tcp_port").value_or(0)); + tox_options_set_hole_punching_enabled(options.get(), conf.get_bool("tox", "hole_punching_enabled").value_or(true)); + + tox_options_set_experimental_groups_persistence(options.get(), true); + + // annoyingly the inverse + tox_options_set_experimental_disable_dns(options.get(), !conf.get_bool("tox", "dns").value_or(false)); Tox_Err_New err_new; - _tox = tox_new(options, &err_new); - tox_options_free(options); + _tox = tox_new(options.get(), &err_new); if (err_new != TOX_ERR_NEW_OK) { std::cerr << "tox_new failed with error code " << err_new << "\n"; throw std::runtime_error{std::string{"toxcore creation failed with '"} + tox_err_new_to_string(err_new) + "'"}; diff --git a/src/tox_client.hpp b/src/tox_client.hpp index ac99866..86b0f4b 100644 --- a/src/tox_client.hpp +++ b/src/tox_client.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include @@ -26,7 +28,7 @@ class ToxClient : public ToxDefaultImpl, public ToxEventProviderBase { public: //ToxClient(/*const CommandLine& cl*/); - ToxClient(std::string_view save_path, std::string_view save_password); + ToxClient(ConfigModelI& conf, std::string_view save_path, std::string_view save_password); ~ToxClient(void); public: // tox stuff