dash-frontend: skymap preview fetch (done), reformat Cargo.toml files

This commit is contained in:
Aleksander 2026-04-06 16:59:09 +02:00 committed by galister
parent f2dcdcc6c3
commit 68daa5b3df
21 changed files with 198 additions and 87 deletions

1
Cargo.lock generated
View File

@ -1548,6 +1548,7 @@ dependencies = [
"smol", "smol",
"smol-hyper", "smol-hyper",
"strum", "strum",
"uuid",
"wayvr-ipc", "wayvr-ipc",
"wgui", "wgui",
"wlx-common", "wlx-common",

View File

@ -1,3 +1,42 @@
[workspace]
resolver = "3"
members = [
"dash-frontend",
"scripts/prost_build",
"uidev",
"wayvr",
"wayvr-ipc",
"wayvrctl",
"wgui",
"wlx-capture",
"wlx-common",
]
[workspace.dependencies]
anyhow = "1.0.100"
clap = { version = "4.5.53", features = ["derive"] }
glam = { version = "0.30.9", features = ["mint", "serde"] }
idmap = "0.2.2"
idmap-derive = "0.2.22"
log = "0.4.29"
regex = "1.12.2"
rust-embed = "8.9.0"
serde = { version = "1", features = ["derive"] }
serde_json = "1.0.145"
slotmap = "1.1.1"
smol = "2.0.2"
strum = { version = "0.27.2", features = ["derive"] }
uuid = { version = "1.19.0", features = ["fast-rng", "v4", "serde"] }
vulkano = { version = "0.35.2", default-features = false, features = [
"macros",
] }
vulkano-shaders = "0.35.0"
wayland-client = { version = "0.31.11" }
xdg = "3.0.0"
[patch.crates-io]
vulkano = { git = "https://github.com/galister/vulkano.git", rev = "cf7f92867928a56ce16b376037c1120f2b167678" }
[profile.dev] [profile.dev]
opt-level = 1 opt-level = 1
debug = true debug = true
@ -19,41 +58,3 @@ incremental = true
[profile.release-with-debug] [profile.release-with-debug]
inherits = "release" inherits = "release"
debug = true debug = true
[workspace]
members = [
"uidev",
"wgui",
"wlx-common",
"wayvr",
"wlx-capture",
"dash-frontend",
"wayvr-ipc",
"wayvrctl",
"scripts/prost_build",
]
resolver = "3"
[patch.crates-io]
vulkano = { git = "https://github.com/galister/vulkano.git", rev = "cf7f92867928a56ce16b376037c1120f2b167678" }
[workspace.dependencies]
anyhow = "1.0.100"
smol = "2.0.2"
glam = { version = "0.30.9", features = ["mint", "serde"] }
clap = { version = "4.5.53", features = ["derive"] }
xdg = "3.0.0"
idmap = "0.2.2"
idmap-derive = "0.2.22"
log = "0.4.29"
regex = "1.12.2"
rust-embed = "8.9.0"
serde = { version = "1", features = ["derive"] }
serde_json = "1.0.145"
slotmap = "1.1.1"
strum = { version = "0.27.2", features = ["derive"] }
vulkano = { version = "0.35.2", default-features = false, features = [
"macros",
] }
vulkano-shaders = "0.35.0"
wayland-client = { version = "0.31.11" }

View File

@ -8,26 +8,25 @@ authors = ["galister", "oo8dev"]
repository = "https://github.com/wlx-team/wayvr" repository = "https://github.com/wlx-team/wayvr"
[dependencies] [dependencies]
wayvr-ipc = { path = "../wayvr-ipc", default-features = false }
wgui = { path = "../wgui/" }
wlx-common = { path = "../wlx-common" }
anyhow.workspace = true anyhow.workspace = true
async-native-tls = "0.5.0"
chrono = "0.4.42"
glam = { workspace = true, features = ["mint", "serde"] } glam = { workspace = true, features = ["mint", "serde"] }
http-body-util = "0.1.3"
hyper = { version = "1.8.1", features = ["client", "http1", "http2"] }
keyvalues-parser = { git = "https://github.com/CosmicHorrorDev/vdf-rs.git", rev = "fc6dcbea9eb13cacb98dea40063f6f56cde6e145" }
log.workspace = true log.workspace = true
xdg.workspace = true
rust-embed.workspace = true rust-embed.workspace = true
serde = { workspace = true, features = ["rc"] } serde = { workspace = true, features = ["rc"] }
serde_json.workspace = true serde_json.workspace = true
strum.workspace = true
chrono = "0.4.42"
keyvalues-parser = { git = "https://github.com/CosmicHorrorDev/vdf-rs.git", rev = "fc6dcbea9eb13cacb98dea40063f6f56cde6e145" }
smol = { workspace = true } smol = { workspace = true }
hyper = { version = "1.8.1", features = ["client", "http1", "http2"] }
http-body-util = "0.1.3"
async-native-tls = "0.5.0"
smol-hyper = "0.1.1" smol-hyper = "0.1.1"
strum.workspace = true
uuid.workspace = true
wayvr-ipc = { path = "../wayvr-ipc", default-features = false }
wgui = { path = "../wgui/" }
wlx-common = { path = "../wlx-common" }
xdg.workspace = true
[features] [features]
default = ["monado"] default = ["monado"]

View File

@ -1,6 +1,6 @@
<layout> <layout>
<elements> <elements>
<div id="list" gap="8" flex_wrap="wrap"> <div id="list" gap="8" flex_wrap="wrap" align_self="baseline">
<!-- filled-in at runtime --> <!-- filled-in at runtime -->
</div> </div>
</elements> </elements>

View File

@ -1,7 +1,7 @@
<layout> <layout>
<elements> <elements>
<div flex_direction="column"> <div flex_direction="column">
<div id="list_parent" gap="8" flex_direction="row" flex_wrap="wrap" overflow_y="scroll"/> <div id="list_parent" gap="8" flex_direction="row" flex_wrap="wrap" />
</div> </div>
<div flex_direction="row" gap="4"> <div flex_direction="row" gap="4">
<Button id="btn_refresh" tooltip="REFRESH" width="32" height="32" sprite_src_builtin="dashboard/refresh.svg" /> <Button id="btn_refresh" tooltip="REFRESH" width="32" height="32" sprite_src_builtin="dashboard/refresh.svg" />

View File

@ -7,10 +7,7 @@
"label_desc" "label_desc"
--> -->
<template name="Cell"> <template name="Cell">
<rectangle <Button
border="2"
color="~color_bg_translucent"
border_color="~color_accent"
padding="8" padding="8"
round="8" round="8"
flex_direction="column" flex_direction="column"
@ -18,9 +15,9 @@
width="256" width="256"
align_items="center" align_items="center"
align_self="start"> align_self="start">
<image id="image_preview" width="100%" height="128"/> <image id="image_preview" width="100%" height="128" round="6"/>
<label id="label_title" wrap="1" weight="bold"/> <label id="label_title" wrap="1" weight="bold"/>
<label id="label_author" wrap="1"/> <label id="label_author" wrap="1"/>
</rectangle> </Button>
</template> </template>
</layout> </layout>

View File

@ -393,7 +393,7 @@ impl<T: 'static> Frontend<T> {
.widgets .widgets
.cast_as::<WidgetSprite>(self.widgets.id_sprite_titlebar_icon)?; .cast_as::<WidgetSprite>(self.widgets.id_sprite_titlebar_icon)?;
sprite.set_content( sprite.set_content(
&mut common, common.alterables,
Some(CustomGlyphData::from_assets(&self.globals, AssetPath::BuiltIn(icon))?), Some(CustomGlyphData::from_assets(&self.globals, AssetPath::BuiltIn(icon))?),
); );
} }

