chore: merge release-v0.0.5 into main
This commit is contained in:
@@ -6,4 +6,4 @@ FROM mcr.microsoft.com/vscode/devcontainers/rust:0-${VARIANT}
|
|||||||
|
|
||||||
RUN printf "alias cls='clear'\nalias ll='ls -l --human-readable --color=auto --group-directories-first --classify --time-style=long-iso -all'" >> /etc/bash.bashrc
|
RUN printf "alias cls='clear'\nalias ll='ls -l --human-readable --color=auto --group-directories-first --classify --time-style=long-iso -all'" >> /etc/bash.bashrc
|
||||||
|
|
||||||
RUN apt-get update && apt-get -y install upx-ucl
|
# RUN apt-get update && apt-get -y install upx-ucl
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
],
|
],
|
||||||
|
|
||||||
"mounts": [
|
"mounts": [
|
||||||
"source=/etc/timezone,target=/etc/timezone,type=bind,readonly",
|
// //"source=/etc/timezone,target=/etc/timezone,type=bind,readonly",
|
||||||
"source=/ramdrive,target=/ramdrive,type=bind",
|
"source=/dev/shm,target=/ramdrive,type=bind",
|
||||||
"source=${localEnv:HOME}/.cargo/bin/cargo-watch,target=/usr/local/cargo/bin/cargo-watch,type=bind,readonly",
|
"source=${localEnv:HOME}/.cargo/bin/cargo-watch,target=/usr/local/cargo/bin/cargo-watch,type=bind,readonly",
|
||||||
"source=${localEnv:HOME}/.cargo/bin/cross,target=/usr/local/cargo/bin/cross,type=bind,readonly",
|
"source=${localEnv:HOME}/.cargo/bin/cross,target=/usr/local/cargo/bin/cross,type=bind,readonly",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
### 2022-05-08
|
### 2022-05-30
|
||||||
|
|
||||||
|
### Docs
|
||||||
|
+ Readme one-liner to download & install latest version, [11d5ba361ee4c11d080f1c3c14d8bb677cbfd1fc]
|
||||||
|
+ Example docker-compose.yml bump alpine version to 3.16, [98c83f2f68f59e78f0c78270c59886630d98913c]
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
+ Help menu logo corrected, [2f5452027e86f714729b804d4bf65306e755df7f]
|
+ use Some() checks to make sure that container item indexes are still valid, else can create out-of-bounds errors, closes [#8], [4cf02e3f04426ef44ec5a7421687f2104ac5102f]
|
||||||
|
+ Remove + replace as many unwrap()'s as possible, [d8e22d7444965f1874d7367259310440a889432b]
|
||||||
|
+ Help panel typo, [e497f3f2d9e1dca99469860c2e728c99e29353ad]
|
||||||
|
|
||||||
|
|
||||||
see <a href='https://github.com/mrjackwills/oxker/blob/main/CHANGELOG.md'>CHANGELOG.md</a> for more details
|
see <a href='https://github.com/mrjackwills/oxker/blob/main/CHANGELOG.md'>CHANGELOG.md</a> for more details
|
||||||
|
|||||||
@@ -1,3 +1,15 @@
|
|||||||
|
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.0.5'>v0.0.5</a>
|
||||||
|
### 2022-05-30
|
||||||
|
|
||||||
|
### Docs
|
||||||
|
+ Readme one-liner to download & install latest version, [11d5ba36](https://github.com/mrjackwills/oxker/commit/11d5ba361ee4c11d080f1c3c14d8bb677cbfd1fc),
|
||||||
|
+ Example docker-compose.yml bump alpine version to 3.16, [98c83f2f](https://github.com/mrjackwills/oxker/commit/98c83f2f68f59e78f0c78270c59886630d98913c),
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
+ use Some() checks to make sure that container item indexes are still valid, else can create out-of-bounds errors, closes [#8](https://github.com/mrjackwills/oxker/issues/8), [4cf02e3f](https://github.com/mrjackwills/oxker/commit/4cf02e3f04426ef44ec5a7421687f2104ac5102f),
|
||||||
|
+ Remove + replace as many unwrap()'s as possible, [d8e22d74](https://github.com/mrjackwills/oxker/commit/d8e22d7444965f1874d7367259310440a889432b),
|
||||||
|
+ Help panel typo, [e497f3f2](https://github.com/mrjackwills/oxker/commit/e497f3f2d9e1dca99469860c2e728c99e29353ad),
|
||||||
|
|
||||||
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.0.4'>v0.0.4</a>
|
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.0.4'>v0.0.4</a>
|
||||||
### 2022-05-08
|
### 2022-05-08
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "oxker"
|
name = "oxker"
|
||||||
version = "0.0.4"
|
version = "0.0.5"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Jack Wills <email@mrjackwills.com>"]
|
authors = ["Jack Wills <email@mrjackwills.com>"]
|
||||||
description = "a simple tui to view & control docker containers"
|
description = "a simple tui to view & control docker containers"
|
||||||
|
|||||||
@@ -25,13 +25,15 @@
|
|||||||
|
|
||||||
See <a href="https://github.com/mrjackwills/oxker/releases" target='_blank' rel='noopener noreferrer'>releases</a>
|
See <a href="https://github.com/mrjackwills/oxker/releases" target='_blank' rel='noopener noreferrer'>releases</a>
|
||||||
|
|
||||||
install
|
download & install (x86_64 one liner)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
tar xzvf oxker_linux_x86_64.tar.gz oxker
|
wget https://www.github.com/mrjackwills/oxker/releases/latest/download/oxker_linux_x86_64.tar.gz &&
|
||||||
install -Dm 755 oxker -t "${HOME}/.local/bin"
|
tar xzvf oxker_linux_x86_64.tar.gz oxker &&
|
||||||
|
install -Dm 755 oxker -t "${HOME}/.local/bin" &&
|
||||||
rm oxker_linux_x86_64.tar.gz oxker
|
rm oxker_linux_x86_64.tar.gz oxker
|
||||||
```
|
```
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
```oxker```
|
```oxker```
|
||||||
@@ -88,7 +90,7 @@ using docker-compose.yml;
|
|||||||
or individually
|
or individually
|
||||||
|
|
||||||
|
|
||||||
```docker run --name redis -d redis:alpine3.15```
|
```docker run --name redis -d redis:alpine3.16```
|
||||||
|
|
||||||
```docker run --name postgres -e POSTGRES_PASSWORD=never_use_this_password_in_production -d postgres:alpine```
|
```docker run --name postgres -e POSTGRES_PASSWORD=never_use_this_password_in_production -d postgres:alpine```
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@ networks:
|
|||||||
name: oxker-examaple-net
|
name: oxker-examaple-net
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:alpine
|
image: postgres:alpine3.16
|
||||||
container_name: postgres
|
container_name: postgres
|
||||||
environment:
|
environment:
|
||||||
- POSTGRES_PASSWORD=never_use_this_password_in_production
|
- POSTGRES_PASSWORD=never_use_this_password_in_production
|
||||||
@@ -18,7 +18,7 @@ services:
|
|||||||
limits:
|
limits:
|
||||||
memory: 128M
|
memory: 128M
|
||||||
redis:
|
redis:
|
||||||
image: redis:alpine
|
image: redis:alpine3.16
|
||||||
container_name: redis
|
container_name: redis
|
||||||
ipc: private
|
ipc: private
|
||||||
restart: always
|
restart: always
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ impl DockerControls {
|
|||||||
match state {
|
match state {
|
||||||
State::Dead | State::Exited => vec![Self::Start, Self::Restart],
|
State::Dead | State::Exited => vec![Self::Start, Self::Restart],
|
||||||
State::Paused => vec![Self::Unpause, Self::Stop],
|
State::Paused => vec![Self::Unpause, Self::Stop],
|
||||||
|
State::Restarting => vec![Self::Stop],
|
||||||
State::Running => vec![Self::Pause, Self::Restart, Self::Stop],
|
State::Running => vec![Self::Pause, Self::Restart, Self::Stop],
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
}
|
}
|
||||||
@@ -276,7 +277,7 @@ impl Stats for ByteStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert from bytes to kb, mb, gb etc
|
// convert from bytes to kB, MB, GB etc
|
||||||
impl fmt::Display for ByteStats {
|
impl fmt::Display for ByteStats {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let one_kb = 1000.0;
|
let one_kb = 1000.0;
|
||||||
|
|||||||
+13
-9
@@ -99,9 +99,9 @@ impl AppData {
|
|||||||
self.error = Some(error);
|
self.error = Some(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the if of the currently selected container
|
/// Find the if of the currently selected container.
|
||||||
/// If any containers on system, will always return
|
/// If any containers on system, will always return a string.
|
||||||
/// Only returns None when no containers found
|
/// Only returns None when no containers found.
|
||||||
pub fn get_selected_container_id(&self) -> Option<String> {
|
pub fn get_selected_container_id(&self) -> Option<String> {
|
||||||
let mut output = None;
|
let mut output = None;
|
||||||
if let Some(index) = self.containers.state.selected() {
|
if let Some(index) = self.containers.state.selected() {
|
||||||
@@ -296,7 +296,7 @@ impl AppData {
|
|||||||
for (index, id) in all_ids.iter().enumerate() {
|
for (index, id) in all_ids.iter().enumerate() {
|
||||||
if !containers
|
if !containers
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| i.id.as_ref().unwrap())
|
.filter_map(|i| i.id.as_ref())
|
||||||
.any(|x| x == id)
|
.any(|x| x == id)
|
||||||
{
|
{
|
||||||
// If removed container is currently selected, then change selected to previous
|
// If removed container is currently selected, then change selected to previous
|
||||||
@@ -304,13 +304,15 @@ impl AppData {
|
|||||||
if self.containers.state.selected().is_some() {
|
if self.containers.state.selected().is_some() {
|
||||||
self.containers.previous();
|
self.containers.previous();
|
||||||
}
|
}
|
||||||
// docker rm -f $(docker ps -aq) will cause this to crash
|
// Check is some, else can cause out of bounds error, if containers get removed before a docker update
|
||||||
|
if self.containers.items.get(index).is_some() {
|
||||||
self.containers.items.remove(index);
|
self.containers.items.remove(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for i in containers.iter() {
|
for i in containers.iter() {
|
||||||
let id = i.id.as_ref().unwrap().to_owned();
|
if let Some(id) = i.id.as_ref() {
|
||||||
let mut name = i
|
let mut name = i
|
||||||
.names
|
.names
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -332,7 +334,7 @@ impl AppData {
|
|||||||
.trim()
|
.trim()
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let image = i.image.as_ref().unwrap_or(&"".to_owned()).trim().to_owned();
|
let image = i.image.as_ref().unwrap_or(&"".to_owned()).trim().to_owned();
|
||||||
if let Some(current_container) = self.get_container_by_id(&id) {
|
if let Some(current_container) = self.get_container_by_id(id) {
|
||||||
if current_container.name != name {
|
if current_container.name != name {
|
||||||
current_container.name = name
|
current_container.name = name
|
||||||
};
|
};
|
||||||
@@ -355,12 +357,14 @@ impl AppData {
|
|||||||
current_container.image = image
|
current_container.image = image
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
let mut container = ContainerItem::new(id, status, image, state, name);
|
let mut container =
|
||||||
|
ContainerItem::new(id.to_owned(), status, image, state, name);
|
||||||
container.logs.end();
|
container.logs.end();
|
||||||
self.containers.items.push(container);
|
self.containers.items.push(container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// update logs of a given container, based on index not id
|
/// update logs of a given container, based on index not id
|
||||||
pub fn update_log_by_index(&mut self, output: Vec<String>, index: usize) {
|
pub fn update_log_by_index(&mut self, output: Vec<String>, index: usize) {
|
||||||
@@ -379,7 +383,7 @@ impl AppData {
|
|||||||
container.logs.items.push(ListItem::new(lines));
|
container.logs.items.push(ListItem::new(lines));
|
||||||
});
|
});
|
||||||
if container.logs.state.selected().is_none()
|
if container.logs.state.selected().is_none()
|
||||||
|| container.logs.state.selected().unwrap() + 1 == current_len
|
|| container.logs.state.selected().unwrap_or_default() + 1 == current_len
|
||||||
{
|
{
|
||||||
container.logs.end();
|
container.logs.end();
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
use crate::app_data::DockerControls;
|
use crate::app_data::DockerControls;
|
||||||
use core::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/// app errors to set in global state
|
/// app errors to set in global state
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|||||||
+16
-12
@@ -34,8 +34,8 @@ impl DockerData {
|
|||||||
if stats.cpu_stats.system_cpu_usage.is_some()
|
if stats.cpu_stats.system_cpu_usage.is_some()
|
||||||
&& stats.precpu_stats.system_cpu_usage.is_some()
|
&& stats.precpu_stats.system_cpu_usage.is_some()
|
||||||
{
|
{
|
||||||
let system_delta = (stats.cpu_stats.system_cpu_usage.unwrap()
|
let system_delta = (stats.cpu_stats.system_cpu_usage.unwrap_or(0)
|
||||||
- stats.precpu_stats.system_cpu_usage.unwrap())
|
- stats.precpu_stats.system_cpu_usage.unwrap_or(0))
|
||||||
as f64;
|
as f64;
|
||||||
let online_cpus = stats.cpu_stats.online_cpus.unwrap_or_else(|| {
|
let online_cpus = stats.cpu_stats.online_cpus.unwrap_or_else(|| {
|
||||||
stats
|
stats
|
||||||
@@ -75,7 +75,7 @@ impl DockerData {
|
|||||||
let mem_stat = stats.memory_stats.usage.unwrap_or(0);
|
let mem_stat = stats.memory_stats.usage.unwrap_or(0);
|
||||||
let mem_limit = stats.memory_stats.limit.unwrap_or(0);
|
let mem_limit = stats.memory_stats.limit.unwrap_or(0);
|
||||||
|
|
||||||
let key = if let Some(networks) = &stats.networks {
|
let some_key = if let Some(networks) = &stats.networks {
|
||||||
networks.keys().next().map(|x| x.to_owned())
|
networks.keys().next().map(|x| x.to_owned())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -83,12 +83,14 @@ impl DockerData {
|
|||||||
|
|
||||||
let cpu_stats = Self::calculate_usage(&stats);
|
let cpu_stats = Self::calculate_usage(&stats);
|
||||||
|
|
||||||
let (rx, tx) = if let Some(k) = key {
|
let no_bytes = (0, 0);
|
||||||
let ii = stats.networks.unwrap();
|
let (rx, tx) = if let Some(key) = some_key {
|
||||||
let v = ii.get(&k).unwrap();
|
match stats.networks.unwrap_or_default().get(&key) {
|
||||||
(v.rx_bytes.to_owned(), v.tx_bytes.to_owned())
|
Some(data) => (data.rx_bytes.to_owned(), data.tx_bytes.to_owned()),
|
||||||
|
None => no_bytes,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(0, 0)
|
no_bytes
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_running {
|
if is_running {
|
||||||
@@ -131,7 +133,7 @@ impl DockerData {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
}))
|
}))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
// iter over containers, to only send ones which have an id, as use ID for extensivley!
|
// iter over containers, to only send ones which have an id, as use ID for extensivley!
|
||||||
@@ -143,12 +145,14 @@ impl DockerData {
|
|||||||
self.app_data.lock().update_containers(&output);
|
self.app_data.lock().update_containers(&output);
|
||||||
output
|
output
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| {
|
.filter_map(|i| {
|
||||||
|
i.id.as_ref().map(|id| {
|
||||||
(
|
(
|
||||||
i.state.as_ref().unwrap() == "running",
|
i.state.as_ref().unwrap_or(&String::new()) == "running",
|
||||||
i.id.as_ref().unwrap().to_owned(),
|
id.to_owned(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-16
@@ -99,11 +99,14 @@ impl InputHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let gui_state = Arc::clone(&self.gui_state);
|
// If the info box sleep handle is currently being executed, as in m is pressed twice within a 4000ms window
|
||||||
|
// then cancel the first handle, as a new handle will be invoked
|
||||||
if self.info_sleep.is_some() {
|
if let Some(info_sleep_timer) = self.info_sleep.as_ref() {
|
||||||
self.info_sleep.as_ref().unwrap().abort()
|
info_sleep_timer.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let gui_state = Arc::clone(&self.gui_state);
|
||||||
|
// Show the info box - with "mouse capture enabled / disabled", for 4000 ms
|
||||||
self.info_sleep = Some(tokio::spawn(async move {
|
self.info_sleep = Some(tokio::spawn(async move {
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(4000)).await;
|
tokio::time::sleep(std::time::Duration::from_millis(4000)).await;
|
||||||
gui_state.lock().reset_info_box()
|
gui_state.lock().reset_info_box()
|
||||||
@@ -176,39 +179,37 @@ impl InputHandler {
|
|||||||
// Does is matter though?
|
// Does is matter though?
|
||||||
let panel = self.gui_state.lock().selected_panel;
|
let panel = self.gui_state.lock().selected_panel;
|
||||||
if panel == SelectablePanel::Commands {
|
if panel == SelectablePanel::Commands {
|
||||||
let command = self.app_data.lock().get_docker_command();
|
let option_command = self.app_data.lock().get_docker_command();
|
||||||
|
|
||||||
if command.is_some() {
|
if let Some(command) = option_command {
|
||||||
let id = self.app_data.lock().get_selected_container_id();
|
let option_id = self.app_data.lock().get_selected_container_id();
|
||||||
if id.is_some() {
|
if let Some(id) = option_id {
|
||||||
let id = id.unwrap();
|
match command {
|
||||||
match command.unwrap() {
|
|
||||||
// TODO handle theses errors?
|
|
||||||
DockerControls::Pause => self
|
DockerControls::Pause => self
|
||||||
.docker_sender
|
.docker_sender
|
||||||
.send(DockerMessage::Pause(id))
|
.send(DockerMessage::Pause(id))
|
||||||
.await
|
.await
|
||||||
.unwrap(),
|
.unwrap_or(()),
|
||||||
DockerControls::Unpause => self
|
DockerControls::Unpause => self
|
||||||
.docker_sender
|
.docker_sender
|
||||||
.send(DockerMessage::Unpause(id))
|
.send(DockerMessage::Unpause(id))
|
||||||
.await
|
.await
|
||||||
.unwrap(),
|
.unwrap_or(()),
|
||||||
DockerControls::Start => self
|
DockerControls::Start => self
|
||||||
.docker_sender
|
.docker_sender
|
||||||
.send(DockerMessage::Start(id))
|
.send(DockerMessage::Start(id))
|
||||||
.await
|
.await
|
||||||
.unwrap(),
|
.unwrap_or(()),
|
||||||
DockerControls::Stop => self
|
DockerControls::Stop => self
|
||||||
.docker_sender
|
.docker_sender
|
||||||
.send(DockerMessage::Stop(id))
|
.send(DockerMessage::Stop(id))
|
||||||
.await
|
.await
|
||||||
.unwrap(),
|
.unwrap_or(()),
|
||||||
DockerControls::Restart => self
|
DockerControls::Restart => self
|
||||||
.docker_sender
|
.docker_sender
|
||||||
.send(DockerMessage::Restart(id))
|
.send(DockerMessage::Restart(id))
|
||||||
.await
|
.await
|
||||||
.unwrap(),
|
.unwrap_or(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -90,6 +90,6 @@ async fn main() {
|
|||||||
update_duration,
|
update_duration,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap_or(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,7 +265,10 @@ pub fn draw_chart<B: Backend>(
|
|||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)].as_ref())
|
||||||
.split(area);
|
.split(area);
|
||||||
let (cpu, mem) = app_data.lock().containers.items[index].get_chart_data();
|
|
||||||
|
// Check is some, else can cause out of bounds error, if containers get removed before a docker update
|
||||||
|
if let Some(data) = app_data.lock().containers.items.get(index) {
|
||||||
|
let (cpu, mem) = data.get_chart_data();
|
||||||
|
|
||||||
let cpu_dataset = vec![Dataset::default()
|
let cpu_dataset = vec![Dataset::default()
|
||||||
.marker(symbols::Marker::Dot)
|
.marker(symbols::Marker::Dot)
|
||||||
@@ -296,6 +299,7 @@ pub fn draw_chart<B: Backend>(
|
|||||||
f.render_widget(cpu_chart, area[0]);
|
f.render_widget(cpu_chart, area[0]);
|
||||||
f.render_widget(mem_chart, area[1]);
|
f.render_widget(mem_chart, area[1]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create charts
|
/// Create charts
|
||||||
@@ -460,7 +464,8 @@ pub fn draw_help_box<B: Backend>(f: &mut Frame<'_, B>) {
|
|||||||
let description_text = format!("\n{}", DESCRIPTION);
|
let description_text = format!("\n{}", DESCRIPTION);
|
||||||
|
|
||||||
let mut help_text = String::from("\n ( tab ) or ( alt+tab ) to change panels");
|
let mut help_text = String::from("\n ( tab ) or ( alt+tab ) to change panels");
|
||||||
help_text.push_str("\n ( ↑ ↓ ← → ) or ( j k ) to change selected line");
|
help_text
|
||||||
|
.push_str("\n ( ↑ ↓ ) or ( j k ) or (PgUp PgDown) or (Home End) to change selected line");
|
||||||
help_text.push_str("\n ( enter ) to send docker container commands");
|
help_text.push_str("\n ( enter ) to send docker container commands");
|
||||||
help_text.push_str("\n ( h ) to toggle this help information");
|
help_text.push_str("\n ( h ) to toggle this help information");
|
||||||
help_text.push_str(
|
help_text.push_str(
|
||||||
|
|||||||
+6
-5
@@ -58,13 +58,13 @@ pub async fn create_ui(
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
disable_raw_mode().unwrap();
|
disable_raw_mode().unwrap_or(());
|
||||||
execute!(
|
execute!(
|
||||||
terminal.backend_mut(),
|
terminal.backend_mut(),
|
||||||
LeaveAlternateScreen,
|
LeaveAlternateScreen,
|
||||||
DisableMouseCapture
|
DisableMouseCapture
|
||||||
)?;
|
)?;
|
||||||
terminal.show_cursor().unwrap();
|
terminal.show_cursor().unwrap_or(());
|
||||||
|
|
||||||
if let Err(err) = res {
|
if let Err(err) = res {
|
||||||
println!("{}", err);
|
println!("{}", err);
|
||||||
@@ -105,8 +105,8 @@ async fn run_app<B: Backend>(
|
|||||||
let mut now = Instant::now();
|
let mut now = Instant::now();
|
||||||
loop {
|
loop {
|
||||||
terminal.draw(|f| ui(f, &app_data, &gui_state)).unwrap();
|
terminal.draw(|f| ui(f, &app_data, &gui_state)).unwrap();
|
||||||
if crossterm::event::poll(input_poll_rate).unwrap() {
|
if crossterm::event::poll(input_poll_rate).unwrap_or_default() {
|
||||||
let event = event::read().unwrap();
|
if let Ok(event) = event::read() {
|
||||||
if let Event::Key(key) = event {
|
if let Event::Key(key) = event {
|
||||||
sender
|
sender
|
||||||
.send(InputMessages::ButtonPress(key.code))
|
.send(InputMessages::ButtonPress(key.code))
|
||||||
@@ -122,9 +122,10 @@ async fn run_app<B: Backend>(
|
|||||||
terminal.autoresize().unwrap_or(());
|
terminal.autoresize().unwrap_or(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if now.elapsed() >= update_duration {
|
if now.elapsed() >= update_duration {
|
||||||
docker_sx.send(DockerMessage::Update).await.unwrap();
|
docker_sx.send(DockerMessage::Update).await.unwrap_or(());
|
||||||
now = Instant::now();
|
now = Instant::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user