mod ui;
use std::sync::mpsc::{Receiver, RecvTimeoutError};
use crate::{
buildkit::{BuildKitD, container_info::SCellContainerInfo, image_info::SCellImageInfo},
cli::{
MIN_FPS,
ls::app::{AppInner, AppItemSuperTrait, ls::LsState},
},
};
pub struct LoadingState<Item> {
buildkit: BuildKitD,
rx: Receiver<color_eyre::Result<Vec<Item>>>,
}
impl LoadingState<SCellContainerInfo> {
pub fn load(buildkit: BuildKitD) -> AppInner<SCellContainerInfo> {
let (tx, rx) = std::sync::mpsc::channel();
tokio::spawn({
let buildkit = buildkit.clone();
async move {
let result = async {
let res = buildkit.list_containers().await;
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
res
}
.await;
drop(tx.send(result));
}
});
AppInner::Loading(Self { buildkit, rx })
}
}
impl LoadingState<SCellImageInfo> {
pub fn load(buildkit: BuildKitD) -> AppInner<SCellImageInfo> {
let (tx, rx) = std::sync::mpsc::channel();
tokio::spawn({
let buildkit = buildkit.clone();
async move {
let result = async {
let res = buildkit.list_images().await;
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
res
}
.await;
drop(tx.send(result));
}
});
AppInner::Loading(Self { buildkit, rx })
}
}
impl<Item: Clone + AppItemSuperTrait> LoadingState<Item> {
pub fn try_recv(self) -> color_eyre::Result<AppInner<Item>> {
match self.rx.recv_timeout(MIN_FPS) {
Ok(Ok(items)) => Ok(LsState::ls(items, self.buildkit)),
Ok(Err(e)) => {
color_eyre::eyre::bail!(e)
},
Err(RecvTimeoutError::Timeout) => Ok(AppInner::Loading(self)),
Err(RecvTimeoutError::Disconnected) => {
color_eyre::eyre::bail!(
"StoppingState channel cannot be disconnected without returning a result"
)
},
}
}
}