Compare commits

..

No commits in common. "master" and "3.0.0" have entirely different histories.

19 changed files with 44 additions and 163 deletions

View File

@ -7,6 +7,3 @@ bun.lockb
# Miscellaneous
/static/
# Tauri
/src-tauri/

View File

@ -9,7 +9,7 @@
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": true,
"plugins": ["prettier-plugin-svelte"],
"plugins": ["prettier-plugin-svelte", "prettier-plugin-rust"],
"overrides": [
{
"files": "*.svelte",

View File

@ -1,7 +1,7 @@
{
"svelte.enable-ts-plugin": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[rust]": {
"[rust]":{
"editor.defaultFormatter": "rust-lang.rust-analyzer"
}
}

View File

@ -27,10 +27,10 @@ It enhances the osu! experience with quality-of-life features and integration sp
## 💻 Supported Platforms
| Platform | Status |
| -------- | ---------------------------------------- |
| Windows | ✅ Supported |
| macOS | ❌ Not supported |
| Platform | Status |
| -------- | ---------------- |
| Windows | ✅ Supported |
| macOS | ❌ Not supported |
| Linux | 🕧 Partially supported (via osu-winello) |
> Currently, only **Windows** is fully supported. Support for other platforms may be considered in the future.

View File

@ -46,7 +46,7 @@
"@lucide/svelte": "^0.525.0",
"@sveltejs/adapter-static": "3.0.8",
"@sveltejs/kit": "2.22.2",
"@sveltejs/vite-plugin-svelte": "^6.1.0",
"@sveltejs/vite-plugin-svelte": "5.1.0",
"@tauri-apps/cli": "2.6.1",
"@types/bun": "^1.2.18",
"@types/crypto-js": "^4.2.2",
@ -73,6 +73,6 @@
"typescript": "5.8.3",
"typescript-eslint": "^8.20.0",
"vite": "7.0.0",
"vite-plugin-devtools-json": "^0.3.0"
"vite-plugin-devtools-json": "^0.2.0"
}
}

10
src-tauri/Cargo.lock generated
View File

