aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorwyhaya <wyhaya@gmail.com>2020-07-05 14:34:43 +0000
committerGitHub <noreply@github.com>2020-07-05 14:34:43 +0000
commit205a5a4cc49e33b86366969a76b3303d71287761 (patch)
tree5c8d73e8380356476cab85b770ab7d983011d639 /src
parentMerge pull request #292 from j2ghz/patch-1 (diff)
downloadminiserve-205a5a4cc49e33b86366969a76b3303d71287761.tar.gz
miniserve-205a5a4cc49e33b86366969a76b3303d71287761.zip
Add generate QR code (#330)
* Add generate QR code * Add --qrcode option
Diffstat (limited to 'src')
-rw-r--r--src/args.rs5
-rw-r--r--src/listing.rs23
-rw-r--r--src/main.rs5
-rw-r--r--src/renderer.rs135
4 files changed, 111 insertions, 57 deletions
diff --git a/src/args.rs b/src/args.rs
index a5bcfea..bf16291 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -77,6 +77,10 @@ struct CLIArgs {
)]
color_scheme: themes::ColorScheme,
+ /// Enable QR code display
+ #[structopt(short = "q", long = "qrcode")]
+ qrcode: bool,
+
/// Enable file uploading
#[structopt(short = "u", long = "upload-files")]
file_upload: bool,
@@ -188,6 +192,7 @@ pub fn parse_args() -> crate::MiniserveConfig {
default_color_scheme,
index: args.index,
overwrite_files: args.overwrite_files,
+ show_qrcode: args.qrcode,
file_upload: args.file_upload,
tar_enabled: args.enable_tar,
zip_enabled: args.enable_zip,
diff --git a/src/listing.rs b/src/listing.rs
index 9ba596a..6181c3a 100644
--- a/src/listing.rs
+++ b/src/listing.rs
@@ -9,6 +9,7 @@ use std::io;
use std::path::{Path, PathBuf};
use std::time::SystemTime;
use strum_macros::{Display, EnumString};
+use qrcodegen::{QrCode, QrCodeEcc};
use crate::archive::CompressionMethod;
use crate::errors::{self, ContextualError};
@@ -24,6 +25,7 @@ pub struct QueryParameters {
pub sort: Option<SortingMethod>,
pub order: Option<SortingOrder>,
pub theme: Option<ColorScheme>,
+ qrcode: Option<String>,
download: Option<CompressionMethod>,
}
@@ -135,6 +137,7 @@ pub fn directory_listing<S>(
file_upload: bool,
random_route: Option<String>,
default_color_scheme: ColorScheme,
+ show_qrcode: bool,
upload_route: String,
tar_enabled: bool,
zip_enabled: bool,
@@ -163,6 +166,23 @@ pub fn directory_listing<S>(
let query_params = extract_query_parameters(req);
+ // If the `qrcode` parameter is included in the url, then should respond to the QR code
+ if let Some(url) = query_params.qrcode {
+ let res = match QrCode::encode_text(&url, QrCodeEcc::Medium) {
+ Ok(qr) => {
+ HttpResponse::Ok()
+ .header("Content-Type", "image/svg+xml")
+ .body(qr.to_svg_string(2))
+ },
+ Err(err) => {
+ log::error!("URL is too long: {:?}", err);
+ HttpResponse::UriTooLong()
+ .body(Body::Empty)
+ }
+ };
+ return Ok(res)
+ }
+
let mut entries: Vec<Entry> = Vec::new();
for entry in dir.path.read_dir()? {
@@ -330,6 +350,7 @@ pub fn directory_listing<S>(
query_params.order,
default_color_scheme,
color_scheme,
+ show_qrcode,
file_upload,
&upload_route,
&current_dir.display().to_string(),
@@ -348,6 +369,7 @@ pub fn extract_query_parameters<S>(req: &HttpRequest<S>) -> QueryParameters {
order: query.order,
download: query.download,
theme: query.theme,
+ qrcode: query.qrcode.to_owned(),
path: query.path.clone(),
},
Err(e) => {
@@ -358,6 +380,7 @@ pub fn extract_query_parameters<S>(req: &HttpRequest<S>) -> QueryParameters {
order: None,
download: None,
theme: None,
+ qrcode: None,
path: None,
}
}
diff --git a/src/main.rs b/src/main.rs
index 3ff35c8..a9e7944 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -57,6 +57,9 @@ pub struct MiniserveConfig {
/// However, if a directory contains this file, miniserve will serve that file instead.
pub index: Option<std::path::PathBuf>,
+ /// Enable QR code display
+ pub show_qrcode: bool,
+
/// Enable file upload
pub file_upload: bool,
@@ -258,6 +261,7 @@ fn configure_app(app: App<MiniserveConfig>) -> App<MiniserveConfig> {
let no_symlinks = app.state().no_symlinks;
let random_route = app.state().random_route.clone();
let default_color_scheme = app.state().default_color_scheme;
+ let show_qrcode = app.state().show_qrcode;
let file_upload = app.state().file_upload;
let tar_enabled = app.state().tar_enabled;
let zip_enabled = app.state().zip_enabled;
@@ -288,6 +292,7 @@ fn configure_app(app: App<MiniserveConfig>) -> App<MiniserveConfig> {
file_upload,
random_route.clone(),
default_color_scheme,
+ show_qrcode,
u_r.clone(),
tar_enabled,
zip_enabled,
diff --git a/src/renderer.rs b/src/renderer.rs
index accb49b..7270e8f 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -19,6 +19,7 @@ pub fn page(
sort_order: Option<SortingOrder>,
default_color_scheme: ColorScheme,
color_scheme: ColorScheme,
+ show_qrcode: bool,
file_upload: bool,
upload_route: &str,
current_dir: &str,
@@ -46,7 +47,7 @@ pub fn page(
}
}
}
- (color_scheme_selector(sort_method, sort_order, color_scheme, default_color_scheme, serve_path))
+ (color_scheme_selector(sort_method, sort_order, color_scheme, default_color_scheme, serve_path, show_qrcode))
div.container {
span#top { }
h1.title { "Index of " (serve_path) }
@@ -133,24 +134,33 @@ fn color_scheme_selector(
active_color_scheme: ColorScheme,
default_color_scheme: ColorScheme,
serve_path: &str,
+ show_qrcode: bool,
) -> Markup {
html! {
nav {
- ul {
- li {
- a.change-theme href="#" title="Change theme" {
- "Change theme..."
+ @if show_qrcode {
+ div {
+ p onmouseover="document.querySelector('#qrcode').src = `/?qrcode=${encodeURIComponent(window.location.href)}`" {
+ "QR code"
}
- ul {
- @for color_scheme in ColorScheme::iter() {
- @if active_color_scheme == color_scheme {
- li.active {
- (color_scheme_link(sort_method, sort_order, color_scheme, default_color_scheme, serve_path))
- }
- } @else {
- li {
- (color_scheme_link(sort_method, sort_order, color_scheme, default_color_scheme, serve_path))
- }
+ div.qrcode {
+ img#qrcode alt="QR code" title="QR code of this page";
+ }
+ }
+ }
+ div {
+ p {
+ "Change theme..."
+ }
+ ul.theme {
+ @for color_scheme in ColorScheme::iter() {
+ @if active_color_scheme == color_scheme {
+ li.active {
+ (color_scheme_link(sort_method, sort_order, color_scheme, default_color_scheme, serve_path))
+ }
+ } @else {
+ li {
+ (color_scheme_link(sort_method, sort_order, color_scheme, default_color_scheme, serve_path))
}
}
}
@@ -429,64 +439,75 @@ fn css(color_scheme: ColorScheme) -> Markup {
}}
nav {{
padding: 0 5rem;
+ display: flex;
+ justify-content: flex-end;
}}
- nav ul {{
- text-align: right;
- list-style: none;
- margin: 0;
- padding: 0;
- }}
- nav ul li {{
- display: block;
- transition-duration: 0.5s;
- float: right;
+ nav > div {{
position: relative;
+ margin-left: 0.5rem;
+ }}
+ nav p {{
padding: 0.5rem 1rem;
- background: {switch_theme_background};
width: 8rem;
text-align: center;
+ background: {switch_theme_background};
+ color: {change_theme_link_color};
+ }}
+ nav p + * {{
+ display: none;
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 100%;
+ animation: show 0.5s ease;
+ }}
+ @keyframes show {{
+ from {{
+ opacity: 0;
+ }}
+ to {{
+ opacity: 1;
+ }}
}}
- nav ul li:hover {{
+ nav > div::hover p {{
cursor: pointer;
- text-decoration: none;
- color: {change_theme_link_color}
+ color: {switch_theme_link_color};
}}
- nav ul li a:hover {{
- text-decoration: none;
- color: {change_theme_link_color_hover};
+ nav > div:hover p + * {{
+ display: block;
+ border-top: 1px solid {switch_theme_border};
}}
- nav ul li ul {{
- visibility: hidden;
- opacity: 0;
- position: absolute;
- transition: all 0.5s ease;
- margin-top: 0.5rem;
- left: 0;
- display: none;
- text-align: center;
+ nav .qrcode {{
+ padding: 0.5rem;
+ background: {switch_theme_background};
}}
- nav ul li:hover > ul,
- nav ul li ul:hover {{
- visibility: visible;
- opacity: 1;
+ nav .qrcode img {{
display: block;
}}
- nav ul li ul li:first-of-type {{
- border-top: 1px solid {switch_theme_border};
+ nav .theme {{
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
}}
- nav ul li ul li {{
- clear: both;
- width: 8rem;
- padding-top: 0.5rem;
- padding-bottom: 0.5rem;
+ nav .theme li {{
+ width: 100%;
+ background: {switch_theme_background};
}}
- nav ul li ul li a:hover {{
- text-decoration: underline;
+ nav .theme li a {{
+ display: block;
+ width: 100%;
+ padding: 0.5rem 0;
+ text-align: center;
+ color: {switch_theme_link_color};
}}
- nav ul li a, nav ul li ul li a, nav ul li a:visited, nav ul li ul li a:visited {{
- color: {switch_theme_link_color}
+ nav .theme li a:visited {{
+ color: {switch_theme_link_color};
+ }}
+ nav .theme li a::hover {{
+ text-decoration: underline;
+ color: {change_theme_link_color_hover};
}}
- nav ul li ul li.active a {{
+ nav .theme li.active a {{
font-weight: bold;
color: {switch_theme_active};
}}