Merged 0.6.0 in keyring-rs-linux

This commit is contained in:
veeso 2021-07-03 14:35:17 +02:00
commit 65fee64132
10 changed files with 139 additions and 55 deletions

View file

@ -23,7 +23,7 @@
Released on FIXME: ??
> 🏄 Summer update 2021🌴
> 🍹 Summer update 2021 🍨
- **Open any file** in explorer:
- Open file with default program for file type with `<V>`
@ -36,12 +36,15 @@ Released on FIXME: ??
- **❗ BREAKING CHANGE ❗**: if you start using keyring on Linux, all the saved password will be lost
- **Installation script**:
- From now on, in case cargo is used to install termscp, all the cargo dependencies will be installed
- **In-app release notes**
- Possibility to see the release note of the new available release whenever a new version is available
- Just press `<CTRL+R>` when a new version is available from the auth activity to read the release notes
- Bugfix:
- Fixed broken input cursor when typing UTF8 characters (tui-realm 0.3.2)
- Dependencies:
- Added `open 1.7.0`
- Updated `textwrap` to `0.14.0`
- Updated `tui-realm` to `0.4.1`
- Updated `tui-realm` to `0.4.3`
## 0.5.1

6
Cargo.lock generated
View file

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aes"
version = "0.6.0"
@ -1451,9 +1453,9 @@ dependencies = [
[[package]]
name = "tuirealm"
version = "0.4.2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9897335542e4a4a87ad391419c35e54b4088661e671ba53e578fbbb1154740c2"
checksum = "0fcbd06f2aa6a2424aaa245c10e8767fe3f0fee234ac8c144cb15eaf2ee37ce9"
dependencies = [
"crossterm",
"textwrap",

View file

@ -52,7 +52,7 @@ tempfile = "3.1.0"
textwrap = "0.14.0"
thiserror = "^1.0.0"
toml = "0.5.8"
tuirealm = { version = "0.4.2", features = [ "with-components" ] }
tuirealm = { version = "0.4.3", features = [ "with-components" ] }
ureq = { version = "2.1.0", features = [ "json" ] }
whoami = "1.1.1"
wildmatch = "2.0.0"

View file

@ -47,6 +47,7 @@ use tuirealm::{Update, View};
const COMPONENT_TEXT_H1: &str = "TEXT_H1";
const COMPONENT_TEXT_H2: &str = "TEXT_H2";
const COMPONENT_TEXT_NEW_VERSION: &str = "TEXT_NEW_VERSION";
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";
@ -66,6 +67,7 @@ const COMPONENT_RECENTS_LIST: &str = "RECENTS_LIST";
// Store keys
const STORE_KEY_LATEST_VERSION: &str = "AUTH_LATEST_VERSION";
const STORE_KEY_RELEASE_NOTES: &str = "AUTH_RELEASE_NOTES";
/// ### AuthActivity
///
@ -111,16 +113,13 @@ impl AuthActivity {
let ctx: &Context = self.context.as_ref().unwrap();
if !ctx.store.isset(STORE_KEY_LATEST_VERSION) {
debug!("Version is not set in storage");
let mut new_version: Option<String> = match ctx.config_client.as_ref() {
let mut github_tag: Option<git::GithubTag> = match ctx.config_client.as_ref() {
Some(client) => {
if client.get_check_for_updates() {
debug!("Check for updates is enabled");
// Send request
match git::check_for_updates(env!("CARGO_PKG_VERSION")) {
Ok(version) => {
info!("Latest version is: {:?}", version);
version
}
Ok(github_tag) => github_tag,
Err(err) => {
// Report error
error!("Failed to get latest version: {}", err);
@ -140,9 +139,18 @@ impl AuthActivity {
};
let ctx: &mut Context = self.context.as_mut().unwrap();
// Set version into the store (or just a flag)
match new_version.take() {
Some(new_version) => ctx.store.set_string(STORE_KEY_LATEST_VERSION, new_version), // If Some, set String
None => ctx.store.set(STORE_KEY_LATEST_VERSION), // If None, just set flag
match github_tag.take() {
Some(git::GithubTag { tag_name, body }) => {
// If some store version and release notes
info!("Latest version is: {}", tag_name);
ctx.store.set_string(STORE_KEY_LATEST_VERSION, tag_name);
ctx.store.set_string(STORE_KEY_RELEASE_NOTES, body);
}
None => {
info!("Latest version is: {} (current)", env!("CARGO_PKG_VERSION"));
// Just set flag as check
ctx.store.set(STORE_KEY_LATEST_VERSION);
}
}
}
}

View file

@ -32,7 +32,7 @@ use super::{
COMPONENT_INPUT_PORT, 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_SIZE_ERR,
COMPONENT_TEXT_HELP, COMPONENT_TEXT_NEW_VERSION_NOTES, COMPONENT_TEXT_SIZE_ERR,
};
use crate::ui::keymap::*;
use tuirealm::components::InputPropsBuilder;
@ -116,18 +116,6 @@ impl Update for AuthActivity {
}
}
}
// <TAB> bookmarks
(COMPONENT_BOOKMARKS_LIST, &MSG_KEY_TAB)
| (COMPONENT_RECENTS_LIST, &MSG_KEY_TAB) => {
// Give focus to address
self.view.active(COMPONENT_INPUT_ADDR);
None
}
// Any <TAB>, go to bookmarks
(_, &MSG_KEY_TAB) => {
self.view.active(COMPONENT_BOOKMARKS_LIST);
None
}
// Bookmarks commands
// <RIGHT> / <LEFT>
(COMPONENT_BOOKMARKS_LIST, &MSG_KEY_RIGHT) => {
@ -219,10 +207,12 @@ impl Update for AuthActivity {
self.umount_recent_del_dialog();
None
}
(COMPONENT_RADIO_BOOKMARK_DEL_RECENT, _) => None,
(COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, &MSG_KEY_ESC) => {
self.umount_bookmark_del_dialog();
None
}
(COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, _) => None,
// Error message
(COMPONENT_TEXT_ERROR, &MSG_KEY_ENTER) | (COMPONENT_TEXT_ERROR, &MSG_KEY_ESC) => {
// Umount text error
@ -230,17 +220,31 @@ impl Update for AuthActivity {
None
}
(COMPONENT_TEXT_ERROR, _) => None,
(COMPONENT_TEXT_NEW_VERSION_NOTES, &MSG_KEY_ESC)
| (COMPONENT_TEXT_NEW_VERSION_NOTES, &MSG_KEY_ENTER) => {
// Umount release notes
self.umount_release_notes();
None
}
(COMPONENT_TEXT_NEW_VERSION_NOTES, _) => None,
// Help
(_, &MSG_KEY_CTRL_H) => {
// Show help
self.mount_help();
None
}
// Release notes
(_, &MSG_KEY_CTRL_R) => {
// Show release notes
self.mount_release_notes();
None
}
(COMPONENT_TEXT_HELP, &MSG_KEY_ENTER) | (COMPONENT_TEXT_HELP, &MSG_KEY_ESC) => {
// Hide text help
self.umount_help();
None
}
(COMPONENT_TEXT_HELP, _) => None,
// Enter setup
(_, &MSG_KEY_CTRL_C) => {
self.exit_reason = Some(super::ExitReason::EnterSetup);
@ -308,6 +312,18 @@ impl Update for AuthActivity {
}
// -- text size error; block everything
(COMPONENT_TEXT_SIZE_ERR, _) => None,
// <TAB> bookmarks
(COMPONENT_BOOKMARKS_LIST, &MSG_KEY_TAB)
| (COMPONENT_RECENTS_LIST, &MSG_KEY_TAB) => {
// Give focus to address
self.view.active(COMPONENT_INPUT_ADDR);
None
}
// Any <TAB>, go to bookmarks
(_, &MSG_KEY_TAB) => {
self.view.active(COMPONENT_BOOKMARKS_LIST);
None
}
// On submit on any unhandled (connect)
(_, Msg::OnSubmit(_)) | (_, &MSG_KEY_ENTER) => {
// Match <ENTER> key for all other components

View file

@ -39,6 +39,7 @@ use tuirealm::components::{
radio::{Radio, RadioPropsBuilder},
scrolltable::{ScrollTablePropsBuilder, Scrolltable},
span::{Span, SpanPropsBuilder},
textarea::{Textarea, TextareaPropsBuilder},
};
use tuirealm::tui::{
layout::{Constraint, Direction, Layout},
@ -185,17 +186,15 @@ impl AuthActivity {
self.view.mount(
super::COMPONENT_TEXT_NEW_VERSION,
Box::new(Span::new(
SpanPropsBuilder::default()
SpanPropsBuilder::default()
.with_foreground(Color::Yellow)
.with_spans(
vec![
TextSpan::from("termscp "),
TextSpanBuilder::new(version).underlined().bold().build(),
TextSpan::from(" is now available! Download it from <https://github.com/veeso/termscp/releases/latest>")
]
)
.build()
))
.with_spans(vec![
TextSpan::from("termscp "),
TextSpanBuilder::new(version).underlined().bold().build(),
TextSpan::from(" is NOW available! Get it from <https://veeso.github.io/termscp/>; view release notes with <CTRL+R>"),
])
.build(),
)),
);
}
// Bookmarks
@ -346,6 +345,15 @@ impl AuthActivity {
.render(super::COMPONENT_RADIO_BOOKMARK_DEL_RECENT, f, popup);
}
}
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);
f.render_widget(Clear, popup);
self.view
.render(super::COMPONENT_TEXT_NEW_VERSION_NOTES, f, popup);
}
}
if let Some(props) = self.view.get_props(super::COMPONENT_TEXT_HELP) {
if props.visible {
// make popup
@ -753,6 +761,35 @@ impl AuthActivity {
self.view.umount(super::COMPONENT_TEXT_HELP);
}
/// ### mount_release_notes
///
/// mount release notes text area
pub(super) fn mount_release_notes(&mut self) {
if let Some(ctx) = self.context.as_ref() {
if let Some(release_notes) = ctx.store.get_string(super::STORE_KEY_RELEASE_NOTES) {
// make spans
let spans: Vec<TextSpan> = release_notes.lines().map(TextSpan::from).collect();
self.view.mount(
super::COMPONENT_TEXT_NEW_VERSION_NOTES,
Box::new(Textarea::new(
TextareaPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow)
.with_texts(Some(String::from("Release notes")), spans)
.build(),
)),
);
self.view.active(super::COMPONENT_TEXT_NEW_VERSION_NOTES);
}
}
}
/// ### umount_release_notes
///
/// Umount release notes text area
pub(super) fn umount_release_notes(&mut self) {
self.view.umount(super::COMPONENT_TEXT_NEW_VERSION_NOTES);
}
/// ### get_input
///
/// Collect input values from view

View file

@ -379,6 +379,7 @@ impl Update for FileTransferActivity {
_ => None,
}
}
(COMPONENT_INPUT_COPY, _) => None,
// -- exec popup
(COMPONENT_INPUT_EXEC, &MSG_KEY_ESC) => {
self.umount_exec();
@ -399,6 +400,7 @@ impl Update for FileTransferActivity {
_ => None,
}
}
(COMPONENT_INPUT_EXEC, _) => None,
// -- find popup
(COMPONENT_INPUT_FIND, &MSG_KEY_ESC) => {
self.umount_find_input();
@ -466,6 +468,7 @@ impl Update for FileTransferActivity {
_ => None,
}
}
(COMPONENT_INPUT_GOTO, _) => None,
// -- make directory
(COMPONENT_INPUT_MKDIR, &MSG_KEY_ESC) => {
self.umount_mkdir();
@ -485,6 +488,7 @@ impl Update for FileTransferActivity {
_ => None,
}
}
(COMPONENT_INPUT_MKDIR, _) => None,
// -- new file
(COMPONENT_INPUT_NEWFILE, &MSG_KEY_ESC) => {
self.umount_newfile();
@ -504,6 +508,7 @@ impl Update for FileTransferActivity {
_ => None,
}
}
(COMPONENT_INPUT_NEWFILE, _) => None,
// -- open with
(COMPONENT_INPUT_OPEN_WITH, &MSG_KEY_ESC) => {
self.umount_openwith();
@ -520,6 +525,7 @@ impl Update for FileTransferActivity {
self.umount_openwith();
None
}
(COMPONENT_INPUT_OPEN_WITH, _) => None,
// -- rename
(COMPONENT_INPUT_RENAME, &MSG_KEY_ESC) => {
self.umount_rename();
@ -539,6 +545,7 @@ impl Update for FileTransferActivity {
_ => None,
}
}
(COMPONENT_INPUT_RENAME, _) => None,
// -- save as
(COMPONENT_INPUT_SAVEAS, &MSG_KEY_ESC) => {
self.umount_saveas();
@ -563,12 +570,14 @@ impl Update for FileTransferActivity {
FileExplorerTab::FindRemote => self.update_local_filelist(),
}
}
(COMPONENT_INPUT_SAVEAS, _) => None,
// -- fileinfo
(COMPONENT_LIST_FILEINFO, &MSG_KEY_ENTER)
| (COMPONENT_LIST_FILEINFO, &MSG_KEY_ESC) => {
self.umount_file_info();
None
}
(COMPONENT_LIST_FILEINFO, _) => None,
// -- delete
(COMPONENT_RADIO_DELETE, &MSG_KEY_ESC)
| (COMPONENT_RADIO_DELETE, Msg::OnSubmit(Payload::One(Value::Usize(1)))) => {
@ -612,6 +621,7 @@ impl Update for FileTransferActivity {
FileExplorerTab::FindRemote => self.update_remote_filelist(),
}
}
(COMPONENT_RADIO_DELETE, _) => None,
// -- disconnect
(COMPONENT_RADIO_DISCONNECT, &MSG_KEY_ESC)
| (COMPONENT_RADIO_DISCONNECT, Msg::OnSubmit(Payload::One(Value::Usize(1)))) => {
@ -623,6 +633,7 @@ impl Update for FileTransferActivity {
self.umount_disconnect();
None
}
(COMPONENT_RADIO_DISCONNECT, _) => None,
// -- quit
(COMPONENT_RADIO_QUIT, &MSG_KEY_ESC)
| (COMPONENT_RADIO_QUIT, Msg::OnSubmit(Payload::One(Value::Usize(1)))) => {
@ -634,6 +645,7 @@ impl Update for FileTransferActivity {
self.umount_quit();
None
}
(COMPONENT_RADIO_QUIT, _) => None,
// -- sorting
(COMPONENT_RADIO_SORTING, &MSG_KEY_ESC)
| (COMPONENT_RADIO_SORTING, Msg::OnSubmit(_)) => {
@ -666,27 +678,32 @@ impl Update for FileTransferActivity {
_ => None,
}
}
(COMPONENT_RADIO_SORTING, _) => None,
// -- error
(COMPONENT_TEXT_ERROR, &MSG_KEY_ESC) | (COMPONENT_TEXT_ERROR, &MSG_KEY_ENTER) => {
self.umount_error();
None
}
(COMPONENT_TEXT_ERROR, _) => None,
// -- fatal
(COMPONENT_TEXT_FATAL, &MSG_KEY_ESC) | (COMPONENT_TEXT_FATAL, &MSG_KEY_ENTER) => {
self.exit_reason = Some(super::ExitReason::Disconnect);
None
}
(COMPONENT_TEXT_FATAL, _) => None,
// -- help
(COMPONENT_TEXT_HELP, &MSG_KEY_ESC) | (COMPONENT_TEXT_HELP, &MSG_KEY_ENTER) => {
self.umount_help();
None
}
(COMPONENT_TEXT_HELP, _) => None,
// -- progress bar
(COMPONENT_PROGRESS_BAR_PARTIAL, &MSG_KEY_CTRL_C) => {
// Set transfer aborted to True
self.transfer.abort();
None
}
(COMPONENT_PROGRESS_BAR_PARTIAL, _) => None,
// -- fallback
(_, _) => None, // Nothing to do
},

View file

@ -79,11 +79,6 @@ pub struct SetupActivity {
impl Default for SetupActivity {
fn default() -> Self {
// Initialize user input
let mut user_input_buffer: Vec<String> = Vec::with_capacity(16);
for _ in 0..16 {
user_input_buffer.push(String::new());
}
SetupActivity {
exit_reason: None,
context: None,

View file

@ -114,6 +114,7 @@ impl Update for SetupActivity {
self.umount_error();
None
}
(COMPONENT_TEXT_ERROR, _) => None,
// Exit
(COMPONENT_RADIO_QUIT, Msg::OnSubmit(Payload::One(Value::Usize(0)))) => {
// Save changes
@ -135,12 +136,14 @@ impl Update for SetupActivity {
self.umount_quit();
None
}
(COMPONENT_RADIO_QUIT, _) => None,
// Close help
(COMPONENT_TEXT_HELP, &MSG_KEY_ENTER) | (COMPONENT_TEXT_HELP, &MSG_KEY_ESC) => {
// Umount help
self.umount_help();
None
}
(COMPONENT_TEXT_HELP, _) => None,
// Delete key
(COMPONENT_RADIO_DEL_SSH_KEY, Msg::OnSubmit(Payload::One(Value::Usize(0)))) => {
// Delete key
@ -156,6 +159,7 @@ impl Update for SetupActivity {
self.umount_del_ssh_key();
None
}
(COMPONENT_RADIO_DEL_SSH_KEY, _) => None,
// Save popup
(COMPONENT_RADIO_SAVE, Msg::OnSubmit(Payload::One(Value::Usize(0)))) => {
// Save config
@ -170,6 +174,7 @@ impl Update for SetupActivity {
self.umount_save_popup();
None
}
(COMPONENT_RADIO_SAVE, _) => None,
// Edit SSH Key
// <TAB> Change view
(COMPONENT_LIST_SSH_KEYS, &MSG_KEY_TAB) => {

View file

@ -30,38 +30,39 @@ use super::parser::parse_semver;
// Others
use serde::Deserialize;
#[derive(Deserialize)]
struct TagInfo {
tag_name: String,
#[derive(Debug, Deserialize)]
/// ## GithubTag
///
/// Info related to a github tag
pub struct GithubTag {
pub tag_name: String,
pub body: String,
}
/// ### check_for_updates
///
/// Check if there is a new version available for termscp.
/// This is performed through the Github API
/// In case of success returns Ok(Option<String>), where the Option is Some(new_version); otherwise if no version is available, return None
/// In case of success returns Ok(Option<GithubTag>), where the Option is Some(new_version); otherwise if no version is available, return None
/// In case of error returns Error with the error description
pub fn check_for_updates(current_version: &str) -> Result<Option<String>, String> {
pub fn check_for_updates(current_version: &str) -> Result<Option<GithubTag>, String> {
// Send request
let github_version: Result<String, String> =
let github_tag: Result<GithubTag, String> =
match ureq::get("https://api.github.com/repos/veeso/termscp/releases/latest").call() {
Ok(response) => match response.into_json::<TagInfo>() {
Ok(tag_info) => Ok(tag_info.tag_name),
Err(err) => Err(err.to_string()),
},
Ok(response) => response.into_json::<GithubTag>().map_err(|x| x.to_string()),
Err(err) => Err(err.to_string()),
};
// Check version
match github_version {
match github_tag {
Err(err) => Err(err),
Ok(version) => {
Ok(tag) => {
// Parse version
match parse_semver(version.as_str()) {
match parse_semver(tag.tag_name.as_str()) {
Some(new_version) => {
// Check if version is different
if new_version.as_str() > current_version {
Ok(Some(new_version)) // New version is available
Ok(Some(tag)) // New version is available
} else {
Ok(None) // No new version
}