Use web-view file dialogs where possible

This commit is contained in:
James 2018-08-03 21:49:38 +10:00
parent 1f6d1e8d52
commit cab17e6832
5 changed files with 47 additions and 32 deletions

View File

@ -23,10 +23,11 @@ serde_json = "1.0.9"
toml = "0.4" toml = "0.4"
# TODO: Use web-view for this one
nfd = "0.0.4"
semver = {version = "0.9.0", features = ["serde"]} semver = {version = "0.9.0", features = ["serde"]}
regex = "0.2" regex = "0.2"
zip = "0.2.8" zip = "0.2.8"
[target.'cfg(windows)'.dependencies]
# NFD is needed on Windows, as web-view doesn't work correctly here
nfd = "0.0.4"

View File

@ -1,7 +1,6 @@
/// installer.rs /// installer.rs
/// ///
/// Contains the main installer structure, as well as high-level means of controlling it. /// Contains the main installer structure, as well as high-level means of controlling it.
use serde_json; use serde_json;
use std::fs::File; use std::fs::File;

View File

@ -1,5 +1,8 @@
#![windows_subsystem = "windows"] #![windows_subsystem = "windows"]
#[cfg(windows)]
extern crate nfd;
extern crate web_view; extern crate web_view;
extern crate futures; extern crate futures;
@ -33,11 +36,17 @@ use config::Config;
use installer::InstallerFramework; use installer::InstallerFramework;
use nfd::Response;
use rest::WebServer; use rest::WebServer;
// TODO: Fetch this over a HTTP request? // TODO: Fetch this over a HTTP request?
static RAW_CONFIG: &'static str = include_str!("../config.toml"); static RAW_CONFIG: &'static str = include_str!("../config.toml");
#[derive(Deserialize, Debug)]
enum CallbackType {
SelectInstallDir { callback_name: String },
}
fn main() { fn main() {
let config = Config::from_toml_str(RAW_CONFIG).unwrap(); let config = Config::from_toml_str(RAW_CONFIG).unwrap();
@ -74,9 +83,32 @@ fn main() {
debug, debug,
|_| {}, |_| {},
|wv, msg, _| { |wv, msg, _| {
println!("Incoming payload: {:?}", msg); let command: CallbackType =
if msg == "select-install-dir" { serde_json::from_str(msg).expect(&format!("Unable to parse string: {:?}", msg));
wv.dialog(Dialog::ChooseDirectory, "Select a install directory...", "");
println!("Incoming payload: {:?}", command);
match command {
CallbackType::SelectInstallDir { callback_name } => {
#[cfg(windows)]
let result =
match nfd::open_pick_folder(None).expect("Unable to open folder dialog") {
Response::Okay(v) => v,
_ => return,
};
#[cfg(not(windows))]
let result =
wv.dialog(Dialog::ChooseDirectory, "Select a install directory...", "");
if result.len() > 0 {
let result =
serde_json::to_string(&result).expect("Unable to serialize response");
let command = format!("{}({});", callback_name, result);
println!("Injecting response: {}", command);
wv.eval(&command);
}
}
} }
}, },
(), (),

View File

@ -2,11 +2,8 @@
/// ///
/// Provides a HTTP/REST server for both frontend<->backend communication, as well /// Provides a HTTP/REST server for both frontend<->backend communication, as well
/// as talking to external applications. /// as talking to external applications.
extern crate nfd;
extern crate url; extern crate url;
use self::nfd::Response as NfdResponse;
use serde_json; use serde_json;
use futures::future; use futures::future;
@ -115,23 +112,6 @@ impl Service for WebService {
.with_header(ContentType::json()) .with_header(ContentType::json())
.with_body(file) .with_body(file)
} }
// Opens a file dialog and returns the path as a string
(&Get, "/api/file-select") => {
let file_dialog = nfd::open_pick_folder(None).unwrap();
let file = match file_dialog {
NfdResponse::Okay(path) => Some(path),
_ => None,
};
let response = FileSelection { path: file };
let file = serde_json::to_string(&response).unwrap();
Response::<hyper::Body>::new()
.with_header(ContentLength(file.len() as u64))
.with_header(ContentType::json())
.with_body(file)
}
// Returns the default path for a installation // Returns the default path for a installation
(&Get, "/api/default-path") => { (&Get, "/api/default-path") => {
let framework = self.framework.read().unwrap(); let framework = self.framework.read().unwrap();

View File

@ -143,6 +143,10 @@
<script src="/js/helpers.js"></script> <script src="/js/helpers.js"></script>
<script src="/js/vue.js"></script> <script src="/js/vue.js"></script>
<script> <script>
function selectFileCallback(name) {
app.install_location = name;
}
var app = new Vue({ var app = new Vue({
el: '#app', el: '#app',
data: { data: {
@ -165,12 +169,11 @@
}, },
methods: { methods: {
"select_file": function() { "select_file": function() {
window.external.invoke("select-install-dir"); window.external.invoke(JSON.stringify({
/*ajax("/api/file-select", function(e) { SelectInstallDir: {
if (e.path != null) { callback_name: "selectFileCallback"
app.install_location = e.path;
} }
});*/ }));
}, },
"install": function() { "install": function() {
this.select_packages = false; this.select_packages = false;