dash-frontend: Remote skymap downloader finished and fully working

This commit is contained in:
Aleksander 2026-04-13 23:52:57 +02:00 committed by galister
parent b0dba25f36
commit 701e41296b
6 changed files with 257 additions and 102 deletions

View File

@ -1,3 +1,5 @@
use std::rc::Rc;
use wgui::{globals::WguiGlobals, renderer_vk::text::custom_glyph::CustomGlyphData};
use wlx_common::async_executor::AsyncExecutor;
@ -7,8 +9,8 @@ pub async fn fetch_to_glyph_data(
globals: &WguiGlobals,
executor: &AsyncExecutor,
url: &str,
) -> anyhow::Result<CustomGlyphData> {
) -> anyhow::Result<(CustomGlyphData, Rc<Vec<u8>>)> {
let res = http_client::get_simple(executor, url).await?;
let glyph_data = CustomGlyphData::from_bytes_raster(globals, url, &res.data)?;
Ok(glyph_data)
Ok((glyph_data, Rc::new(res.data)))
}

View File

@ -2,14 +2,14 @@
use std::path::PathBuf;
// TODO: Remove later
use serde::Deserialize;
use wlx_common::async_executor::AsyncExecutor;
use serde::{Deserialize, Serialize};
use wlx_common::{async_executor::AsyncExecutor, config_io};
use crate::util::networking::{self, WAYVR_SKYMAPS_ROOT, http_client};
pub type SkymapUuid = uuid::Uuid;
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
pub enum SkymapResolution {
Res2k,
Res4k,
@ -26,7 +26,7 @@ impl SkymapResolution {
}
}
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SkymapCatalogEntryFiles {
pub size_8k: Option<String>, // "my_skymap_8k.png"
pub size_4k: Option<String>, // "my_skymap_4k.png"
@ -63,7 +63,7 @@ impl SkymapCatalogEntryFiles {
}
}
#[derive(Clone, Debug, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SkymapCatalogEntry {
pub uuid: SkymapUuid,
pub created_at: String,
@ -75,6 +75,34 @@ pub struct SkymapCatalogEntry {
pub files: SkymapCatalogEntryFiles,
}
impl SkymapCatalogEntry {
pub fn get_destination_path(&self, resolution: SkymapResolution) -> Option<PathBuf> {
let Some(filename) = self.files.get_filename_from_res(resolution) else {
return None;
};
Some(config_io::get_skymaps_root().join(filename))
}
pub fn get_destination_metadata_path(&self) -> PathBuf {
config_io::get_skymaps_root().join(format!("{}.json", self.uuid))
}
pub fn is_downloaded(&self, resolution: SkymapResolution) -> anyhow::Result<bool> {
let Some(full_path) = self.get_destination_path(resolution) else {
return Ok(false);
};
Ok(std::fs::exists(full_path)?)
}
pub fn save_metadata(&self) -> anyhow::Result<()> {
let json = serde_json::to_string_pretty(self)?;
std::fs::write(self.get_destination_metadata_path(), json)?;
Ok(())
}
}
#[derive(Clone, Debug, Deserialize)]
pub struct SkymapCatalog {
pub version: u32,
@ -104,3 +132,21 @@ pub async fn request_catalog(executor: &AsyncExecutor) -> anyhow::Result<SkymapC
Ok(catalog)
}
pub fn get_entries_from_disk() -> anyhow::Result<Vec<SkymapCatalogEntry>> {
let mut entries = Vec::<SkymapCatalogEntry>::new();
let skymaps_root = config_io::get_skymaps_root();
for uuid in config_io::get_skymaps_uuids().unwrap_or_default() {
let metadata_path = skymaps_root.join(format!("{}.json", uuid));
let Ok(data) = std::fs::read_to_string(metadata_path) else {
continue;
};
let entry = serde_json::from_str::<SkymapCatalogEntry>(&data)?;
entries.push(entry);
}
Ok(entries)
}

View File

