Add Borealis GUI for patch extraction on Switch.
All checks were successful
Build NRO / build (push) Successful in 1m48s
All checks were successful
Build NRO / build (push) Successful in 1m48s
Replace the console UI with a Borealis-based flow, bundle ROMFS assets and borealis as a submodule, and apply small upstream patches at build time. Self-delete runs after romfsExit on quit so the NRO can be removed like the old console build.
This commit is contained in:
201
source/patch_activity.cpp
Normal file
201
source/patch_activity.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
#include "patch_activity.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
PatchActivity::PatchActivity() {
|
||||
extractor = std::make_unique<PatchExtractor>();
|
||||
|
||||
extractTimer.setCallback([this]() { onExtractTick(); });
|
||||
extractTimer.setPeriod(0);
|
||||
}
|
||||
|
||||
PatchActivity::~PatchActivity() {
|
||||
extractTimer.stop();
|
||||
if (extractor) extractor->close();
|
||||
}
|
||||
|
||||
brls::View* PatchActivity::createContentView() {
|
||||
frame = new brls::AppletFrame();
|
||||
frame->setTitle("PatchExtractor");
|
||||
frame->setIconFromRes("img/omninx.png");
|
||||
|
||||
contentBox = new brls::Box(brls::Axis::COLUMN);
|
||||
contentBox->setAlignItems(brls::AlignItems::CENTER);
|
||||
contentBox->setJustifyContent(brls::JustifyContent::CENTER);
|
||||
contentBox->setMargins(40, 40, 40, 40);
|
||||
contentBox->setGrow(1.0f);
|
||||
|
||||
titleLabel = new brls::Label();
|
||||
titleLabel->setText("PatchExtractor");
|
||||
titleLabel->setFontSize(28);
|
||||
titleLabel->setHorizontalAlign(brls::HorizontalAlign::CENTER);
|
||||
titleLabel->setMarginBottom(16);
|
||||
|
||||
messageLabel = new brls::Label();
|
||||
messageLabel->setHorizontalAlign(brls::HorizontalAlign::CENTER);
|
||||
messageLabel->setMarginBottom(12);
|
||||
|
||||
detailLabel = new brls::Label();
|
||||
detailLabel->setHorizontalAlign(brls::HorizontalAlign::CENTER);
|
||||
detailLabel->setFontSize(14);
|
||||
detailLabel->setMarginBottom(24);
|
||||
detailLabel->setVisibility(brls::Visibility::GONE);
|
||||
|
||||
progressLabel = new brls::Label();
|
||||
progressLabel->setHorizontalAlign(brls::HorizontalAlign::CENTER);
|
||||
progressLabel->setFontSize(16);
|
||||
progressLabel->setMarginBottom(8);
|
||||
progressLabel->setVisibility(brls::Visibility::GONE);
|
||||
|
||||
progressTrack = new brls::Box(brls::Axis::ROW);
|
||||
progressTrack->setWidth(600);
|
||||
progressTrack->setHeight(12);
|
||||
progressTrack->setMarginBottom(24);
|
||||
progressTrack->setVisibility(brls::Visibility::GONE);
|
||||
|
||||
progressFill = new brls::Rectangle(nvgRGB(0, 190, 80));
|
||||
progressFill->setHeight(12);
|
||||
progressFill->setWidth(0);
|
||||
progressTrack->addView(progressFill);
|
||||
|
||||
actionButton = new brls::Button();
|
||||
actionButton->setStyle(&brls::BUTTONSTYLE_PRIMARY);
|
||||
actionButton->setWidth(320);
|
||||
actionButton->registerClickAction([this](brls::View* view) { return onExtractClicked(view); });
|
||||
|
||||
contentBox->addView(titleLabel);
|
||||
contentBox->addView(messageLabel);
|
||||
contentBox->addView(detailLabel);
|
||||
contentBox->addView(progressLabel);
|
||||
contentBox->addView(progressTrack);
|
||||
contentBox->addView(actionButton);
|
||||
|
||||
frame->setContentView(contentBox);
|
||||
return frame;
|
||||
}
|
||||
|
||||
void PatchActivity::onContentAvailable() {
|
||||
registerExitAction(brls::BUTTON_START);
|
||||
|
||||
if (extractor->open()) {
|
||||
char detail[128];
|
||||
snprintf(detail, sizeof(detail), "%lu Eintraege in patches.zip", extractor->getTotal());
|
||||
detailLabel->setText(detail);
|
||||
showScreen(Screen::Ready);
|
||||
} else {
|
||||
detailLabel->setText(PatchExtractor::PATCHES_ZIP);
|
||||
detailLabel->setVisibility(brls::Visibility::VISIBLE);
|
||||
showScreen(Screen::Error);
|
||||
}
|
||||
}
|
||||
|
||||
void PatchActivity::showScreen(Screen screen) {
|
||||
currentScreen = screen;
|
||||
|
||||
progressLabel->setVisibility(brls::Visibility::GONE);
|
||||
progressTrack->setVisibility(brls::Visibility::GONE);
|
||||
actionButton->setVisibility(brls::Visibility::VISIBLE);
|
||||
|
||||
switch (screen) {
|
||||
case Screen::Error:
|
||||
titleLabel->setText("Fehler");
|
||||
messageLabel->setText("patches.zip nicht gefunden!");
|
||||
detailLabel->setVisibility(brls::Visibility::VISIBLE);
|
||||
actionButton->setText("Beenden");
|
||||
actionButton->registerClickAction([](brls::View*) {
|
||||
brls::Application::quit();
|
||||
return true;
|
||||
});
|
||||
brls::Application::giveFocus(actionButton);
|
||||
break;
|
||||
|
||||
case Screen::Ready:
|
||||
titleLabel->setText("OmniNX OC");
|
||||
messageLabel->setText("SaltyNX / FPSLocker Patch Installer");
|
||||
detailLabel->setVisibility(brls::Visibility::VISIBLE);
|
||||
actionButton->setText("Entpacken");
|
||||
actionButton->registerClickAction([this](brls::View* view) { return onExtractClicked(view); });
|
||||
brls::Application::giveFocus(actionButton);
|
||||
break;
|
||||
|
||||
case Screen::Extracting:
|
||||
titleLabel->setText("Entpacken...");
|
||||
messageLabel->setText("Bitte nicht beenden, bis der Vorgang abgeschlossen ist!");
|
||||
detailLabel->setVisibility(brls::Visibility::VISIBLE);
|
||||
progressLabel->setVisibility(brls::Visibility::VISIBLE);
|
||||
progressTrack->setVisibility(brls::Visibility::VISIBLE);
|
||||
actionButton->setVisibility(brls::Visibility::GONE);
|
||||
break;
|
||||
|
||||
case Screen::Done: {
|
||||
titleLabel->setText("Fertig");
|
||||
const unsigned long ok = extractor->getExtracted() - extractor->getSkipped();
|
||||
char msg[128];
|
||||
if (extractor->getSkipped() == 0 && extractor->cleanupOk())
|
||||
snprintf(msg, sizeof(msg), "Alles erledigt! %lu / %lu entpackt.", ok, extractor->getTotal());
|
||||
else
|
||||
snprintf(msg, sizeof(msg), "Entpacken abgeschlossen. %lu / %lu entpackt.", ok, extractor->getTotal());
|
||||
messageLabel->setText(msg);
|
||||
|
||||
if (extractor->getSkipped() > 0) {
|
||||
char err[64];
|
||||
snprintf(err, sizeof(err), "%lu Eintraege fehlgeschlagen.", extractor->getSkipped());
|
||||
detailLabel->setText(err);
|
||||
detailLabel->setVisibility(brls::Visibility::VISIBLE);
|
||||
} else if (!extractor->cleanupOk()) {
|
||||
detailLabel->setText("Aufräumen teilweise fehlgeschlagen.");
|
||||
detailLabel->setVisibility(brls::Visibility::VISIBLE);
|
||||
} else {
|
||||
detailLabel->setVisibility(brls::Visibility::GONE);
|
||||
}
|
||||
|
||||
actionButton->setText("Beenden");
|
||||
actionButton->setVisibility(brls::Visibility::VISIBLE);
|
||||
actionButton->registerClickAction([](brls::View*) {
|
||||
brls::Application::quit();
|
||||
return true;
|
||||
});
|
||||
brls::Application::unblockInputs();
|
||||
brls::Application::giveFocus(actionButton);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PatchActivity::onExtractClicked(brls::View* view) {
|
||||
(void)view;
|
||||
if (currentScreen != Screen::Ready) return false;
|
||||
startExtraction();
|
||||
return true;
|
||||
}
|
||||
|
||||
void PatchActivity::startExtraction() {
|
||||
showScreen(Screen::Extracting);
|
||||
brls::Application::blockInputs();
|
||||
updateProgressUi();
|
||||
extractTimer.start();
|
||||
}
|
||||
|
||||
void PatchActivity::onExtractTick() {
|
||||
if (!extractor->step()) {
|
||||
extractTimer.stop();
|
||||
extractor->close();
|
||||
extractor->cleanup();
|
||||
updateProgressUi();
|
||||
showScreen(Screen::Done);
|
||||
return;
|
||||
}
|
||||
updateProgressUi();
|
||||
}
|
||||
|
||||
void PatchActivity::updateProgressUi() {
|
||||
const int pct = extractor->getProgressPercent();
|
||||
progressLabel->setText(std::to_string(pct) + "%");
|
||||
|
||||
constexpr float trackWidth = 600.0f;
|
||||
progressFill->setWidth(trackWidth * static_cast<float>(pct) / 100.0f);
|
||||
|
||||
const std::string& file = extractor->getCurrentFile();
|
||||
if (!file.empty())
|
||||
detailLabel->setText(file);
|
||||
}
|
||||
Reference in New Issue
Block a user