Compare commits

..

5 Commits

Author SHA1 Message Date
39128d68cb Fix Apple signing 2025-11-15 15:00:11 +11:00
84f4210479 Bump version 2025-11-15 09:09:58 +11:00
a2d1a989e0 Fix folders not opening (#162) 2025-10-17 15:27:32 +11:00
83d2301056 Fix macOS build 2025-10-16 15:32:28 +11:00
87bbe1da49 156 refactor into workspaces (#157)
* chore: Major refactoring

Still needs a massive go-over because there shouldn't be anything referencing tauri in any of the workspaces except the original one. Process manager has been refactored as an example

Signed-off-by: quexeky <git@quexeky.dev>

* fix: Remote tauri dependency from process

Signed-off-by: quexeky <git@quexeky.dev>

* refactor: Improvements to src-tauri

Signed-off-by: quexeky <git@quexeky.dev>

* refactor: Builds, but some logic still left to move back

Signed-off-by: quexeky <git@quexeky.dev>

* refactor: Finish refactor

Signed-off-by: quexeky <git@quexeky.dev>

* chore: Run cargo clippy && cargo fmt

Signed-off-by: quexeky <git@quexeky.dev>

* refactor: Move everything into src-tauri

Signed-off-by: quexeky <git@quexeky.dev>

---------

Signed-off-by: quexeky <git@quexeky.dev>
2025-10-14 17:12:51 +11:00
88 changed files with 1511 additions and 9229 deletions

View File

@ -63,17 +63,21 @@ jobs:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: | run: |
echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12 echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain # security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security default-keychain -s build.keychain # security default-keychain -s build.keychain
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain # security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
security set-keychain-settings -t 3600 -u build.keychain # security set-keychain-settings -t 3600 -u build.keychain
curl https://droposs.org/drop.crt --output drop.pem curl https://droposs.org/drop.der --output drop.der
sudo security authorizationdb write com.apple.trust-settings.user allow swiftc libs/appletrust/add-certificate.swift
security add-trusted-cert -r trustRoot -k build.keychain -p codeSign -u -1 drop.pem ./add-certificate drop.der
sudo security authorizationdb remove com.apple.trust-settings.user rm add-certificate
security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign # sudo security authorizationdb write com.apple.trust-settings.user allow
# security add-trusted-cert -r trustRoot -k build.keychain -p codeSign -u -1 drop.pem
# sudo security authorizationdb remove com.apple.trust-settings.user
security import certificate.p12 -k /Library/Keychains/System.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain
security find-identity -v -p codesigning build.keychain security find-identity -v -p codesigning build.keychain

View File

@ -1,2 +0,0 @@
*
!.gitignore

8290
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +0,0 @@
[workspace]
members = [
"client",
"database",
"src-tauri",
"process",
"remote",
"utils",
"cloud_saves",
"download_manager",
"games",
]
resolver = "3"

View File

@ -0,0 +1,72 @@
import Foundation
import Security
enum SecurityError: Error {
case generalError
}
func deleteCertificateFromKeyChain(_ certificateLabel: String) -> Bool {
let delQuery: [NSString: Any] = [
kSecClass: kSecClassCertificate,
kSecAttrLabel: certificateLabel,
]
let delStatus: OSStatus = SecItemDelete(delQuery as CFDictionary)
return delStatus == errSecSuccess
}
func saveCertificateToKeyChain(_ certificate: SecCertificate, certificateLabel: String) throws {
SecKeychainSetPreferenceDomain(SecPreferencesDomain.system)
deleteCertificateFromKeyChain(certificateLabel)
let setQuery: [NSString: AnyObject] = [
kSecClass: kSecClassCertificate,
kSecValueRef: certificate,
kSecAttrLabel: certificateLabel as AnyObject,
kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked,
]
let addStatus: OSStatus = SecItemAdd(setQuery as CFDictionary, nil)
guard addStatus == errSecSuccess else {
throw SecurityError.generalError
}
var status = SecTrustSettingsSetTrustSettings(certificate, SecTrustSettingsDomain.admin, nil)
}
func getCertificateFromString(stringData: String) throws -> SecCertificate {
if let data = NSData(base64Encoded: stringData, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) {
if let certificate = SecCertificateCreateWithData(kCFAllocatorDefault, data) {
return certificate
}
}
throw SecurityError.generalError
}
if CommandLine.arguments.count != 2 {
print("Usage: \(CommandLine.arguments[0]) [cert.file]")
print("Usage: \(CommandLine.arguments[0]) --version")
exit(1)
}
if (CommandLine.arguments[1] == "--version") {
let version = "dev"
print(version)
exit(0)
} else {
let fileURL = URL(fileURLWithPath: CommandLine.arguments[1])
do {
let certData = try Data(contentsOf: fileURL)
let certificate = SecCertificateCreateWithData(nil, certData as CFData)
if certificate != nil {
print("Saving certificate")
try? saveCertificateToKeyChain(certificate!, certificateLabel: "DropOSS")
exit(0)
} else {
print("ERROR: Unknown error while reading the \(CommandLine.arguments[1]) file.")
}
} catch {
print("ERROR: Unexpected error while reading the \(CommandLine.arguments[1]) file. \(error)")
}
}
exit(1)

View File

@ -1,7 +1,7 @@
{ {
"name": "view", "name": "view",
"private": true, "private": true,
"version": "0.3.3", "version": "0.3.4",
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "nuxt generate", "build": "nuxt generate",

View File

@ -116,7 +116,7 @@ platformInfo.value = currentPlatform;
async function openDataDir() { async function openDataDir() {
if (!dataDir.value) return; if (!dataDir.value) return;
try { try {
await open(dataDir.value); await invoke("open_fs", { path: dataDir.value });
} catch (error) { } catch (error) {
console.error("Failed to open data dir:", error); console.error("Failed to open data dir:", error);
} }
@ -126,7 +126,7 @@ async function openLogFile() {
if (!dataDir.value) return; if (!dataDir.value) return;
try { try {
const logPath = `${dataDir.value}/drop.log`; const logPath = `${dataDir.value}/drop.log`;
await open(logPath); await invoke("open_fs", { path: logPath });
} catch (error) { } catch (error) {
console.error("Failed to open log file:", error); console.error("Failed to open log file:", error);
} }

View File

@ -9,8 +9,8 @@
"dependencies": { "dependencies": {
"@tauri-apps/api": "^2.7.0", "@tauri-apps/api": "^2.7.0",
"@tauri-apps/plugin-deep-link": "^2.4.1", "@tauri-apps/plugin-deep-link": "^2.4.1",
"@tauri-apps/plugin-dialog": "^2.3.2", "@tauri-apps/plugin-dialog": "^2.4.0",
"@tauri-apps/plugin-opener": "^2.4.0", "@tauri-apps/plugin-opener": "^2.5.0",
"@tauri-apps/plugin-os": "^2.3.0", "@tauri-apps/plugin-os": "^2.3.0",
"@tauri-apps/plugin-shell": "^2.3.0", "@tauri-apps/plugin-shell": "^2.3.0",
"pino": "^9.7.0", "pino": "^9.7.0",

2258
src-tauri/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
[package] [package]
name = "drop-app" name = "drop-app"
version = "0.3.3" version = "0.3.4"
description = "The client application for the open-source, self-hosted game distribution platform Drop" description = "The client application for the open-source, self-hosted game distribution platform Drop"
authors = ["Drop OSS"] authors = ["Drop OSS"]
edition = "2024" edition = "2024"
@ -80,13 +80,13 @@ bytes = "1.10.1"
# Workspaces # Workspaces
client = { version = "0.1.0", path = "../client" } client = { version = "0.1.0", path = "./client" }
database = { path = "../database" } database = { path = "./database" }
process = { path = "../process" } process = { path = "./process" }
remote = { version = "0.1.0", path = "../remote" } remote = { version = "0.1.0", path = "./remote" }
utils = { path = "../utils" } utils = { path = "./utils" }
games = { version = "0.1.0", path = "../games" } games = { version = "0.1.0", path = "./games" }
download_manager = { version = "0.1.0", path = "../download_manager" } download_manager = { version = "0.1.0", path = "./download_manager" }
[dependencies.dynfmt] [dependencies.dynfmt]
version = "0.1.5" version = "0.1.5"
@ -137,3 +137,18 @@ features = ["derive", "rc"]
lto = true lto = true
codegen-units = 1 codegen-units = 1
panic = 'abort' panic = 'abort'
[workspace]
members = [
"client",
"database",
"process",
"remote",
"utils",
"cloud_saves",
"download_manager",
"games",
]
resolver = "3"

View File

@ -27,7 +27,7 @@ impl BackupManager<'_> {
current_platform: Platform::Windows, current_platform: Platform::Windows,
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
current_platform: Platform::MacOs, current_platform: Platform::macOS,
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
current_platform: Platform::Linux, current_platform: Platform::Linux,
@ -43,7 +43,7 @@ impl BackupManager<'_> {
&LinuxBackupManager {} as &(dyn BackupHandler + Sync + Send), &LinuxBackupManager {} as &(dyn BackupHandler + Sync + Send),
), ),
( (
(Platform::MacOs, Platform::MacOs), (Platform::macOS, Platform::macOS),
&MacBackupManager {} as &(dyn BackupHandler + Sync + Send), &MacBackupManager {} as &(dyn BackupHandler + Sync + Send),
), ),
]), ]),

View File

@ -4,20 +4,20 @@ use serde::{Deserialize, Serialize};
pub enum Platform { pub enum Platform {
Windows, Windows,
Linux, Linux,
MacOs, macOS,
} }
impl Platform { impl Platform {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub const HOST: Platform = Self::Windows; pub const HOST: Platform = Self::Windows;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub const HOST: Platform = Self::MacOs; pub const HOST: Platform = Self::macOS;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub const HOST: Platform = Self::Linux; pub const HOST: Platform = Self::Linux;
pub fn is_case_sensitive(&self) -> bool { pub fn is_case_sensitive(&self) -> bool {
match self { match self {
Self::Windows | Self::MacOs => false, Self::Windows | Self::macOS => false,
Self::Linux => true, Self::Linux => true,
} }
} }
@ -28,7 +28,7 @@ impl From<&str> for Platform {
match value.to_lowercase().trim() { match value.to_lowercase().trim() {
"windows" => Self::Windows, "windows" => Self::Windows,
"linux" => Self::Linux, "linux" => Self::Linux,
"mac" | "macos" => Self::MacOs, "mac" | "macos" => Self::macOS,
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
@ -39,7 +39,7 @@ impl From<whoami::Platform> for Platform {
match value { match value {
whoami::Platform::Windows => Platform::Windows, whoami::Platform::Windows => Platform::Windows,
whoami::Platform::Linux => Platform::Linux, whoami::Platform::Linux => Platform::Linux,
whoami::Platform::MacOS => Platform::MacOs, whoami::Platform::MacOS => Platform::macOS,
platform => unimplemented!("Playform {} is not supported", platform), platform => unimplemented!("Playform {} is not supported", platform),
} }
} }

View File

@ -39,7 +39,8 @@ impl DropWriter<File> {
.write(true) .write(true)
.create(true) .create(true)
.truncate(false) .truncate(false)
.open(&path)?; .open(&path)
.inspect_err(|_v| warn!("failed to open {}", path.display()))?;
Ok(Self { Ok(Self {
destination: BufWriter::with_capacity(1024 * 1024, destination), destination: BufWriter::with_capacity(1024 * 1024, destination),
hasher: Context::new(), hasher: Context::new(),
@ -122,7 +123,7 @@ impl<'a> DropDownloadPipeline<'a, Response, File> {
.source .source
.read(&mut copy_buffer[0..size]) .read(&mut copy_buffer[0..size])
.inspect_err(|_| { .inspect_err(|_| {
info!("got error from {}", drop.filename); warn!("got error from {}", drop.filename);
})?; })?;
remaining -= size; remaining -= size;
last_bump += size; last_bump += size;
@ -272,7 +273,12 @@ pub fn download_game_bucket(
#[cfg(unix)] #[cfg(unix)]
{ {
for drop in bucket.drops.iter() { for drop in bucket.drops.iter() {
let permissions = Permissions::from_mode(drop.permissions); let permission = if drop.permissions == 0 {
0o744
} else {
drop.permissions
};
let permissions = Permissions::from_mode(permission);
set_permissions(drop.path.clone(), permissions) set_permissions(drop.path.clone(), permissions)
.map_err(|e| ApplicationDownloadError::IoError(Arc::new(e)))?; .map_err(|e| ApplicationDownloadError::IoError(Arc::new(e)))?;
} }

View File

@ -54,7 +54,7 @@ impl ProcessManager<'_> {
current_platform: Platform::Windows, current_platform: Platform::Windows,
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
current_platform: Platform::MacOs, current_platform: Platform::macOS,
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
current_platform: Platform::Linux, current_platform: Platform::Linux,
@ -72,7 +72,7 @@ impl ProcessManager<'_> {
&NativeGameLauncher {} as &(dyn ProcessHandler + Sync + Send + 'static), &NativeGameLauncher {} as &(dyn ProcessHandler + Sync + Send + 'static),
), ),
( (
(Platform::MacOs, Platform::MacOs), (Platform::macOS, Platform::macOS),
&NativeGameLauncher {} as &(dyn ProcessHandler + Sync + Send + 'static), &NativeGameLauncher {} as &(dyn ProcessHandler + Sync + Send + 'static),
), ),
( (

View File

@ -5,6 +5,7 @@ use download_manager::DOWNLOAD_MANAGER;
use log::{debug, error}; use log::{debug, error};
use tauri::AppHandle; use tauri::AppHandle;
use tauri_plugin_autostart::ManagerExt; use tauri_plugin_autostart::ManagerExt;
use tauri_plugin_opener::OpenerExt;
use crate::AppState; use crate::AppState;
@ -72,3 +73,10 @@ pub fn get_autostart_enabled(app: AppHandle) -> Result<bool, tauri_plugin_autost
Ok(db_state) Ok(db_state)
} }
#[tauri::command]
pub fn open_fs(path: String, app_handle: AppHandle) -> Result<(), tauri_plugin_opener::Error> {
app_handle
.opener()
.open_path(path, None::<&str>)
}

View File

@ -229,6 +229,7 @@ pub fn run() {
fetch_state, fetch_state,
quit, quit,
fetch_system_data, fetch_system_data,
open_fs,
// User utils // User utils
update_settings, update_settings,
fetch_settings, fetch_settings,

View File

@ -1,7 +1,7 @@
{ {
"$schema": "https://schema.tauri.app/config/2.0.0", "$schema": "https://schema.tauri.app/config/2.0.0",
"productName": "Drop Desktop Client", "productName": "Drop Desktop Client",
"version": "0.3.3", "version": "0.3.4",
"identifier": "dev.drop.client", "identifier": "dev.drop.client",
"build": { "build": {
"beforeDevCommand": "yarn --cwd main dev --port 1432", "beforeDevCommand": "yarn --cwd main dev --port 1432",