mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-29 04:46:50 -06:00
M8: Copy link to selection in the layer context menu
Edit > Copy as > Copy link to selection (edit.copyLink) was only in the main menu. Add it to the right-click menu on a layer, after Copy as PNG, labelled with the command's own translated label. The command now says "Link copied" when it copies, and copies nothing when no layer is selected (it used to put figcraft://node/0 on the clipboard).
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
//! The right-click menu on a layer: "Copy link to selection" puts `figcraft://node/<id>` on the
|
||||
//! clipboard and says so; with nothing selected the command copies nothing.
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use egui::Pos2;
|
||||
use figcraft_engine::Session;
|
||||
use serde_json::json;
|
||||
|
||||
use crate::layers_drag_tests::Ui;
|
||||
use crate::live_tests::{flat, text_center};
|
||||
use crate::present_tests::id;
|
||||
|
||||
/// A clipboard that keeps what was copied where the test can read it.
|
||||
struct Copied(Arc<Mutex<Vec<String>>>);
|
||||
|
||||
impl crate::Services for Copied {
|
||||
fn clipboard_set_text(&mut self, s: &str) {
|
||||
if let Ok(mut copied) = self.0.lock() {
|
||||
copied.push(s.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_context_menu_copies_a_link_to_the_selected_frame() {
|
||||
let mut s = Session::new();
|
||||
let f = id(&s.execute("frame.create", &json!({"x": 0, "y": 0, "width": 300, "height": 200, "name": "หน้าแรก"})).unwrap());
|
||||
let copied = Arc::new(Mutex::new(Vec::new()));
|
||||
let mut u = Ui::new(s);
|
||||
u.app.services = Box::new(Copied(copied.clone()));
|
||||
u.frame(vec![]);
|
||||
u.app.ui.context_menu = Some((Pos2::new(700.0, 300.0), vec![f]));
|
||||
u.frame(vec![]);
|
||||
let shapes = flat(&u.frame_output(vec![]).shapes);
|
||||
let at = text_center(&shapes, "Copy link to selection");
|
||||
u.button(at, true);
|
||||
u.button(at, false);
|
||||
assert_eq!(*copied.lock().unwrap(), vec![format!("figcraft://node/{}", f.0)], "the link to the frame");
|
||||
assert_eq!(u.app.ui.toast.as_ref().map(|t| t.0.as_str()), Some("Link copied"));
|
||||
assert!(u.app.ui.context_menu.is_none(), "the menu closes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn copying_a_link_with_nothing_selected_copies_nothing() {
|
||||
let mut s = Session::new();
|
||||
s.execute("frame.create", &json!({"x": 0, "y": 0, "width": 300, "height": 200})).unwrap();
|
||||
s.execute("select.none", &json!({})).unwrap();
|
||||
let copied = Arc::new(Mutex::new(Vec::new()));
|
||||
let mut u = Ui::new(s);
|
||||
u.app.services = Box::new(Copied(copied.clone()));
|
||||
crate::menus::invoke(&mut u.app, "edit.copyLink");
|
||||
assert!(copied.lock().unwrap().is_empty(), "no link to node 0");
|
||||
assert!(u.app.ui.toast.is_none());
|
||||
}
|
||||
@@ -98,6 +98,8 @@ mod comments_tests;
|
||||
#[cfg(test)]
|
||||
mod component_props_reorder_tests;
|
||||
#[cfg(test)]
|
||||
mod context_menu_tests;
|
||||
#[cfg(test)]
|
||||
mod corner_individual_tests;
|
||||
#[cfg(test)]
|
||||
mod cursors_tests;
|
||||
|
||||
@@ -219,8 +219,10 @@ pub fn invoke(app: &mut FigApp, id: &str) {
|
||||
app.toast(tr("Copied as text"));
|
||||
}
|
||||
"edit.copyLink" => {
|
||||
let ids = app.session.selection();
|
||||
app.services.clipboard_set_text(&format!("figcraft://node/{}", ids.first().map(|i| i.0).unwrap_or(0)));
|
||||
if let Some(id) = app.session.selection().first() {
|
||||
app.services.clipboard_set_text(&format!("figcraft://node/{}", id.0));
|
||||
app.toast(tr("Link copied"));
|
||||
}
|
||||
}
|
||||
"edit.findReplace" => app.ui.find = Some((String::new(), String::new())),
|
||||
// The Actions palette invokes commands without parameters. These values are edited in
|
||||
@@ -895,6 +897,7 @@ pub fn popups(app: &mut FigApp, ctx: &egui::Context) {
|
||||
.ok()
|
||||
.filter(|doc| figcraft_engine::cmd::component::can_combine_variants(doc, &app.session.selection()))
|
||||
.map(|_| i18n::command("component.combineVariants", "Combine as variants"));
|
||||
let copy_link = i18n::command("edit.copyLink", "Copy link to selection");
|
||||
let mut entries: Vec<(&str, &str)> = if has_sel {
|
||||
vec![
|
||||
(tr("Copy"), "edit.copy"),
|
||||
@@ -957,6 +960,9 @@ pub fn popups(app: &mut FigApp, ctx: &egui::Context) {
|
||||
{
|
||||
entries.insert(at + 1, (label, "component.combineVariants"));
|
||||
}
|
||||
if let Some(at) = entries.iter().position(|e| e.1 == "edit.copyAsPng") {
|
||||
entries.insert(at + 1, (©_link, "edit.copyLink"));
|
||||
}
|
||||
// A right-clicked ruler guide (selected, with no layers) can be removed.
|
||||
if !has_sel && app.session.ds().is_ok_and(|d| d.selected_guide().is_some()) {
|
||||
entries.splice(0..0, [(tr("Remove guide"), "guide.remove"), ("-", "")]);
|
||||
|
||||
Reference in New Issue
Block a user