153 lines
4.8 KiB
Rust
153 lines
4.8 KiB
Rust
#![windows_subsystem = "windows"]
|
|
|
|
use anyhow::{anyhow, bail, Result};
|
|
use clap::{Arg, Command};
|
|
use log::info;
|
|
use native_dialog::{FileDialog, MessageDialog};
|
|
use rust_embed::RustEmbed;
|
|
use simplelog::{ColorChoice, ConfigBuilder, LevelFilter, TermLogger, TerminalMode};
|
|
use std::{borrow::Cow, path::PathBuf, thread::JoinHandle};
|
|
use warp::Filter;
|
|
use wry::{
|
|
application::{
|
|
event::{Event, StartCause, WindowEvent},
|
|
event_loop::{ControlFlow, EventLoop},
|
|
window::WindowBuilder,
|
|
},
|
|
webview::{WebContext, WebViewBuilder},
|
|
};
|
|
|
|
#[derive(RustEmbed)]
|
|
#[folder = "embed/"]
|
|
struct Embed;
|
|
|
|
fn main() -> Result<()> {
|
|
// Init log
|
|
TermLogger::init(
|
|
LevelFilter::Info,
|
|
ConfigBuilder::new()
|
|
.set_time_offset_to_local()
|
|
.unwrap()
|
|
.build(),
|
|
TerminalMode::Mixed,
|
|
ColorChoice::Auto,
|
|
)?;
|
|
|
|
let cmd = Command::new("Simple panorama viewer")
|
|
.version(env!("CARGO_PKG_VERSION"))
|
|
.author(env!("CARGO_PKG_AUTHORS"))
|
|
.about(env!("CARGO_PKG_DESCRIPTION"))
|
|
.arg(
|
|
Arg::new("filename")
|
|
.value_parser(clap::value_parser!(PathBuf))
|
|
.help("Image path"),
|
|
)
|
|
.get_matches();
|
|
|
|
let img_path = if let Some(img_path) = cmd.get_one::<PathBuf>("filename") {
|
|
Cow::Borrowed(img_path)
|
|
} else {
|
|
let user_dirs = directories::UserDirs::new().unwrap();
|
|
let dir = if let Some(img_dir) = user_dirs.picture_dir() {
|
|
img_dir
|
|
} else {
|
|
user_dirs.home_dir()
|
|
};
|
|
Cow::Owned(
|
|
FileDialog::new()
|
|
.add_filter(
|
|
"Images",
|
|
&[
|
|
"jpg", "JPG", "jpeg", "pjpeg", "pjpg", "PJPG", "webp", "avif",
|
|
],
|
|
)
|
|
.set_location(dir)
|
|
.show_open_single_file()?
|
|
.ok_or_else(|| anyhow!("No file"))?,
|
|
)
|
|
};
|
|
|
|
if !img_path.exists() {
|
|
MessageDialog::new()
|
|
.set_title("Image error")
|
|
.set_text(&format!("Image `{}` does not exist", img_path.display()))
|
|
.set_type(native_dialog::MessageType::Error)
|
|
.show_alert()?;
|
|
bail!("File `{}` does not exist !", img_path.display());
|
|
}
|
|
|
|
info!("Run server");
|
|
run_server(img_path.to_path_buf());
|
|
|
|
info!("Create webview");
|
|
let event_loop = EventLoop::new();
|
|
let window = WindowBuilder::new()
|
|
.with_title("Simple panorama viewer")
|
|
.with_maximized(true)
|
|
.build(&event_loop)?;
|
|
let data_dir = directories::ProjectDirs::from("fr", "dalan", "SimplePanoramaViwer").unwrap();
|
|
let _webview = WebViewBuilder::new(window)?
|
|
.with_url("http://127.0.0.1:62371/index.html")?
|
|
.with_web_context(&mut WebContext::new(Some(
|
|
data_dir.cache_dir().to_path_buf(),
|
|
)))
|
|
.build()?;
|
|
|
|
info!("Event loop");
|
|
event_loop.run(move |event, _, control_flow| {
|
|
*control_flow = ControlFlow::Wait;
|
|
|
|
match event {
|
|
Event::NewEvents(StartCause::Init) => info!("Panorama open"),
|
|
Event::WindowEvent {
|
|
event: WindowEvent::CloseRequested,
|
|
..
|
|
} => {
|
|
info!("Close");
|
|
*control_flow = ControlFlow::Exit
|
|
}
|
|
_ => (),
|
|
}
|
|
});
|
|
}
|
|
|
|
fn run_server(img_path: PathBuf) -> JoinHandle<()> {
|
|
std::thread::spawn(|| {
|
|
info!("Create runtime");
|
|
let async_runtime = tokio::runtime::Builder::new_current_thread()
|
|
.enable_all()
|
|
.build()
|
|
.unwrap();
|
|
info!("Create response");
|
|
let index = warp::path("index.html").map(|| {
|
|
info!("Request `index.html`");
|
|
let datas = get_file_data("index.html");
|
|
warp::reply::html(datas)
|
|
});
|
|
let css = warp::path!("css" / String).map(move |val: String| {
|
|
info!("Request css `{}`", &val);
|
|
let datas = get_file_data(&format!("css/{}", val));
|
|
warp::http::Response::builder().body(datas)
|
|
});
|
|
let js = warp::path!("js" / String).map(move |val: String| {
|
|
info!("Request js `{}`", &val);
|
|
let datas = get_file_data(&format!("js/{}", val));
|
|
warp::http::Response::builder().body(datas)
|
|
});
|
|
let img = warp::path!("img").map(move || std::fs::read(&img_path).unwrap());
|
|
info!("Launch webserver");
|
|
async_runtime
|
|
.block_on(warp::serve(img.or(index).or(css).or(js)).run(([127, 0, 0, 1], 62371)));
|
|
})
|
|
}
|
|
|
|
fn get_file_data(filename: &str) -> String {
|
|
if let Some(file) = Embed::get(filename) {
|
|
std::str::from_utf8(file.data.as_ref())
|
|
.unwrap_or("")
|
|
.to_string()
|
|
} else {
|
|
"".to_string()
|
|
}
|
|
}
|