diff --git a/dash-frontend/assets/dashboard/splash.png b/dash-frontend/assets/dashboard/splash.png
new file mode 100644
index 00000000..15a9b387
Binary files /dev/null and b/dash-frontend/assets/dashboard/splash.png differ
diff --git a/dash-frontend/assets/dashboard/welcome.svg b/dash-frontend/assets/dashboard/welcome.svg
new file mode 100644
index 00000000..1e79ee67
--- /dev/null
+++ b/dash-frontend/assets/dashboard/welcome.svg
@@ -0,0 +1 @@
+
diff --git a/dash-frontend/assets/gui/tab/welcome.xml b/dash-frontend/assets/gui/tab/welcome.xml
new file mode 100644
index 00000000..4753bd37
--- /dev/null
+++ b/dash-frontend/assets/gui/tab/welcome.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
diff --git a/dash-frontend/assets/gui/tab/welcome_page_0.xml b/dash-frontend/assets/gui/tab/welcome_page_0.xml
new file mode 100644
index 00000000..ae29c5d2
--- /dev/null
+++ b/dash-frontend/assets/gui/tab/welcome_page_0.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dash-frontend/assets/gui/tab/welcome_page_1.xml b/dash-frontend/assets/gui/tab/welcome_page_1.xml
new file mode 100644
index 00000000..c7fa5d71
--- /dev/null
+++ b/dash-frontend/assets/gui/tab/welcome_page_1.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/dash-frontend/assets/gui/tab/welcome_page_2.xml b/dash-frontend/assets/gui/tab/welcome_page_2.xml
new file mode 100644
index 00000000..e25b5249
--- /dev/null
+++ b/dash-frontend/assets/gui/tab/welcome_page_2.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/dash-frontend/assets/gui/tab/welcome_page_3.xml b/dash-frontend/assets/gui/tab/welcome_page_3.xml
new file mode 100644
index 00000000..344cbe6e
--- /dev/null
+++ b/dash-frontend/assets/gui/tab/welcome_page_3.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/dash-frontend/assets/gui/tab/welcome_page_4.xml b/dash-frontend/assets/gui/tab/welcome_page_4.xml
new file mode 100644
index 00000000..b7f18379
--- /dev/null
+++ b/dash-frontend/assets/gui/tab/welcome_page_4.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/dash-frontend/assets/lang/en.json b/dash-frontend/assets/lang/en.json
index 14b8d023..e48fe534 100644
--- a/dash-frontend/assets/lang/en.json
+++ b/dash-frontend/assets/lang/en.json
@@ -101,6 +101,7 @@
"SCROLL_SPEED": "Scroll speed",
"SELECT_VARIANT": "Select variant",
"SETS_ON_WATCH": "Sets on watch",
+ "SHOW_WELCOME_SCREEN": "Show welcome screen",
"SKYBOX": "Skybox",
"SKYMAP_ALREADY_DOWNLOADED": "This skymap is already downloaded. Select desired action.",
"SPACE_DRAG_MULTIPLIER": "Space drag multiplier",
@@ -154,6 +155,7 @@
},
"GAMES": "Games",
"GENERAL_SETTINGS": "General settings",
+ "GETTING_STARTED": "Getting started",
"HEIGHT": "Height",
"HELLO": "Hello!",
"HELLO_USER": "Hello, {USER}!",
diff --git a/dash-frontend/src/frontend.rs b/dash-frontend/src/frontend.rs
index 192cbc06..0b1f9bb0 100644
--- a/dash-frontend/src/frontend.rs
+++ b/dash-frontend/src/frontend.rs
@@ -26,7 +26,10 @@ use wlx_common::{
use crate::{
assets,
- tab::{Tab, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, settings::TabSettings},
+ tab::{
+ Tab, TabType, apps::TabApps, games::TabGames, home::TabHome, monado::TabMonado, settings::TabSettings,
+ welcome::TabWelcome,
+ },
util::{
popup_manager::{MountPopupOnceParams, PopupManager, PopupManagerParams},
toast_manager::ToastManager,
@@ -390,6 +393,7 @@ impl Frontend {
self.layout.remove_children(widget_content.id);
let (tab_translation, icon_path) = match tab_type {
+ TabType::Welcome => ("GETTING_STARTED", "dashboard/welcome.svg"),
TabType::Home => ("HOME_SCREEN", "dashboard/home.svg"),
TabType::Apps => ("APPLICATIONS", "dashboard/apps.svg"),
TabType::Games => ("GAMES", "dashboard/games.svg"),
@@ -400,6 +404,7 @@ impl Frontend {
self.set_tab_title(tab_translation, icon_path)?;
let tab: Box> = match tab_type {
+ TabType::Welcome => Box::new(TabWelcome::new(self, widget_content.id, data)?),
TabType::Home => Box::new(TabHome::new(self, widget_content.id, data)?),
TabType::Apps => Box::new(TabApps::new(self, widget_content.id, data)?),
TabType::Games => Box::new(TabGames::new(self, widget_content.id)?),
diff --git a/dash-frontend/src/tab/mod.rs b/dash-frontend/src/tab/mod.rs
index 68e7fb03..915019dc 100644
--- a/dash-frontend/src/tab/mod.rs
+++ b/dash-frontend/src/tab/mod.rs
@@ -5,6 +5,7 @@ pub mod games;
pub mod home;
pub mod monado;
pub mod settings;
+pub mod welcome;
#[derive(Clone, Copy, Debug)]
pub enum TabType {
@@ -13,6 +14,7 @@ pub enum TabType {
Games,
Monado,
Settings,
+ Welcome,
}
pub trait Tab {
diff --git a/dash-frontend/src/tab/settings/mod.rs b/dash-frontend/src/tab/settings/mod.rs
index ab32bdf1..1c0896f5 100644
--- a/dash-frontend/src/tab/settings/mod.rs
+++ b/dash-frontend/src/tab/settings/mod.rs
@@ -81,6 +81,7 @@ enum Task {
RestartSoftware,
RemoveAutostartApp(Rc),
SetTab(TabNameEnum),
+ ShowWelcomeScreen,
}
struct SettingsMountParams<'a> {
@@ -136,6 +137,9 @@ impl Tab for TabSettings {
Task::SetTab(tab) => {
self.set_tab(frontend, data, tab)?;
}
+ Task::ShowWelcomeScreen => {
+ self.frontend_tasks.push(FrontendTask::SetTab(TabType::Welcome));
+ }
Task::UpdateBool(setting, n) => {
self.tasks.push(Task::SettingUpdated(setting));
if let Some(task) = setting.get_frontend_task() {
diff --git a/dash-frontend/src/tab/settings/tab_troubleshooting.rs b/dash-frontend/src/tab/settings/tab_troubleshooting.rs
index 8635efe5..70ba2111 100644
--- a/dash-frontend/src/tab/settings/tab_troubleshooting.rs
+++ b/dash-frontend/src/tab/settings/tab_troubleshooting.rs
@@ -50,6 +50,13 @@ impl State {
"dashboard/refresh.svg",
Task::RestartSoftware,
)?;
+ options_danger_button(
+ par.mp,
+ c,
+ "APP_SETTINGS.SHOW_WELCOME_SCREEN",
+ "dashboard/welcome.svg",
+ Task::ShowWelcomeScreen,
+ )?;
Ok(State {})
}
}
diff --git a/dash-frontend/src/tab/welcome.rs b/dash-frontend/src/tab/welcome.rs
new file mode 100644
index 00000000..40798c2a
--- /dev/null
+++ b/dash-frontend/src/tab/welcome.rs
@@ -0,0 +1,147 @@
+use std::{collections::HashMap, marker::PhantomData, rc::Rc};
+
+use wgui::{
+ assets::AssetPath,
+ components::button::ComponentButton,
+ globals::WguiGlobals,
+ layout::{Layout, WidgetID},
+ parser::{Fetchable, ParseDocumentParams, ParserState},
+ task::Tasks,
+};
+
+use crate::{
+ frontend::Frontend,
+ tab::{Tab, TabType},
+};
+
+#[derive(Clone)]
+#[allow(clippy::enum_variant_names)]
+enum Task {
+ SetPage(u8),
+ SetPageNext,
+ SetPagePrev,
+}
+
+pub struct TabWelcome {
+ #[allow(dead_code)]
+ pub state: ParserState,
+ marker: PhantomData,
+ tasks: Tasks,
+ current_page: u8,
+ id_pips: WidgetID,
+ id_content: WidgetID,
+}
+
+const PAGE_COUNT: u8 = 5; // 0-4 inclusive
+
+impl Tab for TabWelcome {
+ fn get_type(&self) -> TabType {
+ TabType::Welcome
+ }
+
+ fn update(&mut self, frontend: &mut Frontend, _time_ms: u32, _user_data: &mut T) -> anyhow::Result<()> {
+ for task in self.tasks.drain() {
+ match task {
+ Task::SetPage(page_num) => {
+ self.set_page(&mut frontend.layout, page_num)?;
+ }
+ Task::SetPageNext => {
+ if self.current_page < PAGE_COUNT - 1 {
+ self.tasks.push(Task::SetPage(self.current_page + 1));
+ }
+ }
+ Task::SetPagePrev => {
+ if self.current_page > 0 {
+ self.tasks.push(Task::SetPage(self.current_page - 1));
+ }
+ }
+ }
+ }
+
+ Ok(())
+ }
+}
+
+fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
+ ParseDocumentParams {
+ globals: globals.clone(),
+ path: AssetPath::BuiltIn("gui/tab/welcome.xml"),
+ extra: Default::default(),
+ }
+}
+
+impl TabWelcome {
+ pub fn new(frontend: &mut Frontend, parent_id: WidgetID, _data: &mut T) -> anyhow::Result {
+ let state = wgui::parser::parse_from_assets(&doc_params(&frontend.globals), &mut frontend.layout, parent_id)?;
+
+ let tasks = Tasks::::new();
+
+ let btn_prev = state.fetch_component_as::("btn_prev")?;
+ let btn_next = state.fetch_component_as::("btn_next")?;
+
+ tasks.handle_button(&btn_prev, Task::SetPagePrev);
+ tasks.handle_button(&btn_next, Task::SetPageNext);
+
+ let id_pips = state.get_widget_id("pips")?;
+ let id_content = state.get_widget_id("content")?;
+
+ tasks.push(Task::SetPage(0));
+
+ Ok(Self {
+ state,
+ marker: PhantomData,
+ current_page: 0,
+ id_pips,
+ id_content,
+ tasks,
+ })
+ }
+
+ fn refresh_pips(&mut self, layout: &mut Layout) -> anyhow::Result<()> {
+ layout.remove_children(self.id_pips);
+
+ let globals = layout.state.globals.clone();
+
+ for i in 0..PAGE_COUNT {
+ let mut vars = HashMap::, Rc>::new();
+ let is_selected = i == self.current_page;
+ vars.insert(
+ Rc::from("COLOR"),
+ Rc::from(if is_selected { "#FFFFFF" } else { "#FFFFFF11" }),
+ );
+
+ self
+ .state
+ .instantiate_template(&doc_params(&globals), "Pip", layout, self.id_pips, vars)?
+ }
+
+ Ok(())
+ }
+
+ fn fill_page(&mut self, layout: &mut Layout) -> anyhow::Result<()> {
+ layout.remove_children(self.id_content);
+
+ let globals = layout.state.globals.clone();
+
+ let _ = wgui::parser::parse_from_assets(
+ &ParseDocumentParams {
+ globals,
+ path: AssetPath::BuiltIn(&format!("gui/tab/welcome_page_{}.xml", self.current_page)),
+ extra: Default::default(),
+ },
+ layout,
+ self.id_content,
+ )?;
+
+ Ok(())
+ }
+
+ fn set_page(&mut self, layout: &mut Layout, page_num: u8) -> anyhow::Result<()> {
+ self.current_page = page_num;
+
+ self.refresh_pips(layout)?;
+ self.fill_page(layout)?;
+
+ Ok(())
+ }
+}