Files
Rocketmc/theseus_gui/src-tauri/src/macos/delegate.rs
Wyatt Verchere 91d3bf825d Misc settings (#137)
* Initial bug fixes

* fix compile error on non-mac

* Fix even more bugs

* Fix more

* fix more

* fix build

* fix build

* Search fixes

* Fix small instance ui

* working basic

* fix javaw issue

* removed zip

* working functions

* merge fixes

* fixed loadintg bar bug

* menu fix

* wait for settings to sync

* safety expanded and for loading bars

* swtiching to windows

* minimize

* default landing page

* test link registry

* url redirection

* fix formatting

* .mrpack windows

* working mrpack reader

* changed to one layer deep

* working .mrpack + command handling for both opening and existing process

* forge version numbers

* working mac opening mrpack

* reverted changes

* prettier/fmt

* missed debug statement

* improvements + refactoring

* renamed things to fit plugin

* fixed bugs

* removed println

* overrides dont include mrpack

* merge

* fixes

* fixes

* fixed deletion

* merge errors

* force sync before export

* removed testing

* missed line

* removed console log

* mac error reverted

* incoreclty named helper

* additional fixes

* added removed merges

* fixed mislabled invokes

* mac

* added to new register method

* comments, cleanup

* mac clippy change

* review changes

* minor changes

* moved create pack

* removed playground compilation bug

* fixed linux bug; other add ons

* fixed review commets

* cicd fix

* mistaken import for prod

* cicd fix

---------

Co-authored-by: Jai A <jaiagr+gpg@pm.me>
2023-06-30 08:11:32 -07:00

99 lines
2.8 KiB
Rust

use cocoa::{
base::{id, nil},
foundation::NSAutoreleasePool,
};
use objc::{
class,
declare::ClassDecl,
msg_send,
runtime::{Class, Object, Sel},
sel, sel_impl,
};
use once_cell::sync::OnceCell;
use crate::api::TheseusSerializableError;
type Callback = OnceCell<Box<dyn Fn(String) + Send + Sync + 'static>>;
static CALLBACK: Callback = OnceCell::new();
pub struct AppDelegateClass(pub *const Class);
unsafe impl Send for AppDelegateClass {}
unsafe impl Sync for AppDelegateClass {}
// Obj C class for the app delegate
// This inherits from the TaoAppDelegate (used by tauri) so we do not accidentally override any functionality
// The application_open_file method is the only method we override, as it is currently unimplemented in tauri
lazy_static::lazy_static! {
pub static ref THESEUS_APP_DELEGATE_CLASS: AppDelegateClass = unsafe {
let superclass = class!(TaoAppDelegate);
let mut decl = ClassDecl::new("TheseusAppDelegate", superclass).unwrap();
// Add the method to the class
decl.add_method(
sel!(application:openFile:),
application_open_file as extern "C" fn(&Object, Sel, id, id) -> bool,
);
// Other methods are inherited
AppDelegateClass(decl.register())
};
}
extern "C" fn application_open_file(
_: &Object,
_: Sel,
_: id,
file: id,
) -> bool {
let file = nsstring_to_string(file);
callback(file)
}
pub fn callback(file: String) -> bool {
if let Some(callback) = CALLBACK.get() {
callback(file);
true
} else {
false
}
}
pub fn register_open_file<T>(
callback: T,
) -> Result<(), TheseusSerializableError>
where
T: Fn(String) + Send + Sync + 'static,
{
unsafe {
// Modified from tao: https://github.com/tauri-apps/tao
// sets the current app delegate to be the inherited app delegate rather than the default tauri/tao one
let app: id = msg_send![class!(TaoApp), sharedApplication];
let delegate: id = msg_send![THESEUS_APP_DELEGATE_CLASS.0, new];
let pool = NSAutoreleasePool::new(nil);
let _: () = msg_send![app, setDelegate: delegate];
let _: () = msg_send![pool, drain];
}
CALLBACK.set(Box::new(callback)).map_err(|_| {
TheseusSerializableError::Callback("Callback already set".to_string())
})
}
/// Convert an NSString to a Rust `String`
/// From 'fruitbasket' https://github.com/mrmekon/fruitbasket/
#[allow(clippy::cmp_null)]
pub fn nsstring_to_string(nsstring: *mut Object) -> String {
unsafe {
let cstr: *const i8 = msg_send![nsstring, UTF8String];
if cstr != std::ptr::null() {
std::ffi::CStr::from_ptr(cstr)
.to_string_lossy()
.into_owned()
} else {
"".into()
}
}
}