Something went wrong. Try again.
A simple to-do app focused on tasks that can be completed within a specific time span. taskline.tobinio.dev
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144use color_eyre::eyre;use futures::stream::StreamExt;use reqwest_sse::EventSource;use std::time::Duration;use tokio::sync::mpsc::{self, Receiver};use types::{ tag::{Category, Tag}, todo::{AddTodoModel, Todo},};
#[must_use]pub fn get_todos(url: String, token: String) -> Receiver<Vec<Todo>> { let (tx, rx) = mpsc::channel(8);
std::thread::spawn(move || { let Ok(rt) = tokio::runtime::Runtime::new() else { eprintln!("Failed to create Tokio runtime"); return; };
rt.block_on(async move { loop { let todos = loop { match fetch_todos(&url, &token).await { Ok(todos) => break todos, Err(err) => { eprintln!("Error fetching todos: {err}"); tokio::time::sleep(Duration::from_secs(5)).await; } } };
if tx.send(todos).await.is_err() { break; }
let mut event_source = match reqwest::Client::new() .get(format!("{url}/api/updates/sse")) .header("x-api-key", &token) .send() .await { Ok(response) => match response.events().await { Ok(events) => events, Err(err) => { eprintln!("Failed to establish SSE stream: {err}"); tokio::time::sleep(Duration::from_secs(5)).await; continue; } }, Err(err) => { eprintln!("Failed to connect to SSE endpoint: {err}"); tokio::time::sleep(Duration::from_secs(5)).await; continue; } };
while let Some(event) = event_source.next().await { match event { Ok(event) => { if event.event_type == "todos" { match serde_json::from_str(&event.data) { Ok(todos) => { if tx.send(todos).await.is_err() { return; } } Err(err) => { eprintln!("Invalid todos payload: {err}"); } } } } Err(err) => { eprintln!("Error: {err}"); break; } } } } }); });
rx}
async fn fetch_todos(url: &str, token: &str) -> eyre::Result<Vec<Todo>> { let response = reqwest::Client::new() .get(format!("{}{}", url, "/api/todos")) .header("x-api-key", token) .send() .await? .text() .await?;
Ok(serde_json::from_str(&response)?)}
pub async fn add_todo(url: &str, token: &str, todo: &AddTodoModel) -> eyre::Result<()> { let response = reqwest::Client::new() .post(format!("{}{}", url, "/api/todos")) .header("x-api-key", token) .json(todo) .send() .await?;
if !response.status().is_success() { return Err(eyre::eyre!("Failed to add todo: {}", response.status())); }
Ok(())}
pub async fn fetch_tags(url: &str, token: &str) -> eyre::Result<Vec<Tag>> { let response = reqwest::Client::new() .get(format!("{}{}", url, "/api/tags")) .header("x-api-key", token) .send() .await?;
if !response.status().is_success() { return Err(eyre::eyre!("Failed to fetch tags: {}", response.status())); }
Ok(serde_json::from_str(&response.text().await?)?)}
pub async fn fetch_categories(url: &str, token: &str) -> eyre::Result<Vec<Category>> { let response = reqwest::Client::new() .get(format!("{}{}", url, "/api/categories")) .header("x-api-key", token) .send() .await?;
if !response.status().is_success() { return Err(eyre::eyre!( "Failed to fetch categories: {}", response.status() )); }
Ok(serde_json::from_str(&response.text().await?)?)}