start working on example application without rusalka

This commit is contained in:
Daniel Bulant 2024-02-27 13:42:15 +01:00
parent ea298b9dc0
commit 7bc7a6253e
5 changed files with 1640 additions and 7 deletions

19
Cargo.lock generated
View file

@ -841,9 +841,9 @@ dependencies = [
[[package]]
name = "half"
version = "2.3.1"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872"
checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e"
dependencies = [
"cfg-if",
"crunchy",
@ -1121,14 +1121,21 @@ checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc"
[[package]]
name = "mangades"
version = "0.1.0"
dependencies = [
"mangui",
"rusalka",
"rusalka-macro",
]
[[package]]
name = "mangades-plain"
version = "0.1.0"
dependencies = [
"bytes",
"futures",
"image",
"mangui",
"reqwest",
"rusalka",
"rusalka-macro",
"serde",
"serde_json",
"tokio",
@ -1993,9 +2000,9 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.10.0"
version = "3.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67"
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
dependencies = [
"cfg-if",
"fastrand",

View file

@ -5,5 +5,6 @@ members = [
"ui",
"mangades",
"rusalka",
"rusalka-macro"
"rusalka-macro",
"mangades-plain"
]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,143 @@
use bytes::Bytes;
use serde::Deserialize;
use mangui::femtovg::ImageFlags;
use mangui::nodes::image::ImageLoad;
#[derive(Deserialize, Debug)]
struct GraphqlResponse<T> {
data: T
}
#[derive(Deserialize, Debug)]
pub struct MediaListCollectionData {
#[serde(rename = "MediaListCollection")]
media_list_collection: MediaListCollection
}
#[derive(Deserialize, Debug)]
pub struct MediaListCollection {
lists: Vec<MediaList>
}
#[derive(Deserialize, Debug)]
struct MediaList {
name: String,
#[serde(rename = "isCustomList")]
is_custom_list: bool,
status: String,
#[serde(rename = "isSplitCompletedList")]
is_split_completed_list: bool,
entries: Vec<MediaListEntry>,
}
#[derive(Deserialize, Debug)]
struct MediaListEntry {
status: String,
progress: i32,
#[serde(rename = "progressVolumes")]
progress_volumes: i32,
repeat: i32,
priority: i32,
private: bool,
notes: Option<String>,
score: f32,
media: MediaEntry,
}
#[derive(Deserialize, Debug)]
struct MediaEntry {
id: i32,
title: MediaTitle,
status: String,
chapters: Option<i32>,
volumes: Option<i32>,
#[serde(rename = "coverImage")]
cover_image: CoverImage,
#[serde(rename = "isAdult")]
is_adult: bool,
#[serde(rename = "isFavourite")]
is_favourite: bool,
}
#[derive(Deserialize, Debug)]
struct MediaTitle {
romaji: String,
english: Option<String>,
native: String,
#[serde(rename = "userPreferred")]
user_preferred: String,
}
#[derive(Deserialize, Debug)]
struct CoverImage {
large: String,
medium: String,
color: Option<String>,
}
// pub fn load_demo() -> MediaListCollection {
// // For demo purposes, load file in demo/list.json
// let json = include_str!("../../demo/list.json");
// let response: GraphqlResponse<MediaListCollectionData> = serde_json::from_str(json).unwrap();
// response.data.media_list_collection
// }
pub async fn load_demo_async() -> MediaListCollection {
let json = tokio::fs::read_to_string("demo/list.json").await.unwrap();
let response: GraphqlResponse<MediaListCollectionData> = serde_json::from_str(&json).unwrap();
response.data.media_list_collection
}
pub async fn load_demo_image(url: String) -> ImageLoad {
let last_part = url.split('/').last().unwrap();
let path = format!("demo/{}", last_part);
let bytes = tokio::fs::read(path).await.unwrap();
ImageLoad::LoadVec(bytes, ImageFlags::empty())
}
// pub async fn load_data(appref: Weak<MainWindow>) {
// let data = load_demo();
// let urls = data.lists.iter().flat_map(|list| {
// list.entries.iter().map(|entry| {
// entry.media.cover_image.medium.clone()
// })
// }).collect::<Vec<String>>();
// let mut images = futures::future::join_all(urls.into_iter().map(|url| {
// load_image(url)
// })).await;
// images.reverse();
// slint::invoke_from_event_loop(move || {
// let lists = Rc::new(VecModel::default());
// for list in data.lists {
// let entries: Rc<VecModel<AnilistItem>> = Rc::new(VecModel::default());
// for entry in list.entries {
// let image = images.pop().unwrap().unwrap();
// let image = Image::from_rgba8(image);
// let item = AnilistItem {
// id: entry.media.id,
// title: entry.media.title.user_preferred.into(),
// image
// };
// entries.push(item);
// }
// let list = AnilistList {
// name: list.name.into(),
// items: ModelRc::from(entries)
// };
// lists.push(list);
// }
// let app = appref.upgrade().unwrap();
// app.set_lists(ModelRc::from(lists));
// app.set_loading(false);
// }).expect("Load data into UI");
// }
async fn load_image(url: String) -> Result<Bytes, reqwest::Error> {
let response = reqwest::get(url).await?;
let bytes = response.bytes().await?;
Ok(bytes)
}

View file

@ -0,0 +1,29 @@
use std::sync::Arc;
use mangui::SharedNode;
pub fn detach(node: &SharedNode) {
if let Some(parent) = node.read().unwrap().parent() {
parent.write().unwrap().remove_child(node).unwrap();
}
node.clone().write().unwrap().set_parent(None);
}
pub fn insert(parent: &SharedNode, node: &SharedNode, before: Option<&SharedNode>) {
if node.read().unwrap().parent().is_some() && !Arc::ptr_eq(&node.read().unwrap().parent().unwrap(), parent) {
detach(node);
}
match before {
Some(before) => {
parent.write().unwrap().add_child_before(node.clone(), before).unwrap();
node.write().unwrap().set_parent(Some(Arc::downgrade(parent)));
},
None => {
append(parent, node);
}
}
}
pub fn append(parent: &SharedNode, node: &SharedNode) {
parent.write().unwrap().add_child(node.clone()).unwrap();
node.write().unwrap().set_parent(Some(Arc::downgrade(parent)));
}