kael_ui 0.2.0

Professional shadcn-inspired UI component library for Kael. 100+ accessible components for building beautiful, performant desktop applications.
use futures::future::BoxFuture;
use futures::FutureExt;
use kael::http_client::{AsyncBody, HttpClient, Request, Response};
use std::sync::Arc;

#[cfg(feature = "http")]
pub struct SimpleHttpClient {
    client: isahc::HttpClient,
    user_agent: kael::http_client::http::HeaderValue,
}

#[cfg(feature = "http")]
impl SimpleHttpClient {
    pub fn new(user_agent: &str) -> Result<Arc<Self>, isahc::Error> {
        let client = isahc::HttpClient::builder()
            .default_header("User-Agent", user_agent)
            .build()?;

        let user_agent_header = kael::http_client::http::HeaderValue::from_str(user_agent)
            .unwrap_or_else(|_| kael::http_client::http::HeaderValue::from_static("kael_ui"));

        Ok(Arc::new(Self {
            client,
            user_agent: user_agent_header,
        }))
    }

    pub fn with_default_user_agent() -> Result<Arc<Self>, isahc::Error> {
        Self::new("kael_ui/0.2.3")
    }
}

#[cfg(feature = "http")]
impl HttpClient for SimpleHttpClient {
    fn type_name(&self) -> &'static str {
        "SimpleHttpClient"
    }

    fn user_agent(&self) -> Option<&kael::http_client::http::HeaderValue> {
        Some(&self.user_agent)
    }

    fn proxy(&self) -> Option<&kael::http_client::Url> {
        None
    }

    fn send(
        &self,
        req: Request<AsyncBody>,
    ) -> BoxFuture<'static, kael::http_client::Result<Response<AsyncBody>>> {
        let client = self.client.clone();
        let (parts, _body) = req.into_parts();

        async move {
            let method_str = parts.method.as_str();
            let uri_str = parts.uri.to_string();

            let mut request_builder = isahc::Request::builder().method(method_str).uri(&uri_str);

            for (key, value) in parts.headers.iter() {
                if let Ok(value_str) = value.to_str() {
                    request_builder = request_builder.header(key.as_str(), value_str);
                }
            }

            let isahc_request = request_builder
                .body(())
                .map_err(|e| kael::http_client::anyhow!("Failed to build request: {}", e))?;

            let mut response = client
                .send_async(isahc_request)
                .await
                .map_err(|e| kael::http_client::anyhow!("HTTP request failed: {}", e))?;

            let status = response.status();
            let headers = response.headers().clone();

            use isahc::AsyncReadResponseExt;
            let bytes = response
                .bytes()
                .await
                .map_err(|e| kael::http_client::anyhow!("Failed to read response body: {}", e))?;

            let mut builder = kael::http_client::http::Response::builder().status(
                kael::http_client::http::StatusCode::from_u16(status.as_u16())
                    .map_err(|e| kael::http_client::anyhow!("Invalid status code: {}", e))?,
            );

            for (key, value) in headers.iter() {
                builder = builder.header(key.as_str(), value.as_bytes());
            }

            let async_body = AsyncBody::from_bytes(bytes::Bytes::from(bytes));
            let response = builder
                .body(async_body)
                .map_err(|e| kael::http_client::anyhow!("Failed to build response: {}", e))?;

            Ok(response)
        }
        .boxed()
    }
}

pub fn init_http(cx: &mut kael::App) {
    #[cfg(feature = "http")]
    {
        if let Ok(client) = SimpleHttpClient::with_default_user_agent() {
            cx.set_http_client(client);
        }
    }
    #[cfg(not(feature = "http"))]
    {
        let _ = cx;
    }
}

pub fn init_http_with_user_agent(cx: &mut kael::App, user_agent: &str) {
    #[cfg(feature = "http")]
    {
        if let Ok(client) = SimpleHttpClient::new(user_agent) {
            cx.set_http_client(client);
        }
    }
    #[cfg(not(feature = "http"))]
    {
        let _ = cx;
        let _ = user_agent;
    }
}