Fixed bug where external implementations of EditorState with no native front end caused objc2 version mismatch between arboard and trash crates to cause the editor to crash.

For external use cases with pure ICED winit, set default-features=false
This commit is contained in:
jess 2026-05-27 16:05:55 -07:00
parent e9c2b9ed80
commit 23b7b3784b
5 changed files with 20 additions and 16 deletions

View File

@ -29,9 +29,13 @@ filetime = "0.2"
regex = "1"
printpdf = { version = "0.9", default-features = false }
[features]
default = ["native-shell"]
native-shell = ["arboard", "trash"]
[target.'cfg(not(target_os = "ios"))'.dependencies]
arboard = "3"
trash = "5"
arboard = { version = "3", optional = true }
trash = { version = "5", optional = true }
[build-dependencies]
cbindgen = "0.29"

View File

@ -281,14 +281,14 @@ pub fn trash(item_path: &Path) -> std::io::Result<()> {
}
}
#[cfg(not(target_os = "ios"))]
#[cfg(all(not(target_os = "ios"), feature = "native-shell"))]
fn trash_crate_remove(path: &Path) -> Result<(), Box<dyn std::error::Error>> {
trash::delete(path).map_err(|e| Box::new(e) as Box<dyn std::error::Error>)
}
#[cfg(target_os = "ios")]
#[cfg(any(target_os = "ios", not(feature = "native-shell")))]
fn trash_crate_remove(_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
Err("trash crate not available on iOS; falling back to permanent delete".into())
Err("trash not available in embedded mode; falling back to permanent delete".into())
}
pub fn path_segments(current: &Path, root: &Path) -> Vec<(String, PathBuf)> {

View File

@ -14,7 +14,7 @@ mod types;
mod undo;
mod update;
pub use state::EditorState;
#[cfg(not(target_os = "ios"))]
#[cfg(all(not(target_os = "ios"), feature = "native-shell"))]
pub use sidecar_io::write_clipboard_image_to_cache;
pub use types::{
Anchor, ComputedImage, ComputedTable, ComputedTree, ContextMenuState, FindState,

View File

@ -303,7 +303,7 @@ pub(super) fn load_image_from_path(src: &str) -> Option<ImageCacheEntry> {
}
/// encodes a clipboard image to PNG and writes it into the on-disk cache
#[cfg(not(target_os = "ios"))]
#[cfg(all(not(target_os = "ios"), feature = "native-shell"))]
pub fn write_clipboard_image_to_cache(img: &arboard::ImageData) -> Option<String> {
let dir = dirs::home_dir()?.join(".acord").join("cache").join("images");
std::fs::create_dir_all(&dir).ok()?;

View File

@ -20,12 +20,12 @@ use crate::palette;
use crate::table_block::TableMessage;
use crate::ViewportHandle;
#[cfg(not(target_os = "ios"))]
#[cfg(all(not(target_os = "ios"), feature = "native-shell"))]
struct AcordClipboard {
board: std::cell::RefCell<arboard::Clipboard>,
}
#[cfg(not(target_os = "ios"))]
#[cfg(all(not(target_os = "ios"), feature = "native-shell"))]
impl clipboard::Clipboard for AcordClipboard {
fn read(&self, _kind: clipboard::Kind) -> Option<String> {
let mut board = self.board.borrow_mut();
@ -46,11 +46,11 @@ impl clipboard::Clipboard for AcordClipboard {
}
}
/// iOS stub; UIPasteboard access handled on the Swift side via shell-action bus.
#[cfg(target_os = "ios")]
/// stub clipboard for iOS and embedded consumers without native-shell.
#[cfg(any(target_os = "ios", not(feature = "native-shell")))]
struct AcordClipboard;
#[cfg(target_os = "ios")]
#[cfg(any(target_os = "ios", not(feature = "native-shell")))]
impl clipboard::Clipboard for AcordClipboard {
fn read(&self, _kind: clipboard::Kind) -> Option<String> { None }
fn write(&mut self, _kind: clipboard::Kind, _contents: String) {}
@ -224,11 +224,11 @@ pub fn render(handle: &mut ViewportHandle) {
&mut handle.renderer,
);
#[cfg(not(target_os = "ios"))]
#[cfg(all(not(target_os = "ios"), feature = "native-shell"))]
let mut clipboard = AcordClipboard {
board: std::cell::RefCell::new(arboard::Clipboard::new().unwrap()),
};
#[cfg(target_os = "ios")]
#[cfg(any(target_os = "ios", not(feature = "native-shell")))]
let mut clipboard = AcordClipboard;
let mut messages: Vec<Message> = Vec::new();
let mut consumed: Vec<usize> = Vec::new();
@ -673,13 +673,13 @@ pub fn render(handle: &mut ViewportHandle) {
handle.state.update(msg);
}
#[cfg(not(target_os = "ios"))]
#[cfg(all(not(target_os = "ios"), feature = "native-shell"))]
if let Some(text) = handle.state.pending_clipboard.take() {
if let Ok(mut board) = arboard::Clipboard::new() {
let _ = board.set_text(text);
}
}
#[cfg(target_os = "ios")]
#[cfg(any(target_os = "ios", not(feature = "native-shell")))]
let _ = handle.state.pending_clipboard.take();
handle.state.tick();