mirror of
https://github.com/open-goal/launcher.git
synced 2024-10-20 19:07:36 -04:00
frontend: nice flow for decompiling/compiling
This commit is contained in:
parent
5634257381
commit
f118d856c3
|
@ -51,17 +51,27 @@ pub async fn run_decompiler(
|
|||
match &config_lock.installation_dir {
|
||||
None => Ok(()),
|
||||
Some(path) => {
|
||||
let install_path = Path::new(path);
|
||||
let data_folder = install_path.join("active/jak1/data");
|
||||
|
||||
let mut source_path = path_to_iso;
|
||||
if source_path.is_empty() {
|
||||
// TODO - we could probably be more explicit here using a param
|
||||
source_path = data_folder
|
||||
.join("iso_data/jak1")
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
}
|
||||
|
||||
// TODO - be smarter
|
||||
// TODO - make folder if it doesnt exist
|
||||
// TODO - copy over the data folder
|
||||
// TODO - log it to a file
|
||||
let install_path = Path::new(path);
|
||||
let binary_dir = install_path.join("versions/official/v0.1.32/");
|
||||
let data_folder = install_path.join("active/jak1/data");
|
||||
let executable_location = binary_dir.join("extractor.exe");
|
||||
let output = Command::new(&executable_location)
|
||||
.args([
|
||||
path_to_iso,
|
||||
source_path,
|
||||
"--decompile".to_string(),
|
||||
"--proj-path".to_string(),
|
||||
data_folder.to_string_lossy().into_owned(),
|
||||
|
@ -84,17 +94,26 @@ pub async fn run_compiler(
|
|||
match &config_lock.installation_dir {
|
||||
None => Ok(()),
|
||||
Some(path) => {
|
||||
let install_path = Path::new(path);
|
||||
let data_folder = install_path.join("active/jak1/data");
|
||||
|
||||
let mut source_path = path_to_iso;
|
||||
if source_path.is_empty() {
|
||||
// TODO - we could probably be more explicit here using a param
|
||||
source_path = data_folder
|
||||
.join("iso_data/jak1")
|
||||
.to_string_lossy()
|
||||
.to_string();
|
||||
}
|
||||
// TODO - be smarter
|
||||
// TODO - make folder if it doesnt exist
|
||||
// TODO - copy over the data folder
|
||||
// TODO - log it to a file
|
||||
let install_path = Path::new(path);
|
||||
let binary_dir = install_path.join("versions/official/v0.1.32/");
|
||||
let data_folder = install_path.join("active/jak1/data");
|
||||
let executable_location = binary_dir.join("extractor.exe");
|
||||
let output = Command::new(&executable_location)
|
||||
.args([
|
||||
path_to_iso,
|
||||
source_path,
|
||||
"--compile".to_string(),
|
||||
"--proj-path".to_string(),
|
||||
data_folder.to_string_lossy().into_owned(),
|
||||
|
|
|
@ -86,7 +86,9 @@
|
|||
<DropdownDivider />
|
||||
<DropdownItem
|
||||
on:click={async () => {
|
||||
await openDir(settingsDir);
|
||||
dispatch('job', {
|
||||
type: "decompile"
|
||||
})
|
||||
}}
|
||||
>Decompile
|
||||
<!-- NOTE - this is a bug in flowbite-svelte, it's not replacing the default class but just appending -->
|
||||
|
@ -96,7 +98,9 @@
|
|||
>
|
||||
<DropdownItem
|
||||
on:click={async () => {
|
||||
await openDir(settingsDir);
|
||||
dispatch('job', {
|
||||
type: "compile"
|
||||
})
|
||||
}}
|
||||
>Compile
|
||||
<!-- NOTE - this is a bug in flowbite-svelte, it's not replacing the default class but just appending -->
|
||||
|
|
79
src/components/games/job/GameJob.svelte
Normal file
79
src/components/games/job/GameJob.svelte
Normal file
|
@ -0,0 +1,79 @@
|
|||
<script lang="ts">
|
||||
// components
|
||||
import Progress from "../setup/Progress.svelte";
|
||||
// constants
|
||||
import LogViewer from "../setup/LogViewer.svelte";
|
||||
import { createEventDispatcher, onMount } from "svelte";
|
||||
import { Button } from "flowbite-svelte";
|
||||
import { progressTracker } from "$lib/stores/ProgressStore";
|
||||
import type { Job } from "$lib/jobs/jobs";
|
||||
import { getInternalName, type SupportedGame } from "$lib/constants";
|
||||
import { runCompiler, runDecompiler } from "$lib/rpc/extractor";
|
||||
|
||||
export let activeGame: SupportedGame;
|
||||
export let jobType: Job;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let running = false;
|
||||
|
||||
// This is basically a stripped down `GameSetup` component that doesn't care about user initiation
|
||||
// requirement checking, etc
|
||||
//
|
||||
// It's used to provide almost the same interface as the normal installation, with logs, etc
|
||||
// but for arbitrary jobs. Such as decompiling, or compiling.
|
||||
onMount(async () => {
|
||||
if (jobType === "decompile") {
|
||||
progressTracker.init([
|
||||
{
|
||||
status: "queued",
|
||||
label: "Decompile",
|
||||
},
|
||||
{
|
||||
status: "queued",
|
||||
label: "Done",
|
||||
},
|
||||
]);
|
||||
progressTracker.start();
|
||||
await runDecompiler("", getInternalName(activeGame));
|
||||
progressTracker.proceed();
|
||||
progressTracker.proceed();
|
||||
} else if (jobType === "compile") {
|
||||
progressTracker.init([
|
||||
{
|
||||
status: "queued",
|
||||
label: "Compile",
|
||||
},
|
||||
{
|
||||
status: "queued",
|
||||
label: "Done",
|
||||
},
|
||||
]);
|
||||
progressTracker.start();
|
||||
await runCompiler("", getInternalName(activeGame));
|
||||
progressTracker.proceed();
|
||||
progressTracker.proceed();
|
||||
}
|
||||
});
|
||||
|
||||
function dispatchCompleteJob() {
|
||||
dispatch("jobFinished");
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col justify-content">
|
||||
<Progress />
|
||||
{#if $progressTracker.logs}
|
||||
<LogViewer />
|
||||
{/if}
|
||||
</div>
|
||||
{#if $progressTracker.overallStatus === "success"}
|
||||
<div class="flex flex-col justify-end items-end mt-auto">
|
||||
<div class="flex flex-row gap-2">
|
||||
<Button
|
||||
btnClass="border-solid border-2 border-slate-900 rounded bg-slate-900 hover:bg-slate-800 text-sm text-white font-semibold px-5 py-2"
|
||||
on:click={async () => dispatchCompleteJob()}>Continue</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
|
@ -74,8 +74,6 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<!-- TODO - allow passing a folder path -->
|
||||
|
||||
{#if !requirementsMet}
|
||||
<Requirements />
|
||||
{:else if installing}
|
||||
|
|
|
@ -58,8 +58,8 @@
|
|||
<div class="w-full py-6">
|
||||
<div class="flex">
|
||||
{#each progress.steps as step, i}
|
||||
<!-- NOTE - this breaks down if there is only 1 step, or probably if you have a huge number of steps -->
|
||||
<div class="w-1/{progress.steps.length}">
|
||||
<!-- NOTE - this will break if you add too many steps! -->
|
||||
<div class="grow">
|
||||
<div class="relative mb-2">
|
||||
<!-- BAR (skipped for first element) -->
|
||||
{#if i !== 0}
|
||||
|
|
1
src/lib/jobs/jobs.ts
Normal file
1
src/lib/jobs/jobs.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export type Job = "decompile" | "compile";
|
|
@ -1,6 +1,11 @@
|
|||
import { writable } from "svelte/store";
|
||||
|
||||
export type ProgressStatus = "success" | "queued" | "pending" | "failed";
|
||||
export type ProgressStatus =
|
||||
| "inactive"
|
||||
| "success"
|
||||
| "queued"
|
||||
| "pending"
|
||||
| "failed";
|
||||
|
||||
export interface ProgressStep {
|
||||
status: ProgressStatus;
|
||||
|
@ -16,7 +21,7 @@ interface ProgressTracker {
|
|||
|
||||
const storeValue: ProgressTracker = {
|
||||
currentStep: 0,
|
||||
overallStatus: "queued",
|
||||
overallStatus: "inactive",
|
||||
steps: [],
|
||||
logs: [],
|
||||
};
|
||||
|
@ -29,7 +34,7 @@ function createProgressTracker() {
|
|||
init: (steps: ProgressStep[]) =>
|
||||
update((val) => {
|
||||
val.currentStep = 0;
|
||||
val.overallStatus = "queued";
|
||||
val.overallStatus = "inactive";
|
||||
val.steps = steps;
|
||||
val.logs = [];
|
||||
return val;
|
||||
|
|
|
@ -7,15 +7,15 @@
|
|||
import { isDataDirectoryUpToDate } from "$lib/utils/data-files";
|
||||
import { Spinner } from "flowbite-svelte";
|
||||
import { isGameInstalled } from "$lib/rpc/config";
|
||||
import { progressTracker } from "$lib/stores/ProgressStore";
|
||||
import GameJob from "../components/games/job/GameJob.svelte";
|
||||
|
||||
const params = useParams();
|
||||
let activeGame = SupportedGame.Jak1;
|
||||
let componentLoaded = false;
|
||||
|
||||
let gameInstalled = false;
|
||||
|
||||
let dataDirUpToDate = false;
|
||||
let updatingDataDir = false;
|
||||
let gameJobToRun = undefined;
|
||||
|
||||
onMount(async () => {
|
||||
// Figure out what game we are displaying
|
||||
|
@ -43,6 +43,14 @@
|
|||
gameInstalled = await isGameInstalled(getInternalName(activeGame));
|
||||
// TODO - check data dir?
|
||||
}
|
||||
|
||||
async function runGameJob(event) {
|
||||
gameJobToRun = event.detail.type;
|
||||
}
|
||||
|
||||
async function gameJobFinished() {
|
||||
gameJobToRun = undefined;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="ml-20">
|
||||
|
@ -54,9 +62,11 @@
|
|||
<Spinner color="yellow" size={"12"} />
|
||||
</div>
|
||||
{:else if !gameInstalled}
|
||||
<GameSetup {activeGame} on:change={updateGameState} />
|
||||
<GameSetup activeGame={activeGame} on:change={updateGameState} />
|
||||
{:else if gameJobToRun !== undefined}
|
||||
<GameJob activeGame={activeGame} jobType={gameJobToRun} on:jobFinished={gameJobFinished}/>
|
||||
{:else}
|
||||
<GameControls {activeGame} on:change={updateGameState} />
|
||||
<GameControls {activeGame} on:change={updateGameState} on:job={runGameJob} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue