@@ -1,17 +1,318 @@
+#![allow(unused, dead_code)]
use command_palette_hooks::CommandPaletteFilter;
use feature_flags::FeatureFlagAppExt as _;
-use gpui::App;
+use gpui::{Entity, EventEmitter, FocusHandle, Focusable, WeakEntity, actions, prelude::*};
use settings_ui::SettingsUiFeatureFlag;
+use ui::prelude::*;
use workspace::Workspace;
-use gpui::actions;
+actions!(
+ onboarding,
+ [
+ ShowOnboarding,
+ JumpToBasics,
+ JumpToEditing,
+ JumpToAiSetup,
+ JumpToWelcome,
+ NextPage,
+ PreviousPage,
+ ToggleFocus,
+ ResetOnboarding,
+ ]
+);
-actions!(onboarding, [ShowOnboarding]);
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum OnboardingPage {
+ Basics,
+ Editing,
+ AiSetup,
+ Welcome,
+}
+
+impl OnboardingPage {
+ fn next(&self) -> Option<Self> {
+ match self {
+ Self::Basics => Some(Self::Editing),
+ Self::Editing => Some(Self::AiSetup),
+ Self::AiSetup => Some(Self::Welcome),
+ Self::Welcome => None,
+ }
+ }
+
+ fn previous(&self) -> Option<Self> {
+ match self {
+ Self::Basics => None,
+ Self::Editing => Some(Self::Basics),
+ Self::AiSetup => Some(Self::Editing),
+ Self::Welcome => Some(Self::AiSetup),
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum OnboardingFocus {
+ Navigation,
+ Page,
+}
+
+pub struct OnboardingUI {
+ focus_handle: FocusHandle,
+ current_page: OnboardingPage,
+ current_focus: OnboardingFocus,
+ completed_pages: [bool; 4],
+ basics_page: Entity<BasicsPage>,
+ editing_page: Entity<EditingPage>,
+ ai_setup_page: Entity<AiSetupPage>,
+ welcome_page: Entity<WelcomePage>,
+}
+
+pub struct BasicsPage {
+ focus_handle: FocusHandle,
+ parent: WeakEntity<OnboardingUI>,
+}
+
+pub struct EditingPage {
+ focus_handle: FocusHandle,
+ parent: WeakEntity<OnboardingUI>,
+}
+
+pub struct AiSetupPage {
+ focus_handle: FocusHandle,
+ parent: WeakEntity<OnboardingUI>,
+}
+
+pub struct WelcomePage {
+ focus_handle: FocusHandle,
+ parent: WeakEntity<OnboardingUI>,
+}
+
+// Event types for communication between pages and main UI
+#[derive(Clone)]
+pub enum OnboardingEvent {
+ PageCompleted(OnboardingPage),
+}
+
+// Implement EventEmitter for all entities
+impl EventEmitter<OnboardingEvent> for OnboardingUI {}
+impl EventEmitter<OnboardingEvent> for BasicsPage {}
+impl EventEmitter<OnboardingEvent> for EditingPage {}
+impl EventEmitter<OnboardingEvent> for AiSetupPage {}
+impl EventEmitter<OnboardingEvent> for WelcomePage {}
+
+// Implement Focusable for all entities
+impl Focusable for OnboardingUI {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
+ self.focus_handle.clone()
+ }
+}
+
+impl Focusable for BasicsPage {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
+ self.focus_handle.clone()
+ }
+}
+
+impl Focusable for EditingPage {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
+ self.focus_handle.clone()
+ }
+}
+
+impl Focusable for AiSetupPage {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
+ self.focus_handle.clone()
+ }
+}
+
+impl Focusable for WelcomePage {
+ fn focus_handle(&self, _cx: &App) -> FocusHandle {
+ self.focus_handle.clone()
+ }
+}
+
+// Placeholder Render implementations
+impl Render for OnboardingUI {
+ fn render(
+ &mut self,
+ _window: &mut gpui::Window,
+ _cx: &mut Context<Self>,
+ ) -> impl gpui::IntoElement {
+ h_flex()
+ .w(px(904.))
+ .h(px(500.))
+ .gap(px(48.))
+ .child(v_flex().h_full().w(px(256.)).child("nav"))
+ }
+}
+
+impl Render for BasicsPage {
+ fn render(
+ &mut self,
+ _window: &mut gpui::Window,
+ _cx: &mut Context<Self>,
+ ) -> impl gpui::IntoElement {
+ gpui::div()
+ }
+}
+
+impl Render for EditingPage {
+ fn render(
+ &mut self,
+ _window: &mut gpui::Window,
+ _cx: &mut Context<Self>,
+ ) -> impl gpui::IntoElement {
+ gpui::div()
+ }
+}
+
+impl Render for AiSetupPage {
+ fn render(
+ &mut self,
+ _window: &mut gpui::Window,
+ _cx: &mut Context<Self>,
+ ) -> impl gpui::IntoElement {
+ gpui::div()
+ }
+}
+
+impl Render for WelcomePage {
+ fn render(
+ &mut self,
+ _window: &mut gpui::Window,
+ _cx: &mut Context<Self>,
+ ) -> impl gpui::IntoElement {
+ gpui::div()
+ }
+}
+
+impl OnboardingUI {
+ pub fn new(cx: &mut Context<Self>) -> Self {
+ let parent_handle = cx.entity().downgrade();
+
+ let basics_page = cx.new(|cx| BasicsPage {
+ focus_handle: cx.focus_handle(),
+ parent: parent_handle.clone(),
+ });
+
+ let editing_page = cx.new(|cx| EditingPage {
+ focus_handle: cx.focus_handle(),
+ parent: parent_handle.clone(),
+ });
+
+ let ai_setup_page = cx.new(|cx| AiSetupPage {
+ focus_handle: cx.focus_handle(),
+ parent: parent_handle.clone(),
+ });
+
+ let welcome_page = cx.new(|cx| WelcomePage {
+ focus_handle: cx.focus_handle(),
+ parent: parent_handle.clone(),
+ });
+
+ Self {
+ focus_handle: cx.focus_handle(),
+ current_page: OnboardingPage::Basics,
+ current_focus: OnboardingFocus::Page,
+ completed_pages: [false; 4],
+ basics_page,
+ editing_page,
+ ai_setup_page,
+ welcome_page,
+ }
+ }
+
+ fn jump_to_page(
+ &mut self,
+ page: OnboardingPage,
+ _window: &mut gpui::Window,
+ cx: &mut Context<Self>,
+ ) {
+ self.current_page = page;
+ cx.notify();
+ }
+
+ fn next_page(&mut self, _window: &mut gpui::Window, cx: &mut Context<Self>) {
+ if let Some(next) = self.current_page.next() {
+ self.current_page = next;
+ cx.notify();
+ }
+ }
+
+ fn previous_page(&mut self, _window: &mut gpui::Window, cx: &mut Context<Self>) {
+ if let Some(prev) = self.current_page.previous() {
+ self.current_page = prev;
+ cx.notify();
+ }
+ }
+
+ fn toggle_focus(&mut self, _window: &mut gpui::Window, cx: &mut Context<Self>) {
+ self.current_focus = match self.current_focus {
+ OnboardingFocus::Navigation => OnboardingFocus::Page,
+ OnboardingFocus::Page => OnboardingFocus::Navigation,
+ };
+ cx.notify();
+ }
+
+ fn reset(&mut self, _window: &mut gpui::Window, cx: &mut Context<Self>) {
+ self.current_page = OnboardingPage::Basics;
+ self.current_focus = OnboardingFocus::Page;
+ self.completed_pages = [false; 4];
+ cx.notify();
+ }
+
+ fn mark_page_completed(
+ &mut self,
+ page: OnboardingPage,
+ _window: &mut gpui::Window,
+ cx: &mut Context<Self>,
+ ) {
+ let index = match page {
+ OnboardingPage::Basics => 0,
+ OnboardingPage::Editing => 1,
+ OnboardingPage::AiSetup => 2,
+ OnboardingPage::Welcome => 3,
+ };
+ self.completed_pages[index] = true;
+ cx.notify();
+ }
+}
pub fn init(cx: &mut App) {
cx.observe_new(|workspace: &mut Workspace, _, _cx| {
workspace.register_action(|_workspace, _: &ShowOnboarding, _window, _cx| {
- // Onboarding implementation will go here
+ // Show onboarding implementation will go here
+ });
+
+ workspace.register_action(|_workspace, _: &JumpToBasics, _window, _cx| {
+ // Jump to basics implementation
+ });
+
+ workspace.register_action(|_workspace, _: &JumpToEditing, _window, _cx| {
+ // Jump to editing implementation
+ });
+
+ workspace.register_action(|_workspace, _: &JumpToAiSetup, _window, _cx| {
+ // Jump to AI setup implementation
+ });
+
+ workspace.register_action(|_workspace, _: &JumpToWelcome, _window, _cx| {
+ // Jump to welcome implementation
+ });
+
+ workspace.register_action(|_workspace, _: &NextPage, _window, _cx| {
+ // Next page implementation
+ });
+
+ workspace.register_action(|_workspace, _: &PreviousPage, _window, _cx| {
+ // Previous page implementation
+ });
+
+ workspace.register_action(|_workspace, _: &ToggleFocus, _window, _cx| {
+ // Toggle focus implementation
+ });
+
+ workspace.register_action(|_workspace, _: &ResetOnboarding, _window, _cx| {
+ // Reset onboarding implementation
});
})
.detach();