mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
Merge branch 'V2' into V2-CBR-port
This commit is contained in:
commit
79ab223078
@ -8,4 +8,6 @@ public interface UserServiceInterface {
|
||||
long getTotalUsersCount();
|
||||
|
||||
boolean isCurrentUserAdmin();
|
||||
|
||||
boolean isCurrentUserFirstLogin();
|
||||
}
|
||||
|
||||
@ -28,6 +28,8 @@ public class InitialSetup {
|
||||
|
||||
private final ApplicationProperties applicationProperties;
|
||||
|
||||
private static boolean isNewServer = false;
|
||||
|
||||
@PostConstruct
|
||||
public void init() throws IOException {
|
||||
initUUIDKey();
|
||||
@ -88,6 +90,13 @@ public class InitialSetup {
|
||||
}
|
||||
|
||||
public void initSetAppVersion() throws IOException {
|
||||
// Check if this is a new server before setting the version
|
||||
String existingVersion = applicationProperties.getAutomaticallyGenerated().getAppVersion();
|
||||
isNewServer =
|
||||
existingVersion == null
|
||||
|| existingVersion.isEmpty()
|
||||
|| existingVersion.equals("0.0.0");
|
||||
|
||||
String appVersion = "0.0.0";
|
||||
Resource resource = new ClassPathResource("version.properties");
|
||||
Properties props = new Properties();
|
||||
@ -99,4 +108,8 @@ public class InitialSetup {
|
||||
GeneralUtils.saveKeyToSettings("AutomaticallyGenerated.appVersion", appVersion);
|
||||
applicationProperties.getAutomaticallyGenerated().setAppVersion(appVersion);
|
||||
}
|
||||
|
||||
public static boolean isNewServer() {
|
||||
return isNewServer;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
|
||||
import stirling.software.SPDF.config.EndpointConfiguration;
|
||||
import stirling.software.SPDF.config.InitialSetup;
|
||||
import stirling.software.common.annotations.api.ConfigApi;
|
||||
import stirling.software.common.configuration.AppConfig;
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
@ -78,6 +79,22 @@ public class ConfigController {
|
||||
}
|
||||
configData.put("isAdmin", isAdmin);
|
||||
|
||||
// Check if this is a new server (version was 0.0.0 before initialization)
|
||||
configData.put("isNewServer", InitialSetup.isNewServer());
|
||||
|
||||
// Check if the current user is a first-time user
|
||||
boolean isNewUser =
|
||||
false; // Default to false when security is disabled or user not found
|
||||
if (userService != null) {
|
||||
try {
|
||||
isNewUser = userService.isCurrentUserFirstLogin();
|
||||
} catch (Exception e) {
|
||||
// If there's an error, assume not new user for safety
|
||||
isNewUser = false;
|
||||
}
|
||||
}
|
||||
configData.put("isNewUser", isNewUser);
|
||||
|
||||
// System settings
|
||||
configData.put(
|
||||
"enableAlphaFunctionality",
|
||||
|
||||
@ -742,4 +742,31 @@ public class UserController {
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/complete-initial-setup")
|
||||
public ResponseEntity<?> completeInitialSetup() {
|
||||
try {
|
||||
String username = userService.getCurrentUsername();
|
||||
if (username == null) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
|
||||
.body("User not authenticated");
|
||||
}
|
||||
|
||||
Optional<User> userOpt = userService.findByUsernameIgnoreCase(username);
|
||||
if (userOpt.isEmpty()) {
|
||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found");
|
||||
}
|
||||
|
||||
User user = userOpt.get();
|
||||
user.setHasCompletedInitialSetup(true);
|
||||
userRepository.save(user);
|
||||
|
||||
log.info("User {} completed initial setup", username);
|
||||
return ResponseEntity.ok().body(Map.of("success", true));
|
||||
} catch (Exception e) {
|
||||
log.error("Error completing initial setup", e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body("Failed to complete initial setup");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +56,9 @@ public class User implements UserDetails, Serializable {
|
||||
@Column(name = "isFirstLogin")
|
||||
private Boolean isFirstLogin = false;
|
||||
|
||||
@Column(name = "hasCompletedInitialSetup")
|
||||
private Boolean hasCompletedInitialSetup = false;
|
||||
|
||||
@Column(name = "roleName")
|
||||
private String roleName;
|
||||
|
||||
@ -103,6 +106,14 @@ public class User implements UserDetails, Serializable {
|
||||
this.isFirstLogin = isFirstLogin;
|
||||
}
|
||||
|
||||
public boolean hasCompletedInitialSetup() {
|
||||
return hasCompletedInitialSetup != null && hasCompletedInitialSetup;
|
||||
}
|
||||
|
||||
public void setHasCompletedInitialSetup(boolean hasCompletedInitialSetup) {
|
||||
this.hasCompletedInitialSetup = hasCompletedInitialSetup;
|
||||
}
|
||||
|
||||
public void setAuthenticationType(AuthenticationType authenticationType) {
|
||||
this.authenticationType = authenticationType.toString().toLowerCase();
|
||||
}
|
||||
|
||||
@ -663,6 +663,21 @@ public class UserService implements UserServiceInterface {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isCurrentUserFirstLogin() {
|
||||
try {
|
||||
String username = getCurrentUsername();
|
||||
if (username != null) {
|
||||
Optional<User> userOpt = findByUsernameIgnoreCase(username);
|
||||
if (userOpt.isPresent()) {
|
||||
return !userOpt.get().hasCompletedInitialSetup();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug("Error checking first login status", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void syncCustomApiUser(String customApiKey) {
|
||||
if (customApiKey == null || customApiKey.trim().isBlank()) {
|
||||
|
||||
87
frontend/src-tauri/Cargo.lock
generated
87
frontend/src-tauri/Cargo.lock
generated
@ -155,12 +155,6 @@ dependencies = [
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
@ -420,36 +414,6 @@ dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
"core-foundation 0.9.4",
|
||||
"core-graphics 0.22.3",
|
||||
"foreign-types 0.3.2",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa-foundation"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"block",
|
||||
"core-foundation 0.9.4",
|
||||
"core-graphics-types 0.1.3",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.7"
|
||||
@ -502,19 +466,6 @@ version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation 0.9.4",
|
||||
"core-graphics-types 0.1.3",
|
||||
"foreign-types 0.3.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
version = "0.24.0"
|
||||
@ -523,22 +474,11 @@ checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"core-foundation 0.10.1",
|
||||
"core-graphics-types 0.2.0",
|
||||
"core-graphics-types",
|
||||
"foreign-types 0.5.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics-types"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation 0.9.4",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics-types"
|
||||
version = "0.2.0"
|
||||
@ -1992,15 +1932,6 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markup5ever"
|
||||
version = "0.14.1"
|
||||
@ -2200,15 +2131,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-sys"
|
||||
version = "0.3.5"
|
||||
@ -3689,7 +3611,7 @@ checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"cfg_aliases",
|
||||
"core-graphics 0.24.0",
|
||||
"core-graphics",
|
||||
"foreign-types 0.5.0",
|
||||
"js-sys",
|
||||
"log",
|
||||
@ -3739,10 +3661,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
name = "stirling-pdf"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cocoa",
|
||||
"log",
|
||||
"objc",
|
||||
"once_cell",
|
||||
"reqwest 0.11.27",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -3887,7 +3806,7 @@ dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"block2 0.6.2",
|
||||
"core-foundation 0.10.1",
|
||||
"core-graphics 0.24.0",
|
||||
"core-graphics",
|
||||
"crossbeam-channel",
|
||||
"dispatch",
|
||||
"dlopen2",
|
||||
|
||||
@ -10,6 +10,9 @@ rust-version = "1.77.2"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lints.rust]
|
||||
warnings = "deny"
|
||||
|
||||
[lib]
|
||||
name = "app_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
@ -27,9 +30,3 @@ tauri-plugin-shell = "2.1.0"
|
||||
tauri-plugin-fs = "2.4.4"
|
||||
tokio = { version = "1.0", features = ["time"] }
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
|
||||
# macOS-specific dependencies for native file opening
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
objc = "0.2"
|
||||
cocoa = "0.24"
|
||||
once_cell = "1.19"
|
||||
|
||||
@ -5,6 +5,7 @@ use std::sync::Mutex;
|
||||
static OPENED_FILE: Mutex<Option<String>> = Mutex::new(None);
|
||||
|
||||
// Set the opened file path (called by macOS file open events)
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn set_opened_file(file_path: String) {
|
||||
let mut opened_file = OPENED_FILE.lock().unwrap();
|
||||
*opened_file = Some(file_path.clone());
|
||||
|
||||
@ -4,4 +4,6 @@ pub mod files;
|
||||
|
||||
pub use backend::{start_backend, cleanup_backend};
|
||||
pub use health::check_backend_health;
|
||||
pub use files::{get_opened_file, clear_opened_file, set_opened_file};
|
||||
pub use files::{get_opened_file, clear_opened_file};
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use files::set_opened_file;
|
||||
|
||||
@ -1,189 +0,0 @@
|
||||
/// Multi-platform file opening handler
|
||||
///
|
||||
/// This module provides unified file opening support across platforms:
|
||||
/// - macOS: Uses native NSApplication delegate (proper Apple Events)
|
||||
/// - Windows/Linux: Uses command line arguments (fallback approach)
|
||||
/// - All platforms: Runtime event handling via Tauri events
|
||||
|
||||
use crate::utils::add_log;
|
||||
use crate::commands::set_opened_file;
|
||||
use tauri::AppHandle;
|
||||
|
||||
|
||||
/// Initialize file handling for the current platform
|
||||
pub fn initialize_file_handler(app: &AppHandle<tauri::Wry>) {
|
||||
add_log("🔧 Initializing file handler...".to_string());
|
||||
|
||||
// Platform-specific initialization
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
add_log("🍎 Using macOS native file handler".to_string());
|
||||
macos_native::register_open_file_handler(app);
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
add_log("🖥️ Using command line argument file handler".to_string());
|
||||
let _ = app; // Suppress unused variable warning
|
||||
}
|
||||
|
||||
// Universal: Check command line arguments (works on all platforms)
|
||||
check_command_line_args();
|
||||
}
|
||||
|
||||
/// Early initialization for macOS delegate registration
|
||||
pub fn early_init() {
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
add_log("🔄 Early macOS initialization...".to_string());
|
||||
macos_native::register_delegate_early();
|
||||
}
|
||||
}
|
||||
|
||||
/// Check command line arguments for file paths (universal fallback)
|
||||
fn check_command_line_args() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
add_log(format!("🔍 DEBUG: All command line args: {:?}", args));
|
||||
|
||||
// Check command line arguments for file opening
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
add_log(format!("🔍 DEBUG: Arg {}: {}", i, arg));
|
||||
if i > 0 && arg.ends_with(".pdf") && std::path::Path::new(arg).exists() {
|
||||
add_log(format!("📂 File argument detected: {}", arg));
|
||||
set_opened_file(arg.clone());
|
||||
break; // Only handle the first PDF file
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle runtime file open events (for future single-instance support)
|
||||
#[allow(dead_code)]
|
||||
pub fn handle_runtime_file_open(file_path: String) {
|
||||
if file_path.ends_with(".pdf") && std::path::Path::new(&file_path).exists() {
|
||||
add_log(format!("📂 Runtime file open: {}", file_path));
|
||||
set_opened_file(file_path);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
mod macos_native {
|
||||
use objc::{class, msg_send, sel, sel_impl};
|
||||
use objc::runtime::{Class, Object, Sel};
|
||||
use cocoa::appkit::NSApplication;
|
||||
use cocoa::base::{id, nil};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::sync::Mutex;
|
||||
use tauri::{AppHandle, Emitter};
|
||||
|
||||
use crate::utils::add_log;
|
||||
use crate::commands::set_opened_file;
|
||||
|
||||
// Static app handle storage
|
||||
static APP_HANDLE: Lazy<Mutex<Option<AppHandle<tauri::Wry>>>> = Lazy::new(|| Mutex::new(None));
|
||||
|
||||
// Store files opened during launch
|
||||
static LAUNCH_FILES: Lazy<Mutex<Vec<String>>> = Lazy::new(|| Mutex::new(Vec::new()));
|
||||
|
||||
|
||||
extern "C" fn open_files(_self: &Object, _cmd: Sel, _sender: id, filenames: id) {
|
||||
unsafe {
|
||||
add_log(format!("📂 macOS native openFiles event called"));
|
||||
|
||||
// filenames is an NSArray of NSString objects
|
||||
let count: usize = msg_send![filenames, count];
|
||||
add_log(format!("📂 Number of files to open: {}", count));
|
||||
|
||||
for i in 0..count {
|
||||
let filename: id = msg_send![filenames, objectAtIndex: i];
|
||||
let cstr = {
|
||||
let bytes: *const std::os::raw::c_char = msg_send![filename, UTF8String];
|
||||
std::ffi::CStr::from_ptr(bytes)
|
||||
};
|
||||
|
||||
if let Ok(path) = cstr.to_str() {
|
||||
add_log(format!("📂 macOS file open: {}", path));
|
||||
if path.ends_with(".pdf") {
|
||||
// Always set the opened file for command-line interface
|
||||
set_opened_file(path.to_string());
|
||||
|
||||
if let Some(app) = APP_HANDLE.lock().unwrap().as_ref() {
|
||||
// App is running, emit event immediately
|
||||
add_log(format!("✅ App running, emitting file event: {}", path));
|
||||
let _ = app.emit("macos://open-file", path.to_string());
|
||||
} else {
|
||||
// App not ready yet, store for later processing
|
||||
add_log(format!("🚀 App not ready, storing file for later: {}", path));
|
||||
LAUNCH_FILES.lock().unwrap().push(path.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register the delegate immediately when the module loads
|
||||
pub fn register_delegate_early() {
|
||||
add_log("🔧 Registering macOS delegate early...".to_string());
|
||||
|
||||
unsafe {
|
||||
let ns_app = NSApplication::sharedApplication(nil);
|
||||
|
||||
// Check if there's already a delegate
|
||||
let existing_delegate: id = msg_send![ns_app, delegate];
|
||||
if existing_delegate != nil {
|
||||
add_log("⚠️ Tauri already has an NSApplication delegate, trying to extend it...".to_string());
|
||||
|
||||
// Try to add our method to the existing delegate's class
|
||||
let delegate_class: id = msg_send![existing_delegate, class];
|
||||
let class_name: *const std::os::raw::c_char = msg_send![delegate_class, name];
|
||||
let class_name_str = std::ffi::CStr::from_ptr(class_name).to_string_lossy();
|
||||
add_log(format!("🔍 Existing delegate class: {}", class_name_str));
|
||||
|
||||
// This approach won't work with existing classes, so let's try a different method
|
||||
// We'll use method swizzling or create a new delegate that forwards to the old one
|
||||
add_log("🔄 Will try alternative approach...".to_string());
|
||||
}
|
||||
|
||||
let delegate_class = Class::get("StirlingAppDelegate").unwrap_or_else(|| {
|
||||
let superclass = class!(NSObject);
|
||||
let mut decl = objc::declare::ClassDecl::new("StirlingAppDelegate", superclass).unwrap();
|
||||
|
||||
// Add file opening delegate method (modern plural version)
|
||||
decl.add_method(
|
||||
sel!(application:openFiles:),
|
||||
open_files as extern "C" fn(&Object, Sel, id, id)
|
||||
);
|
||||
|
||||
decl.register()
|
||||
});
|
||||
|
||||
let delegate: id = msg_send![delegate_class, new];
|
||||
let _: () = msg_send![ns_app, setDelegate:delegate];
|
||||
}
|
||||
|
||||
add_log("✅ macOS delegate registered early".to_string());
|
||||
}
|
||||
|
||||
pub fn register_open_file_handler(app: &AppHandle<tauri::Wry>) {
|
||||
add_log("🔧 Connecting app handle to file handler...".to_string());
|
||||
|
||||
// Store the app handle
|
||||
*APP_HANDLE.lock().unwrap() = Some(app.clone());
|
||||
|
||||
// Process any files that were opened during launch
|
||||
let launch_files = {
|
||||
let mut files = LAUNCH_FILES.lock().unwrap();
|
||||
let result = files.clone();
|
||||
files.clear();
|
||||
result
|
||||
};
|
||||
|
||||
for file_path in launch_files {
|
||||
add_log(format!("📂 Processing stored launch file: {}", file_path));
|
||||
set_opened_file(file_path.clone());
|
||||
let _ = app.emit("macos://open-file", file_path);
|
||||
}
|
||||
|
||||
add_log("✅ macOS file handler connected successfully".to_string());
|
||||
}
|
||||
}
|
||||
@ -1,26 +1,22 @@
|
||||
use tauri::{RunEvent, WindowEvent, Emitter};
|
||||
use tauri::{RunEvent, WindowEvent};
|
||||
#[cfg(target_os = "macos")]
|
||||
use tauri::Emitter;
|
||||
|
||||
mod utils;
|
||||
mod commands;
|
||||
mod file_handler;
|
||||
|
||||
use commands::{start_backend, check_backend_health, get_opened_file, clear_opened_file, cleanup_backend, set_opened_file};
|
||||
use commands::{start_backend, check_backend_health, get_opened_file, clear_opened_file, cleanup_backend};
|
||||
#[cfg(target_os = "macos")]
|
||||
use commands::set_opened_file;
|
||||
use utils::{add_log, get_tauri_logs};
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
// Initialize file handler early for macOS
|
||||
file_handler::early_init();
|
||||
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.setup(|app| {
|
||||
.setup(|_app| {
|
||||
add_log("🚀 Tauri app setup started".to_string());
|
||||
|
||||
// Initialize platform-specific file handler
|
||||
file_handler::initialize_file_handler(&app.handle());
|
||||
|
||||
add_log("🔍 DEBUG: Setup completed".to_string());
|
||||
Ok(())
|
||||
})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user