Render file expiry time and secret in history view

This commit is contained in:
timvisee 2018-04-29 23:20:10 +02:00
parent cb0638c5c9
commit a6186975b2
No known key found for this signature in database
GPG key ID: 109CBA0BF74036C2
3 changed files with 80 additions and 3 deletions

View file

@ -6,9 +6,8 @@ use url::{
ParseError as UrlParseError,
Url,
};
use self::chrono::{DateTime, Utc};
use self::chrono::{DateTime, Duration, Utc};
use self::regex::Regex;
use time::Duration;
use url_serde;
use config::SEND_DEFAULT_EXPIRE_TIME;
@ -157,6 +156,23 @@ impl RemoteFile {
&self.id
}
/// Get the duration the file will expire after,
/// if an expiry time is known.
/// Otherwise `None` is returned.
pub fn expire_duration(&self) -> Option<Duration> {
self.expire_at.as_ref().map(|time| {
// Get the current time
let now = Utc::now();
// Return the duration if not expired, otherwise return zero
if time > &now {
*time - now
} else {
Duration::zero()
}
})
}
/// Set the time this file will expire at.
/// None may be given if the expire time is unknown.
pub fn set_expire_at(&mut self, expire_at: Option<DateTime<Utc>>) {

View file

@ -18,6 +18,7 @@ use history::{
History as HistoryManager,
LoadError as HistoryLoadError,
};
use util::format_duration;
/// A history action.
pub struct History<'a> {
@ -61,14 +62,23 @@ impl<'a> History<'a> {
Cell::new("#"),
Cell::new("FILE ID"),
Cell::new("URL"),
Cell::new("EXPIRY"),
]));
// Add an entry for each file
for (i, file) in history.files().iter().enumerate() {
// Build the expiry time string
let expiry = match file.expire_duration() {
Some(ref expire) => format_duration(expire),
None => "?".into(),
};
// Add the row
table.add_row(Row::new(vec![
Cell::new(&format!("{}", i + 1)),
Cell::new(file.id()),
Cell::new(file.download_url(false).as_str()),
Cell::new(file.download_url(true).as_str()),
Cell::new(&expiry),
]));
}

View file

@ -21,6 +21,7 @@ use self::colored::*;
use failure::{err_msg, Fail};
use ffsend_api::url::Url;
use rpassword::prompt_password_stderr;
use time::Duration;
use cmd::matcher::MainMatcher;
@ -442,6 +443,56 @@ pub fn format_bytes(bytes: u64) -> String {
}
}
/// Format the given duration in a human readable format.
/// This method builds a string of time components to represent
/// the given duration.
///
/// The following time units are used:
/// - `w`: weeks
/// - `d`: days
/// - `h`: hours
/// - `m`: minutes
/// - `s`: seconds
///
/// Only the two most significant units are returned.
/// If the duration is zero seconds or less `now` is returned.
///
/// The following time strings may be produced:
/// - `8w6d`
/// - `23h14m`
/// - `9m55s`
/// - `1s`
/// - `now`
pub fn format_duration(duration: &Duration) -> String {
// Get the total number of seconds, return immediately if zero or less
let mut secs = duration.num_seconds();
if secs <= 0 {
return "now".into();
}
// Build a list of time units, define a list for time components
let mut components = Vec::new();
let units = [
(1 * 60 * 60 * 24 * 7, "w"),
(1 * 60 * 60 * 24, "d"),
(1 * 60 * 60, "h"),
(1 * 60, "m"),
(1, "s"),
];
// Fill the list of time components based on the units which fit
for unit in units.iter() {
if secs >= unit.0 {
components.push(format!("{}{}", secs / unit.0, unit.1));
secs %= unit.0;
}
}
// Show only the two most significant components and join them in a string
components.truncate(2);
components.join("")
}
/// Get the name of the executable that was invoked.
pub fn exe_name() -> String {
current_exe()