Add front-end share functionality, make API just redirect to generated share URL instead of JSON response

This commit is contained in:
NGnius (Graham) 2025-01-23 22:52:46 -05:00
parent 606e0a4c69
commit d3519e534b
8 changed files with 1154 additions and 629 deletions

1731
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,7 @@ name = "frontend"
name = "backend"
[dependencies]
reqwest = { version = "0.11.8", features = ["json"] }
reqwest = { version = "0.12", features = ["json"] }
serde = { version = "1.0.132", features = ["derive"] }
uuid = { version = "1.0.0", features = ["serde"] }
futures = "0.3"
@ -28,7 +28,8 @@ yew_icons = {version = "0.7", features = [
"FeatherFilm",
"FeatherImage",
"FeatherFile",
"FeatherRefreshCcw"
"FeatherRefreshCcw",
"LucideShare2",
] }
log = "0.4"
hex = "0.4"
@ -56,7 +57,7 @@ tokio = { version = "1", features = ["full"] }
actix-web = { version = "4.3" }
actix-files = { version = "0.6" }
actix-web-httpauth = { version = "0.8" }
clap = { version = "3.1.7", features = ["derive"] }
clap = { version = "4.5", features = ["derive"] }
url-escape = { version = "0.1.1" }
rand = "0.8"
ring = "0.17"

View file

@ -144,7 +144,7 @@ div.yarrr-rant {
}
.yarrr-file-entry-file {
display: inline-block;
display: inline-flex;
width: 100%;
margin: auto;
vertical-align: middle;
@ -181,6 +181,16 @@ a.yarrr-file-entry-link:hover {
.yarrr-file-entry-name {
vertical-align: middle;
display: inline-block;
width: 90%;
flex-grow: 1;
//width: 90%;
margin: auto;
}
.yarrr-file-entry-share-icon {
vertical-align: middle;
display: inline-block;
margin: 0;
padding: 0.5em;
width: 2em;
height: 2em;
}

View file

@ -21,7 +21,7 @@ pub struct CliArgs {
#[clap(short, long)]
pub password: Option<String>,
/// Display hidden files
#[clap(short, long)]
#[clap(short = 'i', long)]
pub hidden: bool,
/// Local network port
#[clap(long)]

View file

@ -9,7 +9,6 @@ use ring::aead::{UnboundKey, SealingKey, OpeningKey, BoundKey, AES_256_GCM, Nonc
use bytes::Buf;
use super::get_files::{FileRequest, DeliveryMode};
use crate::data::ShareInfo;
const DEFAULT_SHARE_TIME_S: u64 = 24 * 60 * 60;
static AES256_KEY: RwLock<Option<[u8; 32]>> = RwLock::new(None);
@ -220,10 +219,6 @@ pub async fn share(path: web::Path<String>, auth: BasicAuth) -> std::io::Result<
path: path.to_owned(),
expiry: expiry_time,
}.to_hex(enc_key_file)?;
let share_info = ShareInfo {
path: std::path::PathBuf::from(&*path),
url_path: format!("/share/{}", &hex_str),
full_url: format!("{}/share/{}", args.domain, &hex_str),
};
Ok(web::Json(share_info))
let url_path = format!("/share/{}", &hex_str);
Ok(web::Redirect::to(url_path).temporary())
}

View file

@ -1,5 +1,3 @@
mod file_entry;
mod share_info;
pub use file_entry::FileEntry;
pub use share_info::ShareInfo;

View file

@ -1,8 +0,0 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct ShareInfo {
pub path: std::path::PathBuf,
pub url_path: String,
pub full_url: String,
}

View file

@ -49,6 +49,10 @@ pub fn entry(props: &Props) -> Html {
if s_ctx.ssl { "https" } else { "http" },
s_ctx.domain,
props.entry.path.to_string_lossy());
let share_url = format!("{}://{}/api/share/{}",
if s_ctx.ssl { "https" } else { "http" },
s_ctx.domain,
props.entry.path.to_string_lossy());
let icon = if props.entry.name.ends_with(".mkv") {
html! { <Icon icon_id={IconId::FeatherFilm}
width={icon_dimension.clone()} height={icon_dimension.clone()}/> }
@ -59,6 +63,7 @@ pub fn entry(props: &Props) -> Html {
html! { <Icon icon_id={IconId::FeatherFile}
width={icon_dimension.clone()} height={icon_dimension.clone()} /> }
};
html! {
<a href={download_url} class={classes!("yarrr-file-entry-link")}>
<div class={classes!("yarrr-file-entry-file")}>
@ -68,6 +73,11 @@ pub fn entry(props: &Props) -> Html {
<div class={classes!("yarrr-file-entry-name")}>
{&props.entry.name}
</div>
<div class={classes!("yarrr-file-entry-share-icon")}>
<a href={share_url} target={"_blank"} class={classes!("yarrr-file-entry-link")}>
<Icon icon_id={IconId::LucideShare2} width={icon_dimension.clone()} height={icon_dimension.clone()} />
</a>
</div>
</div>
</a>
}