View File

@ -1,9 +1,8 @@
use crate::util::{networking::http_client, steam_utils::AppID};
use anyhow::Context; use anyhow::Context;
use serde::Deserialize; use serde::Deserialize;
use wlx_common::{async_executor::AsyncExecutor, cache_dir}; use wlx_common::{async_executor::AsyncExecutor, cache_dir};
use crate::util::{http_client, steam_utils::AppID};
pub struct CoverArt { pub struct CoverArt {
// can be empty in case if data couldn't be fetched (use a fallback image then) // can be empty in case if data couldn't be fetched (use a fallback image then)
pub compressed_image_data: Vec<u8>, pub compressed_image_data: Vec<u8>,

View File

@ -1,5 +1,4 @@
pub mod cached_fetcher; pub mod cached_fetcher;
pub mod http_client;
pub mod networking; pub mod networking;
pub mod pactl_wrapper; pub mod pactl_wrapper;
pub mod popup_manager; pub mod popup_manager;

View File

@ -0,0 +1,14 @@
use wgui::{globals::WguiGlobals, renderer_vk::text::custom_glyph::CustomGlyphData};
use wlx_common::async_executor::AsyncExecutor;
use crate::util::networking::http_client;
pub async fn fetch_to_glyph_data(
globals: &WguiGlobals,
executor: &AsyncExecutor,
url: &str,
) -> anyhow::Result<CustomGlyphData> {
let res = http_client::get(executor, url).await?;
let glyph_data = CustomGlyphData::from_bytes_raster(globals, url, &res.data)?;
Ok(glyph_data)
}

View File

@ -1,3 +1,5 @@
pub mod http_client;
pub mod image_fetch;
pub mod skymap_catalog; pub mod skymap_catalog;
// pub const WAYVR_ROOT_URL: &'static str = "https://wayvr.org"; // pub const WAYVR_ROOT_URL: &'static str = "https://wayvr.org";

View File

@ -2,9 +2,16 @@
use serde::Deserialize; use serde::Deserialize;
use wlx_common::async_executor::AsyncExecutor; use wlx_common::async_executor::AsyncExecutor;
use crate::util::{http_client, networking}; use crate::util::networking::{self, WAYVR_SKYMAPS_ROOT, http_client};
pub type SkymapUuid = String; pub type SkymapUuid = uuid::Uuid;
pub enum SkymapResolution {
Res2k,
Res4k,
Res8k,
Res16k,
}
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
pub struct SkymapCatalogEntryFiles { pub struct SkymapCatalogEntryFiles {
@ -15,6 +22,30 @@ pub struct SkymapCatalogEntryFiles {
pub preview: String, pub preview: String,
} }
impl SkymapCatalogEntryFiles {
pub fn get_url_preview(&self) -> String {
format!("{}/files/{}", WAYVR_SKYMAPS_ROOT, self.preview)
}
pub fn get_filename_from_res(&self, res: SkymapResolution) -> Option<&String> {
match res {
SkymapResolution::Res2k => Some(&self.size_2k),
SkymapResolution::Res4k => self.size_4k.as_ref(),
SkymapResolution::Res8k => self.size_8k.as_ref(),
SkymapResolution::Res16k => self.size_16k.as_ref(),
}
}
// example result: "https://wayvr.org/skymaps/files/my_skymap_8k.png"
pub fn get_url_from_res(&self, res: SkymapResolution) -> Option<String> {
let Some(filename) = self.get_filename_from_res(res) else {
return None;
};
Some(format!("{}/files/{}", WAYVR_SKYMAPS_ROOT, filename))
}
}
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
pub struct SkymapCatalogEntry { pub struct SkymapCatalogEntry {
pub uuid: SkymapUuid, pub uuid: SkymapUuid,

View File

@ -4,6 +4,7 @@ use wgui::{
i18n::Translation, i18n::Translation,
layout::{Layout, WidgetID}, layout::{Layout, WidgetID},
parser::{Fetchable, ParseDocumentParams}, parser::{Fetchable, ParseDocumentParams},
renderer_vk::text::custom_glyph::CustomGlyphData,
task::Tasks, task::Tasks,
}; };
use wlx_common::async_executor::AsyncExecutor; use wlx_common::async_executor::AsyncExecutor;
@ -11,7 +12,10 @@ use wlx_common::async_executor::AsyncExecutor;
use crate::{ use crate::{
frontend::{FrontendTask, FrontendTasks}, frontend::{FrontendTask, FrontendTasks},
util::{ util::{
networking::{self}, networking::{
self,
skymap_catalog::{SkymapCatalogEntry, SkymapUuid},
},
popup_manager::{MountPopupOnceParams, PopupHolder}, popup_manager::{MountPopupOnceParams, PopupHolder},
wgui_simple, wgui_simple,
}, },
@ -28,6 +32,12 @@ pub struct Params<'a> {
enum Task { enum Task {
SetSkymapCatalog(anyhow::Result<networking::skymap_catalog::SkymapCatalog>), SetSkymapCatalog(anyhow::Result<networking::skymap_catalog::SkymapCatalog>),
SetSkymapPreview((SkymapUuid, Option<CustomGlyphData>)),
}
struct MountedCell {
skymap_uuid: SkymapUuid,
view: views::skymap_list_cell::View,
} }
pub struct View { pub struct View {
@ -36,7 +46,8 @@ pub struct View {
id_loading: WidgetID, id_loading: WidgetID,
globals: WguiGlobals, globals: WguiGlobals,
tasks: Tasks<Task>, tasks: Tasks<Task>,
mounted_cells: Vec<views::skymap_list_cell::View>, mounted_cells: Vec<MountedCell>,
executor: AsyncExecutor,
} }
impl View { impl View {
@ -61,9 +72,22 @@ impl View {
tasks, tasks,
globals: par.globals.clone(), globals: par.globals.clone(),
mounted_cells: Vec::new(), mounted_cells: Vec::new(),
executor: par.executor.clone(),
}) })
} }
async fn request_skymap_preview(
globals: WguiGlobals,
executor: AsyncExecutor,
entry: SkymapCatalogEntry,
tasks: Tasks<Task>,
) {
let glyph_data = networking::image_fetch::fetch_to_glyph_data(&globals, &executor, &entry.files.get_url_preview())
.await
.ok();
tasks.push(Task::SetSkymapPreview((entry.uuid, glyph_data)));
}
fn mount_catalog( fn mount_catalog(
&mut self, &mut self,
layout: &mut Layout, layout: &mut Layout,
@ -80,12 +104,23 @@ impl View {
let id_list = parser_state.fetch_widget(&layout.state, "list")?.id; let id_list = parser_state.fetch_widget(&layout.state, "list")?.id;
for entry in catalog.entries { for entry in catalog.entries {
let view_cell = views::skymap_list_cell::View::new(views::skymap_list_cell::Params { let task = View::request_skymap_preview(
id_parent: id_list, self.globals.clone(),
layout, self.executor.clone(),
entry, entry.clone(),
})?; self.tasks.clone(),
self.mounted_cells.push(view_cell); );
self.mounted_cells.push(MountedCell {
skymap_uuid: entry.uuid.clone(),
view: views::skymap_list_cell::View::new(views::skymap_list_cell::Params {
id_parent: id_list,
layout,
entry,
})?,
});
self.executor.spawn(task).detach();
} }
Ok(()) Ok(())
@ -107,6 +142,15 @@ impl View {
)?, )?,
} }
} }
Task::SetSkymapPreview((skymap_uuid, glyph_data)) => {
if let Some(cell) = &mut self
.mounted_cells
.iter_mut()
.find(|cell| cell.skymap_uuid == skymap_uuid)
{
cell.view.set_image(layout, glyph_data)?;
}
}
} }
} }
Ok(()) Ok(())

