added ability to save the current url to a filepath

master
deadjakk 1 year ago committed by chris west
parent 3f2ae945db
commit 4a5328a14e

@ -112,6 +112,51 @@ fn clean_response(res: &mut String) {
})
}
/// Downloads a binary to disk to a provided file name.
/// Allows canceling with Ctrl-c, but it's
/// kind of hacky - needs the UI receiver passed in.
/// Returns a tuple of:
/// (path it was saved to, the size in bytes)
pub fn download_url_with_filename(
url: &str,
tls: bool,
tor: bool,
chan: ui::KeyReceiver,
filename: &str,
) -> Result<(String, usize)> {
let u = parse_url(url);
let mut path = std::path::PathBuf::from(".");
path.push(filename);
let mut stream = request(u.host, u.port, u.sel, tls, tor)?;
let mut file = fs::OpenOptions::new()
.write(true)
.create_new(true)
.append(true)
.open(&path)
.map_err(|e| error!("`open` error: {}", e))?;
let mut buf = [0; 1024];
let mut bytes = 0;
while let Ok(count) = stream.read(&mut buf) {
if count == 0 {
break;
}
bytes += count;
file.write_all(&buf[..count])?;
if let Ok(chan) = chan.lock() {
if let Ok(Key::Ctrl('c')) = chan.try_recv() {
if path.exists() {
fs::remove_file(path)?;
}
return Err(error!("Download cancelled"));
}
}
}
Ok((filename.to_string(), bytes))
}
/// Downloads a binary to disk. Allows canceling with Ctrl-c, but it's
/// kind of hacky - needs the UI receiver passed in.
/// Returns a tuple of:

@ -236,6 +236,31 @@ impl UI {
})
}
/// Used to download content of the current view with a provided filename
fn download_file_with_filename(&mut self, url: &str, filename: String) -> Result<()> {
let url = url.to_string();
let (tls, tor) = (
self.config.read().unwrap().tls,
self.config.read().unwrap().tor,
);
let chan = self.keys.clone();
self.spinner(&format!("Downloading {}", url), move || {
gopher::download_url_with_filename(&url, tls, tor, chan, &filename)
})
.and_then(|res| res)
.map(|(path, bytes)| {
self.set_status(
format!(
"Download complete! {} saved to {}",
utils::human_bytes(bytes),
path
)
.as_ref(),
);
})
}
/// Download a binary file. Used by `open()` internally.
fn download(&mut self, url: &str) -> Result<()> {
let url = url.to_string();
@ -659,6 +684,19 @@ impl UI {
Action::Keypress(Key::Char(key)) | Action::Keypress(Key::Ctrl(key)) => match key {
'a' => self.open("History", "gopher://phetch/1/history")?,
'b' => self.open("Bookmarks", "gopher://phetch/1/bookmarks")?,
'c' => {
let url = match self.views.get(self.focused) {
Some(view)=> String::from(view.url()),
None => {return Err(error!("Could not get url from view"));},
};
if let Some(filename) = self.prompt("Provide a filepath: ", ""){
match self.download_file_with_filename(url.as_str(), String::from(filename)){
Ok(()) => (),
Err(e) => return Err(error!("Save failed: {}", e)),
}
}
}
'g' => {
if let Some(url) = self.prompt("Go to URL: ", "") {
self.open(&url, &url)?;

Loading…
Cancel
Save