Fix cluster being stuck on downloading
This commit is contained in:
parent
60e5356120
commit
a2329b59a5
4 changed files with 90 additions and 37 deletions
|
|
@ -303,10 +303,18 @@ export type VersionType =
|
|||
*/
|
||||
"old_beta"
|
||||
|
||||
const ARGS_MAP = { 'oneclient':'{"getClustersGroupedByMajor":[],"checkForUpdate":[],"getVersions":[],"installUpdate":[],"getBundlesFor":["cluster_id"]}', 'folders':'{"fromCluster":["folder_name"],"openCluster":["folder_name"]}', 'debug':'{"getArch":[],"getBuildTimestamp":[],"isInDev":[],"getPlatform":[],"getType":[],"getOsVersion":[],"getPackageVersion":[],"getFamily":[],"openDevTools":[],"getLocale":[],"getGitCommitHash":[]}', 'events':'{"ingress":["event"],"message":["event"],"process":["event"]}', 'core':'{"killProcess":["pid"],"uploadSkinBytes":["access_token","skin_data","image_format","skin_variant"],"getClusterById":["id"],"setDiscordRPCMessage":["message"],"fetchMinecraftProfile":["uuid"],"getLoadersForVersion":["mc_version"],"installModpack":["modpack","cluster_id"],"openMsaLogin":[],"createCluster":["options"],"updateClusterProfile":["name","profile"],"getPackage":["provider","slug"],"readSettings":[],"updateClusterById":["id","request"],"removeCape":["access_token"],"removeCluster":["id"],"getWorlds":["id"],"removeUser":["uuid"],"writeSettings":["setting"],"launchCluster":["id","uuid","search_for_java"],"getUsers":[],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"setDefaultUser":["uuid"],"getMultiplePackages":["provider","slugs"],"getClusters":[],"getProfileOrDefault":["name"],"downloadExternalPackage":["package","cluster_id","force","skip_compatibility"],"getUsersFromAuthor":["provider","author"],"getGlobalProfile":[],"getRunningProcessesByClusterId":["cluster_id"],"createSettingsProfile":["name"],"getLinkedPackages":["cluster_id"],"removePackage":["cluster_id","package_hash"],"fetchLoggedInProfile":["access_token"],"changeSkin":["access_token","skin_url","skin_variant"],"convertUsernameUUID":["username_uuid"],"getDefaultUser":["fallback"],"searchPackages":["provider","query"],"getPackageBody":["provider","body"],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"],"getLogByName":["id","name"],"changeCape":["access_token","cape_uuid"],"getScreenshots":["id"],"getGameVersions":[],"open":["input"],"getUser":["uuid"],"isClusterRunning":["cluster_id"],"getLogs":["id"],"getRunningProcesses":[]}' }
|
||||
export type Router = { 'events': { ingress: (event: IngressPayload) => Promise<void>,
|
||||
message: (event: MessagePayload) => Promise<void>,
|
||||
process: (event: ProcessPayload) => Promise<void> },
|
||||
const ARGS_MAP = { 'debug':'{"getPackageVersion":[],"getPlatform":[],"getLocale":[],"openDevTools":[],"getGitCommitHash":[],"getFamily":[],"getArch":[],"getType":[],"getOsVersion":[],"isInDev":[],"getBuildTimestamp":[]}', 'folders':'{"fromCluster":["folder_name"],"openCluster":["folder_name"]}', 'oneclient':'{"installUpdate":[],"getClustersGroupedByMajor":[],"getVersions":[],"getBundlesFor":["cluster_id"],"checkForUpdate":[]}', 'core':'{"readSettings":[],"getLinkedPackages":["cluster_id"],"createSettingsProfile":["name"],"uploadSkinBytes":["access_token","skin_data","image_format","skin_variant"],"getMultiplePackages":["provider","slugs"],"searchPackages":["provider","query"],"isClusterRunning":["cluster_id"],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"],"getUsersFromAuthor":["provider","author"],"getProfileOrDefault":["name"],"createCluster":["options"],"getLoadersForVersion":["mc_version"],"getGlobalProfile":[],"getWorlds":["id"],"fetchMinecraftProfile":["uuid"],"getLogs":["id"],"fetchLoggedInProfile":["access_token"],"changeCape":["access_token","cape_uuid"],"launchCluster":["id","uuid","search_for_java"],"getUsers":[],"getGameVersions":[],"removePackage":["cluster_id","package_hash"],"removeCape":["access_token"],"convertUsernameUUID":["username_uuid"],"getRunningProcesses":[],"removeCluster":["id"],"getRunningProcessesByClusterId":["cluster_id"],"getClusters":[],"downloadExternalPackage":["package","cluster_id","force","skip_compatibility"],"setDefaultUser":["uuid"],"getUser":["uuid"],"getLogByName":["id","name"],"changeSkin":["access_token","skin_url","skin_variant"],"removeUser":["uuid"],"getScreenshots":["id"],"setClusterStage":["id","stage"],"setDiscordRPCMessage":["message"],"open":["input"],"updateClusterById":["id","request"],"installModpack":["modpack","cluster_id"],"getPackage":["provider","slug"],"getDefaultUser":["fallback"],"openMsaLogin":[],"writeSettings":["setting"],"getClusterById":["id"],"killProcess":["pid"],"updateClusterProfile":["name","profile"],"getPackageBody":["provider","body"],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"]}', 'events':'{"message":["event"],"process":["event"],"ingress":["event"]}' }
|
||||
export type Router = { 'debug': { openDevTools: () => Promise<void>,
|
||||
isInDev: () => Promise<boolean>,
|
||||
getArch: () => Promise<string>,
|
||||
getFamily: () => Promise<string>,
|
||||
getLocale: () => Promise<string | null>,
|
||||
getType: () => Promise<string>,
|
||||
getPlatform: () => Promise<string>,
|
||||
getOsVersion: () => Promise<string>,
|
||||
getGitCommitHash: () => Promise<string>,
|
||||
getBuildTimestamp: () => Promise<string>,
|
||||
getPackageVersion: () => Promise<string> },
|
||||
'oneclient': { getClustersGroupedByMajor: () => Promise<Partial<{ [key in number]: ClusterModel[] }>>,
|
||||
getBundlesFor: (clusterId: number) => Promise<ModpackArchive[]>,
|
||||
getVersions: () => Promise<OnlineClusterManifest>,
|
||||
|
|
@ -318,6 +326,7 @@ removeCluster: (id: number) => Promise<null>,
|
|||
createCluster: (options: CreateCluster) => Promise<ClusterModel>,
|
||||
launchCluster: (id: number, uuid: string | null, searchForJava: boolean | null) => Promise<null>,
|
||||
updateClusterById: (id: number, request: ClusterUpdate) => Promise<null>,
|
||||
setClusterStage: (id: number, stage: ClusterStage) => Promise<null>,
|
||||
getScreenshots: (id: number) => Promise<string[]>,
|
||||
getWorlds: (id: number) => Promise<string[]>,
|
||||
getLogs: (id: number) => Promise<string[]>,
|
||||
|
|
@ -360,19 +369,11 @@ removeCape: (accessToken: string) => Promise<MojangFullPlayerProfile>,
|
|||
convertUsernameUUID: (usernameUuid: string) => Promise<MowojangProfile>,
|
||||
setDiscordRPCMessage: (message: string) => Promise<null>,
|
||||
open: (input: string) => Promise<null> },
|
||||
'events': { ingress: (event: IngressPayload) => Promise<void>,
|
||||
message: (event: MessagePayload) => Promise<void>,
|
||||
process: (event: ProcessPayload) => Promise<void> },
|
||||
'folders': { fromCluster: (folderName: string) => Promise<string>,
|
||||
openCluster: (folderName: string) => Promise<null> },
|
||||
'debug': { openDevTools: () => Promise<void>,
|
||||
isInDev: () => Promise<boolean>,
|
||||
getArch: () => Promise<string>,
|
||||
getFamily: () => Promise<string>,
|
||||
getLocale: () => Promise<string | null>,
|
||||
getType: () => Promise<string>,
|
||||
getPlatform: () => Promise<string>,
|
||||
getOsVersion: () => Promise<string>,
|
||||
getGitCommitHash: () => Promise<string>,
|
||||
getBuildTimestamp: () => Promise<string>,
|
||||
getPackageVersion: () => Promise<string> } };
|
||||
openCluster: (folderName: string) => Promise<null> } };
|
||||
|
||||
|
||||
export type { InferCommandOutput }
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export function LaunchButton({
|
|||
}: LaunchButtonProps) {
|
||||
const { data: currentAccount } = useCommandSuspense(['getDefaultUser'], () => bindings.core.getDefaultUser(true));
|
||||
const { data: installedPackages } = useCommandSuspense(['getLinkedPackages', cluster.id], () => bindings.core.getLinkedPackages(cluster.id));
|
||||
const launchCluster = useLaunchCluster(cluster.id);
|
||||
const { launch: launchCluster, showDownloadWarning, setShowDownloadWarning, forceLaunch } = useLaunchCluster(cluster.id);
|
||||
const isRunning = useIsRunning(cluster.id);
|
||||
|
||||
const [reason, setReason] = useState<'account' | 'packages' | 'kill' | null>(null);
|
||||
|
|
@ -85,21 +85,44 @@ export function LaunchButton({
|
|||
};
|
||||
|
||||
return (
|
||||
<Overlay.Trigger isOpen={reason !== null} onOpenChange={open => !open && setReason(null)}>
|
||||
<Button
|
||||
className={launchButtonVariants({ isRunning, className })}
|
||||
isDisabled={isDisabled}
|
||||
onPress={launch}
|
||||
{...rest}
|
||||
>
|
||||
{isRunning ? 'Running' : 'Launch'}
|
||||
</Button>
|
||||
<>
|
||||
<Overlay.Trigger isOpen={reason !== null} onOpenChange={open => !open && setReason(null)}>
|
||||
<Button
|
||||
className={launchButtonVariants({ isRunning, className })}
|
||||
isDisabled={isDisabled}
|
||||
onPress={launch}
|
||||
{...rest}
|
||||
>
|
||||
{isRunning ? 'Running' : 'Launch'}
|
||||
</Button>
|
||||
|
||||
<Overlay>
|
||||
{reason === 'kill' && <KillMinecraft setOpen={() => setReason(null)} />}
|
||||
{reason === 'packages' && <PromptForOnboarding cluster={cluster} launch={launch} setSkipPackagesCheck={setSkipPackagesCheck} />}
|
||||
{reason === 'account' && <NoAccountPopup />}
|
||||
<Overlay>
|
||||
{reason === 'kill' && <KillMinecraft setOpen={() => setReason(null)} />}
|
||||
{reason === 'packages' && <PromptForOnboarding cluster={cluster} launch={launch} setSkipPackagesCheck={setSkipPackagesCheck} />}
|
||||
{reason === 'account' && <NoAccountPopup />}
|
||||
</Overlay>
|
||||
</Overlay.Trigger>
|
||||
|
||||
<Overlay isOpen={showDownloadWarning} onOpenChange={setShowDownloadWarning}>
|
||||
<Overlay.Dialog>
|
||||
<Overlay.Title>Cluster is downloading</Overlay.Title>
|
||||
<div className="flex flex-col items-center">
|
||||
<p className="max-w-sm text-fg-secondary">The cluster is currently downloading. Launching it now might cause issues or corruption. Are you sure you want to proceed?</p>
|
||||
</div>
|
||||
<Overlay.Buttons
|
||||
buttons={[
|
||||
{ color: 'secondary', key: 'Cancel', children: 'Cancel', size: 'normal', onClick: () => setShowDownloadWarning(false) },
|
||||
{
|
||||
color: 'primary',
|
||||
key: 'Proceed',
|
||||
children: 'Proceed Anyways',
|
||||
size: 'normal',
|
||||
onClick: forceLaunch,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Overlay.Dialog>
|
||||
</Overlay>
|
||||
</Overlay.Trigger>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@ import { bindings } from '@/main';
|
|||
import { toast } from '@/utils/toast';
|
||||
import { getMessageFromError, isLauncherError } from '@onelauncher/common';
|
||||
import { useNavigate } from '@tanstack/react-router';
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
export function useLaunchCluster(): (clusterId: number | undefined | null) => void;
|
||||
export function useLaunchCluster(clusterId: number | undefined | null): () => void;
|
||||
export function useLaunchCluster(): { launch: (clusterId: number | undefined | null) => void; showDownloadWarning: boolean; setShowDownloadWarning: (show: boolean) => void; forceLaunch: () => void };
|
||||
export function useLaunchCluster(clusterId: number | undefined | null): { launch: () => void; showDownloadWarning: boolean; setShowDownloadWarning: (show: boolean) => void; forceLaunch: () => void };
|
||||
|
||||
export function useLaunchCluster(clusterId?: number | undefined | null) {
|
||||
const navigate = useNavigate();
|
||||
const [showDownloadWarning, setShowDownloadWarning] = useState(false);
|
||||
const [lastAttemptedId, setLastAttemptedId] = useState<number | null>(null);
|
||||
|
||||
const launch = useCallback(
|
||||
async (id?: number | null) => {
|
||||
|
|
@ -17,6 +19,8 @@ export function useLaunchCluster(clusterId?: number | undefined | null) {
|
|||
if (!targetId)
|
||||
return;
|
||||
|
||||
setLastAttemptedId(targetId);
|
||||
|
||||
try {
|
||||
await bindings.core.launchCluster(targetId, null, false);
|
||||
|
||||
|
|
@ -25,7 +29,12 @@ export function useLaunchCluster(clusterId?: number | undefined | null) {
|
|||
search: { clusterId: targetId },
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
catch (err: any) {
|
||||
if (err.type === 'ClusterError' && err.data.type === 'ClusterDownloading') {
|
||||
setShowDownloadWarning(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isLauncherError(err))
|
||||
toast({
|
||||
type: 'error',
|
||||
|
|
@ -37,5 +46,14 @@ export function useLaunchCluster(clusterId?: number | undefined | null) {
|
|||
[clusterId, navigate],
|
||||
);
|
||||
|
||||
return launch;
|
||||
const forceLaunch = useCallback(async () => {
|
||||
if (!lastAttemptedId)
|
||||
return;
|
||||
// @ts-ignore - ignoring
|
||||
await bindings.core.setClusterStage(lastAttemptedId, 'notready');
|
||||
setShowDownloadWarning(false);
|
||||
launch(lastAttemptedId);
|
||||
}, [lastAttemptedId, launch]);
|
||||
|
||||
return { launch, showDownloadWarning, setShowDownloadWarning, forceLaunch };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use crate::store::processes::Process;
|
|||
use crate::store::{Settings, State};
|
||||
use crate::utils::pagination::Paginated;
|
||||
use interpulse::api::minecraft::Version;
|
||||
use onelauncher_entity::cluster_stage::ClusterStage;
|
||||
use onelauncher_entity::icon::Icon;
|
||||
use onelauncher_entity::loader::GameLoader;
|
||||
use onelauncher_entity::package::Provider;
|
||||
|
|
@ -51,6 +52,9 @@ pub trait TauriLauncherApi {
|
|||
#[taurpc(alias = "updateClusterById")]
|
||||
async fn update_cluster_by_id(id: ClusterId, request: ClusterUpdate) -> LauncherResult<()>;
|
||||
|
||||
#[taurpc(alias = "setClusterStage")]
|
||||
async fn set_cluster_stage(id: ClusterId, stage: ClusterStage) -> LauncherResult<()>;
|
||||
|
||||
#[taurpc(alias = "getScreenshots")]
|
||||
async fn get_screenshots(id: ClusterId) -> LauncherResult<Vec<String>>;
|
||||
|
||||
|
|
@ -407,7 +411,14 @@ impl TauriLauncherApi for TauriLauncherApiImpl {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_cluster_stage(self, id: ClusterId, stage: ClusterStage) -> LauncherResult<()> {
|
||||
api::cluster::dao::update_cluster_by_id(id, |mut model: ClusterPartial| async move {
|
||||
model.stage = Set(stage);
|
||||
Ok(model)
|
||||
})
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn get_screenshots(self, id: ClusterId) -> LauncherResult<Vec<String>> {
|
||||
let cluster = api::cluster::dao::get_cluster_by_id(id)
|
||||
.await?
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue