Skip to main content

embedded_wg_display/widget/store/
mod.rs

1//! Remote widget store catalog fetched from GitHub.
2use crate::runtime::http_sync::{self};
3use alloc::string::FromUtf8Error;
4use alloc::vec::Vec;
5use common::models::WidgetStoreItem;
6use defmt::info;
7
8const WIDGET_LISTING_URL: &str = "https://siryll.github.io/wg_display_embedded/widget_store.json";
9
10#[derive(Debug, defmt::Format)]
11pub enum WidgetStoreError {
12    Http(&'static str),
13    Utf8,
14    Json,
15}
16
17impl From<&'static str> for WidgetStoreError {
18    fn from(e: &'static str) -> Self {
19        WidgetStoreError::Http(e)
20    }
21}
22
23impl From<FromUtf8Error> for WidgetStoreError {
24    fn from(_: FromUtf8Error) -> Self {
25        WidgetStoreError::Utf8
26    }
27}
28
29impl From<serde_json::Error> for WidgetStoreError {
30    fn from(_: serde_json::Error) -> Self {
31        WidgetStoreError::Json
32    }
33}
34
35impl From<reqwless::Error> for WidgetStoreError {
36    fn from(_: reqwless::Error) -> Self {
37        WidgetStoreError::Http("HTTP request failed")
38    }
39}
40
41#[derive(Clone)]
42pub struct WidgetStore {
43    store_items: Vec<WidgetStoreItem>,
44}
45
46impl WidgetStore {
47    pub fn new() -> Self {
48        Self {
49            store_items: Vec::new(),
50        }
51    }
52
53    /// Get all items in the store
54    /// Use `fetch_from_store` to fetch the store before
55    /// # Returns
56    /// A vector of all items in the store
57    pub fn get_items(&self) -> &Vec<WidgetStoreItem> {
58        &self.store_items
59    }
60
61    /// Fetch the store from the internet
62    /// # Returns
63    /// An error if the fetch failed
64    pub async fn fetch_from_store(&mut self) -> Result<(), WidgetStoreError> {
65        info!("Fetching widget store from {}", WIDGET_LISTING_URL);
66        let response = http_sync::http_request_async(http_sync::HttpRequest {
67            method: reqwless::request::Method::GET,
68            url: alloc::string::String::from(WIDGET_LISTING_URL),
69            body: None,
70        })
71        .await
72        .map_err(|_| WidgetStoreError::Http("HTTP bridge request failed"))?;
73
74        let body = alloc::string::String::from_utf8(response.bytes)?;
75        self.store_items = serde_json::from_str(&body)?;
76        Ok(())
77    }
78}