mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Auto update (w/ cli)
This commit is contained in:
@@ -27,6 +27,9 @@
|
||||
*/
|
||||
use super::{AuthActivity, FileTransferParams, FileTransferProtocol};
|
||||
use crate::filetransfer::params::{AwsS3Params, GenericProtocolParams, ProtocolParams};
|
||||
use crate::system::auto_update::{Update, UpdateStatus};
|
||||
|
||||
use tuirealm::tui::style::Color;
|
||||
|
||||
impl AuthActivity {
|
||||
/// ### protocol_opt_to_enum
|
||||
@@ -151,4 +154,31 @@ impl AuthActivity {
|
||||
entry_directory: None,
|
||||
})
|
||||
}
|
||||
|
||||
// -- update install
|
||||
|
||||
/// ### install_update
|
||||
///
|
||||
/// Install latest termscp version via GUI
|
||||
pub(super) fn install_update(&mut self) {
|
||||
// Umount release notes
|
||||
self.umount_release_notes();
|
||||
// Mount wait box
|
||||
self.mount_wait("Installing update. Please wait…");
|
||||
// Install update
|
||||
let result = Update::default().show_progress(false).upgrade();
|
||||
// Umount wait
|
||||
self.umount_wait();
|
||||
// Show outcome
|
||||
match result {
|
||||
Ok(UpdateStatus::AlreadyUptodate) => {
|
||||
self.mount_info("termscp is already up to date!", Color::Cyan)
|
||||
}
|
||||
Ok(UpdateStatus::UpdateInstalled(ver)) => self.mount_info(
|
||||
format!("termscp has been updated to version {}!", ver),
|
||||
Color::Green,
|
||||
),
|
||||
Err(err) => self.mount_error(format!("Could not install update: {}", err)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ mod view;
|
||||
use super::{Activity, Context, ExitReason};
|
||||
use crate::config::themes::Theme;
|
||||
use crate::filetransfer::{FileTransferParams, FileTransferProtocol};
|
||||
use crate::system::auto_update::{Release, Update as TermscpUpdate};
|
||||
use crate::system::bookmarks_client::BookmarksClient;
|
||||
use crate::utils::git;
|
||||
|
||||
// Includes
|
||||
use crossterm::event::Event;
|
||||
@@ -51,6 +51,8 @@ const COMPONENT_TEXT_NEW_VERSION_NOTES: &str = "TEXTAREA_NEW_VERSION";
|
||||
const COMPONENT_TEXT_FOOTER: &str = "TEXT_FOOTER";
|
||||
const COMPONENT_TEXT_HELP: &str = "TEXT_HELP";
|
||||
const COMPONENT_TEXT_ERROR: &str = "TEXT_ERROR";
|
||||
const COMPONENT_TEXT_INFO: &str = "TEXT_INFO";
|
||||
const COMPONENT_TEXT_WAIT: &str = "TEXT_WAIT";
|
||||
const COMPONENT_TEXT_SIZE_ERR: &str = "TEXT_SIZE_ERR";
|
||||
const COMPONENT_INPUT_ADDR: &str = "INPUT_ADDRESS";
|
||||
const COMPONENT_INPUT_PORT: &str = "INPUT_PORT";
|
||||
@@ -65,6 +67,7 @@ const COMPONENT_RADIO_QUIT: &str = "RADIO_QUIT";
|
||||
const COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK: &str = "RADIO_DELETE_BOOKMARK";
|
||||
const COMPONENT_RADIO_BOOKMARK_DEL_RECENT: &str = "RADIO_DELETE_RECENT";
|
||||
const COMPONENT_RADIO_BOOKMARK_SAVE_PWD: &str = "RADIO_SAVE_PASSWORD";
|
||||
const COMPONENT_RADIO_INSTALL_UPDATE: &str = "RADIO_INSTALL_UPDATE";
|
||||
const COMPONENT_BOOKMARKS_LIST: &str = "BOOKMARKS_LIST";
|
||||
const COMPONENT_RECENTS_LIST: &str = "RECENTS_LIST";
|
||||
|
||||
@@ -119,12 +122,12 @@ impl AuthActivity {
|
||||
if ctx.config().get_check_for_updates() {
|
||||
debug!("Check for updates is enabled");
|
||||
// Send request
|
||||
match git::check_for_updates(env!("CARGO_PKG_VERSION")) {
|
||||
Ok(Some(git::GithubTag { tag_name, body })) => {
|
||||
match TermscpUpdate::is_new_version_available() {
|
||||
Ok(Some(Release { version, body })) => {
|
||||
// If some, store version and release notes
|
||||
info!("Latest version is: {}", tag_name);
|
||||
info!("Latest version is: {}", version);
|
||||
ctx.store_mut()
|
||||
.set_string(STORE_KEY_LATEST_VERSION, tag_name);
|
||||
.set_string(STORE_KEY_LATEST_VERSION, version);
|
||||
ctx.store_mut().set_string(STORE_KEY_RELEASE_NOTES, body);
|
||||
}
|
||||
Ok(None) => {
|
||||
|
||||
@@ -32,8 +32,9 @@ use super::{
|
||||
COMPONENT_INPUT_S3_BUCKET, COMPONENT_INPUT_S3_PROFILE, COMPONENT_INPUT_S3_REGION,
|
||||
COMPONENT_INPUT_USERNAME, COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK,
|
||||
COMPONENT_RADIO_BOOKMARK_DEL_RECENT, COMPONENT_RADIO_BOOKMARK_SAVE_PWD,
|
||||
COMPONENT_RADIO_PROTOCOL, COMPONENT_RADIO_QUIT, COMPONENT_RECENTS_LIST, COMPONENT_TEXT_ERROR,
|
||||
COMPONENT_TEXT_HELP, COMPONENT_TEXT_NEW_VERSION_NOTES, COMPONENT_TEXT_SIZE_ERR,
|
||||
COMPONENT_RADIO_INSTALL_UPDATE, COMPONENT_RADIO_PROTOCOL, COMPONENT_RADIO_QUIT,
|
||||
COMPONENT_RECENTS_LIST, COMPONENT_TEXT_ERROR, COMPONENT_TEXT_HELP, COMPONENT_TEXT_INFO,
|
||||
COMPONENT_TEXT_NEW_VERSION_NOTES, COMPONENT_TEXT_SIZE_ERR, COMPONENT_TEXT_WAIT,
|
||||
};
|
||||
use crate::ui::keymap::*;
|
||||
use tui_realm_stdlib::InputPropsBuilder;
|
||||
@@ -252,15 +253,44 @@ impl Update for AuthActivity {
|
||||
self.umount_error();
|
||||
None
|
||||
}
|
||||
(COMPONENT_TEXT_ERROR, _) => None,
|
||||
(COMPONENT_TEXT_NEW_VERSION_NOTES, key)
|
||||
if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER =>
|
||||
{
|
||||
// -- Text info
|
||||
(COMPONENT_TEXT_INFO, key) if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => {
|
||||
// Umount text info
|
||||
self.umount_info();
|
||||
None
|
||||
}
|
||||
(COMPONENT_TEXT_ERROR, _) | (COMPONENT_TEXT_INFO, _) => None,
|
||||
// -- Text wait
|
||||
(COMPONENT_TEXT_WAIT, _) => None,
|
||||
// -- Release notes
|
||||
(COMPONENT_TEXT_NEW_VERSION_NOTES, key) if key == &MSG_KEY_ESC => {
|
||||
// Umount release notes
|
||||
self.umount_release_notes();
|
||||
None
|
||||
}
|
||||
(COMPONENT_TEXT_NEW_VERSION_NOTES, key) if key == &MSG_KEY_TAB => {
|
||||
// Focus to radio update
|
||||
self.view.active(COMPONENT_RADIO_INSTALL_UPDATE);
|
||||
None
|
||||
}
|
||||
(COMPONENT_TEXT_NEW_VERSION_NOTES, _) => None,
|
||||
// -- Install update radio
|
||||
(COMPONENT_RADIO_INSTALL_UPDATE, Msg::OnSubmit(Payload::One(Value::Usize(0)))) => {
|
||||
// Install update
|
||||
self.install_update();
|
||||
None
|
||||
}
|
||||
(COMPONENT_RADIO_INSTALL_UPDATE, Msg::OnSubmit(Payload::One(Value::Usize(1)))) => {
|
||||
// Umount
|
||||
self.umount_release_notes();
|
||||
None
|
||||
}
|
||||
(COMPONENT_RADIO_INSTALL_UPDATE, key) if key == &MSG_KEY_TAB => {
|
||||
// Focus to changelog
|
||||
self.view.active(COMPONENT_TEXT_NEW_VERSION_NOTES);
|
||||
None
|
||||
}
|
||||
(COMPONENT_RADIO_INSTALL_UPDATE, _) => None,
|
||||
// Help
|
||||
(_, key) if key == &MSG_KEY_CTRL_H => {
|
||||
// Show help
|
||||
|
||||
@@ -209,7 +209,7 @@ impl AuthActivity {
|
||||
.with_spans(vec![
|
||||
TextSpan::from("termscp "),
|
||||
TextSpan::new(version.as_str()).underlined().bold(),
|
||||
TextSpan::from(" is NOW available! Get it from <https://veeso.github.io/termscp/>; view release notes with <CTRL+R>"),
|
||||
TextSpan::from(" is NOW available! Install update and view release notes with <CTRL+R>"),
|
||||
])
|
||||
.build(),
|
||||
)),
|
||||
@@ -360,6 +360,22 @@ impl AuthActivity {
|
||||
self.view.render(super::COMPONENT_TEXT_ERROR, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_INFO) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 50, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_TEXT_INFO, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_WAIT) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 50, 10);
|
||||
f.render_widget(Clear, popup);
|
||||
// make popup
|
||||
self.view.render(super::COMPONENT_TEXT_WAIT, f, popup);
|
||||
}
|
||||
}
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_SIZE_ERR) {
|
||||
if props.visible {
|
||||
let popup = draw_area_in(f.size(), 80, 20);
|
||||
@@ -403,10 +419,22 @@ impl AuthActivity {
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_NEW_VERSION_NOTES) {
|
||||
if props.visible {
|
||||
// make popup
|
||||
let popup = draw_area_in(f.size(), 90, 90);
|
||||
let popup = draw_area_in(f.size(), 90, 85);
|
||||
f.render_widget(Clear, popup);
|
||||
let popup_chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(
|
||||
[
|
||||
Constraint::Percentage(90), // Notes
|
||||
Constraint::Length(3), // Install radio
|
||||
]
|
||||
.as_ref(),
|
||||
)
|
||||
.split(popup);
|
||||
self.view
|
||||
.render(super::COMPONENT_TEXT_NEW_VERSION_NOTES, f, popup);
|
||||
.render(super::COMPONENT_TEXT_NEW_VERSION_NOTES, f, popup_chunks[0]);
|
||||
self.view
|
||||
.render(super::COMPONENT_RADIO_INSTALL_UPDATE, f, popup_chunks[1]);
|
||||
}
|
||||
}
|
||||
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_HELP) {
|
||||
@@ -515,7 +543,7 @@ impl AuthActivity {
|
||||
/// ### mount_error
|
||||
///
|
||||
/// Mount error box
|
||||
pub(super) fn mount_error(&mut self, text: &str) {
|
||||
pub(super) fn mount_error<S: AsRef<str>>(&mut self, text: S) {
|
||||
// Mount
|
||||
let err_color = self.theme().misc_error_dialog;
|
||||
self.view.mount(
|
||||
@@ -526,7 +554,7 @@ impl AuthActivity {
|
||||
.with_borders(Borders::ALL, BorderType::Thick, err_color)
|
||||
.bold()
|
||||
.with_text_alignment(Alignment::Center)
|
||||
.with_texts(vec![TextSpan::from(text)])
|
||||
.with_texts(vec![TextSpan::from(text.as_ref().to_string())])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
@@ -541,6 +569,61 @@ impl AuthActivity {
|
||||
self.view.umount(super::COMPONENT_TEXT_ERROR);
|
||||
}
|
||||
|
||||
/// ### mount_info
|
||||
///
|
||||
/// Mount info box
|
||||
pub(super) fn mount_info<S: AsRef<str>>(&mut self, text: S, color: Color) {
|
||||
// Mount
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_INFO,
|
||||
Box::new(Paragraph::new(
|
||||
ParagraphPropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Thick, color)
|
||||
.bold()
|
||||
.with_text_alignment(Alignment::Center)
|
||||
.with_texts(vec![TextSpan::from(text.as_ref().to_string())])
|
||||
.with_foreground(color)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
// Give focus to error
|
||||
self.view.active(super::COMPONENT_TEXT_INFO);
|
||||
}
|
||||
|
||||
/// ### umount_info
|
||||
///
|
||||
/// Umount info message
|
||||
pub(super) fn umount_info(&mut self) {
|
||||
self.view.umount(super::COMPONENT_TEXT_INFO);
|
||||
}
|
||||
|
||||
/// ### mount_error
|
||||
///
|
||||
/// Mount wait box
|
||||
pub(super) fn mount_wait(&mut self, text: &str) {
|
||||
// Mount
|
||||
self.view.mount(
|
||||
super::COMPONENT_TEXT_WAIT,
|
||||
Box::new(Paragraph::new(
|
||||
ParagraphPropsBuilder::default()
|
||||
.with_borders(Borders::ALL, BorderType::Thick, Color::Reset)
|
||||
.bold()
|
||||
.with_text_alignment(Alignment::Center)
|
||||
.with_texts(vec![TextSpan::from(text)])
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
// Give focus to error
|
||||
self.view.active(super::COMPONENT_TEXT_WAIT);
|
||||
}
|
||||
|
||||
/// ### umount_wait
|
||||
///
|
||||
/// Umount wait message
|
||||
pub(super) fn umount_wait(&mut self) {
|
||||
self.view.umount(super::COMPONENT_TEXT_WAIT);
|
||||
}
|
||||
|
||||
/// ### mount_size_err
|
||||
///
|
||||
/// Mount size error
|
||||
@@ -785,7 +868,22 @@ impl AuthActivity {
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
self.view.active(super::COMPONENT_TEXT_NEW_VERSION_NOTES);
|
||||
// Mount install popup
|
||||
self.view.mount(
|
||||
super::COMPONENT_RADIO_INSTALL_UPDATE,
|
||||
Box::new(Radio::new(
|
||||
RadioPropsBuilder::default()
|
||||
.with_color(Color::LightYellow)
|
||||
.with_inverted_color(Color::Black)
|
||||
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow)
|
||||
.with_title("Install new version?", Alignment::Left)
|
||||
.with_options(&["Yes", "No"])
|
||||
.with_value(0)
|
||||
.rewind(true)
|
||||
.build(),
|
||||
)),
|
||||
);
|
||||
self.view.active(super::COMPONENT_RADIO_INSTALL_UPDATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -795,6 +893,7 @@ impl AuthActivity {
|
||||
/// Umount release notes text area
|
||||
pub(super) fn umount_release_notes(&mut self) {
|
||||
self.view.umount(super::COMPONENT_TEXT_NEW_VERSION_NOTES);
|
||||
self.view.umount(super::COMPONENT_RADIO_INSTALL_UPDATE);
|
||||
}
|
||||
|
||||
/// ### get_protocol
|
||||
|
||||
Reference in New Issue
Block a user