mirror of https://github.com/wayvr-org/wayvr.git
dash-frontend: Remote skymap downloader finished and fully working
This commit is contained in:
parent
b0dba25f36
commit
701e41296b
|
|
@ -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)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue