macOS port: build, rendering, daemon, and mining fixes

Build & setup:
- Fix setup.sh and build.sh for macOS (bundle daemon, xmrig, sapling params, asmap.dat into .app)
- Fix CMakeLists.txt libsodium linking for macOS
- Fix incbin.h to use __DATA,__const section on macOS
- Remove vendored libsodium-1.0.18 source tree (use fetch script instead)
- Remove prebuilt-binaries/xmrig (replaced by xmrig-hac)
- Add .DS_Store to .gitignore

Rendering & UI:
- Use GLSL #version 150 and OpenGL 3.2 Core Profile on macOS
- Force dpiScale=1.0 on macOS to fix Retina double-scaling
- Set default window/UI opacity to 100% on Mac/Linux
- Add scroll fade shader guard for macOS GL compatibility
- Add ImGui error recovery around render loop and mining tab

Daemon & bootstrap:
- Fix getDragonXDataDir() to return ~/Library/Application Support/Hush/DRAGONX/ on macOS
- Fix isPortInUse() with connect() fallback (no /proc/net/tcp on macOS)
- Increase daemon watchdog timeout from 3s to 15s
- Add daemon status indicator (colored dot + label) in wizard bootstrap phases

Mining tab:
- Fix EmbeddedDaemon::getMemoryUsageMB() crash on macOS (was using Linux /proc)
- Fix XmrigManager::getMemoryUsageMB() to use ps on macOS instead of /proc
- Restructure RenderMiningTab with wrapper pattern for exception safety
- Fix default pool URL to include port (pool.dragonx.is:3433)
This commit is contained in:
M
2026-03-19 14:26:04 -05:00
parent 8645a82e4f
commit 53d08de639
572 changed files with 284 additions and 146732 deletions

View File

@@ -110,7 +110,11 @@ struct ScrollFadeShader {
#ifdef DRAGONX_HAS_GLAD
static constexpr const char* kFadeVS_130 =
#ifdef __APPLE__
"#version 150\n"
#else
"#version 130\n"
#endif
"uniform mat4 ProjMtx;\n"
"in vec2 Position;\n"
"in vec2 UV;\n"
@@ -124,7 +128,11 @@ struct ScrollFadeShader {
"}\n";
static constexpr const char* kFadeFS_130 =
#ifdef __APPLE__
"#version 150\n"
#else
"#version 130\n"
#endif
"uniform sampler2D Texture;\n"
"uniform float u_fadeTopY;\n"
"uniform float u_fadeBottomY;\n"

View File

@@ -19,6 +19,7 @@
#include "../notifications.h"
#include "../../embedded/IconsMaterialDesign.h"
#include "imgui.h"
#include "imgui_internal.h"
#include <thread>
#include <algorithm>
@@ -104,19 +105,39 @@ static std::string FormatEstTime(double est_hours)
return std::string(buf);
}
static void RenderMiningTabContent(App* app);
void RenderMiningTab(App* app)
{
// Scrollable child to contain all content within available space
ImVec2 miningAvail = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##MiningScroll", miningAvail, false, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoScrollbar);
ImGuiErrorRecoveryState erState;
ImGui::ErrorRecoveryStoreState(&erState);
try {
RenderMiningTabContent(app);
} catch (const std::exception& e) {
DEBUG_LOGF("[MiningTab] Exception: %s\n", e.what());
ImGui::ErrorRecoveryTryToRecoverState(&erState);
} catch (...) {
DEBUG_LOGF("[MiningTab] Unknown exception\n");
ImGui::ErrorRecoveryTryToRecoverState(&erState);
}
ImGui::EndChild(); // ##MiningScroll
}
static void RenderMiningTabContent(App* app)
{
auto& S = schema::UI();
ImVec2 miningAvail = ImGui::GetContentRegionAvail();
auto sliderInput = S.input("tabs.mining", "thread-slider");
auto startBtn = S.button("tabs.mining", "start-button");
auto lbl = S.label("tabs.mining", "label-column");
const auto& state = app->getWalletState();
const auto& mining = state.mining;
// Scrollable child to contain all content within available space
ImVec2 miningAvail = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##MiningScroll", miningAvail, false, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoScrollbar);
// Responsive: scale factors per frame
float availWidth = ImGui::GetContentRegionAvail().x;
float hs = Layout::hScale(availWidth);
@@ -155,6 +176,9 @@ void RenderMiningTab(App* app)
ImFont* ovFont = Type().overline();
ImFont* capFont = Type().caption();
ImFont* sub1 = Type().subtitle1();
if (!ovFont || !capFont || !sub1) {
return;
}
char buf[128];
// Load pool state from settings on first frame
@@ -750,7 +774,7 @@ void RenderMiningTab(App* app)
OnSurfaceMedium(), resetIcon);
if (btnClk) {
strncpy(s_pool_url, "pool.dragonx.is", sizeof(s_pool_url) - 1);
strncpy(s_pool_url, "pool.dragonx.is:3433", sizeof(s_pool_url) - 1);
// Default to user's first shielded (z) address for pool payouts.
// Leave blank if no z-address exists yet.
std::string defaultAddr;
@@ -1977,11 +2001,13 @@ void RenderMiningTab(App* app)
if (!mining_address.empty()) {
float addrAvailW = colW - pad - valOffX;
float charW = capFont->CalcTextSizeA(capFont->LegacySize, 10000, 0, "M").x;
if (charW <= 0.0f) charW = 8.0f;
int maxChars = std::max(8, (int)(addrAvailW / charW));
std::string truncAddr = mining_address;
if ((int)truncAddr.length() > maxChars) {
if ((int)truncAddr.length() > maxChars && maxChars > 5) {
int half = (maxChars - 3) / 2;
truncAddr = truncAddr.substr(0, half) + "..." + truncAddr.substr(truncAddr.length() - half);
if (half > 0 && (size_t)half < truncAddr.length())
truncAddr = truncAddr.substr(0, half) + "..." + truncAddr.substr(truncAddr.length() - half);
}
dl->AddText(capFont, capFont->LegacySize, ImVec2(col3X + valOffX, cy), OnSurface(), truncAddr.c_str());
@@ -2342,8 +2368,6 @@ void RenderMiningTab(App* app)
OnSurfaceMedium(), statusText);
ImGui::Dummy(ImVec2(availWidth, capFont->LegacySize + 4 * dp));
}
ImGui::EndChild(); // ##MiningScroll
}
} // namespace ui