View File

@ -1,9 +1,11 @@
use wgui::{ use wgui::{
assets::AssetPath, assets::AssetPath,
event::EventAlterables,
i18n::Translation, i18n::Translation,
layout::{Layout, WidgetID}, layout::{Layout, WidgetID},
parser::{Fetchable, ParseDocumentParams, ParserState}, parser::{Fetchable, ParseDocumentParams, ParserState},
widget::label::WidgetLabel, renderer_vk::text::custom_glyph::CustomGlyphData,
widget::{image::WidgetImage, label::WidgetLabel},
}; };
use crate::util::{networking, wgui_simple}; use crate::util::{networking, wgui_simple};
@ -17,6 +19,8 @@ pub struct Params<'a> {
pub struct View { pub struct View {
#[allow(dead_code)] #[allow(dead_code)]
parser_state: ParserState, parser_state: ParserState,
id_loading: WidgetID,
id_image_preview: WidgetID,
} }
impl View { impl View {
@ -45,12 +49,28 @@ impl View {
); );
} }
wgui_simple::create_loading(wgui_simple::CreateLoadingParams { let id_loading = wgui_simple::create_loading(wgui_simple::CreateLoadingParams {
layout: par.layout, layout: par.layout,
parent_id: id_image_preview, parent_id: id_image_preview,
with_text: false, with_text: false,
})?; })?;
Ok(Self { parser_state }) Ok(Self {
parser_state,
id_loading,
id_image_preview,
})
}
pub fn set_image(&mut self, layout: &mut Layout, content: Option<CustomGlyphData>) -> anyhow::Result<()> {
layout.remove_widget(self.id_loading);
let mut alt = EventAlterables::default();
{
let mut image_preview = layout.state.widgets.cast_as::<WidgetImage>(self.id_image_preview)?;
image_preview.set_content(&mut alt, content);
}
layout.process_alterables(alt)?;
Ok(())
} }
} }

