Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions _cmake/copy_styles_to_build_dir.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ if (NOT OMIT_FRONTEND_BUILD)
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/pagination.css"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/popup_menu.css"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/dropdown_menu.css"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/spotlight_overlay.css"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/tabs.css"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/tree.css"
"${CMAKE_BINARY_DIR}/styles/5cript-nui-components/message_strip.css"
Expand All @@ -32,6 +33,7 @@ if (NOT OMIT_FRONTEND_BUILD)
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/pagination.css" "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/pagination.css"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/popup_menu.css" "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/popup_menu.css"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/dropdown_menu.css" "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/dropdown_menu.css"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/spotlight_overlay.css" "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/spotlight_overlay.css"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/tabs.css" "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/tabs.css"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/tree.css" "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/tree.css"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/message_strip.css" "${CMAKE_BINARY_DIR}/styles/5cript-nui-components/message_strip.css"
Expand All @@ -49,6 +51,7 @@ if (NOT OMIT_FRONTEND_BUILD)
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/pagination.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/popup_menu.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/dropdown_menu.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/spotlight_overlay.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/tabs.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/tree.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/message_strip.css"
Expand Down
11 changes: 11 additions & 0 deletions frontend/include/frontend/events/frontend_events.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,19 @@ struct FrontendEvents : public AppWideEvents
{}

Nui::Observed<std::string> onNewSession{};
/// Fires (via `.modify()`) when the user clicks the "Add New" entry in
/// the Settings side panel. Carries no payload — the new-session dialog
/// owns the actual creation flow; this is purely an intent signal for
/// observers like the onboarding orchestrator.
Nui::Observed<bool> onAddNewSessionRequested{false};
Nui::Observed<bool> onLayoutsChanged{false};
Nui::Observed<bool> settingsOpen{false};
/// Latches to true the first time the Settings panel finishes its
/// initial 3-pass reveal (loader -> heavy subtree mount -> loader hidden).
/// Stays true for the rest of the session; consumers that need to wait
/// for the panel to be visually settled (e.g. onboarding step 2) can
/// gate on this rather than polling the DOM.
Nui::Observed<bool> settingsInitialLoadComplete{false};
Nui::Observed<bool> licensesOpen{false};
/// Opens settings and scrolls to the rendered element whose DOM id equals
/// this string. Settings walks up from the element to find its
Expand Down
58 changes: 58 additions & 0 deletions frontend/include/frontend/onboarding/onboarding.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#pragma once

#include <persistence/state_holder.hpp>
#include <frontend/events/frontend_events.hpp>

#include <roar/detail/pimpl_special_functions.hpp>

#include <memory>

namespace Frontend
{
/** @brief Strongly-typed step identifier for the onboarding state
* machine. Adding a new step is as simple as appending an
* enumerator and wiring it in `Onboarding::Implementation`. */
enum class OnboardingStep : unsigned
{
Inactive = 0,
OpenSettings = 1,
// User clicked the Settings button; the spotlight is hidden while we
// wait for the panel's initial 3-pass reveal to finish so step 2
// doesn't overlap with the loader.
WaitingForSettingsLoad = 2,
AddNewServer = 3,
Done = 4,
};

/** @brief DOM ids the onboarding orchestrator targets. The application
* attaches these ids to the actual buttons; keeping the
* constants here makes the binding explicit and grep-friendly. */
namespace OnboardingTargets
{
inline constexpr char toolbarSettingsButtonId[] = "toolbar-settings-button";
inline constexpr char settingsAddNewButtonId[] = "settings-add-new-button";
}

/** @brief First-launch onboarding flow. Auto-fires once when no servers
* are configured and the user has not previously completed or
* dismissed the flow. Persists the completion flag so it never
* reappears. */
class Onboarding
{
public:
Onboarding(Persistence::StateHolder* stateHolder, FrontendEvents* events);
ROAR_PIMPL_SPECIAL_FUNCTIONS(Onboarding);

/** @brief Evaluate trigger conditions and start the flow if they
* hold. Idempotent. Call from `MainPage::onSetupComplete`
* after persistence has loaded. */
void maybeStart();

/** @brief Force-start the flow (debug / manual replay entry point). */
void start();

private:
struct Implementation;
std::unique_ptr<Implementation> impl_;
};
} // namespace Frontend
2 changes: 2 additions & 0 deletions frontend/source/frontend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ target_sources(
terminal/ssh_engine.cpp
terminal/ssh_channel.cpp
components/progress_bar.cpp
onboarding/onboarding.cpp
file_explorer/side_model.cpp
file_explorer/remote_side_model.cpp
file_explorer/local_side_model.cpp
Expand Down Expand Up @@ -289,6 +290,7 @@ nui_prepare_emscripten_target(
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/popup_menu.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/dropdown_menu.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/resizeable_table.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/spotlight_overlay.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/select.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/switch.css"
"${CMAKE_SOURCE_DIR}/dependencies/5cript-nui-components/styles/tabs.css"
Expand Down
18 changes: 17 additions & 1 deletion frontend/source/frontend/main_page.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <frontend/dialog/input_dialog.hpp>
#include <frontend/dialog/archive_transfer_dialog.hpp>
#include <frontend/dialog/direct_connect_dialog.hpp>
#include <frontend/onboarding/onboarding.hpp>
#include <log/log.hpp>

#include <nui/frontend/api/timer.hpp>
Expand All @@ -34,6 +35,7 @@ struct MainPage::Implementation
SessionArea sessionArea;
Settings settings;
Licenses licenses;
Frontend::Onboarding onboarding;
Nui::Observed<bool> darkMode;
Nui::TimerHandle setupWait;

Expand All @@ -54,6 +56,7 @@ struct MainPage::Implementation
return sessionArea.getActiveSessionLayout();
}, newItemAskDialog, confirmDialog, multiInputDialog}
, licenses{events}
, onboarding{stateHolder, events}
, darkMode{true}
, setupWait{}
{
Expand Down Expand Up @@ -83,16 +86,26 @@ void MainPage::onSetupComplete()
auto showPersistenceWarning = [this, response]()
{
if (!response.hasOwnProperty("warning"))
{
impl_->onboarding.maybeStart();
return;
}
const auto warning = response["warning"].as<std::string>();
if (warning.empty())
{
impl_->onboarding.maybeStart();
return;
}
impl_->confirmDialog.open({
.styleVariant = ScriptNuiComponents::StyleVariant::Warning,
.headerText = language->get("persistence", "warningLoadingState"),
.text = fmt::format(fmt::runtime(language->get("persistence", "loadedWithWarnings")), warning),
.buttons = ConfirmDialog::Button::Ok,
.neverShowAgainId = "persistenceLoadWarning",
.onClose = [this](auto)
{
impl_->onboarding.maybeStart();
},
});
};

Expand All @@ -103,7 +116,10 @@ void MainPage::onSetupComplete()
.headerText = language->get("rootWarning", "header"),
.text = language->get("rootWarning", "text"),
.buttons = ConfirmDialog::Button::Ok,
.onClose = [showPersistenceWarning](auto) { showPersistenceWarning(); },
.onClose = [showPersistenceWarning](auto)
{
showPersistenceWarning();
},
});
return;
}
Expand Down
Loading
Loading