Skip to content

Commit 9bb9346

Browse files
committed
fix: Fix various UX issues and improve error reporting
1 parent e1a1a82 commit 9bb9346

5 files changed

Lines changed: 148 additions & 54 deletions

File tree

src/components/checkbox.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
using namespace ImGui;
4141

42-
const CheckBoxState* RenderCheckBox(bool checked, const char* description, const char* tooltipText, bool disabled, bool endChild)
42+
const CheckBoxState* RenderCheckBox(bool checked, std::string description, std::string tooltipText, bool disabled, bool endChild)
4343
{
4444
static std::unordered_map<std::string, CheckBoxState> checkBoxStates;
4545
auto& state = checkBoxStates.try_emplace(description, checked).first->second;
@@ -66,15 +66,15 @@ const CheckBoxState* RenderCheckBox(bool checked, const char* description, const
6666
EndChild();
6767
SameLine(0, ScaleX(20));
6868
SetCursorPosY(GetCursorPosY() + ScaleY(3));
69-
Text(description);
69+
Text(description.c_str());
7070
} else {
7171
std::string checkBoxMessage = " " + std::string(description);
7272

7373
Checkbox(checkBoxMessage.c_str(), &state.isChecked);
7474
EndDisabled();
7575
}
7676

77-
if (tooltipText) {
77+
if (!tooltipText.empty()) {
7878
float autoUpdateColor = EaseInOutFloat(description, 0.f, 1.f, state.isHovered, 0.3f);
7979

8080
if (autoUpdateColor) {
@@ -85,7 +85,7 @@ const CheckBoxState* RenderCheckBox(bool checked, const char* description, const
8585
PushStyleVar(ImGuiStyleVar_Alpha, autoUpdateColor);
8686
PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.098f, 0.102f, 0.11f, 1.0f));
8787

88-
SetTooltip(tooltipText);
88+
SetTooltip(tooltipText.c_str());
8989

9090
PopStyleVar(3);
9191
PopStyleColor();

src/include/components.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/include/http.h

Lines changed: 66 additions & 23 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/routes/install_prompt.cc

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include <util.h>
4747
#include <imgui_markdown.h>
4848
#include <mini/ini.h>
49+
#include <format>
4950

5051
using namespace ImGui;
5152

@@ -113,23 +114,38 @@ static void UpdateSelectedRelease(const std::string& tag)
113114

114115
const bool FetchVersionInfo()
115116
{
117+
constexpr int MAX_PAGES = 50; // Safety limit (5000 releases max)
118+
116119
// fetch all pages of releases from GitHub (per_page=100)
117120
releasesList = nlohmann::json::array();
118-
int page = 1;
119-
for (;;) {
121+
122+
for (int page = 1; page <= MAX_PAGES; ++page) {
120123
const auto url = std::format("https://api.github.com/repos/SteamClientHomebrew/Millennium/releases?per_page=100&page={}", page);
121-
const auto response = Http::Get(url.c_str(), false);
124+
const auto response = Http::GetEx(url.c_str());
125+
126+
if (response.isNetworkError()) {
127+
if (page == 1) {
128+
ShowMessageBox("Whoops!", "Failed to connect to the GitHub API! Make sure you have a valid internet connection.", Error);
129+
return false;
130+
}
131+
break;
132+
}
133+
134+
if (response.isRateLimited()) {
135+
ShowMessageBox("Whoops!", "GitHub API rate limit exceeded. Please wait a few minutes and try again.", Error);
136+
return false;
137+
}
122138

123-
if (response.empty()) {
139+
if (!response.ok()) {
124140
if (page == 1) {
125-
ShowMessageBox("Whoops!", "Failed to fetch version information from the GitHub API! Make sure you have a valid internet connection.", Error);
141+
ShowMessageBox("Whoops!", std::format("Failed to fetch version information (HTTP {}). Please try again later.", response.statusCode), Error);
126142
return false;
127143
}
128144
break;
129145
}
130146

131147
try {
132-
auto pageJson = nlohmann::json::parse(response);
148+
auto pageJson = nlohmann::json::parse(response.body);
133149
if (!pageJson.is_array() || pageJson.empty())
134150
break;
135151

@@ -138,11 +154,9 @@ const bool FetchVersionInfo()
138154
releasesList.push_back(r);
139155
} catch (const nlohmann::json::exception& e) {
140156
std::cerr << "JSON parse error: " << e.what() << std::endl;
141-
ShowMessageBox("Whoops!", "Failed to parse version information from the GitHub API! Please wait a moment and try again, you're likely rate limited.", Error);
157+
ShowMessageBox("Whoops!", "Failed to parse version information from the GitHub API!", Error);
142158
return false;
143159
}
144-
145-
page += 1;
146160
}
147161

148162
// choose default selectedRelease: prefer latest non-prerelease, fall back to first release
@@ -202,7 +216,12 @@ const bool FetchVersionInfo()
202216
}
203217
}
204218

205-
return hasFoundReleaseInfo;
219+
if (!hasFoundReleaseInfo) {
220+
ShowMessageBox("Whoops!", "We failed to find the latest Millennium release!", Error);
221+
return false;
222+
}
223+
224+
return true;
206225
}
207226

208227
const void RenderInstallPrompt(std::shared_ptr<RouterNav> router, float xPos)

src/routes/uninstall_select.cc

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ const void RenderComponents()
211211
{
212212
/** Not currently uninstalling, the user is selecting components to be uninstalled */
213213
if (!isUninstalling) {
214-
state.isSelected = RenderCheckBox(state.isSelected, formattedComponent.c_str(), strPathList.c_str(), false, true)->isChecked;
214+
state.isSelected = RenderCheckBox(state.isSelected, formattedComponent, strPathList, false, true)->isChecked;
215215
continue;
216216
}
217217

@@ -348,34 +348,66 @@ const void RenderUninstallSelect(std::shared_ptr<RouterNav> router, float xPos)
348348
RenderBottomNavBar("InstallPrompt", xPos, [router, xPos]
349349
{
350350
static bool isButtonHovered = false;
351-
float currentColor = EaseInOutFloat("##NextButton", 1.0f, 0.8f, isButtonHovered, 0.3f);
352-
353-
PushStyleColor(ImGuiCol_Button, ImVec4(currentColor, currentColor, currentColor, 1.0f));
354-
PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(currentColor, currentColor, currentColor, 1.0f));
355-
PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
356351

357352
if (uninstallFinished) {
353+
float currentColor = EaseInOutFloat("##NextButton", 1.0f, 0.8f, isButtonHovered, 0.3f);
354+
355+
PushStyleColor(ImGuiCol_Button, ImVec4(currentColor, currentColor, currentColor, 1.0f));
356+
PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(currentColor, currentColor, currentColor, 1.0f));
357+
PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
358+
358359
if (Button("Exit", ImVec2(xPos + GetContentRegionAvail().x, GetContentRegionAvail().y))) {
359360
std::exit(0);
360361
}
362+
363+
if (isButtonHovered) {
364+
SetMouseCursor(ImGuiMouseCursor_Hand);
365+
}
366+
367+
PopStyleColor(3);
368+
isButtonHovered = IsItemHovered() || (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && IsMouseDown(ImGuiMouseButton_Left));
369+
} else if (isUninstalling) {
370+
PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.6f, 0.6f, 0.6f, 1.0f));
371+
PushStyleVar(ImGuiStyleVar_ChildRounding, ScaleX(10.0f));
372+
373+
const float childWidth = GetContentRegionAvail().x;
374+
const float childHeight = GetContentRegionAvail().y;
375+
376+
BeginChild("##ButtonIsBusy", { xPos + childWidth, childHeight }, true, ImGuiWindowFlags_NoScrollbar);
377+
{
378+
const float spinnerSize = ScaleX(12.f);
379+
SetCursorPos({ childWidth / 2 - spinnerSize, spinnerSize });
380+
381+
Spinner<SpinnerTypeT::e_st_ang>("SpinnerAngNoBg", Radius{ spinnerSize }, Thickness{ ScaleX(2) }, Color{ ImColor(0, 0, 0, 255) },
382+
BgColor{ ImColor(255, 255, 255, 0) }, Speed{ 6 }, Angle{ IM_PI }, Mode{ 0 });
383+
}
384+
EndChild();
385+
PopStyleColor();
386+
PopStyleVar();
387+
388+
if (IsItemHovered()) {
389+
SetMouseCursor(ImGuiMouseCursor_NotAllowed);
390+
}
361391
} else {
362-
if (Button("Uninstall", ImVec2(xPos + GetContentRegionAvail().x, GetContentRegionAvail().y))) {
363-
if (isUninstalling) {
364-
return;
365-
}
392+
float currentColor = EaseInOutFloat("##NextButton", 1.0f, 0.8f, isButtonHovered, 0.3f);
393+
394+
PushStyleColor(ImGuiCol_Button, ImVec4(currentColor, currentColor, currentColor, 1.0f));
395+
PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(currentColor, currentColor, currentColor, 1.0f));
396+
PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
366397

398+
if (Button("Uninstall", ImVec2(xPos + GetContentRegionAvail().x, GetContentRegionAvail().y))) {
367399
std::cout << "Uninstalling components..." << std::endl;
368400

369401
isUninstalling = true;
370402
std::thread(StartUninstall).detach();
371403
}
372-
}
373404

374-
if (isButtonHovered) {
375-
SetMouseCursor(ImGuiMouseCursor_Hand);
376-
}
405+
if (isButtonHovered) {
406+
SetMouseCursor(ImGuiMouseCursor_Hand);
407+
}
377408

378-
PopStyleColor(3);
379-
isButtonHovered = IsItemHovered() || (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && IsMouseDown(ImGuiMouseButton_Left));
409+
PopStyleColor(3);
410+
isButtonHovered = IsItemHovered() || (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && IsMouseDown(ImGuiMouseButton_Left));
411+
}
380412
});
381413
}

0 commit comments

Comments
 (0)