@ -1094,9 +1094,8 @@ dependencies = [
[[package]]
name = "ezpplauncher"
version = "3.0.2"
version = "3.0.0-beta.5"
dependencies = [
"base64 0.21.7",
"discord-rich-presence",
"hardware-id",
"md5",
@ -1116,7 +1115,6 @@ dependencies = [
"tauri-plugin-single-instance",
"tauri-plugin-sql",
"tokio",
"widestring",
"winapi",
"windows-sys 0.60.2",
"winreg 0.55.0",
@ -5800,12 +5798,6 @@ dependencies = [
"wasite",
]
[[package]]
name = "widestring"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d"
[[package]]
name = "winapi"
version = "0.3.9"

View File

@ -1,6 +1,6 @@
[package]
name = "ezpplauncher"
version = "3.0.2"
version = "3.0.0-beta.5"
description = "EZPPLauncher redefined."
authors = ["HorizonCode"]
edition = "2024"
@ -39,9 +39,7 @@ once_cell = "1.21.3"
[target.'cfg(windows)'.dependencies]
winreg = "0.55.0"
winapi = { version = "0.3", features = ["winuser", "wincrypt", "memoryapi", "winbase", "dpapi"] }
base64 = "0.21"
widestring = "1.0"
winapi = { version = "0.3", features = ["winuser"] }
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
tauri-plugin-single-instance = "2.3.0"

View File

@ -13,9 +13,9 @@ use tokio::time::{Duration, sleep};
use crate::presence;
use crate::utils::{
check_folder_completeness, encrypt_password, get_osu_config, get_osu_user_config,
get_window_title_by_pid, is_net8_installed, is_osuwinello_available, is_wmctrl_available,
set_osu_config_vals, set_osu_user_config_vals,
check_folder_completeness, get_osu_config, get_osu_user_config, get_window_title_by_pid,
is_net8_installed, is_osuwinello_available, is_wmctrl_available, set_osu_config_vals,
set_osu_user_config_vals,
};
#[tauri::command]
@ -719,21 +719,3 @@ pub fn has_osuwinello() -> bool {
pub async fn has_net8() -> bool {
is_net8_installed().await
}
#[cfg(windows)]
#[tauri::command]
pub fn encrypt_string(string: String, entropy: String) -> String {
let encrypted = encrypt_password(&string, &entropy);
match encrypted {
Ok(encrypted_vec) => encrypted_vec,
Err(_) => string,
}
}
// NOTE: should not be called by tauri on non windows systems, return the string nonthenless
#[cfg(not(windows))]
#[tauri::command]
pub fn encrypt_string(string: String, _entropy: String) -> String {
string
}

View File

@ -5,17 +5,18 @@ pub mod commands;
pub mod presence;
pub mod utils;
use crate::commands::{
check_for_corruption, download_ezpp_launcher_update_files, encrypt_string, exit,
find_osu_installation, get_beatmapsets_count, get_ezpp_launcher_update_files, get_hwid,
get_launcher_version, get_osu_release_stream, get_osu_skin, get_osu_version, get_platform,
get_skins_count, has_net8, has_osuwinello, has_wmctrl, 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,
check_for_corruption, download_ezpp_launcher_update_files, exit, find_osu_installation,
get_beatmapsets_count, get_ezpp_launcher_update_files, get_hwid, get_launcher_version,
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,
has_net8
};
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
#[cfg(target_os = "linux")]
unsafe {
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
@ -26,6 +27,9 @@ pub fn run() {
{
builder = builder.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
let app_window = app.get_webview_window("main").expect("no main window");
app_window
.set_always_on_top(true)
.expect("failed to set always on top");
app_window.set_focus().expect("failed to focus");
}));
}
@ -60,8 +64,7 @@ pub fn run() {
presence_is_connected,
has_osuwinello,
has_wmctrl,
has_net8,
encrypt_string
has_net8
])
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_dialog::init())

View File

@ -307,69 +307,3 @@ pub async fn is_net8_installed() -> bool {
Err(_) => false,
}
}
#[cfg(windows)]
pub fn encrypt_password(password: &str, entropy: &str) -> Result<String, String> {
use base64::{Engine as _, engine::general_purpose};
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::ptr;
use std::slice;
use winapi::shared::minwindef::{BYTE, DWORD, LPVOID};
use winapi::shared::ntdef::LPCWSTR;
use winapi::um::dpapi::{CRYPTPROTECT_UI_FORBIDDEN, CryptProtectData};
use winapi::um::winbase::LocalFree;
use winapi::um::wincrypt::DATA_BLOB;
let description = "Encrypted";
let password_bytes = password.as_bytes();
let mut input_blob = DATA_BLOB {
cbData: password_bytes.len() as DWORD,
pbData: password_bytes.as_ptr() as *mut BYTE,
};
let entropy_bytes = entropy.as_bytes();
let mut entropy_blob = DATA_BLOB {
cbData: entropy_bytes.len() as DWORD,
pbData: entropy_bytes.as_ptr() as *mut BYTE,
};
let mut output_blob = DATA_BLOB {
cbData: 0,
pbData: ptr::null_mut(),
};
let wide_description: Vec<u16> = OsStrExt::encode_wide(OsStr::new(description))
.chain(Some(0))
.collect();
let p_description: LPCWSTR = wide_description.as_ptr();
let result = unsafe {
CryptProtectData(
&mut input_blob,
p_description,
&mut entropy_blob,
ptr::null_mut(),
ptr::null_mut(),
CRYPTPROTECT_UI_FORBIDDEN,
&mut output_blob,
)
};
if result == 0 {
return Err("CryptProtectData failed".to_string());
}
let encrypted_data =
unsafe { slice::from_raw_parts(output_blob.pbData, output_blob.cbData as usize).to_vec() };
unsafe {
LocalFree(output_blob.pbData as LPVOID);
}
let base64_string = general_purpose::STANDARD.encode(&encrypted_data);
Ok(base64_string)
}

View File

@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "ezpplauncher",
"version": "3.0.2",
"version": "3.0.0-beta.5",
"identifier": "farm.ezpp.launcher",
"build": {
"beforeDevCommand": "bun run vite:dev",
@ -12,7 +12,7 @@
"app": {
"windows": [
{
"title": "EZPPLauncher",
"title": "ezpplauncher",
"width": 1000,
"height": 700,
"decorations": false,
@ -26,10 +26,6 @@
}
},
"bundle": {
"publisher": "EZPPFarm",
"copyright": "EZPPFarm",
"homepage": "https://ez-pp.farm",
"license": "GPL-3.0",
"active": true,
"targets": [
"app"
@ -40,12 +36,6 @@
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
],
"windows": {
"webviewInstallMode": {
"silent": true,
"type": "downloadBootstrapper"
}
}
]
}
}

