diff options
| author | Aldrik Ramaekers <aldrik@mailbox.org> | 2026-01-01 14:33:14 +0100 |
|---|---|---|
| committer | Aldrik Ramaekers <aldrik@mailbox.org> | 2026-01-01 14:33:14 +0100 |
| commit | a1d639e963eaad1f8d24d47cd004c22052166978 (patch) | |
| tree | 473a9a1b8b9ed5bd0c24a81fa848c31d3db788d0 | |
| parent | be5c11029adb25c586c4fcde6fedfa01d1bdcd49 (diff) | |
export dropdown ui
| -rw-r--r-- | include/config.hpp | 3 | ||||
| -rw-r--r-- | include/exporter.hpp | 7 | ||||
| -rw-r--r-- | include/ui.hpp | 3 | ||||
| -rw-r--r-- | libs/imgui-1.92.1/imgui.cpp | 8 | ||||
| -rw-r--r-- | libs/imgui-1.92.1/imgui.h | 1 | ||||
| -rw-r--r-- | src/exporter.cpp | 6 | ||||
| -rw-r--r-- | src/providers/MailerSend.cpp | 5 | ||||
| -rw-r--r-- | src/ui/imgui_extensions.cpp | 65 | ||||
| -rw-r--r-- | src/ui/ui_invoices.cpp | 36 | ||||
| -rw-r--r-- | src/ui/ui_settings.cpp | 6 |
10 files changed, 122 insertions, 18 deletions
diff --git a/include/config.hpp b/include/config.hpp index ff36364..dcc476b 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -31,12 +31,15 @@ #define u32 uint32_t #define u64 uint64_t +#define SIMULATE_EMAIL 1 + namespace config { static const char* PROGRAM_VERSION = "0.1.0"; // major.minor.patch namespace colors { static const ImU32 COLOR_ERROR_OUTLINE = IM_COL32(255, 0, 0, 80); static const ImU32 COLOR_ERROR = IM_COL32(235, 64, 52, 255); + static const ImU32 COLOR_SUCCESS = IM_COL32(125, 214, 66, 255); static const ImU32 COLOR_DEFAULT = IM_COL32(235, 255, 255, 255); } } diff --git a/include/exporter.hpp b/include/exporter.hpp index 00eaf32..82c18b2 100644 --- a/include/exporter.hpp +++ b/include/exporter.hpp @@ -26,6 +26,7 @@ typedef uint32_t e_err; namespace exporter { + typedef enum { EXPORT_STARTING, @@ -33,15 +34,19 @@ namespace exporter { EXPORT_DONE, } status; + typedef void (*send_email_callback)(e_err err); + typedef struct { time_t started_at; + time_t done_at; e_err error; status status; char* sender; char* recipient; const char* subject; const char* text; + send_email_callback callback; } export_request; typedef struct @@ -51,5 +56,5 @@ namespace exporter { } email_provider_impl; email_provider_impl get_email_provider_implementation(email_provider provider); - exporter::export_request* send_email(char* sender, char* recipient, const char* subject, const char* text); + exporter::export_request* send_email(char* sender, char* recipient, const char* subject, const char* text, send_email_callback ev); }
\ No newline at end of file diff --git a/include/ui.hpp b/include/ui.hpp index 86778bc..2e85dc2 100644 --- a/include/ui.hpp +++ b/include/ui.hpp @@ -17,6 +17,7 @@ #pragma once #include "imgui.h" +#include "exporter.hpp" #include "administration.hpp" #define STATUS_TEXT_LEN 64 @@ -102,4 +103,6 @@ namespace ImGui void TaxRateDropdown(char* tax_internal_code, bool outgoing, bool has_error); bool CurrencyDropdown(char* currency); void ToggleDropdown(bool *buffer, char* option1, char* option2); + + bool BeginExportDropdown(const char* title, const char* text, exporter::export_request* active_request); }
\ No newline at end of file diff --git a/libs/imgui-1.92.1/imgui.cpp b/libs/imgui-1.92.1/imgui.cpp index d3d82d4..dd13cc1 100644 --- a/libs/imgui-1.92.1/imgui.cpp +++ b/libs/imgui-1.92.1/imgui.cpp @@ -16677,6 +16677,14 @@ void ImGui::DebugBreakButtonTooltip(bool keyboard_only, const char* description_ EndTooltip(); } +void ImGui::LoadingIndicatorCircleSmall() +{ + float radius = 10.0f; + const ImVec4 col = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); + const ImVec4 bg = ImGui::GetStyleColorVec4(ImGuiCol_Button); + ImGui::LoadingIndicatorCircle(radius, bg, col, 6, 4.0f); +} + // From https://github.com/ocornut/imgui/issues/1901#issuecomment-444929973 void ImGui::LoadingIndicatorCircle(const float indicator_radius, const ImVec4& main_color, const ImVec4& backdrop_color, diff --git a/libs/imgui-1.92.1/imgui.h b/libs/imgui-1.92.1/imgui.h index 3b48ad8..ad874ab 100644 --- a/libs/imgui-1.92.1/imgui.h +++ b/libs/imgui-1.92.1/imgui.h @@ -377,6 +377,7 @@ namespace ImGui { IMGUI_API bool BeginComboPreview(); IMGUI_API void EndComboPreview(); + IMGUI_API void LoadingIndicatorCircleSmall(); IMGUI_API void LoadingIndicatorCircle(const float indicator_radius, const ImVec4& main_color, const ImVec4& backdrop_color, const int circle_count, const float speed); diff --git a/src/exporter.cpp b/src/exporter.cpp index c53b70d..e296973 100644 --- a/src/exporter.cpp +++ b/src/exporter.cpp @@ -45,11 +45,14 @@ static int _send_email_t(void* arg) { request->error = impl.send_email(request->sender, request->recipient, request->subject, request->text); request->status = exporter::status::EXPORT_DONE; + request->done_at = time(NULL); + + if (request->callback) request->callback(request->error); return 0; } -exporter::export_request* exporter::send_email(char* sender, char* recipient, const char* subject, const char* text) +exporter::export_request* exporter::send_email(char* sender, char* recipient, const char* subject, const char* text, send_email_callback ev) { exporter::export_request* result = (exporter::export_request*)memops::alloc(sizeof(exporter::export_request)); result->started_at = time(NULL); @@ -59,6 +62,7 @@ exporter::export_request* exporter::send_email(char* sender, char* recipient, co result->recipient = recipient; result->subject = subject; result->text = text; + result->callback = ev; thrd_t thr; if (thrd_create(&thr, _send_email_t, result) != thrd_success) { diff --git a/src/providers/MailerSend.cpp b/src/providers/MailerSend.cpp index 1a633d9..122b7b2 100644 --- a/src/providers/MailerSend.cpp +++ b/src/providers/MailerSend.cpp @@ -24,6 +24,11 @@ bool _MailerSend_send_email(char* sender, char* recipient, const char* subject, const char* text) { + #if SIMULATE_EMAIL + usleep(1000 * 1000); + return E_ERR_SUCCESS; + #endif + const char *api_key = administration::get_email_service().api_key; httplib::SSLClient cli("api.mailersend.com", 443); cli.enable_server_certificate_verification(false); diff --git a/src/ui/imgui_extensions.cpp b/src/ui/imgui_extensions.cpp index f8adb70..05eeb7b 100644 --- a/src/ui/imgui_extensions.cpp +++ b/src/ui/imgui_extensions.cpp @@ -1,3 +1,5 @@ +#include <time.h> + #include "ui.hpp" #include "strops.hpp" #include "memops.hpp" @@ -707,4 +709,67 @@ namespace ImGui ImGui::CountryDropdown(buffer->country_code, IM_ARRAYSIZE(buffer->country_code), active_countries_only); } + + bool BeginExportDropdown(const char* title, const char* text, exporter::export_request* active_request) + { + static bool is_new_request = false; + static bool show_status_change = false; + static time_t status_changed_at = 0; + static e_err last_err; + + if (active_request && active_request->status == exporter::status::EXPORT_DONE && is_new_request) + { + is_new_request = false; + show_status_change = true; + last_err = active_request->error; + status_changed_at = time(NULL); + } + + if (active_request && active_request->status != exporter::status::EXPORT_DONE) { + is_new_request = true; + ImGui::BeginDisabled(); + ImGui::BeginCombo("##sendStatus", NULL, 1 << 20); + { + if (ImGui::BeginComboPreview()) + { + ImGui::Text("Sending"); // @Localize + ImGui::SameLine(); + ImGui::LoadingIndicatorCircleSmall(); + ImGui::EndComboPreview(); + } + } + ImGui::EndDisabled(); + } + else if (show_status_change) { + ImGui::BeginDisabled(); + ImGui::BeginCombo("##sendStatus", NULL, 1 << 20); + { + if (ImGui::BeginComboPreview()) + { + if (last_err == E_ERR_SUCCESS) { + ImGui::PushStyleColor(ImGuiCol_Text, config::colors::COLOR_SUCCESS); + ImGui::Text("√"); + ImGui::PopStyleColor(); + ImGui::Text("Success"); // @Localize + } + else { + ImGui::PushStyleColor(ImGuiCol_Text, config::colors::COLOR_ERROR); + ImGui::Text("X"); + ImGui::PopStyleColor(); + ImGui::Text("Failed"); // @Localize + } + ImGui::EndComboPreview(); + } + } + ImGui::EndDisabled(); + + if (difftime(time(NULL), status_changed_at) > 1.0f) { + show_status_change = false; + } + } + else { + return ImGui::BeginCombo(title, text); + } + return false; + } }
\ No newline at end of file diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp index 6a50c7f..eb04af4 100644 --- a/src/ui/ui_invoices.cpp +++ b/src/ui/ui_invoices.cpp @@ -20,6 +20,7 @@ #include "ui.hpp" #include "imgui.h" #include "memops.hpp" +#include "config.hpp" #include "strops.hpp" #include "locales.hpp" #include "importer.hpp" @@ -484,6 +485,28 @@ static void draw_invoice_create() ImGui::EndChild(); } +static void draw_send_options() +{ + static exporter::export_request* active_request = NULL; + + if (ImGui::BeginExportDropdown("##Send", locale::get("ui.sendAs"), active_request)) + { + if (ImGui::Selectable(locale::get("ui.sendAs.email"), false)) { + active_request = exporter::send_email("test@test-vz9dlemj2564kj50.mlsender.net", "aldrikboy@gmail.com", "test", "test 123", + [](e_err status) { + if (status == E_ERR_SUCCESS) { + administration::activity_add(ACTIVITY_USER, active_invoice.id, "Sent email", 0); + _reload_activities(); + } + }); + } + // if (ImGui::Selectable(locale::get("ui.sendAs.einvoice"), false)) { + + // } + ImGui::EndCombo(); + } +} + static void draw_invoice_view() { if (ImGui::Button(locale::get("form.back"), true, false)) { @@ -499,17 +522,8 @@ static void draw_invoice_view() ImGui::SameLine(); - ImGui::PushItemWidth(100.0f); - if (ImGui::BeginCombo("##Send", locale::get("ui.sendAs"))) - { - if (ImGui::Selectable(locale::get("ui.sendAs.email"), false)) { - exporter::send_email("test@test-vz9dlemj2564kj50.mlsender.net", "aldrikboy@gmail.com", "test", "test 123"); - } - // if (ImGui::Selectable(locale::get("ui.sendAs.einvoice"), false)) { - - // } - ImGui::EndCombo(); - } + ImGui::PushItemWidth(180.0f); + draw_send_options(); ImGui::PushItemWidth(0.0f); ImGui::SameLine(); diff --git a/src/ui/ui_settings.cpp b/src/ui/ui_settings.cpp index fd0d5b9..fb02738 100644 --- a/src/ui/ui_settings.cpp +++ b/src/ui/ui_settings.cpp @@ -314,11 +314,7 @@ static void draw_ai_service_ui() if (ImGui::BeginComboPreview()) { if (model_request->status != importer::status::IMPORT_DONE) { - float radius = 10.0f; - const ImVec4 col = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); - const ImVec4 bg = ImGui::GetStyleColorVec4(ImGuiCol_Button); - ImGui::LoadingIndicatorCircle(radius, bg, col, 6, 4.0f); - + ImGui::LoadingIndicatorCircleSmall(); ImGui::SameLine(); } ImGui::TextUnformatted(new_ai_service.model_name); |
