From 66583e1b037b7e2f3e47948d70d8a4c6f6a2f2d5 Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Wed, 7 Sep 2022 14:33:03 +0000 Subject: [PATCH] feat: is_loading use HashSet each set loading function uses a unique uuid, so that the loading animation will always be played, previously would stop on any remove_loading call --- Cargo.toml | 1 + containerised/Dockerfile_dev | 11 ++++++++--- src/docker_data/mod.rs | 36 +++++++++++++++++++----------------- src/ui/gui_state.rs | 21 ++++++++++----------- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index af45ac5..dd11a33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ tokio = {version = "1.21", features=["full"]} tracing = "0.1" tracing-subscriber = "0.3" tui = "0.19" +uuid = {version = "1.1", features = ["v4", "fast-rng"]} [dev-dependencies] diff --git a/containerised/Dockerfile_dev b/containerised/Dockerfile_dev index ea142ab..f6f5148 100644 --- a/containerised/Dockerfile_dev +++ b/containerised/Dockerfile_dev @@ -8,8 +8,13 @@ FROM alpine:latest AS runtime COPY ./target/x86_64-unknown-linux-musl/release/oxker /usr/local/bin COPY ./containerised/start_oxker.sh ./ -# Run the application +## Run the application ENTRYPOINT [ "./start_oxker.sh"] -# One liner to build musl program, build docker image, then execute the image -# cargo build --release --target x86_64-unknown-linux-musl && docker build -t oxker_dev -f containerised/Dockerfile_dev . && docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock:ro oxker_dev \ No newline at end of file +## One liner to build musl program, build docker image, then execute the image +# cargo build --release --target x86_64-unknown-linux-musl && docker build -t oxker_dev -f containerised/Dockerfile_dev . && docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock:ro oxker_dev + + +## Buildx command to build musl version for all three platforms, should probably be executed in create_release +# docker buildx create --use +# docker buildx build --platform linux/arm/v6,linux/arm64,linux/amd64 -t oxker_dev_all -o type=tar,dest=/tmp/oxker_dev_all.tar -f containerised/Dockerfile . \ No newline at end of file diff --git a/src/docker_data/mod.rs b/src/docker_data/mod.rs index 60f030c..d639d10 100644 --- a/src/docker_data/mod.rs +++ b/src/docker_data/mod.rs @@ -5,6 +5,7 @@ use bollard::{ }; use futures_util::StreamExt; use parking_lot::Mutex; +use uuid::Uuid; use std::{ collections::HashMap, sync::{ @@ -295,25 +296,26 @@ impl DockerData { } /// Animate the loading icon - async fn loading_spin(&mut self) -> JoinHandle<()> { + async fn loading_spin(&mut self, loading_uuid: Uuid) -> JoinHandle<()> { let gui_state = Arc::clone(&self.gui_state); tokio::spawn(async move { loop { tokio::time::sleep(std::time::Duration::from_millis(100)).await; - gui_state.lock().next_loading(); + gui_state.lock().next_loading(loading_uuid); } }) } /// Stop the loading_spin function, and reset gui loading status - fn stop_loading_spin(&mut self, handle: &JoinHandle<()>) { + fn stop_loading_spin(&mut self, handle: &JoinHandle<()>, loading_uuid: Uuid) { handle.abort(); - self.gui_state.lock().reset_loading(); + self.gui_state.lock().remove_loading(loading_uuid); } // Initialize docker container data, before any messages are received async fn initialise_container_data(&mut self) { - let loading_spin = self.loading_spin().await; + let loading_uuid = Uuid::new_v4(); + let loading_spin = self.loading_spin(loading_uuid).await; let all_ids = self.update_all_containers().await; self.update_all_container_stats(&all_ids).await; @@ -331,7 +333,7 @@ impl DockerData { self.initialised = self.app_data.lock().initialised(&all_ids); } self.app_data.lock().init = true; - self.stop_loading_spin(&loading_spin); + self.stop_loading_spin(&loading_spin, loading_uuid); } /// Handle incoming messages, container controls & all container information update @@ -339,27 +341,28 @@ impl DockerData { while let Some(message) = self.receiver.recv().await { let docker = Arc::clone(&self.docker); let app_data = Arc::clone(&self.app_data); + let loading_uuid = Uuid::new_v4(); match message { DockerMessage::Pause(id) => { - let loading_spin = self.loading_spin().await; + let loading_spin = self.loading_spin(loading_uuid).await; if docker.pause_container(&id).await.is_err() { app_data .lock() .set_error(AppError::DockerCommand(DockerControls::Pause)); }; - self.stop_loading_spin(&loading_spin); + self.stop_loading_spin(&loading_spin, loading_uuid); } DockerMessage::Restart(id) => { - let loading_spin = self.loading_spin().await; + let loading_spin = self.loading_spin(loading_uuid).await; if docker.restart_container(&id, None).await.is_err() { app_data .lock() .set_error(AppError::DockerCommand(DockerControls::Restart)); }; - self.stop_loading_spin(&loading_spin); + self.stop_loading_spin(&loading_spin, loading_uuid); } DockerMessage::Start(id) => { - let loading_spin = self.loading_spin().await; + let loading_spin = self.loading_spin(loading_uuid).await; if docker .start_container(&id, None::>) .await @@ -369,20 +372,19 @@ impl DockerData { .lock() .set_error(AppError::DockerCommand(DockerControls::Start)); }; - self.stop_loading_spin(&loading_spin); + self.stop_loading_spin(&loading_spin, loading_uuid); } DockerMessage::Stop(id) => { - let loading_spin = self.loading_spin().await; + let loading_spin = self.loading_spin(loading_uuid).await; if docker.stop_container(&id, None).await.is_err() { app_data .lock() .set_error(AppError::DockerCommand(DockerControls::Stop)); }; - self.stop_loading_spin(&loading_spin); + self.stop_loading_spin(&loading_spin, loading_uuid); } DockerMessage::Unpause(id) => { - // gen uuid, leading_spin(uuid) - let loading_spin = self.loading_spin().await; + let loading_spin = self.loading_spin(loading_uuid).await; if docker.unpause_container(&id).await.is_err() { app_data .lock() @@ -390,7 +392,7 @@ impl DockerData { }; // loading sping take uuid to remove // stop_loading_sping(uuid) - self.stop_loading_spin(&loading_spin); + self.stop_loading_spin(&loading_spin, loading_uuid); self.update_everything().await; } DockerMessage::Update => self.update_everything().await, diff --git a/src/ui/gui_state.rs b/src/ui/gui_state.rs index a9ddeb2..f0e3639 100644 --- a/src/ui/gui_state.rs +++ b/src/ui/gui_state.rs @@ -1,5 +1,6 @@ -use std::{collections::HashMap, fmt}; +use std::{collections::{HashMap, HashSet}, fmt}; use tui::layout::{Constraint, Rect}; +use uuid::Uuid; use crate::app_data::Header; @@ -174,9 +175,7 @@ pub struct GuiState { panel_map: HashMap, heading_map: HashMap, loading_icon: Loading, - // Should be a vec, each time loading add a new to the vec, and reset remove from vec - // for for if is_loading just check if vec is empty or not - is_loading: bool, + is_loading: HashSet, pub selected_panel: SelectablePanel, pub show_help: bool, pub info_box_text: Option, @@ -190,7 +189,7 @@ impl GuiState { loading_icon: Loading::One, selected_panel: SelectablePanel::Containers, show_help: false, - is_loading: false, + is_loading: HashSet::new(), info_box_text: None, } } @@ -250,14 +249,14 @@ impl GuiState { } /// Advance loading animation - pub fn next_loading(&mut self) { + pub fn next_loading(&mut self, uuid: Uuid) { self.loading_icon = self.loading_icon.next(); - self.is_loading = true; - } + self.is_loading.insert(uuid); + } /// if is_loading, return loading animation frame, else single space pub fn get_loading(&mut self) -> String { - if self.is_loading { + if !self.is_loading.is_empty() { self.loading_icon.to_string() } else { String::from(" ") @@ -265,8 +264,8 @@ impl GuiState { } /// set is_loading to false, but keep animation frame at same state - pub fn reset_loading(&mut self) { - self.is_loading = false; + pub fn remove_loading(&mut self, uuid: Uuid) { + self.is_loading.remove(&uuid); } /// Set info box content