mirror of
https://github.com/yuzu-emu/liftinstall.git
synced 2025-01-03 21:05:33 +00:00
Dynamically fetch configuration file
This commit is contained in:
parent
08cf5dea6f
commit
b32e9f6f33
31
config.toml
31
config.toml
|
@ -1,31 +1,2 @@
|
||||||
[general]
|
|
||||||
name = "yuzu"
|
name = "yuzu"
|
||||||
installing_message = "Reminder: yuzu is an <b>experimental</b> emulator. Stuff will break!"
|
target_url = "https://raw.githubusercontent.com/j-selby/test-installer/master/config.v1.toml"
|
||||||
|
|
||||||
[[packages]]
|
|
||||||
name = "yuzu Nightly"
|
|
||||||
description = "The nightly build of yuzu contains already reviewed and tested features."
|
|
||||||
[packages.source]
|
|
||||||
name = "github"
|
|
||||||
match = "^yuzu-#PLATFORM#(-mingw)?-[0-9]*-[0-9a-f]*.zip$"
|
|
||||||
[packages.source.config]
|
|
||||||
repo = "yuzu-emu/yuzu-nightly"
|
|
||||||
|
|
||||||
[[packages]]
|
|
||||||
name = "yuzu Canary"
|
|
||||||
description = "The canary build of yuzu has additional features that are still waiting on review."
|
|
||||||
[packages.source]
|
|
||||||
name = "github"
|
|
||||||
match = "^yuzu-#PLATFORM#(-mingw)?-[0-9]*-[0-9a-f]*.zip$"
|
|
||||||
[packages.source.config]
|
|
||||||
repo = "yuzu-emu/yuzu-canary"
|
|
||||||
|
|
||||||
[[packages]]
|
|
||||||
name = "Test package"
|
|
||||||
description = "Just a testing package"
|
|
||||||
default = true
|
|
||||||
[packages.source]
|
|
||||||
name = "github"
|
|
||||||
match = "^TestPackage.zip$"
|
|
||||||
[packages.source.config]
|
|
||||||
repo = "j-selby/test-installer"
|
|
||||||
|
|
|
@ -30,14 +30,26 @@ pub struct PackageDescription {
|
||||||
|
|
||||||
/// Describes the application itself.
|
/// Describes the application itself.
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||||
pub struct GeneralConfig {
|
pub struct BaseAttributes {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub installing_message: String,
|
pub target_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BaseAttributes {
|
||||||
|
/// Serialises as a JSON string.
|
||||||
|
pub fn to_json_str(&self) -> Result<String, SerdeError> {
|
||||||
|
serde_json::to_string(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds a configuration from a specified TOML string.
|
||||||
|
pub fn from_toml_str(contents: &str) -> Result<Self, TomlError> {
|
||||||
|
toml::from_str(contents)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub general: GeneralConfig,
|
pub installing_message: String,
|
||||||
pub packages: Vec<PackageDescription>,
|
pub packages: Vec<PackageDescription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
src/http.rs
13
src/http.rs
|
@ -8,6 +8,19 @@ use reqwest;
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
|
/// Downloads a text file from the specified URL.
|
||||||
|
pub fn download_text(url: &str) -> Result<String, String> {
|
||||||
|
// TODO: Decrease check time
|
||||||
|
let mut client = match reqwest::get(url) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(v) => return Err(format!("Failed to GET resource: {:?}", v)),
|
||||||
|
};
|
||||||
|
|
||||||
|
client
|
||||||
|
.text()
|
||||||
|
.map_err(|v| format!("Failed to get text from resource: {:?}", v))
|
||||||
|
}
|
||||||
|
|
||||||
/// Streams a file from a HTTP server.
|
/// Streams a file from a HTTP server.
|
||||||
pub fn stream_file<F>(url: &str, mut callback: F) -> Result<(), String>
|
pub fn stream_file<F>(url: &str, mut callback: F) -> Result<(), String>
|
||||||
where
|
where
|
||||||
|
|
|
@ -13,6 +13,7 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
|
|
||||||
|
use config::BaseAttributes;
|
||||||
use config::Config;
|
use config::Config;
|
||||||
|
|
||||||
use sources::types::Version;
|
use sources::types::Version;
|
||||||
|
@ -36,7 +37,8 @@ pub enum InstallMessage {
|
||||||
/// The installer framework contains metadata about packages, what is installable, what isn't,
|
/// The installer framework contains metadata about packages, what is installable, what isn't,
|
||||||
/// etc.
|
/// etc.
|
||||||
pub struct InstallerFramework {
|
pub struct InstallerFramework {
|
||||||
pub config: Config,
|
pub base_attributes: BaseAttributes,
|
||||||
|
pub config: Option<Config>,
|
||||||
pub database: Vec<LocalInstallation>,
|
pub database: Vec<LocalInstallation>,
|
||||||
pub install_path: Option<PathBuf>,
|
pub install_path: Option<PathBuf>,
|
||||||
pub preexisting_install: bool,
|
pub preexisting_install: bool,
|
||||||
|
@ -64,13 +66,13 @@ pub struct LocalInstallation {
|
||||||
|
|
||||||
impl InstallerFramework {
|
impl InstallerFramework {
|
||||||
/// Returns a copy of the configuration.
|
/// Returns a copy of the configuration.
|
||||||
pub fn get_config(&self) -> Config {
|
pub fn get_config(&self) -> Option<Config> {
|
||||||
self.config.clone()
|
self.config.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the default install path.
|
/// Returns the default install path.
|
||||||
pub fn get_default_path(&self) -> Option<String> {
|
pub fn get_default_path(&self) -> Option<String> {
|
||||||
let app_name = &self.config.general.name;
|
let app_name = &self.base_attributes.name;
|
||||||
|
|
||||||
let base_dir = match var("LOCALAPPDATA") {
|
let base_dir = match var("LOCALAPPDATA") {
|
||||||
Ok(path) => PathBuf::from(path),
|
Ok(path) => PathBuf::from(path),
|
||||||
|
@ -194,9 +196,10 @@ impl InstallerFramework {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new instance of the Installer Framework with a specified Config.
|
/// Creates a new instance of the Installer Framework with a specified Config.
|
||||||
pub fn new(config: Config) -> Self {
|
pub fn new(attrs: BaseAttributes) -> Self {
|
||||||
InstallerFramework {
|
InstallerFramework {
|
||||||
config,
|
base_attributes: attrs,
|
||||||
|
config: None,
|
||||||
database: Vec::new(),
|
database: Vec::new(),
|
||||||
install_path: None,
|
install_path: None,
|
||||||
preexisting_install: false,
|
preexisting_install: false,
|
||||||
|
@ -207,7 +210,7 @@ impl InstallerFramework {
|
||||||
|
|
||||||
/// Creates a new instance of the Installer Framework with a specified Config, managing
|
/// Creates a new instance of the Installer Framework with a specified Config, managing
|
||||||
/// a pre-existing installation.
|
/// a pre-existing installation.
|
||||||
pub fn new_with_db(config: Config, install_path: &Path) -> Result<Self, String> {
|
pub fn new_with_db(attrs: BaseAttributes, install_path: &Path) -> Result<Self, String> {
|
||||||
let path = install_path.to_owned();
|
let path = install_path.to_owned();
|
||||||
let metadata_path = path.join("metadata.json");
|
let metadata_path = path.join("metadata.json");
|
||||||
let metadata_file = match File::open(metadata_path) {
|
let metadata_file = match File::open(metadata_path) {
|
||||||
|
@ -221,7 +224,8 @@ impl InstallerFramework {
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(InstallerFramework {
|
Ok(InstallerFramework {
|
||||||
config,
|
base_attributes: attrs,
|
||||||
|
config: None,
|
||||||
database,
|
database,
|
||||||
install_path: Some(path),
|
install_path: Some(path),
|
||||||
preexisting_install: true,
|
preexisting_install: true,
|
||||||
|
|
|
@ -17,7 +17,8 @@ pub fn setup_logger() -> Result<(), fern::InitError> {
|
||||||
record.level(),
|
record.level(),
|
||||||
message
|
message
|
||||||
))
|
))
|
||||||
}).level(log::LevelFilter::Info)
|
})
|
||||||
|
.level(log::LevelFilter::Info)
|
||||||
.chain(io::stdout())
|
.chain(io::stdout())
|
||||||
.chain(fern::log_file("installer.log")?)
|
.chain(fern::log_file("installer.log")?)
|
||||||
.apply()?;
|
.apply()?;
|
||||||
|
@ -31,6 +32,7 @@ where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
/// Unwraps this object. See `unwrap()`.
|
/// Unwraps this object. See `unwrap()`.
|
||||||
|
#[inline]
|
||||||
fn log_unwrap(self) -> T {
|
fn log_unwrap(self) -> T {
|
||||||
self.log_expect("Failed to unwrap")
|
self.log_expect("Failed to unwrap")
|
||||||
}
|
}
|
||||||
|
@ -40,6 +42,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, E: Debug> LoggingErrors<T> for Result<T, E> {
|
impl<T, E: Debug> LoggingErrors<T> for Result<T, E> {
|
||||||
|
#[inline]
|
||||||
fn log_expect(self, msg: &str) -> T {
|
fn log_expect(self, msg: &str) -> T {
|
||||||
match self {
|
match self {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
|
@ -52,6 +55,7 @@ impl<T, E: Debug> LoggingErrors<T> for Result<T, E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> LoggingErrors<T> for Option<T> {
|
impl<T> LoggingErrors<T> for Option<T> {
|
||||||
|
#[inline]
|
||||||
fn log_expect(self, msg: &str) -> T {
|
fn log_expect(self, msg: &str) -> T {
|
||||||
match self {
|
match self {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -50,8 +50,6 @@ mod tasks;
|
||||||
|
|
||||||
use web_view::*;
|
use web_view::*;
|
||||||
|
|
||||||
use config::Config;
|
|
||||||
|
|
||||||
use installer::InstallerFramework;
|
use installer::InstallerFramework;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
@ -71,6 +69,8 @@ use clap::App;
|
||||||
use clap::Arg;
|
use clap::Arg;
|
||||||
use log::Level;
|
use log::Level;
|
||||||
|
|
||||||
|
use config::BaseAttributes;
|
||||||
|
|
||||||
// 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");
|
||||||
|
|
||||||
|
@ -83,9 +83,10 @@ enum CallbackType {
|
||||||
fn main() {
|
fn main() {
|
||||||
logging::setup_logger().expect("Unable to setup logging!");
|
logging::setup_logger().expect("Unable to setup logging!");
|
||||||
|
|
||||||
let config = Config::from_toml_str(RAW_CONFIG).log_expect("Config file could not be read");
|
let config =
|
||||||
|
BaseAttributes::from_toml_str(RAW_CONFIG).log_expect("Config file could not be read");
|
||||||
|
|
||||||
let app_name = config.general.name.clone();
|
let app_name = config.name.clone();
|
||||||
|
|
||||||
let matches = App::new(format!("{} installer", app_name))
|
let matches = App::new(format!("{} installer", app_name))
|
||||||
.version(env!("CARGO_PKG_VERSION"))
|
.version(env!("CARGO_PKG_VERSION"))
|
||||||
|
@ -96,7 +97,8 @@ fn main() {
|
||||||
.value_name("TARGET")
|
.value_name("TARGET")
|
||||||
.help("Launches the specified executable after checking for updates")
|
.help("Launches the specified executable after checking for updates")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
).get_matches();
|
)
|
||||||
|
.get_matches();
|
||||||
|
|
||||||
info!("{} installer", app_name);
|
info!("{} installer", app_name);
|
||||||
|
|
||||||
|
|
66
src/rest.rs
66
src/rest.rs
|
@ -32,6 +32,10 @@ use installer::InstallerFramework;
|
||||||
use logging::LoggingErrors;
|
use logging::LoggingErrors;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
|
use http;
|
||||||
|
|
||||||
|
use config::Config;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct FileSelection {
|
struct FileSelection {
|
||||||
path: Option<String>,
|
path: Option<String>,
|
||||||
|
@ -55,7 +59,8 @@ impl WebServer {
|
||||||
Ok(WebService {
|
Ok(WebService {
|
||||||
framework: framework.clone(),
|
framework: framework.clone(),
|
||||||
})
|
})
|
||||||
}).log_expect("Failed to bind to port");
|
})
|
||||||
|
.log_expect("Failed to bind to port");
|
||||||
|
|
||||||
server.run().log_expect("Failed to run HTTP server");
|
server.run().log_expect("Failed to run HTTP server");
|
||||||
});
|
});
|
||||||
|
@ -79,16 +84,16 @@ impl Service for WebService {
|
||||||
fn call(&self, req: Self::Request) -> Self::Future {
|
fn call(&self, req: Self::Request) -> Self::Future {
|
||||||
Box::new(future::ok(match (req.method(), req.path()) {
|
Box::new(future::ok(match (req.method(), req.path()) {
|
||||||
// This endpoint should be usable directly from a <script> tag during loading.
|
// This endpoint should be usable directly from a <script> tag during loading.
|
||||||
(&Get, "/api/config") => {
|
(&Get, "/api/attrs") => {
|
||||||
let framework = self
|
let framework = self
|
||||||
.framework
|
.framework
|
||||||
.read()
|
.read()
|
||||||
.log_expect("InstallerFramework has been dirtied");
|
.log_expect("InstallerFramework has been dirtied");
|
||||||
|
|
||||||
let file = encapsulate_json(
|
let file = encapsulate_json(
|
||||||
"config",
|
"base_attributes",
|
||||||
&framework
|
&framework
|
||||||
.get_config()
|
.base_attributes
|
||||||
.to_json_str()
|
.to_json_str()
|
||||||
.log_expect("Failed to render JSON representation of config"),
|
.log_expect("Failed to render JSON representation of config"),
|
||||||
);
|
);
|
||||||
|
@ -98,6 +103,59 @@ impl Service for WebService {
|
||||||
.with_header(ContentType::json())
|
.with_header(ContentType::json())
|
||||||
.with_body(file)
|
.with_body(file)
|
||||||
}
|
}
|
||||||
|
// Returns the web config loaded
|
||||||
|
(&Get, "/api/config") => {
|
||||||
|
let mut framework = self
|
||||||
|
.framework
|
||||||
|
.write()
|
||||||
|
.log_expect("InstallerFramework has been dirtied");
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Downloading configuration from {:?}...",
|
||||||
|
framework.base_attributes.target_url
|
||||||
|
);
|
||||||
|
|
||||||
|
match http::download_text(&framework.base_attributes.target_url)
|
||||||
|
.map(|x| Config::from_toml_str(&x))
|
||||||
|
{
|
||||||
|
Ok(Ok(config)) => {
|
||||||
|
framework.config = Some(config.clone());
|
||||||
|
|
||||||
|
info!("Configuration file downloaded successfully.");
|
||||||
|
|
||||||
|
let file = framework
|
||||||
|
.get_config()
|
||||||
|
.log_expect("Config should be loaded by now")
|
||||||
|
.to_json_str()
|
||||||
|
.log_expect("Failed to render JSON representation of config");
|
||||||
|
|
||||||
|
Response::<hyper::Body>::new()
|
||||||
|
.with_header(ContentLength(file.len() as u64))
|
||||||
|
.with_header(ContentType::json())
|
||||||
|
.with_body(file)
|
||||||
|
}
|
||||||
|
Ok(Err(v)) => {
|
||||||
|
error!("Bad configuration file: {:?}", v);
|
||||||
|
|
||||||
|
Response::<hyper::Body>::new()
|
||||||
|
.with_status(StatusCode::ServiceUnavailable)
|
||||||
|
.with_header(ContentType::plaintext())
|
||||||
|
.with_body("Bad HTTP response")
|
||||||
|
}
|
||||||
|
Err(v) => {
|
||||||
|
error!(
|
||||||
|
"General connectivity error while downloading config: {:?}",
|
||||||
|
v
|
||||||
|
);
|
||||||
|
|
||||||
|
Response::<hyper::Body>::new()
|
||||||
|
.with_status(StatusCode::ServiceUnavailable)
|
||||||
|
.with_header(ContentLength(v.len() as u64))
|
||||||
|
.with_header(ContentType::plaintext())
|
||||||
|
.with_body(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// This endpoint should be usable directly from a <script> tag during loading.
|
// This endpoint should be usable directly from a <script> tag during loading.
|
||||||
(&Get, "/api/packages") => {
|
(&Get, "/api/packages") => {
|
||||||
let framework = self
|
let framework = self
|
||||||
|
|
|
@ -40,7 +40,8 @@ impl ReleaseSource for GithubReleases {
|
||||||
.get(&format!(
|
.get(&format!(
|
||||||
"https://api.github.com/repos/{}/releases",
|
"https://api.github.com/repos/{}/releases",
|
||||||
config.repo
|
config.repo
|
||||||
)).header(UserAgent::new("liftinstall (j-selby)"))
|
))
|
||||||
|
.header(UserAgent::new("liftinstall (j-selby)"))
|
||||||
.send()
|
.send()
|
||||||
.map_err(|x| format!("Error while sending HTTP request: {:?}", x))?;
|
.map_err(|x| format!("Error while sending HTTP request: {:?}", x))?;
|
||||||
|
|
||||||
|
@ -52,8 +53,8 @@ impl ReleaseSource for GithubReleases {
|
||||||
.text()
|
.text()
|
||||||
.map_err(|x| format!("Failed to decode HTTP response body: {:?}", x))?;
|
.map_err(|x| format!("Failed to decode HTTP response body: {:?}", x))?;
|
||||||
|
|
||||||
let result: serde_json::Value = serde_json::from_str(&body)
|
let result: serde_json::Value =
|
||||||
.map_err(|x| format!("Failed to parse response: {:?}", x))?;
|
serde_json::from_str(&body).map_err(|x| format!("Failed to parse response: {:?}", x))?;
|
||||||
|
|
||||||
let result: &Vec<serde_json::Value> = result
|
let result: &Vec<serde_json::Value> = result
|
||||||
.as_array()
|
.as_array()
|
||||||
|
|
|
@ -41,7 +41,12 @@ impl Task for InstallPackageTask {
|
||||||
let mut installed_files = Vec::new();
|
let mut installed_files = Vec::new();
|
||||||
|
|
||||||
let mut metadata: Option<PackageDescription> = None;
|
let mut metadata: Option<PackageDescription> = None;
|
||||||
for description in &context.config.packages {
|
for description in &context
|
||||||
|
.config
|
||||||
|
.as_ref()
|
||||||
|
.log_expect("Should have packages by now")
|
||||||
|
.packages
|
||||||
|
{
|
||||||
if self.name == description.name {
|
if self.name == description.name {
|
||||||
metadata = Some(description.clone());
|
metadata = Some(description.clone());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -26,7 +26,12 @@ impl Task for ResolvePackageTask {
|
||||||
) -> Result<TaskParamType, String> {
|
) -> Result<TaskParamType, String> {
|
||||||
assert_eq!(input.len(), 0);
|
assert_eq!(input.len(), 0);
|
||||||
let mut metadata: Option<PackageDescription> = None;
|
let mut metadata: Option<PackageDescription> = None;
|
||||||
for description in &context.config.packages {
|
for description in &context
|
||||||
|
.config
|
||||||
|
.as_ref()
|
||||||
|
.log_expect("Should have packages by now")
|
||||||
|
.packages
|
||||||
|
{
|
||||||
if self.name == description.name {
|
if self.name == description.name {
|
||||||
metadata = Some(description.clone());
|
metadata = Some(description.clone());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column is-one-third" v-if="!is_launcher">
|
<div class="column is-one-third" v-if="!is_launcher">
|
||||||
<h1 class="title">
|
<h1 class="title">
|
||||||
Welcome to the {{ config.general.name }} installer!
|
Welcome to the {{ attrs.name }} installer!
|
||||||
</h1>
|
</h1>
|
||||||
<h2 class="subtitle">
|
<h2 class="subtitle">
|
||||||
We will have you up and running in just a few moments.
|
We will have you up and running in just a few moments.
|
||||||
|
@ -37,6 +37,15 @@
|
||||||
<a class="button is-primary is-pulled-right" v-on:click="back_to_packages">Back</a>
|
<a class="button is-primary is-pulled-right" v-on:click="back_to_packages">Back</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="column" v-else-if="is_downloading_config">
|
||||||
|
<h4 class="subtitle">Downloading config...</h4>
|
||||||
|
|
||||||
|
<div v-html="progress_message"></div>
|
||||||
|
<progress class="progress is-info is-medium" v-bind:value="progress" max="100">
|
||||||
|
{{ progress }}%
|
||||||
|
</progress>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="column" v-else-if="modify_install">
|
<div class="column" v-else-if="modify_install">
|
||||||
<h4 class="subtitle">Choose an option:</h4>
|
<h4 class="subtitle">Choose an option:</h4>
|
||||||
|
|
||||||
|
@ -99,7 +108,7 @@
|
||||||
<div class="column" v-else-if="is_installing">
|
<div class="column" v-else-if="is_installing">
|
||||||
<h4 class="subtitle" v-if="is_launcher">Checking for updates...</h4>
|
<h4 class="subtitle" v-if="is_launcher">Checking for updates...</h4>
|
||||||
<h4 class="subtitle" v-else>Installing...</h4>
|
<h4 class="subtitle" v-else>Installing...</h4>
|
||||||
<div v-html="config.general.installing_message"></div>
|
<div v-html="config.installing_message"></div>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<div v-html="progress_message"></div>
|
<div v-html="progress_message"></div>
|
||||||
|
@ -109,7 +118,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column" v-else-if="is_finished">
|
<div class="column" v-else-if="is_finished">
|
||||||
<h4 class="subtitle">Thanks for installing {{ config.general.name }}!</h4>
|
<h4 class="subtitle">Thanks for installing {{ attrs.name }}!</h4>
|
||||||
|
|
||||||
<a class="button is-primary is-pulled-right" v-on:click="exit">Exit</a>
|
<a class="button is-primary is-pulled-right" v-on:click="exit">Exit</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -126,7 +135,7 @@
|
||||||
<div class="modal-background"></div>
|
<div class="modal-background"></div>
|
||||||
<div class="modal-card">
|
<div class="modal-card">
|
||||||
<header class="modal-card-head">
|
<header class="modal-card-head">
|
||||||
<p class="modal-card-title">Are you sure you want to uninstall {{ config.general.name }}?</p>
|
<p class="modal-card-title">Are you sure you want to uninstall {{ attrs.name }}?</p>
|
||||||
</header>
|
</header>
|
||||||
<footer class="modal-card-foot">
|
<footer class="modal-card-foot">
|
||||||
<button class="button is-danger" v-on:click="uninstall">Yes</button>
|
<button class="button is-danger" v-on:click="uninstall">Yes</button>
|
||||||
|
@ -136,7 +145,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/api/config"></script>
|
<script src="/api/attrs"></script>
|
||||||
<script src="/js/helpers.js"></script>
|
<script src="/js/helpers.js"></script>
|
||||||
<script src="/js/vue.min.js"></script>
|
<script src="/js/vue.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
@ -168,7 +177,7 @@
|
||||||
intercept(methods[i]);
|
intercept(methods[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("window-title").innerText = config.name + " Installer";
|
document.getElementById("window-title").innerText = base_attributes.name + " Installer";
|
||||||
|
|
||||||
function selectFileCallback(name) {
|
function selectFileCallback(name) {
|
||||||
app.install_location = name;
|
app.install_location = name;
|
||||||
|
@ -177,7 +186,8 @@
|
||||||
var app = new Vue({
|
var app = new Vue({
|
||||||
el: '#app',
|
el: '#app',
|
||||||
data: {
|
data: {
|
||||||
config : config,
|
attrs: base_attributes,
|
||||||
|
config : {},
|
||||||
install_location : "",
|
install_location : "",
|
||||||
// If the initial modify menu should be shown
|
// If the initial modify menu should be shown
|
||||||
modify_install : false,
|
modify_install : false,
|
||||||
|
@ -192,6 +202,8 @@
|
||||||
launcher_path : undefined,
|
launcher_path : undefined,
|
||||||
// If a confirmation prompt should be shown
|
// If a confirmation prompt should be shown
|
||||||
confirm_uninstall : false,
|
confirm_uninstall : false,
|
||||||
|
// If the downloading config page should be shown
|
||||||
|
is_downloading_config : false,
|
||||||
progress : 0,
|
progress : 0,
|
||||||
progress_message : "",
|
progress_message : "",
|
||||||
has_error : false,
|
has_error : false,
|
||||||
|
@ -205,6 +217,59 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
"download_config": function() {
|
||||||
|
app.is_downloading_config = true;
|
||||||
|
|
||||||
|
ajax("/api/config", function(e) {
|
||||||
|
app.download_install_status();
|
||||||
|
app.config = e;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"download_install_status": function() {
|
||||||
|
ajax("/api/installation-status", function(e) {
|
||||||
|
app.is_downloading_config = false;
|
||||||
|
app.metadata = e;
|
||||||
|
if (e.preexisting_install) {
|
||||||
|
app.modify_install = true;
|
||||||
|
app.select_packages = false;
|
||||||
|
app.show_install_location = false;
|
||||||
|
app.install_location = e.install_path;
|
||||||
|
|
||||||
|
// Copy over installed packages
|
||||||
|
for (var x = 0; x < app.config.packages.length; x++) {
|
||||||
|
app.config.packages[x].default = false;
|
||||||
|
app.config.packages[x].installed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < app.metadata.database.length; i++) {
|
||||||
|
// Find this config package
|
||||||
|
for (var x = 0; x < app.config.packages.length; x++) {
|
||||||
|
if (app.config.packages[x].name === app.metadata.database[i].name) {
|
||||||
|
app.config.packages[x].default = true;
|
||||||
|
app.config.packages[x].installed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.is_launcher) {
|
||||||
|
document.getElementById("window-title").innerText = config.name + " Updater";
|
||||||
|
|
||||||
|
app.is_launcher = true;
|
||||||
|
app.install();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var x = 0; x < app.config.packages.length; x++) {
|
||||||
|
app.config.packages[x].installed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ajax("/api/default-path", function(e) {
|
||||||
|
if (e.path != null) {
|
||||||
|
app.install_location = e.path;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
"select_file": function() {
|
"select_file": function() {
|
||||||
window.external.invoke(JSON.stringify({
|
window.external.invoke(JSON.stringify({
|
||||||
SelectInstallDir: {
|
SelectInstallDir: {
|
||||||
|
@ -297,48 +362,7 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ajax("/api/installation-status", function(e) {
|
app.download_config();
|
||||||
app.metadata = e;
|
|
||||||
if (e.preexisting_install) {
|
|
||||||
app.modify_install = true;
|
|
||||||
app.select_packages = false;
|
|
||||||
app.show_install_location = false;
|
|
||||||
app.install_location = e.install_path;
|
|
||||||
|
|
||||||
// Copy over installed packages
|
|
||||||
for (var x = 0; x < app.config.packages.length; x++) {
|
|
||||||
app.config.packages[x].default = false;
|
|
||||||
app.config.packages[x].installed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < app.metadata.database.length; i++) {
|
|
||||||
// Find this config package
|
|
||||||
for (var x = 0; x < app.config.packages.length; x++) {
|
|
||||||
if (app.config.packages[x].name === app.metadata.database[i].name) {
|
|
||||||
app.config.packages[x].default = true;
|
|
||||||
app.config.packages[x].installed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.is_launcher) {
|
|
||||||
document.getElementById("window-title").innerText = config.name + " Updater";
|
|
||||||
|
|
||||||
app.is_launcher = true;
|
|
||||||
app.install();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (var x = 0; x < app.config.packages.length; x++) {
|
|
||||||
app.config.packages[x].installed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ajax("/api/default-path", function(e) {
|
|
||||||
if (e.path != null) {
|
|
||||||
app.install_location = e.path;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in a new issue