Skip to content

Commit ce29ccf

Browse files
committed
2 parents 8af9289 + 2d2beb2 commit ce29ccf

File tree

5 files changed

+87
-3
lines changed

5 files changed

+87
-3
lines changed

cmake/dependencies.cmake

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@ function(add_main_dependencies)
3737
)
3838
list(APPEND EXTERNAL_LINKS nlohmann_json)
3939

40+
# brotli
41+
CPMAddPackage(
42+
NAME brotli
43+
GITHUB_REPOSITORY google/brotli
44+
GIT_TAG v1.2.0
45+
EXCLUDE_FROM_ALL YES
46+
SOURCE_DIR "${EXTERNAL_DIR}/brotli"
47+
)
48+
if (brotli_ADDED)
49+
add_library(Brotli::common ALIAS brotlicommon)
50+
add_library(Brotli::encoder ALIAS brotlienc)
51+
add_library(Brotli::decoder ALIAS brotlidec)
52+
endif()
53+
list(APPEND EXTERNAL_LINKS brotlienc)
54+
4055
# fmt
4156
CPMAddPackage(
4257
NAME fmt

src/app.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "gui/helper/saveCallback.h"
99
#include "gui/mainWindow/circuitView/circuitViewWidget.h"
1010
#include "network/network.h"
11+
#include "util/version.h"
1112
// #include "computerAPI/directoryManager.h" // TEMPORARY
1213

1314
#include <SDL3/SDL.h>
@@ -292,6 +293,7 @@ void App::stopTryingToQuit() { tryingToQuit = false; }
292293
nlohmann::json App::dumpState() const {
293294
nlohmann::json stateJson;
294295
stateJson["environment"] = environment.dumpState();
296+
stateJson["version"] = getCurrentVersion().toString();
295297
return stateJson;
296298
}
297299

src/gui/mainWindow/popUps/popUpManager.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "gui/helper/saveCallback.h"
88
#include "gui/mainWindow/mainWindow.h"
99
#include "network/network.h"
10+
#include "util/compression.h"
11+
#include "util/version.h"
1012

1113
#include <RmlUi/Debugger.h>
1214

@@ -316,12 +318,35 @@ void PopUpManager::addFeedbackPopup() { // feature request, bug report, feature
316318
submitButton->SetClass("popup-button", true);
317319
submitButton->AddEventListener(
318320
Rml::EventId::Click,
319-
new EventPasser([popUpWindow, textarea, includeStateCheckbox](Rml::Event& event) {
321+
new EventPasser([this, popUpWindow, textarea, includeStateCheckbox](Rml::Event& event) {
320322
auto* textareaControl = dynamic_cast<Rml::ElementFormControlTextArea*>(textarea);
321323
std::string textareaValue = textareaControl ? textareaControl->GetValue().c_str() : "";
322324

323-
logInfo("Feedback body: {}", "", textareaValue);
324-
logInfo("Include app state: {}", "", includeStateCheckbox->HasAttribute("checked") ? "true" : "false");
325+
// logInfo("Feedback body: {}", "", textareaValue);
326+
// logInfo("Include app state: {}", "", includeStateCheckbox->HasAttribute("checked") ? "true" : "false");
327+
std::vector<Network::Attachment> attachments;
328+
if (includeStateCheckbox->HasAttribute("checked")) {
329+
Network::Attachment appStateAttachment;
330+
std::string appState = App::get().dumpState().dump(1, '\t');
331+
std::optional<std::string> compressedAppState = compressString(appState);
332+
if (compressedAppState){
333+
appStateAttachment.data = compressedAppState.value();
334+
appStateAttachment.context = "app_state.json.json.br";
335+
appStateAttachment.contentType = "application/x-brotli";
336+
} else {
337+
appStateAttachment.data = appState;
338+
appStateAttachment.context = "app_state.json";
339+
appStateAttachment.contentType = "application/json";
340+
}
341+
attachments.push_back(appStateAttachment);
342+
}
343+
344+
Network::get().sendFeedback(
345+
*this,
346+
"User Feedback from Connection Machine UI v" + getCurrentVersion().toString(),
347+
textareaValue,
348+
attachments
349+
);
325350

326351
popUpWindow.destroy();
327352
})

src/util/compression.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include "compression.h"
2+
3+
#include <brotli/encode.h>
4+
5+
std::optional<std::string> compressString(const std::string& input) {
6+
if (input.empty()) {
7+
return {};
8+
}
9+
10+
const size_t maxSize = BrotliEncoderMaxCompressedSize(input.size());
11+
if (maxSize == 0) {
12+
logError("BrotliEncoderMaxCompressedSize returned 0");
13+
return std::nullopt;
14+
}
15+
16+
std::string output(maxSize, '\0');
17+
size_t encodedSize = maxSize;
18+
19+
const auto result = BrotliEncoderCompress(
20+
BROTLI_DEFAULT_QUALITY,
21+
BROTLI_DEFAULT_WINDOW,
22+
BROTLI_DEFAULT_MODE,
23+
input.size(),
24+
reinterpret_cast<const uint8_t*>(input.data()),
25+
&encodedSize,
26+
reinterpret_cast<uint8_t*>(output.data())
27+
);
28+
29+
if (result == BROTLI_FALSE) {
30+
logError("BrotliEncoderCompress failed");
31+
return std::nullopt;
32+
}
33+
34+
output.resize(encodedSize);
35+
return output;
36+
}

src/util/compression.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef compression_h
2+
#define compression_h
3+
4+
std::optional<std::string> compressString(const std::string& input);
5+
6+
#endif /* compression_h */

0 commit comments

Comments
 (0)