mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-25 07:08:12 +08:00
Introduce network request handler (#4194)
* Impl NetworkMessageHandler * Repalce Frontend fetch like messages with NetworkMessage * Reimpl resource loading with NetworkMessage * Fix wasm * dedublicate resource requests * Embedd font resources created by migration * Fixup * Fix tests * Fix font catalog not loading * Cleanup * Fix layouts not updating when font catalog is loaded * Review * Review * Cleanup
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
mod network_message;
|
||||
mod network_message_handler;
|
||||
pub mod utility_types;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use network_message::{NetworkMessage, NetworkMessageDiscriminant};
|
||||
#[doc(inline)]
|
||||
pub use network_message_handler::{NetworkMessageContext, NetworkMessageHandler};
|
||||
#[doc(inline)]
|
||||
pub use utility_types::Client;
|
||||
@@ -0,0 +1,49 @@
|
||||
use std::pin::Pin;
|
||||
|
||||
use dyn_any::WasmNotSend;
|
||||
|
||||
use crate::messages::network::utility_types::Client;
|
||||
use crate::messages::prelude::*;
|
||||
|
||||
#[impl_message(Message, Network)]
|
||||
#[derive(derivative::Derivative, serde::Serialize, serde::Deserialize)]
|
||||
#[derivative(Debug, PartialEq)]
|
||||
pub enum NetworkMessage {
|
||||
Request {
|
||||
#[serde(skip, default)]
|
||||
#[derivative(Debug = "ignore", PartialEq = "ignore")]
|
||||
request: Option<RequestFn>,
|
||||
},
|
||||
}
|
||||
impl NetworkMessage {
|
||||
pub fn request<F, Fut>(f: F) -> Self
|
||||
where
|
||||
F: FnOnce(Client) -> Fut + WasmNotSend + 'static,
|
||||
Fut: Future<Output = Message> + WasmNotSend + 'static,
|
||||
{
|
||||
NetworkMessage::Request {
|
||||
request: Some(Box::new(move |c| Box::pin(f(c)))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
type RequestFuture = Pin<Box<dyn Future<Output = Message> + Send>>;
|
||||
#[cfg(target_family = "wasm")]
|
||||
type RequestFuture = Pin<Box<dyn Future<Output = Message>>>;
|
||||
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
type RequestFn = Box<dyn FnOnce(Client) -> RequestFuture + Send>;
|
||||
#[cfg(target_family = "wasm")]
|
||||
type RequestFn = Box<dyn FnOnce(Client) -> RequestFuture>;
|
||||
|
||||
impl Clone for NetworkMessage {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
NetworkMessage::Request { .. } => {
|
||||
log::error!("Cloning a NetworkMessage::Request is not supported");
|
||||
NetworkMessage::Request { request: None }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
use crate::messages::network::utility_types::Client;
|
||||
use crate::messages::prelude::*;
|
||||
|
||||
#[derive(ExtractField)]
|
||||
pub struct NetworkMessageContext {}
|
||||
|
||||
#[derive(Debug, Default, ExtractField)]
|
||||
pub struct NetworkMessageHandler {
|
||||
client: Client,
|
||||
}
|
||||
#[message_handler_data]
|
||||
impl MessageHandler<NetworkMessage, NetworkMessageContext> for NetworkMessageHandler {
|
||||
fn process_message(&mut self, message: NetworkMessage, responses: &mut VecDeque<Message>, _context: NetworkMessageContext) {
|
||||
match message {
|
||||
NetworkMessage::Request { request } => {
|
||||
if let Some(request) = request {
|
||||
responses.add(request(self.client.clone()));
|
||||
} else {
|
||||
log::error!("received a empty NetworkMessage::Request");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
advertise_actions!(NetworkMessageDiscriminant;
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
use reqwest::IntoUrl;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Client {
|
||||
inner: Option<reqwest::Client>,
|
||||
}
|
||||
|
||||
impl Default for Client {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
inner: reqwest::Client::builder().timeout(std::time::Duration::from_secs(100)).build().ok(),
|
||||
#[cfg(target_family = "wasm")]
|
||||
inner: reqwest::Client::builder().build().ok(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub async fn fetch<U: IntoUrl>(&self, url: U) -> Option<Box<[u8]>> {
|
||||
let Some(client) = &self.inner else {
|
||||
log::error!("HTTP client failed to initialize, cannot fetch");
|
||||
return None;
|
||||
};
|
||||
let response = client.get(url).send().await;
|
||||
let response = response.and_then(|r| r.error_for_status()).map_err(|err| log::error!("failed to fetch: {err}")).ok()?;
|
||||
let bytes = response.bytes().await.map_err(|err| log::error!("failed to read response body: {err}")).ok()?;
|
||||
Some(bytes.to_vec().into_boxed_slice())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user