@ -21,14 +21,12 @@ use wgui::{
};
use wlx_common::async_executor::AsyncExecutor;
pub struct Params<'a> {
pub globals: &'a WguiGlobals,
pub layout: &'a mut Layout,
pub executor: &'a AsyncExecutor,
pub parent_id: WidgetID,
pub struct Params {
pub globals: WguiGlobals,
pub executor: AsyncExecutor,
pub target_path: PathBuf,
pub url: String,
pub on_close_request: Box<dyn FnOnce()>,
pub on_downloaded: Box<dyn FnOnce()>,
}
#[derive(Clone)]
@ -41,7 +39,6 @@ enum Task {
}
pub struct View {
id_parent: WidgetID,
globals: WguiGlobals,
tasks: Tasks<Task>,
executor: AsyncExecutor,
@ -53,9 +50,10 @@ pub struct View {
id_loading_parent: WidgetID,
id_content: WidgetID,
on_close_request: Option<Box<dyn FnOnce()>>,
on_downloaded: Option<Box<dyn FnOnce()>>,
}
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams {
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
ParseDocumentParams {
globals: globals.clone(),
path: AssetPath::BuiltIn("gui/view/download_file.xml"),
@ -68,10 +66,18 @@ impl ViewTrait for View {
for task in self.tasks.drain() {
match task {
Task::StartDownload(url, path) => {
self
.executor
.spawn(View::download(self.tasks.clone(), self.executor.clone(), url, path))
.detach();
if let Some(on_downloaded) = self.on_downloaded.take() {
self
.executor
.spawn(View::download(
self.tasks.clone(),
self.executor.clone(),
url,
path,
on_downloaded,
))
.detach();
}
}
Task::SetStatusText(text) => {
let widgets = &mut par.layout.state.widgets;
@ -137,28 +143,31 @@ where
}
impl View {
pub fn new(par: Params) -> anyhow::Result<Self> {
pub fn new(
layout: &mut Layout,
id_parent: WidgetID,
on_close_request: Box<dyn FnOnce()>,
par: Params,
) -> anyhow::Result<Self> {
let tasks = Tasks::<Task>::new();
let parser_state = wgui::parser::parse_from_assets(&doc_params(&par.globals), par.layout, par.parent_id)?;
let parser_state = wgui::parser::parse_from_assets(&doc_params(&par.globals), layout, id_parent)?;
let id_label_status = parser_state.get_widget_id("label_status")?;
let id_content = parser_state.get_widget_id("content")?;
let id_loading_parent = parser_state.get_widget_id("loading_parent")?;
wgui_simple::create_loading(wgui_simple::CreateLoadingParams {
parent_id: id_loading_parent,
layout: par.layout,
layout: layout,
with_text: false,
})?;
let str_target_path = par.globals.i18n().translate("TARGET_PATH");
{
let label_target_path = parser_state
.fetch_widget(&par.layout.state, "label_target_path")?
.widget;
let label_target_path = parser_state.fetch_widget(&layout.state, "label_target_path")?.widget;
label_target_path.cast::<WidgetLabel>()?.set_text(
&mut par.layout.common(),
&mut layout.common(),
Translation::from_raw_text_string(format!("{}: {}", str_target_path, par.target_path.display())),
);
}
@ -166,7 +175,6 @@ impl View {
tasks.push(Task::StartDownload(par.url, par.target_path));
Ok(Self {
id_parent: par.parent_id,
tasks,
globals: par.globals.clone(),
executor: par.executor.clone(),
@ -174,11 +182,18 @@ impl View {
id_label_status,
id_loading_parent,
id_content,
on_close_request: Some(par.on_close_request),
on_close_request: Some(on_close_request),
on_downloaded: Some(par.on_downloaded),
})
}
async fn download(tasks: Tasks<Task>, executor: AsyncExecutor, url: String, target_path: PathBuf) -> Option<()> {
async fn download(
tasks: Tasks<Task>,
executor: AsyncExecutor,
url: String,
target_path: PathBuf,
on_downloaded: Box<dyn FnOnce()>,
) -> Option<()> {
tasks.push(Task::SetStatusText(String::from("Connecting to the server...")));
// start downloading from the server with progress reporting
@ -223,18 +238,17 @@ impl View {
tasks.push(Task::SetStatusText(String::from("Download finished")));
tasks.push(Task::ShowIconSuccess);
on_downloaded();
None
}
}
pub fn mount_popup(
frontend_tasks: FrontendTasks,
executor: AsyncExecutor,
globals: WguiGlobals,
popup: PopupHolder<View>,
target_path: PathBuf,
url: String,
frontend_tasks: FrontendTasks,
on_view_close: Box<dyn FnOnce()>,
params: Params,
) {
frontend_tasks
.clone()
@ -242,15 +256,7 @@ pub fn mount_popup(
Translation::from_translation_key("DOWNLOADER"),
Box::new(move |data| {
let on_close_request = popup.get_close_callback(data.layout);
let view = View::new(Params {
globals: &globals,
layout: data.layout,
executor: &executor,
parent_id: data.id_content,
on_close_request,
target_path,
url,
})?;
let view = View::new(data.layout, data.id_content, on_close_request, params)?;
popup.set_view(data.handle, view, Some(on_view_close));
Ok(popup.get_close_callback(data.layout))

View File

@ -1,12 +1,9 @@
use std::{collections::HashMap, path::PathBuf, rc::Rc};
use std::{collections::HashMap, rc::Rc};
use crate::{
frontend::{FrontendTask, FrontendTasks},
util::{
networking::{
self,
skymap_catalog::{SkymapCatalogEntry, SkymapResolution},
},
networking::{self, skymap_catalog::SkymapResolution},
popup_manager::{MountPopupOnceParams, PopupHolder},
},
views::{self, ViewTrait, ViewUpdateParams},
@ -32,18 +29,19 @@ pub struct Params<'a> {
pub frontend_tasks: FrontendTasks,
pub parent_id: WidgetID,
pub entry: networking::skymap_catalog::SkymapCatalogEntry,
pub on_close_request: Box<dyn FnOnce()>,
pub preview_image: Option<CustomGlyphData>,
pub preview_image: CustomGlyphData,
pub preview_image_compressed: Rc<Vec<u8>>,
pub on_updated_library: Rc<dyn Fn()>,
}
#[derive(Clone)]
enum Task {
Refresh,
ResolutionClicked(networking::skymap_catalog::SkymapResolution),
DownloadFinished,
}
pub struct View {
id_parent: WidgetID,
entry: networking::skymap_catalog::SkymapCatalogEntry,
frontend_tasks: FrontendTasks,
globals: WguiGlobals,
@ -56,6 +54,8 @@ pub struct View {
parser_state: ParserState,
popup_download: PopupHolder<views::download_file::View>,
preview_image_compressed: Rc<Vec<u8>>,
on_updated_library: Rc<dyn Fn()>,
}
fn mount_resolution_button(
@ -96,6 +96,9 @@ impl ViewTrait for View {
Task::Refresh => {
self.refresh(par.layout)?;
}
Task::DownloadFinished => {
self.download_finished()?;
}
}
}
@ -104,23 +107,7 @@ impl ViewTrait for View {
}
}
fn get_skymap_resolution_full_path(entry: &SkymapCatalogEntry, resolution: SkymapResolution) -> Option<PathBuf> {
let Some(filename) = entry.files.get_filename_from_res(resolution) else {
return None;
};
Some(config_io::get_skymaps_root().join(filename))
}
fn is_downloaded(entry: &SkymapCatalogEntry, resolution: SkymapResolution) -> anyhow::Result<bool> {
let Some(full_path) = get_skymap_resolution_full_path(entry, resolution) else {
return Ok(false);
};
Ok(std::fs::exists(full_path)?)
}
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams {
fn doc_params(globals: &WguiGlobals) -> ParseDocumentParams<'_> {
ParseDocumentParams {
globals: globals.clone(),
path: AssetPath::BuiltIn("gui/view/remote_skymap_downloader.xml"),
@ -132,7 +119,7 @@ impl View {
pub fn new(par: Params) -> anyhow::Result<Self> {
let tasks = Tasks::<Task>::new();
let mut parser_state = wgui::parser::parse_from_assets(&doc_params(&par.globals), par.layout, par.parent_id)?;
let parser_state = wgui::parser::parse_from_assets(&doc_params(&par.globals), par.layout, par.parent_id)?;
let id_resolution_buttons = parser_state.get_widget_id("resolution_buttons")?;
let str_version = par.globals.i18n().translate("VERSION");
@ -141,7 +128,7 @@ impl View {
let image = parser_state.fetch_widget(&par.layout.state, "image")?.widget;
let mut image = image.cast::<WidgetImage>()?;
image.set_content(&mut par.layout.alterables, par.preview_image);
image.set_content(&mut par.layout.alterables, Some(par.preview_image));
// Set author label
parser_state
@ -186,7 +173,6 @@ impl View {
tasks.push(Task::Refresh);
Ok(Self {
id_parent: par.parent_id,
tasks,
globals: par.globals.clone(),
executor: par.executor.clone(),
@ -195,6 +181,8 @@ impl View {
frontend_tasks: par.frontend_tasks,
popup_download: Default::default(),
id_resolution_buttons,
preview_image_compressed: par.preview_image_compressed,
on_updated_library: par.on_updated_library,
})
}
@ -210,7 +198,7 @@ impl View {
self.id_resolution_buttons,
res,
&self.tasks,
is_downloaded(&self.entry, res)?,
self.entry.is_downloaded(res)?,
)
};
@ -224,23 +212,44 @@ impl View {
Ok(())
}
fn download_finished(&mut self) -> anyhow::Result<()> {
self.entry.save_metadata()?;
let mut uuids = config_io::get_skymaps_uuids().unwrap_or_default();
let uuid_str = self.entry.uuid.to_string();
if !uuids.contains(&uuid_str) {
uuids.push(uuid_str);
}
config_io::set_skymaps_uuids(&uuids)?;
// Save preview image
let preview_path = config_io::get_skymaps_root().join(&self.entry.files.preview);
std::fs::write(preview_path, self.preview_image_compressed.as_ref())?;
(*self.on_updated_library)();
Ok(())
}
fn run_download(&mut self, resolution: SkymapResolution) -> anyhow::Result<()> {
let Some(url) = self.entry.files.get_url_from_res(resolution) else {
return Ok(());
};
let Some(full_path) = get_skymap_resolution_full_path(&self.entry, resolution) else {
let Some(target_path) = self.entry.get_destination_path(resolution) else {
return Ok(());
};
views::download_file::mount_popup(
self.frontend_tasks.clone(),
self.executor.clone(),
self.globals.clone(),
self.popup_download.clone(),
full_path,
url,
self.frontend_tasks.clone(),
self.tasks.make_callback_box(Task::Refresh),
views::download_file::Params {
globals: self.globals.clone(),
executor: self.executor.clone(),
target_path,
url,
on_downloaded: self.tasks.make_callback_box(Task::DownloadFinished),
},
);
Ok(())
}
@ -251,7 +260,9 @@ pub fn mount_popup(
executor: AsyncExecutor,
globals: WguiGlobals,
entry: networking::skymap_catalog::SkymapCatalogEntry,
preview_image: Option<CustomGlyphData>,
preview_image: CustomGlyphData,
preview_image_compressed: Rc<Vec<u8>>,
on_updated_library: Rc<dyn Fn()>,
popup: PopupHolder<View>,
) {
frontend_tasks
@ -259,16 +270,16 @@ pub fn mount_popup(
.push(FrontendTask::MountPopupOnce(MountPopupOnceParams::new(
Translation::from_raw_text(&entry.name),
Box::new(move |data| {
let on_close_request = popup.get_close_callback(data.layout);
let view = View::new(Params {
globals: &globals,
layout: data.layout,
executor: &executor,
parent_id: data.id_content,
entry,
on_close_request,
preview_image,
frontend_tasks: frontend_tasks.clone(),
preview_image_compressed,
on_updated_library,
})?;
popup.set_view(data.handle, view, None);

View File

@ -29,25 +29,33 @@ pub struct Params<'a> {
pub layout: &'a mut Layout,
pub executor: &'a AsyncExecutor,
pub parent_id: WidgetID,
pub on_close_request: Box<dyn FnOnce()>,
pub frontend_tasks: FrontendTasks,
pub on_updated_library: Rc<dyn Fn()>,
}
#[derive(Clone)]
enum Task {
SetSkymapCatalog(Rc<anyhow::Result<networking::skymap_catalog::SkymapCatalog>>),
SetSkymapPreview((SkymapUuid, Option<CustomGlyphData>)),
SetSkymapPreview(
(
SkymapUuid,
Option<(
CustomGlyphData, /* ready-to-use preview image data */
Rc<Vec<u8>>, /* compressed preview image data (should weigh about 10-15 KiB) */
)>,
),
),
ShowRemoteSkymapDownloader(SkymapUuid),
}
struct MountedCell {
skymap_uuid: SkymapUuid,
view: views::skymap_list_cell::View,
preview_image_compressed: Option<Rc<Vec<u8>>>,
}
pub struct View {
id_parent: WidgetID,
id_list: WidgetID,
id_loading: WidgetID,
globals: WguiGlobals,
tasks: Tasks<Task>,
@ -56,6 +64,7 @@ pub struct View {
frontend_tasks: FrontendTasks,
catalog: Option<networking::skymap_catalog::SkymapCatalog>,
popup_remote_skymap_downloader: PopupHolder<views::remote_skymap_downloader::View>,
on_updated_library: Rc<dyn Fn()>,
}
impl ViewTrait for View {
@ -77,18 +86,26 @@ impl ViewTrait for View {
)?,
}
}
Task::SetSkymapPreview((skymap_uuid, glyph_data)) => {
Task::SetSkymapPreview((skymap_uuid, opt_preview_image)) => {
if let Some(cell) = &mut self
.mounted_cells
.iter_mut()
.find(|cell| cell.skymap_uuid == skymap_uuid)
{
cell.view.set_image(par.layout, glyph_data)?;
if let Some((preview_image, preview_image_compressed)) = opt_preview_image {
cell.view.set_image(par.layout, Some(preview_image))?;
cell.preview_image_compressed = Some(preview_image_compressed);
} else {
cell.view.set_image(par.layout, None)?;
}
}
}
Task::ShowRemoteSkymapDownloader(skymap_uuid) => {
let preview_image = self.get_image_preview(skymap_uuid);
self.show_remote_skymap_downloader(skymap_uuid, preview_image)?;
if let Some((preview_image, preview_image_compressed)) = self.get_image_preview(skymap_uuid) {
self.show_remote_skymap_downloader(skymap_uuid, preview_image, preview_image_compressed)?;
} else {
log::error!("preview image not present, ignoring request");
}
}
}
}
@ -113,7 +130,6 @@ impl View {
par.executor.spawn(fut).detach();
Ok(Self {
id_parent: par.parent_id,
id_list: WidgetID::default(),
id_loading,
tasks,
globals: par.globals.clone(),
@ -122,6 +138,7 @@ impl View {
frontend_tasks: par.frontend_tasks,
catalog: None,
popup_remote_skymap_downloader: Default::default(),
on_updated_library: par.on_updated_library,
})
}
@ -131,10 +148,12 @@ impl View {
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)));
tasks.push(Task::SetSkymapPreview((
entry.uuid,
networking::image_fetch::fetch_to_glyph_data(&globals, &executor, &entry.files.get_url_preview())
.await
.ok(),
)));
}
fn mount_catalog(
@ -163,6 +182,7 @@ impl View {
let skymap_uuid = entry.uuid.clone();
self.mounted_cells.push(MountedCell {
preview_image_compressed: None,
skymap_uuid: entry.uuid.clone(),
view: views::skymap_list_cell::View::new(views::skymap_list_cell::Params {
id_parent: id_list,
@ -184,7 +204,8 @@ impl View {
fn show_remote_skymap_downloader(
&mut self,
uuid: SkymapUuid,
preview_image: Option<CustomGlyphData>,
preview_image: CustomGlyphData,
preview_image_compressed: Rc<Vec<u8>>,
) -> anyhow::Result<()> {
let Some(catalog) = &self.catalog else {
debug_assert!(false); // impossible
@ -202,15 +223,27 @@ impl View {
self.globals.clone(),
entry.clone(),
preview_image,
preview_image_compressed,
self.on_updated_library.clone(),
self.popup_remote_skymap_downloader.clone(),
);
Ok(())
}
fn get_image_preview(&self, skymap_uuid: SkymapUuid) -> Option<CustomGlyphData> {
fn get_image_preview(
&self,
skymap_uuid: SkymapUuid,
) -> Option<(CustomGlyphData, Rc<Vec<u8>> /* preview_image_compressed */)> {
if let Some(cell) = &self.mounted_cells.iter().find(|mc| mc.skymap_uuid == skymap_uuid) {
return cell.view.get_image();
let Some(image) = cell.view.get_image() else {
return None;
};
let Some(preview_image_compressed) = cell.preview_image_compressed.clone() else {
return None;
};
return Some((image, preview_image_compressed));
}
None
}
@ -220,6 +253,7 @@ pub fn mount_popup(
frontend_tasks: FrontendTasks,
executor: AsyncExecutor,
globals: WguiGlobals,
on_updated_library: Rc<dyn Fn()>,
popup: PopupHolder<View>,
) {
frontend_tasks
@ -227,14 +261,13 @@ pub fn mount_popup(
.push(FrontendTask::MountPopupOnce(MountPopupOnceParams::new(
Translation::from_translation_key("APP_SETTINGS.DOWNLOAD_SKYMAPS"),
Box::new(move |data| {
let on_close_request = popup.get_close_callback(data.layout);
let view = View::new(Params {
globals: &globals,
layout: data.layout,
executor: &executor,
parent_id: data.id_content,
on_close_request,
frontend_tasks,
on_updated_library,
})?;
popup.set_view(data.handle, view, None);

View File

@ -1,3 +1,4 @@
use anyhow::Context;
use wgui::{
assets::AssetPath,
components::button::ComponentButton,
@ -5,13 +6,18 @@ use wgui::{
i18n::Translation,
layout::{Layout, WidgetID},
parser::{Fetchable, ParseDocumentParams, ParserState},
renderer_vk::text::custom_glyph::CustomGlyphData,
task::Tasks,
};
use wlx_common::{async_executor::AsyncExecutor, config_io};
use crate::{
frontend::FrontendTasks,
util::{popup_manager::PopupHolder, wgui_simple},
util::{
networking::skymap_catalog::{self, SkymapCatalogEntry, SkymapResolution},
popup_manager::PopupHolder,
wgui_simple,
},
views::{self, ViewTrait, ViewUpdateParams},
};
@ -19,6 +25,7 @@ use crate::{
enum Task {
DownloadSkymaps,
Refresh,
SetSkymap(SkymapCatalogEntry),
}
pub struct Params<'a> {
@ -28,6 +35,11 @@ pub struct Params<'a> {
pub frontend_tasks: &'a FrontendTasks,
}
struct Cell {
#[allow(dead_code)]
view: views::skymap_list_cell::View,
}
pub struct View {
#[allow(dead_code)]
parser_state: ParserState,
@ -36,6 +48,7 @@ pub struct View {
frontend_tasks: FrontendTasks,
globals: WguiGlobals,
popup_remote_skymap_list: PopupHolder<views::remote_skymap_list::View>,
cells: Vec<Cell>,
}
impl ViewTrait for View {
@ -55,6 +68,9 @@ impl ViewTrait for View {
Task::Refresh => {
self.refresh(&mut par.layout)?;
}
Task::SetSkymap(entry) => {
self.set_skymap(entry)?;
}
}
}
}
@ -94,6 +110,7 @@ impl View {
frontend_tasks: params.frontend_tasks.clone(),
globals: params.globals.clone(),
popup_remote_skymap_list: Default::default(),
cells: Vec::new(),
})
}
@ -102,18 +119,38 @@ impl View {
self.frontend_tasks.clone(),
executor.clone(),
self.globals.clone(),
self.tasks.make_callback_rc(Task::Refresh), /* on_updated_library */
self.popup_remote_skymap_list.clone(),
);
Ok(())
}
fn set_skymap(&mut self, entry: SkymapCatalogEntry) -> anyhow::Result<()> {
let skymap_file_path = entry
.get_destination_path(SkymapResolution::Res2k /* todo: resolution selector */)
.context("Skymap not found" /* you shouldn't really see this, like ever. */)?;
log::error!(
"not implemented (skymap path to be loaded: {})",
skymap_file_path.to_string_lossy()
);
Ok(())
}
fn refresh(&mut self, layout: &mut Layout) -> anyhow::Result<()> {
let skymaps_uuids = config_io::get_skymaps_uuids().unwrap_or_default();
log::info!("skymap uuids {:?}", skymaps_uuids);
let entries = match skymap_catalog::get_entries_from_disk() {
Ok(entries) => entries,
Err(e) => {
log::error!("failed to get skymap entries: {}", e);
Default::default()
}
};
layout.remove_children(self.list_parent);
self.cells.clear();
if skymaps_uuids.is_empty() {
if entries.is_empty() {
wgui_simple::create_label(
layout,
self.list_parent,
@ -122,6 +159,26 @@ impl View {
return Ok(());
}
let skymaps_root = config_io::get_skymaps_root();
for entry in &entries {
let mut view = views::skymap_list_cell::View::new(views::skymap_list_cell::Params {
id_parent: self.list_parent,
layout,
entry: entry.clone(),
on_click: self.tasks.get_button_click_callback(Task::SetSkymap(entry.clone())),
})?;
// load preview image
if let Ok(data) = std::fs::read(skymaps_root.join(&entry.files.preview)) {
if let Ok(glyph_data) = CustomGlyphData::from_bytes_raster(&self.globals, &entry.files.preview, &data) {
view.set_image(layout, Some(glyph_data))?;
}
}
self.cells.push(Cell { view });
}
Ok(())
}
}