}
fn save_page(&self) -> io::Result<()> {
if let Some(page) = &self.page {
match page.ready() {
None => Err(io::Error::new(io::ErrorKind::NotFound, "No page")),
Some(page) => match page {
Err(_) => Err(io::Error::new(io::ErrorKind::NotFound, "No page")),
Ok((gemini, _)) => match gemini.body_bytes() {
None => Err(io::Error::new(io::ErrorKind::NotFound, "No page")),
Some(page) => {
let url = Url::parse(self.url_history.last().unwrap()).unwrap();
let path = url.path_segments().unwrap();
let mut filename = path.last().unwrap();
if filename.is_empty() {
filename = "index.gmi";
}
let file = rfd::FileDialog::new().set_file_name(filename).save_file();
if let Some(file) = file {
let mut file = fs::File::create(file)?;
file.write_all(page)?;
}
Ok(())
}
},
},
}
} else {
Err(io::Error::new(io::ErrorKind::NotFound, "No page"))
}
}
fn check_reload(&mut self, ctx: &egui::Context) {
if self.reload {
self.reload = false;
let new_url = self.url_history.last().unwrap().clone();
let new_url = match new_url.split_once("://") {
Some(_) => new_url,
None => "gemini://".to_string() + &new_url,
};
if let Ok(new_url) = Url::parse(&new_url) {
match new_url.scheme() {
"gemini" => (),
_ => {
// TODO: Mime launch
self.url_history.pop();
self.reload = true;
return;
}
}
self.url_bar = new_url.as_str().to_string();
let tls_config = self.tls_config.clone();
let ctx = ctx.clone();
let (sender, promise) = Promise::new();
self.page = Some(promise);
thread::spawn(move || {
sender.send((|| -> io::Result<(gemini::response::Response, Option<gemini::Builder>)> {
let addr = new_url.socket_addrs(|| match new_url.scheme() {
"gemini" => Some(1965),
_ => None,
})?[0];
let mut conn = rustls::ClientConnection::new(
tls_config,
new_url.host_str()
.ok_or_else(|| io::Error::new(
io::ErrorKind::InvalidInput,
"No hostname",
))?
.try_into()
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?,
)
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
let mut sock = net::TcpStream::connect(addr)?;
let mut tls = rustls::Stream::new(&mut conn, &mut sock);
tls.write_all((new_url.as_str().to_string() + "\r\n").as_bytes())?;
let mut response = Vec::new();
tls.read_to_end(&mut response)?;
let gemini = gemini::parse::parse_response(response)
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
// TODO: cleanup
let body =
if let Some(mime_type) = gemini.header.mime_type() {
if mime_type.split(';').next().unwrap() == "text/gemini" {
if let Some(body) = gemini.body_text() {
Some(gemini::parse::parse_gemtext(body).map_err(|err| {
io::Error::new(io::ErrorKind::Other, err)
})?)
} else {
None
}
} else {
None
}
} else {
None
};
Ok((gemini, body))
})());
ctx.request_repaint();
});
}
}