LAUNCHER-12 fix: frontend not reacting to game close

This commit is contained in:
LynithDev 2024-12-22 12:28:37 +01:00
parent e8ad2e0da7
commit c74d091b8e
4 changed files with 66 additions and 33 deletions

View file

@ -1,6 +1,7 @@
import type { UnlistenFn } from '@tauri-apps/api/event';
import type { NotificationData } from '~ui/components/overlay/notifications/NotificationComponent';
import { events } from '@onelauncher/client/bindings';
import { randomString } from '~utils';
import { type Accessor, type Context, createContext, createSignal, onCleanup, onMount, type ParentProps, type Signal, useContext } from 'solid-js';
type Notifications = Record<string, NotificationData>;
@ -8,6 +9,7 @@ type Notifications = Record<string, NotificationData>;
interface HookReturn {
list: Accessor<Notifications>;
set: (id: string, data: NotificationData) => void;
create: (data: NotificationData) => void;
clear: () => void;
}
@ -44,11 +46,14 @@ export function NotificationProvider(props: ParentProps) {
function useNotifications(): HookReturn {
const [notifications, setNotifications] = useContext(NotificationContext);
return {
const ctx = {
list: notifications,
set: (id, data) => setNotifications(notifications => ({ ...notifications, [id]: data })),
create: data => ctx.set(randomString(6), data),
clear: () => setNotifications({}),
};
} satisfies HookReturn;
return ctx;
}
export default useNotifications;

View file

@ -11,6 +11,7 @@ import Modal, { createModal } from '~ui/components/overlay/Modal';
import Sidebar from '~ui/components/Sidebar';
import useClusterContext from '~ui/hooks/useCluster';
import useCommand from '~ui/hooks/useCommand';
import useNotifications from '~ui/hooks/useNotifications';
import { createSignal, onCleanup, onMount } from 'solid-js';
import { render } from 'solid-js/web';
@ -26,6 +27,7 @@ function ClusterGame() {
const [params] = useSearchParams<ClusterGameParams>();
const [log] = useCommand(() => bridge.commands.getClusterLog(cluster()!.uuid, 'latest.log'));
const [isRunning, setIsRunning] = createSignal(true);
const notifications = useNotifications();
const [unlisten, setUnlisten] = createSignal<UnlistenFn>();
let codeRef!: HTMLElement;
@ -39,6 +41,11 @@ function ClusterGame() {
render(() => <Line line={event.payload.message} />, codeRef);
else if (event.payload.event === 'finished')
setIsRunning(false);
else if (event.payload.event === 'modified')
notifications.create({
title: 'Process Status',
message: event.payload.message,
});
});
setUnlisten(() => unlisten);

View file

@ -54,6 +54,15 @@ export function int32ToBigInt([high, low]: [number, number]): bigint {
return (BigInt(high | 0) << 32n) | BigInt(low >>> 0);
}
export function randomString(len: number = 6, charSet: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') {
let randomString = '';
for (let i = 0; i < len; i++) {
const randomPos = Math.floor(Math.random() * charSet.length);
randomString += charSet.substring(randomPos, randomPos + 1);
}
return randomString;
}
export function abbreviateNumber(n: number | bigint, locale: string = 'en-US'): string {
return new Intl.NumberFormat(locale, {
notation: 'compact',

View file

@ -13,7 +13,7 @@ use uuid::Uuid;
use crate::api::cluster;
use crate::constants::PROCESSOR_FILE;
use crate::proxy::send::send_process;
use crate::proxy::send::{send_ingress, send_message, send_process};
use crate::proxy::ProcessPayloadType;
use crate::utils::http::read_json;
use crate::State;
@ -427,7 +427,7 @@ impl Processor {
#[cfg(target_os = "linux")]
{
if enable_gamemode.is_some_and(|x| x == true) {
if enable_gamemode.is_some_and(|x| x) {
if let Err(err) = onelauncher_gamemode::request_start_for_wrapper(pid) {
tracing::warn!("failed to enable gamemode, continuing: {}", err);
};
@ -654,8 +654,8 @@ impl Processor {
});
tokio::spawn(async {
let state = State::get();
let state = match state.await {
let state = State::get().await;
let state = match state {
Ok(state) => state,
Err(err) => {
tracing::warn!("failed to get state: {}", err);
@ -689,47 +689,59 @@ impl Processor {
}
let post = if let Some(hook) = post {
let mut cmd = hook.split(' ');
if let Some(c) = cmd.next() {
let mut c = Command::new(c);
c.args(cmd).current_dir(cluster_path.full_path().await?);
Some(c)
} else {
if hook.is_empty() {
None
} else {
let mut cmd = hook.split(' ');
if let Some(c) = cmd.next() {
let mut c = Command::new(c);
c.args(cmd).current_dir(cluster_path.full_path().await?);
Some(c)
} else {
None
}
}
} else {
None
};
if let Some(mut m_c) = post {
{
let mut current_child: tokio::sync::RwLockWriteGuard<'_, ChildType> =
current_child.write().await;
let new_child = m_c.spawn().map_err(IOError::from)?;
current_pid = new_child
.id()
.ok_or_else(|| anyhow::anyhow!("process failed, couldnt get pid"))?;
*current_child = ChildType::ChildProcess(new_child);
}
let result = {
{
let mut current_child: tokio::sync::RwLockWriteGuard<'_, ChildType> =
current_child.write().await;
send_process(
uuid,
current_pid,
ProcessPayloadType::Modified,
"running post hook",
)
.await?;
let new_child = m_c.spawn().map_err(IOError::from)?;
current_pid = new_child
.id()
.ok_or_else(|| anyhow::anyhow!("process failed, couldnt get pid"))?;
*current_child = ChildType::ChildProcess(new_child);
};
send_process(
uuid,
current_pid,
ProcessPayloadType::Modified,
"running post hook",
)
.await?;
loop {
let value = current_child.write().await.try_wait();
if let Some(stat) = value? {
if let Ok(Some(stat)) = value {
exit_status = stat;
break;
}
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
Ok::<(), crate::Error>(())
};
if let Err(err) = result {
tracing::error!("failed to run post hook: {err}");
let _ = send_message(format!("failed to run post hook: {err}").as_str()).await;
}
}
};
send_process(
uuid,