#include "setup_app.h" #include "platform/identity.h" #include "ui/fonts.h" #include "ui/widgets.h" namespace roro { using Step = SetupWizard::Step; SetupApp::SetupApp(Settings& settings, AppManager& apps) : apps_(apps), wizard_(settings, identity::defaultLongName(), identity::defaultShortName()) {} bool SetupApp::onKey(const KeyEvent& e) { requestRedraw(); bool choosing = wizard_.choiceCount() > 0; bool typing = wizard_.step() == Step::LongName || wizard_.step() == Step::ShortName; switch (e.key) { case Key::Select: if (choosing) wizard_.selectChoice(choices_.selected()); if (wizard_.next()) { if (wizard_.finished()) { apps_.endModal(); return true; } choices_.setCount(wizard_.choiceCount()); if (wizard_.choiceCount()) choices_.select(wizard_.selectedChoice()); } break; case Key::Back: case Key::Home: wizard_.back(); choices_.setCount(wizard_.choiceCount()); if (wizard_.choiceCount()) choices_.select(wizard_.selectedChoice()); break; case Key::Up: if (choosing) choices_.up(); break; case Key::Down: if (choosing) choices_.down(); break; case Key::Left: if (typing) wizard_.editor().left(); break; case Key::Right: if (typing) wizard_.editor().right(); break; case Key::Delete: if (typing) wizard_.editor().backspace(); break; case Key::Char: if (typing) wizard_.editor().insert(e.ch); break; default: break; } return true; } void SetupApp::draw(Canvas& c) { const auto& area = theme::kContent; auto heading = [&](const char* text) { c.setFont(&fonts::bold); c.setTextColor(theme::kAccent); c.drawString(text, 4, area.y + 3); c.setFont(&fonts::body); }; auto note = [&](const std::string& text, int y, uint16_t color = theme::kMuted) { auto lines = wrapText(text, area.w - 8, widgets::bodyMeasure(c)); c.setTextColor(color); for (size_t i = 0; i < lines.size(); i++) c.drawString(lines[i].c_str(), 4, y + i * theme::kLineHeight); }; switch (wizard_.step()) { case Step::Welcome: heading("Welcome to roro9stack"); note("Let's set up this device: your names on the mesh, your radio region and your timezone.", area.y + 22, theme::kText); note("Enter: continue", area.y + area.h - 14); break; case Step::LongName: heading("Long name (1/4)"); note("Shown to other mesh users. Up to 39 bytes.", area.y + 20); widgets::lineEditor(c, wizard_.editor(), {4, area.y + 50, area.w - 8, 0}); break; case Step::ShortName: heading("Short name (2/4)"); note("Up to 4 characters, shown where space is tight.", area.y + 20); widgets::lineEditor(c, wizard_.editor(), {4, area.y + 50, area.w - 8, 0}); break; case Step::Region: heading("Radio region (3/4)"); note("The radio only transmits once you confirm your region.", area.y + 18); widgets::list(c, choices_, {0, area.y + 48, area.w, 4 * theme::kLineHeight}, [this](int i) { return wizard_.choiceLabel(i); }); note("Enter: I confirm I'm in this region", area.y + area.h - 14); break; case Step::Timezone: heading("Timezone (4/4)"); widgets::list(c, choices_, {0, area.y + 20, area.w, 4 * theme::kLineHeight}, [this](int i) { return wizard_.choiceLabel(i); }); break; case Step::Done: heading("All set"); note("You can change all of this later in Settings.", area.y + 22, theme::kText); note("Enter: start `: go back", area.y + area.h - 14); break; } if (!wizard_.error().empty()) note(wizard_.error(), area.y + area.h - 14, theme::kWarning); } } // namespace roro