Compare commits
9 Commits
1a563e64d5
...
3.0.0
Author | SHA1 | Date | |
---|---|---|---|
c395662134 | |||
89d1bcbd86 | |||
c3c13b0e07 | |||
4e1f76a713 | |||
4fb2ab7bed | |||
bb90e28d92 | |||
a554c53f89 | |||
307e0c9747 | |||
86033e2d6a |
@@ -20,8 +20,8 @@ It enhances the osu! experience with quality-of-life features and integration sp
|
||||
- [x] Shows the number of imported beatmapsets
|
||||
- [x] Shows the number of imported skins
|
||||
- [x] Displays ping to the EZPPFarm server
|
||||
- [ ] Discord Rich Presence (planned and in development)
|
||||
- [ ] Performance Display Overlay (planned)
|
||||
- [x] Discord Rich Presence
|
||||
- [x] Performance Display Overlay (currently in experimental patcher release stream)
|
||||
|
||||
---
|
||||
|
||||
@@ -31,9 +31,9 @@ It enhances the osu! experience with quality-of-life features and integration sp
|
||||
| -------- | ---------------- |
|
||||
| Windows | ✅ Supported |
|
||||
| macOS | ❌ Not supported |
|
||||
| Linux | ❌ Not supported |
|
||||
| Linux | 🕧 Partially supported (via osu-winello) |
|
||||
|
||||
> Currently, only **Windows** is supported. Support for other platforms may be considered in the future.
|
||||
> Currently, only **Windows** is fully supported. Support for other platforms may be considered in the future.
|
||||
|
||||
---
|
||||
|
||||
|
4
bun.lock
4
bun.lock
@@ -7,7 +7,7 @@
|
||||
"@better-fetch/fetch": "^1.1.18",
|
||||
"@fontsource/sora": "^5.2.6",
|
||||
"@fontsource/space-mono": "^5.2.8",
|
||||
"@iarna/toml": "^3.0.0",
|
||||
"@iarna/toml": "2.2.5",
|
||||
"@number-flow/svelte": "^0.3.9",
|
||||
"@tailwindcss/typography": "0.5.16",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
@@ -158,7 +158,7 @@
|
||||
|
||||
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
|
||||
|
||||
"@iarna/toml": ["@iarna/toml@3.0.0", "", {}, "sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q=="],
|
||||
"@iarna/toml": ["@iarna/toml@2.2.5", "", {}, "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="],
|
||||
|
||||
"@internationalized/date": ["@internationalized/date@3.8.2", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-/wENk7CbvLbkUvX1tu0mwq49CVkkWpkXubGel6birjRPyo6uQ4nQpnq5xZu823zRCwwn82zgHrvgF1vZyvmVgA=="],
|
||||
|
||||
|
@@ -21,7 +21,7 @@
|
||||
"@better-fetch/fetch": "^1.1.18",
|
||||
"@fontsource/sora": "^5.2.6",
|
||||
"@fontsource/space-mono": "^5.2.8",
|
||||
"@iarna/toml": "^3.0.0",
|
||||
"@iarna/toml": "2.2.5",
|
||||
"@number-flow/svelte": "^0.3.9",
|
||||
"@tailwindcss/typography": "0.5.16",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
|
2
src-tauri/Cargo.lock
generated
2
src-tauri/Cargo.lock
generated
@@ -1094,7 +1094,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ezpplauncher"
|
||||
version = "3.0.0-beta.4"
|
||||
version = "3.0.0-beta.5"
|
||||
dependencies = [
|
||||
"discord-rich-presence",
|
||||
"hardware-id",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ezpplauncher"
|
||||
version = "3.0.0-beta.4"
|
||||
version = "3.0.0-beta.5"
|
||||
description = "EZPPLauncher redefined."
|
||||
authors = ["HorizonCode"]
|
||||
edition = "2024"
|
||||
|
@@ -14,7 +14,8 @@ use tokio::time::{Duration, sleep};
|
||||
use crate::presence;
|
||||
use crate::utils::{
|
||||
check_folder_completeness, get_osu_config, get_osu_user_config, get_window_title_by_pid,
|
||||
set_osu_config_vals, set_osu_user_config_vals, is_wmctrl_available, is_osuwinello_available
|
||||
is_net8_installed, is_osuwinello_available, is_wmctrl_available, set_osu_config_vals,
|
||||
set_osu_user_config_vals,
|
||||
};
|
||||
|
||||
#[tauri::command]
|
||||
@@ -336,10 +337,8 @@ pub async fn run_osu_updater(folder: String) -> Result<(), String> {
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
}
|
||||
|
||||
// Wait for updater process to fully exit
|
||||
let _ = updater_process.wait().await;
|
||||
|
||||
// Clean up update-related files
|
||||
let force_update_files = [".require_update", "help.txt", "_pending"];
|
||||
for update_file_name in &force_update_files {
|
||||
let path = PathBuf::from(&folder).join(update_file_name);
|
||||
@@ -435,6 +434,7 @@ pub struct UpdateFile {
|
||||
pub async fn get_ezpp_launcher_update_files(
|
||||
folder: String,
|
||||
update_url: String,
|
||||
update_stream: String,
|
||||
) -> Result<(Vec<UpdateFile>, Vec<UpdateFile>), String> {
|
||||
let osu_path = PathBuf::from(folder);
|
||||
let client = Client::new();
|
||||
@@ -442,6 +442,7 @@ pub async fn get_ezpp_launcher_update_files(
|
||||
let update_files = client
|
||||
.patch(update_url)
|
||||
.header("User-Agent", "EZPPLauncher")
|
||||
.query(&[("stream", update_stream)])
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| e.to_string())?
|
||||
@@ -534,7 +535,6 @@ pub async fn download_ezpp_launcher_update_files(
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
// Emit progress to frontend
|
||||
app.emit(
|
||||
"download-progress",
|
||||
UpdateStatus {
|
||||
@@ -714,3 +714,8 @@ pub fn has_wmctrl() -> bool {
|
||||
pub fn has_osuwinello() -> bool {
|
||||
is_osuwinello_available()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn has_net8() -> bool {
|
||||
is_net8_installed().await
|
||||
}
|
||||
|
@@ -10,7 +10,8 @@ use crate::commands::{
|
||||
get_osu_release_stream, get_osu_skin, get_osu_version, get_platform, get_skins_count,
|
||||
is_osu_running, open_url_in_browser, presence_connect, presence_disconnect,
|
||||
presence_is_connected, presence_update_status, presence_update_user, replace_ui_files, run_osu,
|
||||
run_osu_updater, set_osu_config_values, set_osu_user_config_values, valid_osu_folder, has_osuwinello, has_wmctrl
|
||||
run_osu_updater, set_osu_config_values, set_osu_user_config_values, valid_osu_folder, has_osuwinello, has_wmctrl,
|
||||
has_net8
|
||||
};
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
@@ -62,7 +63,8 @@ pub fn run() {
|
||||
presence_update_user,
|
||||
presence_is_connected,
|
||||
has_osuwinello,
|
||||
has_wmctrl
|
||||
has_wmctrl,
|
||||
has_net8
|
||||
])
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
|
@@ -1,6 +1,5 @@
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use sysinfo::Pid;
|
||||
|
||||
pub fn check_folder_completeness<P: AsRef<Path>>(folder_path: P, required_files: &[&str]) -> f32 {
|
||||
@@ -72,7 +71,6 @@ pub fn set_osu_user_config_vals(
|
||||
}
|
||||
}
|
||||
|
||||
// Collect indices and keys to update to avoid borrow checker issues
|
||||
let mut updates = Vec::new();
|
||||
for (i, line) in lines.iter().enumerate() {
|
||||
if let Some((existing_key, _)) = line.split_once(" = ") {
|
||||
@@ -87,7 +85,6 @@ pub fn set_osu_user_config_vals(
|
||||
keys_to_add.remove(trimmed_key.as_str());
|
||||
}
|
||||
|
||||
// Add new keys that were not found
|
||||
for key in keys_to_add {
|
||||
if let Some(value) = keys_to_set.get(key) {
|
||||
lines.push(format!("{} = {}", key, value));
|
||||
@@ -140,7 +137,6 @@ pub fn set_osu_config_vals(
|
||||
keys_to_add.remove(trimmed_key.as_str());
|
||||
}
|
||||
|
||||
// Add new keys that were not found
|
||||
for key in keys_to_add {
|
||||
if let Some(value) = keys_to_set.get(key) {
|
||||
lines.push(format!("{} = {}", key, value));
|
||||
@@ -179,12 +175,13 @@ pub fn get_osu_config<P: AsRef<Path>>(
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub fn is_osuwinello_available() -> bool {
|
||||
use std::process::Command;
|
||||
Command::new("osu-wine")
|
||||
.arg("--info") // A lightweight operation like getting the version is ideal.
|
||||
.stdout(std::process::Stdio::null()) // Suppress stdout
|
||||
.stderr(std::process::Stdio::null()) // Suppress stderr
|
||||
.status() // Execute the command and get its status
|
||||
.is_ok() // is_ok() will be true if the command was found and ran
|
||||
.arg("--info")
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::null())
|
||||
.status()
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
@@ -194,12 +191,13 @@ pub fn is_osuwinello_available() -> bool {
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub fn is_wmctrl_available() -> bool {
|
||||
use std::process::Command;
|
||||
Command::new("wmctrl")
|
||||
.arg("-V") // A lightweight operation like getting the version is ideal.
|
||||
.stdout(std::process::Stdio::null()) // Suppress stdout
|
||||
.stderr(std::process::Stdio::null()) // Suppress stderr
|
||||
.status() // Execute the command and get its status
|
||||
.is_ok() // is_ok() will be true if the command was found and ran
|
||||
.arg("-V")
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::null())
|
||||
.status()
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
@@ -209,27 +207,24 @@ pub fn is_wmctrl_available() -> bool {
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub fn get_window_title_by_pid(target_pid: Pid) -> String {
|
||||
use std::process::Command;
|
||||
let find_title = || -> Option<String> {
|
||||
// 1. Execute `wmctrl -lp`
|
||||
let output = Command::new("wmctrl").arg("-lp").output().ok()?;
|
||||
|
||||
if !output.status.success() {
|
||||
return None; // wmctrl command failed (e.g., not on X11)
|
||||
return None;
|
||||
}
|
||||
|
||||
let output_str = String::from_utf8(output.stdout).ok()?;
|
||||
|
||||
// 2. Parse the output line by line
|
||||
for line in output_str.lines() {
|
||||
let parts: Vec<&str> = line.split_whitespace().collect();
|
||||
if parts.len() < 4 {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The PID is typically the 3rd column (index 2)
|
||||
if let Ok(pid) = parts[2].parse::<u32>() {
|
||||
if pid == target_pid.as_u32() {
|
||||
// 3. Extract the title and return it as Some(title)
|
||||
let title = parts[4..].join(" ");
|
||||
return Some(title);
|
||||
}
|
||||
@@ -244,13 +239,13 @@ pub fn get_window_title_by_pid(target_pid: Pid) -> String {
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn get_window_title_by_pid(pid: Pid) -> String {
|
||||
use std::ffi::OsString;
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use winapi::shared::windef::HWND;
|
||||
use winapi::um::winuser::{
|
||||
EnumWindows, GetWindowTextW, GetWindowThreadProcessId, IsWindowVisible,
|
||||
};
|
||||
use std::ffi::OsString;
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
|
||||
extern "system" fn enum_windows_proc(
|
||||
hwnd: HWND,
|
||||
@@ -271,11 +266,11 @@ pub fn get_window_title_by_pid(pid: Pid) -> String {
|
||||
let title_str = title.to_string_lossy().into_owned();
|
||||
if !title_str.is_empty() {
|
||||
*result.lock().unwrap() = Some(title_str);
|
||||
return 0; // Stop enumeration
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
1 // Continue enumeration
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,3 +284,26 @@ pub fn get_window_title_by_pid(pid: Pid) -> String {
|
||||
}
|
||||
result.lock().unwrap().clone().unwrap_or_default()
|
||||
}
|
||||
|
||||
pub async fn is_net8_installed() -> bool {
|
||||
use std::process::Command;
|
||||
let output_result = Command::new("dotnet").arg("--list-runtimes").output();
|
||||
match output_result {
|
||||
Ok(output) => {
|
||||
if !output.status.success() {
|
||||
eprintln!(
|
||||
"Error: `dotnet --list-runtimes` failed with status: {}",
|
||||
output.status
|
||||
);
|
||||
eprintln!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||
return false;
|
||||
}
|
||||
|
||||
let stdout_str = String::from_utf8_lossy(&output.stdout);
|
||||
stdout_str
|
||||
.lines()
|
||||
.any(|line| line.starts_with("Microsoft.WindowsDesktop.App 8."))
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "ezpplauncher",
|
||||
"version": "3.0.0-beta.2",
|
||||
"version": "3.0.0-beta.5",
|
||||
"identifier": "farm.ezpp.launcher",
|
||||
"build": {
|
||||
"beforeDevCommand": "bun run vite:dev",
|
||||
|
@@ -11,6 +11,9 @@ export const platform = writable<string>("");
|
||||
export const launcherVersion = writable<string>('');
|
||||
export const newVersion = writable<Release | undefined>(undefined);
|
||||
|
||||
export const launcherStreams = writable<string[]>(['stable']);
|
||||
export const launcherStream = writable<string>('stable');
|
||||
|
||||
export const discordPresence = writable<boolean>(false);
|
||||
export const presenceLoading = writable<boolean>(false);
|
||||
|
||||
|
@@ -1,8 +1,9 @@
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import type { UpdateFile, UpdateStatus } from './types';
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
import { betterFetch } from '@better-fetch/fetch';
|
||||
|
||||
const updateUrl = 'https://ez-pp.farm/ezpplauncher';
|
||||
const updateUrl = 'https://next.ez-pp.farm/api/ezpplauncher';
|
||||
|
||||
export const getHWID = async () => {
|
||||
const hwid = await invoke('get_hwid');
|
||||
@@ -73,8 +74,24 @@ export const runUpdater = async (folder: string) => await invoke('run_osu_update
|
||||
export const runOsu = async (folder: string, patch: boolean) =>
|
||||
await invoke('run_osu', { folder, patch });
|
||||
|
||||
export const getEZPPLauncherUpdateFiles = async (folder: string) => {
|
||||
const result = await invoke('get_ezpp_launcher_update_files', { folder, updateUrl });
|
||||
export const getEZPPLauncherStreams = async () => {
|
||||
const resp = await betterFetch<{ streams: string[] }>(updateUrl, {
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
if (!resp.error) {
|
||||
return resp.data.streams;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const getEZPPLauncherUpdateFiles = async (folder: string, updateStream: string) => {
|
||||
const result = await invoke('get_ezpp_launcher_update_files', {
|
||||
folder,
|
||||
updateUrl,
|
||||
updateStream,
|
||||
});
|
||||
if (typeof result === 'object') {
|
||||
const [filesToDownload, updateFiles] = result as [UpdateFile[], UpdateFile[]];
|
||||
return {
|
||||
@@ -120,3 +137,5 @@ export const hasWMCTRL = async () =>
|
||||
await invoke<boolean>('has_wmctrl');
|
||||
export const hasOsuWinello = async () =>
|
||||
await invoke<boolean>('has_osuwinello');
|
||||
export const hasNet8 = async () =>
|
||||
await invoke<boolean>('has_net8');
|
@@ -9,6 +9,8 @@
|
||||
currentSkin,
|
||||
currentView,
|
||||
discordPresence,
|
||||
launcherStream,
|
||||
launcherStreams,
|
||||
launcherVersion,
|
||||
launching,
|
||||
newVersion,
|
||||
@@ -88,6 +90,7 @@
|
||||
getSkin,
|
||||
getSkinsCount,
|
||||
getVersion,
|
||||
hasNet8,
|
||||
hasOsuWinello,
|
||||
hasWMCTRL,
|
||||
isOsuCorrupted,
|
||||
@@ -187,7 +190,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if($platform === "linux"){
|
||||
if ($platform === 'linux') {
|
||||
if (!(await hasWMCTRL())) {
|
||||
toast.error('Hmmm...', {
|
||||
description: 'wmctrl seems to be missing, please install via AUR.',
|
||||
@@ -206,7 +209,7 @@
|
||||
|
||||
try {
|
||||
launchInfo = 'Looking for EZPPLauncher File updates...';
|
||||
const updateResult = await getEZPPLauncherUpdateFiles(osuPath);
|
||||
const updateResult = await getEZPPLauncherUpdateFiles(osuPath, $launcherStream);
|
||||
|
||||
if (updateResult) {
|
||||
if (updateResult.filesToDownload.length > 0) {
|
||||
@@ -1048,12 +1051,18 @@
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-custom-cursor">Patching</Label>
|
||||
<div class="text-muted-foreground text-xs">Shows misses in Relax and Autopilot {#if $platform !== "windows"}<span class="text-red-500 bg-red-800/20 border border-red-600/20 p-0.5 mx-1 px-2 rounded-lg">currently only on windows!</span> {/if}</div>
|
||||
<div class="text-muted-foreground text-xs">
|
||||
Shows misses in Relax and Autopilot {#if $platform !== 'windows'}<span
|
||||
class="text-red-500 bg-red-800/20 border border-red-600/20 p-0.5 mx-1 px-2 rounded-lg"
|
||||
>currently only on windows!</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<Checkbox
|
||||
id="setting-custom-cursor"
|
||||
checked={$platform === "windows" ? $patch : false}
|
||||
disabled={$platform !== "windows"}
|
||||
checked={$platform === 'windows' ? $patch : false}
|
||||
disabled={$platform !== 'windows'}
|
||||
onCheckedChange={async (e) => {
|
||||
patch.set(e);
|
||||
$userSettings.save();
|
||||
@@ -1136,7 +1145,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="grid grid-cols-[0.7fr_auto] gap-y-5 items-center border-theme-800 pl-6 pr-5 pb-4"
|
||||
class="grid grid-cols-[0.7fr_auto] gap-y-1 items-center border-theme-800 pl-6 pr-5 pb-4"
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-custom-cursor">osu! installation path</Label>
|
||||
@@ -1156,6 +1165,54 @@
|
||||
onclick={browse_osu_installation}>Browse</Button
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<Label class="text-sm" for="setting-custom-cursor">patcher release stream</Label>
|
||||
<div class="text-muted-foreground text-xs">
|
||||
test different versions of the patcher
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row w-full">
|
||||
<Select.Root
|
||||
type="single"
|
||||
bind:value={$launcherStream}
|
||||
onValueChange={async (newStream) => {
|
||||
if (newStream === 'experimental' && !(await hasNet8())) {
|
||||
launcherStream.set('stable');
|
||||
toast.error('.NET 8.0 Desktop Runtime not found!', {
|
||||
action: {
|
||||
label: 'Download .NET 8.0',
|
||||
onClick: async () =>
|
||||
await openURL(
|
||||
'https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-desktop-8.0.18-windows-x64-installer'
|
||||
),
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
$userSettings.value('patcherStream').set(newStream);
|
||||
launcherStream.set(newStream);
|
||||
await $userSettings.save();
|
||||
}}
|
||||
>
|
||||
<Select.Trigger
|
||||
class="border-theme-800 bg-theme-950 !text-muted-foreground font-semibold"
|
||||
>
|
||||
<div class="flex flex-row items-center gap-2 font-normal text-foreground">
|
||||
{$launcherStream}
|
||||
</div>
|
||||
</Select.Trigger>
|
||||
<Select.Content class="bg-theme-950 border border-theme-950 rounded-lg">
|
||||
{#each $launcherStreams as stream (stream)}
|
||||
<Select.Item value={stream}>
|
||||
<div class="flex flex-row gap-2 items-center">
|
||||
{stream}
|
||||
</div>
|
||||
</Select.Item>
|
||||
{/each}
|
||||
</Select.Content>
|
||||
</Select.Root>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -7,6 +7,8 @@
|
||||
currentSkin,
|
||||
currentView,
|
||||
firstStartup,
|
||||
launcherStream,
|
||||
launcherStreams,
|
||||
launcherVersion,
|
||||
newVersion,
|
||||
osuBuild,
|
||||
@@ -30,6 +32,7 @@
|
||||
import { currentUserInfo } from '@/data';
|
||||
import {
|
||||
getBeatmapSetsCount,
|
||||
getEZPPLauncherStreams,
|
||||
getReleaseStream,
|
||||
getSkin,
|
||||
getSkinsCount,
|
||||
@@ -148,6 +151,14 @@
|
||||
newVersion.set(launcherUpdate);
|
||||
}
|
||||
|
||||
const ezpplauncherStreams = await getEZPPLauncherStreams();
|
||||
if (ezpplauncherStreams) launcherStreams.set(ezpplauncherStreams);
|
||||
|
||||
const selectedLauncherStream = $userSettings.value('patcherStream').get('stable');
|
||||
if ($launcherStreams.includes(selectedLauncherStream)) {
|
||||
launcherStream.set(selectedLauncherStream);
|
||||
}
|
||||
|
||||
animate(ezppLogo, {
|
||||
opacity: [1, 0],
|
||||
scale: [1, 1.05],
|
||||
|
Reference in New Issue
Block a user