diff --git a/src/app.cpp b/src/app.cpp index 3634538..043c1dc 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -1394,7 +1394,10 @@ void App::render() if (show_about_) { ui::RenderAboutDialog(this, &show_about_); } - + + // Lite first-run welcome: prompt to create/restore when no wallet file exists yet. + renderLiteFirstRunPrompt(); + if (show_import_key_) { renderImportKeyDialog(); } @@ -1785,6 +1788,61 @@ void App::reloadThemeImages(const std::string& bgPath, const std::string& logoPa coin_logo_h_ = 0; } +void App::renderLiteFirstRunPrompt() +{ + // Lite-only: a brief welcome shown when no wallet file exists yet (full-node uses the wizard, + // which is skipped in lite). Routes to the existing create/restore + Backup flows in Settings. + if (!lite_wallet_ || lite_firstrun_dismissed_) return; + if (lite_wallet_->walletOpen() || lite_wallet_->walletExists()) return; + + if (!ImGui::IsPopupOpen("##LiteFirstRun")) ImGui::OpenPopup("##LiteFirstRun"); + + ImGuiViewport* vp = ImGui::GetMainViewport(); + ImGui::SetNextWindowPos(ImVec2(vp->Pos.x + vp->Size.x * 0.5f, vp->Pos.y + vp->Size.y * 0.5f), + ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); + if (ImGui::BeginPopupModal("##LiteFirstRun", nullptr, + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar)) { + ImGui::PushFont(ui::material::Type().subtitle1()); + ImGui::TextUnformatted(TR("lite_welcome_title")); + ImGui::PopFont(); + ImGui::Spacing(); + ImGui::PushTextWrapPos(ImGui::GetCursorPosX() + 360.0f); + ImGui::TextUnformatted(TR("lite_welcome_msg")); + ImGui::PopTextWrapPos(); + ImGui::Spacing(); + ImGui::Spacing(); + + const float btnW = 170.0f; + if (ImGui::Button(TR("lite_welcome_create"), ImVec2(btnW, 0))) { + // One-click create (unencrypted by default); the user backs up the seed next via the + // Settings → Backup & keys flow, where the seed can be revealed and copied. + const auto result = lite_wallet_->createWallet(wallet::LiteWalletCreateRequest{}); + if (result.walletReady) { + ui::Notifications::instance().success(TR("lite_welcome_created"), 8.0f); + setCurrentPage(ui::NavPage::Settings); + } else { + ui::Notifications::instance().warning(TR("lite_welcome_create_failed")); + } + lite_firstrun_dismissed_ = true; + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + if (ImGui::Button(TR("lite_welcome_restore"), ImVec2(btnW, 0))) { + ui::Notifications::instance().info(TR("lite_welcome_restore_hint"), 8.0f); + setCurrentPage(ui::NavPage::Settings); + lite_firstrun_dismissed_ = true; + ImGui::CloseCurrentPopup(); + } + ImGui::Spacing(); + if (ImGui::Button(TR("lite_welcome_later"), + ImVec2(btnW * 2 + ImGui::GetStyle().ItemSpacing.x, 0))) { + lite_firstrun_dismissed_ = true; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } +} + void App::renderAboutDialog() { auto dlg = ui::schema::UI().drawElement("inline-dialogs", "about"); diff --git a/src/app.h b/src/app.h index 45af2dd..acf68e9 100644 --- a/src/app.h +++ b/src/app.h @@ -425,6 +425,8 @@ private: // One-shot guard: auto-open an existing lite wallet on the first update() tick (kept off // init() so a slow initialize_existing network call doesn't freeze startup before the window). bool lite_autoopen_done_ = false; + // Lite first-run welcome prompt: dismissed for the session once the user picks an action. + bool lite_firstrun_dismissed_ = false; std::unique_ptr daemon_controller_; std::unique_ptr xmrig_manager_; util::AsyncTaskManager async_tasks_; @@ -648,6 +650,7 @@ private: // Private methods - rendering void renderStatusBar(); void renderAboutDialog(); + void renderLiteFirstRunPrompt(); // lite-only welcome modal when no wallet exists yet void renderImportKeyDialog(); void renderExportKeyDialog(); void renderBackupDialog(); diff --git a/src/util/i18n.cpp b/src/util/i18n.cpp index b9b3862..eab4601 100644 --- a/src/util/i18n.cpp +++ b/src/util/i18n.cpp @@ -579,6 +579,15 @@ void I18n::loadBuiltinEnglish() // strings when no wallet is open (isConnected() tracks the lite wallet in lite builds). strings_["lite_no_wallet"] = "No wallet open — create or open one in Settings"; strings_["lite_no_wallet_short"] = "No wallet open"; + // Lite first-run welcome prompt (shown when no wallet file exists yet). + strings_["lite_welcome_title"] = "Welcome to ObsidianDragon Lite"; + strings_["lite_welcome_msg"] = "You don't have a wallet yet. Create a new one or restore from a recovery phrase."; + strings_["lite_welcome_create"] = "Create new wallet"; + strings_["lite_welcome_restore"] = "Restore from seed"; + strings_["lite_welcome_later"] = "Later"; + strings_["lite_welcome_created"] = "Wallet created — back up your recovery phrase now in Settings → Backup & keys"; + strings_["lite_welcome_restore_hint"] = "Restore your wallet under Settings → Lite wallet request"; + strings_["lite_welcome_create_failed"] = "Could not create wallet"; // Send Tab strings_["pay_from"] = "Pay From";