Implement file selection

This commit is contained in:
James 2018-01-27 15:02:49 +11:00
parent 68b3811304
commit 3305fa412d
6 changed files with 151 additions and 8 deletions

16
Cargo.lock generated
View File

@ -122,6 +122,11 @@ name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "gcc"
version = "0.3.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "includedir"
version = "0.2.2"
@ -190,6 +195,14 @@ dependencies = [
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nfd"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num"
version = "0.1.41"
@ -453,6 +466,7 @@ version = "0.1.0"
dependencies = [
"includedir 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"includedir_codegen 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
@ -481,6 +495,7 @@ dependencies = [
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
"checksum includedir 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ed470a2a5c0afe4587796a886aa185fcef159feaefd8c4f40d85423aeeec4a3a"
"checksum includedir_codegen 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4cb2bb86e79496ab481fc7865ce8c2960cf1eb40cc1411524ce67fce54f3c95e"
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
@ -490,6 +505,7 @@ dependencies = [
"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
"checksum nfd 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8e752e3c216bc8a491c5b59fa46da10f1379ae450b19ac688e07f4bb55042e98"
"checksum num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4083e14b542ea3eb9b5f33ff48bd373a92d78687e74f4cc0a30caeb754f0ca"
"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"

View File

@ -16,5 +16,7 @@ serde_json = "1.0.9"
toml = "0.4"
nfd = "0.0.4"
[build-dependencies]
includedir_codegen = "0.2.0"

View File

@ -12,6 +12,8 @@ extern crate serde_derive;
extern crate serde_json;
extern crate toml;
extern crate nfd;
mod assets;
mod rest;
mod config;

View File

@ -5,6 +5,11 @@
use tiny_http::{Server, Request, Response, Header};
use nfd;
use nfd::Response as NfdResponse;
use serde_json;
use std::error::Error;
use std::net::{SocketAddr, IpAddr, Ipv4Addr};
use std::thread::{self, JoinHandle};
@ -14,6 +19,11 @@ use assets;
use installer::InstallerFramework;
#[derive(Serialize)]
struct FileSelection {
path : Option<String>
}
/// Encapsulates tiny_http's state.
pub struct WebServer {
server : Server,
@ -34,7 +44,9 @@ impl WebServer {
let call_response = self.rest_call(api_url);
match call_response {
Some(response) => request.respond(Response::from_string(response)),
Some(response) => request.respond(Response::from_data(response.into_bytes())
.with_header(Header::from_str("Content-Type: application/json")
.unwrap())),
None => request.respond(Response::empty(404))
}.unwrap();
return;
@ -62,10 +74,41 @@ impl WebServer {
/// Makes a call to a REST endpoint.
fn rest_call(&self, path : &str) -> Option<String> {
match path {
let mut path = path.to_owned();
// Strip off query params
let query = match path.rfind("?") {
Some(pos) => {
let ext = path[pos + 1 ..].to_owned();
path = path[0 .. pos].to_owned();
println!("Got query string: {}", ext);
Some(ext)
},
None => None
};
match path.as_str() {
// This endpoint should be usable directly from a <script> tag during loading.
// TODO: Handle errors
"config" => Some(enscapsulate_json("config",
&self.framework.get_config().to_json_str().unwrap())),
"file-select" => {
println!("Pick folder!");
let file_dialog = nfd::open_pick_folder(None).unwrap();
println!("OK!");
let file = match file_dialog {
NfdResponse::Okay(path) => Some(path),
_ => None
};
let response = FileSelection {
path : file
};
println!("Built!");
Some(serde_json::to_string(&response).unwrap())
}
_ => None
}
}

View File

@ -1,5 +1,5 @@
<!doctype html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport"
@ -53,10 +53,16 @@
</div>
</div>
<div class="field">
<label class="label subtitle is-6">Install Location</label>
<div class="subtitle is-6">Install Location</div>
<div class="field has-addons">
<div class="control is-expanded">
<input class="input" type="text" v-model="install_location"
placeholder="%localappdata%\yuzu">
</div>
<div class="control">
<input class="input" type="text" placeholder="%localappdata%\yuzu">
<a class="button is-info" v-on:click="select_file">
Select
</a>
</div>
</div>
@ -68,12 +74,24 @@
</div>
<script src="/api/config"></script>
<script src="/js/helpers.js"></script>
<script src="/js/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
config : config
config : config,
install_location : "%localappdata%\yuzu"
},
methods: {
"select_file": function() {
ajax("/api/file-select", function(e) {
alert(e);
if (e.path != null) {
app.install_location = e.path;
}
});
}
}
});
</script>

62
static/js/helpers.js Normal file
View File

@ -0,0 +1,62 @@
/**
* helpers.js
*
* Additional state-less helper methods.
*/
var request_id = 0;
/**
* Makes a AJAX request.
*
* @param path The path to connect to.
* @param successCallback A callback with a JSON payload.
* @param failCallback A fail callback. Optional.
* @param data POST data. Optional.
*/
function ajax(path, successCallback, failCallback, data) {
if (failCallback === undefined) {
failCallback = defaultFailHandler;
}
var req = new XMLHttpRequest();
req.addEventListener("load", function() {
// The server can sometimes return a string error. Make sure we handle this.
if (this.status === 200 && this.getResponseHeader('Content-Type').indexOf("application/json") !== -1) {
successCallback(JSON.parse(this.responseText));
} else {
failCallback();
}
});
req.addEventListener("error", failCallback);
req.open(data == null ? "GET" : "POST", path + "?nocache=" + request_id++, true);
// Rocket only currently supports URL encoded forms.
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
if (data != null) {
var form = "";
for (var key in data) {
if (form !== "") {
form += "&";
}
form += encodeURIComponent(key) + "=" + encodeURIComponent(data[key]);
}
req.send(form);
} else {
req.send();
}
}
/**
* The default handler if a AJAX request fails. Not to be used directly.
*
* @param e The XMLHttpRequest that failed.
*/
function defaultFailHandler(e) {
console.error("A AJAX request failed, and was not caught:");
console.error(e);
}