You've already forked AstralRinth
forked from didirus/AstralRinth
Monorepo missing features (#1273)
* fix tauri config * fix package patch * regen pnpm lock * use new workflow * New GH actions * Update lockfile * update scripts * Fix build script * Fix missing deps * Fix assets eslint * Update libraries lint * Fix all lint configs * update lockfile * add fmt + clippy fails * Separate App Tauri portion * fix app features * Fix lints * install tauri cli * update lockfile * corepack, fix lints * add store path * fix unused import * Fix tests * Issue templates + port over tauri release * fix actions * fix before build command * Add X86 target * Update build matrix * finalize actions * make debug build smaller * Use debug build to make cache smaller * dummy commit * change proj name * update file name * Use release builds for less space use * Remove rust cache * Readd for app build * add merge queue trigger
This commit is contained in:
98
apps/app/src/macos/delegate.rs
Normal file
98
apps/app/src/macos/delegate.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
2
apps/app/src/macos/mod.rs
Normal file
2
apps/app/src/macos/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod delegate;
|
||||
pub mod window_ext;
|
||||
70
apps/app/src/macos/window_ext.rs
Normal file
70
apps/app/src/macos/window_ext.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
/// from: https://github.com/tauri-apps/tauri/issues/4789, full credit to haasal
|
||||
#[cfg(target_os = "macos")]
|
||||
use tauri::{Runtime, Window};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub trait WindowExt {
|
||||
fn set_transparent_titlebar(&self, transparent: bool);
|
||||
fn position_traffic_lights(&self, x: f64, y: f64);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
impl<R: Runtime> WindowExt for Window<R> {
|
||||
fn set_transparent_titlebar(&self, transparent: bool) {
|
||||
use cocoa::appkit::{NSWindow, NSWindowTitleVisibility};
|
||||
let window = self.ns_window().unwrap() as cocoa::base::id;
|
||||
|
||||
unsafe {
|
||||
window.setTitleVisibility_(
|
||||
NSWindowTitleVisibility::NSWindowTitleHidden,
|
||||
);
|
||||
|
||||
if transparent {
|
||||
window.setTitlebarAppearsTransparent_(cocoa::base::YES);
|
||||
} else {
|
||||
window.setTitlebarAppearsTransparent_(cocoa::base::NO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn position_traffic_lights(&self, x: f64, y: f64) {
|
||||
use cocoa::appkit::{NSView, NSWindow, NSWindowButton};
|
||||
use cocoa::foundation::NSRect;
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
|
||||
let window = self.ns_window().unwrap() as cocoa::base::id;
|
||||
|
||||
unsafe {
|
||||
let close = window
|
||||
.standardWindowButton_(NSWindowButton::NSWindowCloseButton);
|
||||
let miniaturize = window.standardWindowButton_(
|
||||
NSWindowButton::NSWindowMiniaturizeButton,
|
||||
);
|
||||
let zoom = window
|
||||
.standardWindowButton_(NSWindowButton::NSWindowZoomButton);
|
||||
|
||||
let title_bar_container_view = close.superview().superview();
|
||||
|
||||
let close_rect: NSRect = msg_send![close, frame];
|
||||
let button_height = close_rect.size.height;
|
||||
|
||||
let title_bar_frame_height = button_height + y;
|
||||
let mut title_bar_rect = NSView::frame(title_bar_container_view);
|
||||
title_bar_rect.size.height = title_bar_frame_height;
|
||||
title_bar_rect.origin.y =
|
||||
NSView::frame(window).size.height - title_bar_frame_height;
|
||||
let _: () =
|
||||
msg_send![title_bar_container_view, setFrame: title_bar_rect];
|
||||
|
||||
let window_buttons = vec![close, miniaturize, zoom];
|
||||
let space_between = NSView::frame(miniaturize).origin.x
|
||||
- NSView::frame(close).origin.x;
|
||||
|
||||
for (i, button) in window_buttons.into_iter().enumerate() {
|
||||
let mut rect: NSRect = NSView::frame(button);
|
||||
rect.origin.x = x + (i as f64 * space_between);
|
||||
button.setFrameOrigin(rect.origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user