View File

@ -20,14 +20,10 @@
</script>
<div data-tauri-drag-region class="titlebar z-[60] border-b border-theme-800/90">
<div
class="mr-auto ms-2 flex flex-row gap-2 items-center text-[1.05rem] font-semibold pointer-events-none"
>
<div class="mr-auto ms-2 flex flex-row gap-2 items-center text-[1.05rem] font-semibold pointer-events-none">
<img src={Logo} alt="EZPP Launcher Logo" class="h-11 w-11 inline-block" />
<span>EZPPLauncher</span>
<Badge class="!text-[0.6rem] py-[0.5px] bg-primary-500 hover:bg-primary-500"
>{$launcherVersion}</Badge
>
<Badge class="!text-[0.6rem] py-[0.5px] bg-primary-500 hover:bg-primary-500">{$launcherVersion}</Badge>
</div>
<div class="titlebar-button rounded-lg transition-colors duration-75" id="titlebar-minimize">
<Minimize size={18} />

View File

@ -1,12 +1,12 @@
import { writable } from 'svelte/store';
import { ezppfarm } from './api/ezpp';
import type { Component } from 'svelte';
import Loading from '../screens/Loading.svelte';
import Loading from '../pages/Loading.svelte';
import type { Release } from './types';
export const currentView = writable<Component>(Loading);
export const platform = writable<string>('');
export const platform = writable<string>("");
export const launcherVersion = writable<string>('');
export const newVersion = writable<Release | undefined>(undefined);

View File

@ -133,8 +133,9 @@ export const exit = async () => await invoke('exit');
export const getPlatform = async () => await invoke<string>('get_platform');
export const isOsuCorrupted = async (folder: string) =>
await invoke<boolean>('check_for_corruption', { folder });
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');
export const encryptString = async (str: string, entropy: string) =>
await invoke<string>('encrypt_string', { string: str, entropy });
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');

View File

@ -83,7 +83,6 @@
import { osuapi } from '@/api/osuapi';
import {
downloadEZPPLauncherUpdateFiles,
encryptString,
exit,
getBeatmapSetsCount,
getEZPPLauncherUpdateFiles,
@ -297,10 +296,7 @@
},
{
key: 'Password',
value:
$platform === 'windows'
? await encryptString(password, 'cu24180ncjeiu0ci1nwui')
: password,
value: password,
},
{
key: 'SaveUsername',
@ -535,11 +531,7 @@
</AlertDialog.Root>
<AlertDialog.Root open={$newVersion !== undefined}>
<AlertDialog.Content
class="bg-theme-950 border-theme-800 p-0"
escapeKeydownBehavior="ignore"
interactOutsideBehavior="ignore"
>
<AlertDialog.Content class="bg-theme-950 border-theme-800 p-0">
<div
class="flex flex-col items-center justify-center border-b border-theme-800 bg-black/40 rounded-t-lg p-3"
>
@ -575,11 +567,7 @@
</AlertDialog.Root>
<AlertDialog.Root bind:open={$launching}>
<AlertDialog.Content
class="bg-theme-950 border-theme-800 p-0"
escapeKeydownBehavior="ignore"
interactOutsideBehavior="ignore"
>
<AlertDialog.Content class="bg-theme-950 border-theme-800 p-0">
<div
class="flex flex-col items-center justify-center border-b border-theme-800 bg-black/40 rounded-t-lg p-3"
>

View File

@ -26,7 +26,7 @@
import { Buffer } from 'buffer';
import { Toaster } from '@/components/ui/sonner';
import { userAuth } from '@/userAuthentication';
import { encryptString, exit, getLauncherVersion, getPlatform } from '@/osuUtil';
import { exit, getLauncherVersion, getPlatform } from '@/osuUtil';
import Button from '@/components/ui/button/button.svelte';
import * as presence from '@/presence';
@ -92,7 +92,7 @@
setupValues();
launcherVersion.set(await getLauncherVersion());
platform.set(await getPlatform());
if ($platform !== 'windows' && $platform !== 'linux') unsupported_platform = true;
if ($platform !== "windows" && $platform !== "linux") unsupported_platform = true;
const isFirstStartup = await $userSettings.init();
$userAuth.init();