View File

@ -83,7 +83,7 @@ sysinfo = { version = "0.37" }
thiserror = "2.0" thiserror = "2.0"
tracing = "0.1.43" tracing = "0.1.43"
tracing-subscriber = { version = "0.3.22", features = ["env-filter"] } tracing-subscriber = { version = "0.3.22", features = ["env-filter"] }
uuid = { version = "1.19.0", features = ["fast-rng", "v4"] } uuid = { workspace = true }
wayland-client = { workspace = true } wayland-client = { workspace = true }
winit = { version = "0.30.12", optional = true } winit = { version = "0.30.12", optional = true }
xcb = { version = "1.6.0", features = [ xcb = { version = "1.6.0", features = [

View File

@ -527,9 +527,9 @@ pub fn apply_custom_command<T>(
.context("Could not load content from supplied path.")?; .context("Could not load content from supplied path.")?;
if let Some(mut sprite) = pair.widget.get_as::<WidgetSprite>() { if let Some(mut sprite) = pair.widget.get_as::<WidgetSprite>() {
sprite.set_content(&mut com, Some(data)); sprite.set_content(com.alterables, Some(data));
} else if let Some(mut image) = pair.widget.get_as::<WidgetImage>() { } else if let Some(mut image) = pair.widget.get_as::<WidgetImage>() {
image.set_content(&mut com, Some(data)); image.set_content(com.alterables, Some(data));
} else { } else {
anyhow::bail!("No <sprite> or <image> with such id."); anyhow::bail!("No <sprite> or <image> with such id.");
} }

View File

@ -105,7 +105,7 @@ where
.widgets .widgets
.get_as::<WidgetSprite>(self.top_sprite_id) .get_as::<WidgetSprite>(self.top_sprite_id)
{ {
sprite.set_content(common, Some(new.sprite.clone())); sprite.set_content(common.alterables, Some(new.sprite.clone()));
} }
} }

View File

@ -129,6 +129,11 @@ impl EventAlterables {
self.dirty_widgets.push(widget_id); self.dirty_widgets.push(widget_id);
} }
pub fn mark_dirty_and_redraw(&mut self, widget_id: WidgetID) {
self.mark_dirty(widget_id);
self.mark_redraw();
}
pub fn mark_tick(&mut self, widget_id: WidgetID) { pub fn mark_tick(&mut self, widget_id: WidgetID) {
self.widgets_to_tick.insert(widget_id); self.widgets_to_tick.insert(widget_id);
} }
@ -174,8 +179,7 @@ impl CallbackDataCommon<'_> {
// helper functions // helper functions
pub fn mark_widget_dirty(&mut self, id: WidgetID) { pub fn mark_widget_dirty(&mut self, id: WidgetID) {
self.alterables.mark_dirty(id); self.alterables.mark_dirty_and_redraw(id);
self.alterables.mark_redraw();
} }
pub fn globals(&self) -> RefMut<'_, globals::Globals> { pub fn globals(&self) -> RefMut<'_, globals::Globals> {

View File

@ -4,7 +4,7 @@ use slotmap::Key;
use crate::{ use crate::{
drawing::{self, ImagePrimitive, PrimitiveExtent}, drawing::{self, ImagePrimitive, PrimitiveExtent},
event::CallbackDataCommon, event::EventAlterables,
globals::Globals, globals::Globals,
layout::WidgetID, layout::WidgetID,
renderer_vk::text::custom_glyph::CustomGlyphData, renderer_vk::text::custom_glyph::CustomGlyphData,
@ -44,13 +44,13 @@ impl WidgetImage {
) )
} }
pub fn set_content(&mut self, common: &mut CallbackDataCommon, content: Option<CustomGlyphData>) { pub fn set_content(&mut self, alterables: &mut EventAlterables, content: Option<CustomGlyphData>) {
if self.params.glyph_data == content { if self.params.glyph_data == content {
return; return;
} }
self.params.glyph_data = content; self.params.glyph_data = content;
common.mark_widget_dirty(self.id); alterables.mark_dirty_and_redraw(self.id);
} }
pub fn get_content(&self) -> Option<CustomGlyphData> { pub fn get_content(&self) -> Option<CustomGlyphData> {

View File

@ -5,7 +5,7 @@ use slotmap::Key;
use crate::{ use crate::{
drawing::{self, PrimitiveExtent}, drawing::{self, PrimitiveExtent},
event::CallbackDataCommon, event::{CallbackDataCommon, EventAlterables},
globals::Globals, globals::Globals,
layout::WidgetID, layout::WidgetID,
renderer_vk::text::{ renderer_vk::text::{
@ -49,13 +49,13 @@ impl WidgetSprite {
self.params.color self.params.color
} }
pub fn set_content(&mut self, common: &mut CallbackDataCommon, content: Option<CustomGlyphData>) { pub fn set_content(&mut self, alterables: &mut EventAlterables, content: Option<CustomGlyphData>) {
if self.params.glyph_data == content { if self.params.glyph_data == content {
return; return;
} }
self.params.glyph_data = content; self.params.glyph_data = content;
common.mark_widget_dirty(self.id); alterables.mark_dirty_and_redraw(self.id);
} }
pub fn get_content(&self) -> Option<CustomGlyphData> { pub fn get_content(&self) -> Option<CustomGlyphData> {