#include "patch_activity.hpp" #include PatchActivity::PatchActivity() { extractor = std::make_unique(); 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(pct) / 100.0f); const std::string& file = extractor->getCurrentFile(); if (!file.empty()) detailLabel->setText(file); }