mirror of
https://github.com/open-goal/launcher.git
synced 2024-10-20 04:57:38 -04:00
splash: polish splash flow, prompt to delete data/
directory
This commit is contained in:
parent
01efa31c2b
commit
4456f114d3
|
@ -1,8 +1,24 @@
|
|||
use crate::config::LauncherConfig;
|
||||
use crate::{config::LauncherConfig, util::file::delete_dir};
|
||||
use tauri::Manager;
|
||||
|
||||
use super::CommandError;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn has_old_data_directory(app_handle: tauri::AppHandle) -> Result<bool, CommandError> {
|
||||
match &app_handle.path_resolver().app_config_dir() {
|
||||
None => Ok(false),
|
||||
Some(dir) => Ok(dir.join("data").join("iso_data").exists()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn delete_old_data_directory(app_handle: tauri::AppHandle) -> Result<(), CommandError> {
|
||||
match &app_handle.path_resolver().app_config_dir() {
|
||||
None => Ok(()),
|
||||
Some(dir) => Ok(delete_dir(&dir.join("data"))?),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_install_directory(
|
||||
config: tauri::State<'_, tokio::sync::Mutex<LauncherConfig>>,
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
//
|
||||
// serde does not support defaultLiterals yet - https://github.com/serde-rs/serde/issues/368
|
||||
|
||||
use std::{fs, path::PathBuf};
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -116,8 +117,6 @@ pub struct LauncherConfig {
|
|||
pub active_version_folder: Option<String>,
|
||||
}
|
||||
|
||||
// TODO - what is _loaded?
|
||||
|
||||
fn default_version() -> Option<String> {
|
||||
Some("1.0".to_string())
|
||||
}
|
||||
|
@ -195,10 +194,28 @@ impl LauncherConfig {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_install_directory(&mut self, new_dir: String) -> Result<(), ConfigError> {
|
||||
pub fn set_install_directory(&mut self, new_dir: String) -> Result<Option<String>, ConfigError> {
|
||||
// Do some tests on this folder, if they fail, return a decent error
|
||||
let path = Path::new(&new_dir);
|
||||
if path.exists() {
|
||||
return Ok(Some("Provided folder does not exist".to_owned()));
|
||||
}
|
||||
|
||||
if !path.is_dir() {
|
||||
return Ok(Some("Provided folder is not a folder".to_owned()));
|
||||
}
|
||||
|
||||
// Check our permissions on the folder
|
||||
let md = fs::metadata(path)?;
|
||||
let permissions = md.permissions();
|
||||
let readonly = permissions.readonly();
|
||||
if readonly {
|
||||
return Ok(Some("Provided folder is read-only".to_owned()));
|
||||
}
|
||||
|
||||
self.installation_dir = Some(new_dir);
|
||||
self.save_config()?;
|
||||
Ok(())
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn set_opengl_requirement_met(&mut self, new_val: bool) -> Result<(), ConfigError> {
|
||||
|
|
|
@ -84,6 +84,8 @@ fn main() {
|
|||
commands::binaries::run_compiler,
|
||||
commands::binaries::run_decompiler,
|
||||
commands::config::finalize_installation,
|
||||
commands::config::has_old_data_directory,
|
||||
commands::config::delete_old_data_directory,
|
||||
commands::config::get_active_version_folder,
|
||||
commands::config::get_active_version,
|
||||
commands::config::get_install_directory,
|
||||
|
|
|
@ -1,5 +1,22 @@
|
|||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
|
||||
export async function oldDataDirectoryExists(): Promise<boolean> {
|
||||
try {
|
||||
return await invoke("has_old_data_directory", {});
|
||||
} catch (e) {
|
||||
console.log("[OG] Unable to check if the old data directory exists");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteOldDataDirectory(): Promise<void> {
|
||||
try {
|
||||
await invoke("delete_old_data_directory", {});
|
||||
} catch (e) {
|
||||
console.log("[OG] Unable to check if the old data directory exists");
|
||||
}
|
||||
}
|
||||
|
||||
export async function getInstallationDirectory(): Promise<string | null> {
|
||||
try {
|
||||
return await invoke("get_install_directory", {});
|
||||
|
@ -10,11 +27,15 @@ export async function getInstallationDirectory(): Promise<string | null> {
|
|||
|
||||
export async function setInstallationDirectory(
|
||||
newInstallDir: string
|
||||
): Promise<void> {
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
await invoke("set_install_directory", { newDir: newInstallDir });
|
||||
return await invoke("set_install_directory", { newDir: newInstallDir });
|
||||
} catch (e) {
|
||||
console.log("TODO AH!");
|
||||
console.log(
|
||||
"[OG] Unexpected error occurred when setting installation dir",
|
||||
e
|
||||
);
|
||||
return "Unexpected error occurred";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,26 +2,37 @@
|
|||
import { closeSplashScreen } from "$lib/rpc/commands";
|
||||
import { onMount } from "svelte";
|
||||
import logo from "$assets/images/icon.webp";
|
||||
import {
|
||||
copyDataDirectory,
|
||||
dataDirectoryExists,
|
||||
} from "$lib/utils/data-files";
|
||||
import { log } from "$lib/utils/log";
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import { folderPrompt } from "$lib/utils/file";
|
||||
import {
|
||||
deleteOldDataDirectory,
|
||||
getInstallationDirectory,
|
||||
oldDataDirectoryExists,
|
||||
setInstallationDirectory,
|
||||
} from "$lib/rpc/config";
|
||||
|
||||
let currentProgress = 10;
|
||||
let currentStatusText = "Reading Settings";
|
||||
|
||||
let installationDirSet = true;
|
||||
let stepError = undefined;
|
||||
let oldDataDirToClean = false;
|
||||
|
||||
// Events
|
||||
onMount(async () => {
|
||||
currentStatusText = "Checking Directories";
|
||||
currentProgress = 15;
|
||||
// Check to see if the install dir has been setup or not
|
||||
const install_dir = await invoke("get_install_directory");
|
||||
const install_dir = await getInstallationDirectory();
|
||||
if (install_dir === null) {
|
||||
// Check to see if they have the old data directory, ask them if they'd like us to
|
||||
// remove it
|
||||
const hasOldDataDir = await oldDataDirectoryExists();
|
||||
if (hasOldDataDir) {
|
||||
oldDataDirToClean = true;
|
||||
}
|
||||
installationDirSet = false;
|
||||
} else {
|
||||
currentProgress = 25;
|
||||
finishSplash();
|
||||
}
|
||||
});
|
||||
|
@ -30,59 +41,67 @@
|
|||
// If not -- let's ask the user to set one up
|
||||
// This is part of what allows for the user to install the games and such wherever they want
|
||||
currentStatusText = "Pick an Installation Folder";
|
||||
// TODO - change to a save dialog instead
|
||||
const new_install_dir = await folderPrompt("Pick an Installation Folder");
|
||||
// TODO - put invokes into a nice typescript interface
|
||||
if (new_install_dir !== undefined) {
|
||||
await invoke("set_install_directory", { newDir: new_install_dir });
|
||||
// TODO - we are kinda assuming it succeeded here, improve that
|
||||
// - what if the install directory no longer exists
|
||||
// - what if what they provide isn't writable?
|
||||
installationDirSet = true;
|
||||
finishSplash();
|
||||
currentProgress = 25;
|
||||
const newInstallDir = await folderPrompt("Pick an Installation Folder");
|
||||
if (newInstallDir !== undefined) {
|
||||
const result = await setInstallationDirectory(newInstallDir);
|
||||
if (result !== null) {
|
||||
stepError = result;
|
||||
} else {
|
||||
installationDirSet = true;
|
||||
finishSplash();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function finishSplash(evt) {
|
||||
currentStatusText = "Checking Data Files";
|
||||
currentProgress = 25;
|
||||
// TODO - this can likely go away
|
||||
// Check if the data directory exists or not
|
||||
// - if it doesn't this is the users first launch, so lets copy it
|
||||
if (!(await dataDirectoryExists())) {
|
||||
try {
|
||||
currentStatusText = "Copying Data Files";
|
||||
currentProgress = 50;
|
||||
await copyDataDirectory();
|
||||
} catch (err) {
|
||||
log.error("error encountered when copying data files", {
|
||||
error: err,
|
||||
});
|
||||
currentStatusText = `Error - ${err}`;
|
||||
return;
|
||||
}
|
||||
}
|
||||
await new Promise((res) => setTimeout(res, 1000));
|
||||
currentProgress = 50;
|
||||
currentStatusText = "Finishing Up";
|
||||
await new Promise((res) => setTimeout(res, 1000));
|
||||
currentProgress = 100;
|
||||
await new Promise((res) => setTimeout(res, 2000));
|
||||
await closeSplashScreen();
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="content" data-tauri-drag-region>
|
||||
<div class="splash-logo">
|
||||
<div class="splash-logo no-pointer-events">
|
||||
<img src={logo} alt="" draggable="false" />
|
||||
</div>
|
||||
<div class="splash-contents">
|
||||
{#if installationDirSet}
|
||||
<div class="splash-status-text">{currentStatusText}</div>
|
||||
{:else}
|
||||
{#if oldDataDirToClean}
|
||||
The old installation folder is no longer needed, delete it?
|
||||
<br />
|
||||
<span>
|
||||
<button
|
||||
class="splash-button"
|
||||
on:click={() => {
|
||||
oldDataDirToClean = false;
|
||||
deleteOldDataDirectory();
|
||||
}}>Yes</button
|
||||
>
|
||||
<button
|
||||
class="splash-button"
|
||||
on:click={() => {
|
||||
oldDataDirToClean = false;
|
||||
}}>No</button
|
||||
>
|
||||
</span>
|
||||
{:else if !installationDirSet}
|
||||
{#if stepError !== undefined}
|
||||
{stepError}
|
||||
{:else}
|
||||
No installation directory set!
|
||||
{/if}
|
||||
<br />
|
||||
<button class="splash-button" on:click={selectInstallationFolder}
|
||||
>Select Install Folder</button
|
||||
>Set Install Folder</button
|
||||
>
|
||||
{:else}
|
||||
<div class="splash-status-text">{currentStatusText}</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div>
|
||||
<div class="splash-bar">
|
||||
<div class="splash-status-bar fg" style="width: {currentProgress}%" />
|
||||
<div class="splash-status-bar bg" />
|
||||
</div>
|
||||
|
@ -101,19 +120,30 @@
|
|||
|
||||
.content {
|
||||
color: white;
|
||||
height: 100%;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.splash-contents {
|
||||
display: flex;
|
||||
height: 35%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 1.5em;
|
||||
font-family: "Roboto Mono", monospace;
|
||||
font-size: 10pt;
|
||||
text-align: center;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.splash-bar {
|
||||
height: 10%;
|
||||
}
|
||||
|
||||
.splash-logo {
|
||||
height: 65vh;
|
||||
margin-bottom: 1em;
|
||||
padding: 10px;
|
||||
height: 50%;
|
||||
}
|
||||
|
||||
.splash-logo img {
|
||||
|
@ -122,15 +152,10 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.splash-status-text {
|
||||
text-align: center;
|
||||
font-family: "Roboto Mono", monospace;
|
||||
font-size: 8pt;
|
||||
}
|
||||
|
||||
.splash-status-bar {
|
||||
width: 100%;
|
||||
height: 15px;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.splash-status-bar.bg {
|
||||
|
@ -144,6 +169,7 @@
|
|||
}
|
||||
|
||||
.splash-button {
|
||||
margin-top: 5px;
|
||||
appearance: none;
|
||||
background-color: #ffb807;
|
||||
border-radius: 6px;
|
||||
|
@ -180,4 +206,8 @@
|
|||
.splash-button:active {
|
||||
background-color: #775500;
|
||||
}
|
||||
|
||||
.no-pointer-events {
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in a new issue