Keyboard Shortcuts: Accept and Go to Conflict / Undo Changes, and reserved keys (K4a)

A key that another command holds now offers Photoshop's two answers under the warning.
Accept and Go to Conflict takes the key from the other command at once (its main key or
an alternate) and selects it for a new one. Undo Changes puts the edited command's main and
further keys back as they were. OK without either still accepts, as in Photoshop.

Keys the system takes before the app sees them are refused with a message: Alt+Tab,
Alt+F4, Ctrl+Alt+Delete, Ctrl+Esc and Ctrl+Shift+Esc off the Mac; Cmd+Tab, Cmd+` and
Cmd+Opt+Esc on it.
This commit is contained in:
Tanish Manku committed 2026-10-13 17:02:11 -07:00
1 parent 484499aa4e
commit d055725952
22 files changed
+278 -1

No files matched your search

+7
View File
@@ -3760,3 +3760,10 @@ navigator Zoom Zvětšení
There are too many sets: delete one first. Sad je příliš mnoho: nejprve jednu smažte.
set name název sady
{set} (modified) {set} (změněno)
Accept and Go to Conflict Přijmout a přejít ke konfliktu
Changes undone. Změny vráceny.
Choose a new shortcut for this command, or leave it without one. Zvolte pro tento příkaz novou zkratku, nebo ho nechte bez ní.
Put this command's shortcuts back as they were Vrátit zkratky tohoto příkazu do původního stavu
Take the shortcut from the other command and select it Odebrat zkratku druhému příkazu a vybrat ho
Undo Changes Vrátit změny
{shortcut} is reserved by the system and can't be assigned. {shortcut} je vyhrazena systémem a nelze ji přiřadit.
Can't render this file because it contains an unexpected character in line 6 and column 47.
+7
View File
@@ -3150,3 +3150,10 @@ curves Smooth Glätten
There are too many sets: delete one first. Zu viele Sätze: Löschen Sie zuerst einen.
set name Name des Satzes
{set} (modified) {set} (geändert)
Accept and Go to Conflict Übernehmen und zum Konflikt
Changes undone. Änderungen rückgängig gemacht.
Choose a new shortcut for this command, or leave it without one. Wählen Sie einen neuen Kurzbefehl für diesen Befehl oder lassen Sie ihn ohne.
Put this command's shortcuts back as they were Die Kurzbefehle dieses Befehls wiederherstellen
Take the shortcut from the other command and select it Den Kurzbefehl dem anderen Befehl entziehen und diesen auswählen
Undo Changes Änderungen rückgängig machen
{shortcut} is reserved by the system and can't be assigned. {shortcut} ist vom System reserviert und kann nicht zugewiesen werden.
Can't render this file because it contains an unexpected character in line 6 and column 47.
+7
View File
@@ -3850,3 +3850,10 @@ curves Smooth Εξομάλυνση
There are too many sets: delete one first. Υπάρχουν πάρα πολλά σύνολα: διαγράψτε πρώτα ένα.
set name όνομα συνόλου
{set} (modified) {set} (τροποποιημένο)
Accept and Go to Conflict Αποδοχή και μετάβαση στη σύγκρουση
Changes undone. Οι αλλαγές αναιρέθηκαν.
Choose a new shortcut for this command, or leave it without one. Επιλέξτε νέα συντόμευση για αυτήν την εντολή ή αφήστε την χωρίς.
Put this command's shortcuts back as they were Επαναφορά των συντομεύσεων αυτής της εντολής όπως ήταν
Take the shortcut from the other command and select it Αφαίρεση της συντόμευσης από την άλλη εντολή και επιλογή της
Undo Changes Αναίρεση αλλαγών
{shortcut} is reserved by the system and can't be assigned. Η συντόμευση {shortcut} δεσμεύεται από το σύστημα και δεν μπορεί να εκχωρηθεί.
Can't render this file because it contains an unexpected character in line 1030 and column 18.
+7
View File
@@ -2837,3 +2837,10 @@ curves Smooth Suavizar
There are too many sets: delete one first. Hay demasiados conjuntos: elimine uno primero.
set name nombre del conjunto
{set} (modified) {set} (modificado)
Accept and Go to Conflict Aceptar e ir al conflicto
Changes undone. Cambios deshechos.
Choose a new shortcut for this command, or leave it without one. Elija un nuevo método abreviado para este comando o déjelo sin ninguno.
Put this command's shortcuts back as they were Restaurar los métodos abreviados de este comando como estaban
Take the shortcut from the other command and select it Quitar el método abreviado al otro comando y seleccionarlo
Undo Changes Deshacer cambios
{shortcut} is reserved by the system and can't be assigned. {shortcut} está reservado por el sistema y no se puede asignar.
Can't render this file because it contains an unexpected character in line 4 and column 47.
+7
View File
@@ -3154,3 +3154,10 @@ curves Smooth Lisser
There are too many sets: delete one first. Il y a trop de jeux : supprimez-en un d’abord.
set name nom du jeu
{set} (modified) {set} (modifié)
Accept and Go to Conflict Accepter et aller au conflit
Changes undone. Modifications annulées.
Choose a new shortcut for this command, or leave it without one. Choisissez un nouveau raccourci pour cette commande ou laissez-la sans raccourci.
Put this command's shortcuts back as they were Rétablir les raccourcis de cette commande
Take the shortcut from the other command and select it Retirer le raccourci de l’autre commande et la sélectionner
Undo Changes Annuler les modifications
{shortcut} is reserved by the system and can't be assigned. {shortcut} est réservé par le système et ne peut pas être attribué.
Can't render this file because it contains an unexpected character in line 6 and column 47.
+7
View File
@@ -4073,3 +4073,10 @@ cameraRaw Yellow Sárga
There are too many sets: delete one first. Túl sok készlet van: előbb töröljön egyet.
set name készlet neve
{set} (modified) {set} (módosítva)
Accept and Go to Conflict Elfogadás és ugrás az ütközéshez
Changes undone. Változások visszavonva.
Choose a new shortcut for this command, or leave it without one. Válasszon új billentyűparancsot ehhez a parancshoz, vagy hagyja nélküle.
Put this command's shortcuts back as they were A parancs billentyűparancsainak visszaállítása
Take the shortcut from the other command and select it A billentyűparancs elvétele a másik parancstól, és annak kijelölése
Undo Changes Változások visszavonása
{shortcut} is reserved by the system and can't be assigned. A(z) {shortcut} a rendszer számára fenntartott, nem rendelhető hozzá.
Can't render this file because it contains an unexpected character in line 6 and column 47.
+7
View File
@@ -3141,3 +3141,10 @@ curves Smooth Haluskan
There are too many sets: delete one first. Terlalu banyak set: hapus satu terlebih dahulu.
set name nama set
{set} (modified) {set} (diubah)
Accept and Go to Conflict Terima dan Buka Konflik
Changes undone. Perubahan dibatalkan.
Choose a new shortcut for this command, or leave it without one. Pilih pintasan baru untuk perintah ini, atau biarkan tanpa pintasan.
Put this command's shortcuts back as they were Kembalikan pintasan perintah ini seperti semula
Take the shortcut from the other command and select it Ambil pintasan dari perintah lain dan pilih perintah itu
Undo Changes Batalkan Perubahan
{shortcut} is reserved by the system and can't be assigned. {shortcut} dicadangkan oleh sistem dan tidak dapat ditetapkan.
Can't render this file because it contains an unexpected character in line 4 and column 47.
+7
View File
@@ -4115,3 +4115,10 @@ navigator Zoom Zoom
There are too many sets: delete one first. Ci sono troppi set: eliminane prima uno.
set name nome del set
{set} (modified) {set} (modificato)
Accept and Go to Conflict Accetta e vai al conflitto
Changes undone. Modifiche annullate.
Choose a new shortcut for this command, or leave it without one. Scegli una nuova scorciatoia per questo comando o lascialo senza.
Put this command's shortcuts back as they were Ripristina le scorciatoie di questo comando com'erano
Take the shortcut from the other command and select it Togli la scorciatoia all'altro comando e selezionalo
Undo Changes Annulla modifiche
{shortcut} is reserved by the system and can't be assigned. {shortcut} è riservata dal sistema e non può essere assegnata.
Can't render this file because it contains an unexpected character in line 2648 and column 53.
+7
View File
@@ -3830,3 +3830,10 @@ curves Smooth スムーズ
There are too many sets: delete one first. セットが多すぎます。先に 1 つ削除してください。
set name セット名
{set} (modified) {set}(変更あり)
Accept and Go to Conflict 適用して競合へ移動
Changes undone. 変更を取り消しました。
Choose a new shortcut for this command, or leave it without one. このコマンドに新しいショートカットを選択するか、なしのままにしてください。
Put this command's shortcuts back as they were このコマンドのショートカットを元に戻す
Take the shortcut from the other command and select it もう一方のコマンドからショートカットを外して選択
Undo Changes 変更を取り消し
{shortcut} is reserved by the system and can't be assigned. {shortcut} はシステムで予約されているため割り当てられません。
Can't render this file because it contains an unexpected character in line 6 and column 47.
+7
View File
@@ -3327,3 +3327,10 @@ curves Smooth 매끄럽게
There are too many sets: delete one first. 세트가 너무 많습니다. 먼저 하나를 삭제하세요.
set name 세트 이름
{set} (modified) {set}(수정됨)
Accept and Go to Conflict 적용 후 충돌 항목으로 이동
Changes undone. 변경 사항을 취소했습니다.
Choose a new shortcut for this command, or leave it without one. 이 명령의 새 단축키를 선택하거나 단축키 없이 두세요.
Put this command's shortcuts back as they were 이 명령의 단축키를 원래대로 되돌리기
Take the shortcut from the other command and select it 다른 명령에서 단축키를 빼고 그 명령 선택
Undo Changes 변경 사항 취소
{shortcut} is reserved by the system and can't be assigned. {shortcut}은(는) 시스템에서 예약되어 할당할 수 없습니다.
Can't render this file because it contains an unexpected character in line 3161 and column 53.
+7
View File
@@ -3912,3 +3912,10 @@ curves Smooth Vloeiend maken
There are too many sets: delete one first. Er zijn te veel sets: verwijder er eerst een.
set name naam van de set
{set} (modified) {set} (gewijzigd)
Accept and Go to Conflict Accepteren en naar conflict
Changes undone. Wijzigingen ongedaan gemaakt.
Choose a new shortcut for this command, or leave it without one. Kies een nieuwe sneltoets voor deze opdracht of laat hem zonder.
Put this command's shortcuts back as they were De sneltoetsen van deze opdracht herstellen
Take the shortcut from the other command and select it De sneltoets van de andere opdracht afnemen en die selecteren
Undo Changes Wijzigingen ongedaan maken
{shortcut} is reserved by the system and can't be assigned. {shortcut} is door het systeem gereserveerd en kan niet worden toegewezen.
Can't render this file because it contains an unexpected character in line 8 and column 34.
+7
View File
@@ -3750,3 +3750,10 @@ curves Smooth Wygładź
There are too many sets: delete one first. Zestawów jest za dużo: najpierw usuń jeden.
set name nazwa zestawu
{set} (modified) {set} (zmieniony)
Accept and Go to Conflict Akceptuj i przejdź do konfliktu
Changes undone. Zmiany cofnięte.
Choose a new shortcut for this command, or leave it without one. Wybierz nowy skrót dla tego polecenia lub zostaw je bez skrótu.
Put this command's shortcuts back as they were Przywróć skróty tego polecenia
Take the shortcut from the other command and select it Odbierz skrót drugiemu poleceniu i zaznacz je
Undo Changes Cofnij zmiany
{shortcut} is reserved by the system and can't be assigned. {shortcut} jest zarezerwowany przez system i nie można go przypisać.
Can't render this file because it contains an unexpected character in line 6 and column 47.
+7
View File
@@ -3942,3 +3942,10 @@ layerLabel No Color Sem cor
There are too many sets: delete one first. Há conjuntos demais: exclua um primeiro.
set name nome do conjunto
{set} (modified) {set} (modificado)
Accept and Go to Conflict Aceitar e ir para o conflito
Changes undone. Alterações desfeitas.
Choose a new shortcut for this command, or leave it without one. Escolha um novo atalho para este comando ou deixe-o sem atalho.
Put this command's shortcuts back as they were Restaurar os atalhos deste comando como estavam
Take the shortcut from the other command and select it Tirar o atalho do outro comando e selecioná-lo
Undo Changes Desfazer alterações
{shortcut} is reserved by the system and can't be assigned. {shortcut} é reservado pelo sistema e não pode ser atribuído.
Can't render this file because it contains an unexpected character in line 6 and column 47.
+7
View File
@@ -3118,3 +3118,10 @@ curves Smooth Сгладить
There are too many sets: delete one first. Слишком много наборов: сначала удалите один.
set name имя набора
{set} (modified) {set} (изменён)
Accept and Go to Conflict Принять и перейти к конфликту
Changes undone. Изменения отменены.
Choose a new shortcut for this command, or leave it without one. Выберите новую комбинацию для этой команды или оставьте её без комбинации.
Put this command's shortcuts back as they were Вернуть комбинации этой команды
Take the shortcut from the other command and select it Снять комбинацию с другой команды и выбрать её
Undo Changes Отменить изменения
{shortcut} is reserved by the system and can't be assigned. Комбинация {shortcut} зарезервирована системой и не может быть назначена.
Can't render this file because it contains an unexpected character in line 6 and column 47.
+7
View File
@@ -4226,3 +4226,10 @@ shape Appearance Izgled
There are too many sets: delete one first. Previše skupova: prvo obrišite jedan.
set name ime skupa
{set} (modified) {set} (izmenjen)
Accept and Go to Conflict Prihvati i idi na sukob
Changes undone. Izmene su poništene.
Choose a new shortcut for this command, or leave it without one. Izaberite novu prečicu za ovu komandu ili je ostavite bez prečice.
Put this command's shortcuts back as they were Vrati prečice ove komande kakve su bile
Take the shortcut from the other command and select it Uzmi prečicu drugoj komandi i izaberi je
Undo Changes Poništi izmene
{shortcut} is reserved by the system and can't be assigned. {shortcut} je rezervisana od strane sistema i ne može se dodeliti.
Can't render this file because it contains an unexpected character in line 6 and column 47.
+7
View File
@@ -3884,3 +3884,10 @@ cameraData Lens Lens
There are too many sets: delete one first. Çok fazla küme var: önce birini silin.
set name küme adı
{set} (modified) {set} (değiştirildi)
Accept and Go to Conflict Kabul Et ve Çakışmaya Git
Changes undone. Değişiklikler geri alındı.
Choose a new shortcut for this command, or leave it without one. Bu komut için yeni bir kısayol seçin veya kısayolsuz bırakın.
Put this command's shortcuts back as they were Bu komutun kısayollarını eski haline getir
Take the shortcut from the other command and select it Kısayolu diğer komuttan al ve o komutu seç
Undo Changes Değişiklikleri Geri Al
{shortcut} is reserved by the system and can't be assigned. {shortcut} sistem tarafından ayrılmıştır ve atanamaz.
Can't render this file because it contains an unexpected character in line 8 and column 34.
+7
View File
@@ -3851,3 +3851,10 @@ curves Smooth Згладити
There are too many sets: delete one first. Забагато наборів: спершу видаліть один.
set name назва набору
{set} (modified) {set} (змінено)
Accept and Go to Conflict Прийняти й перейти до конфлікту
Changes undone. Зміни скасовано.
Choose a new shortcut for this command, or leave it without one. Виберіть нове клавіатурне скорочення для цієї команди або залиште її без нього.
Put this command's shortcuts back as they were Повернути клавіатурні скорочення цієї команди
Take the shortcut from the other command and select it Забрати скорочення в іншої команди й вибрати її
Undo Changes Скасувати зміни
{shortcut} is reserved by the system and can't be assigned. {shortcut} зарезервовано системою, його не можна призначити.
Can't render this file because it contains an unexpected character in line 1387 and column 18.
+7
View File
@@ -3639,3 +3639,10 @@ curves Smooth Làm mượt
There are too many sets: delete one first. Có quá nhiều bộ: hãy xóa một bộ trước.
set name tên bộ
{set} (modified) {set} (đã sửa đổi)
Accept and Go to Conflict Chấp nhận và đến xung đột
Changes undone. Đã hoàn tác thay đổi.
Choose a new shortcut for this command, or leave it without one. Chọn phím tắt mới cho lệnh này, hoặc để lệnh không có phím tắt.
Put this command's shortcuts back as they were Khôi phục phím tắt của lệnh này như cũ
Take the shortcut from the other command and select it Lấy phím tắt khỏi lệnh kia và chọn lệnh đó
Undo Changes Hoàn tác thay đổi
{shortcut} is reserved by the system and can't be assigned. {shortcut} được hệ thống dành riêng và không thể gán.
Can't render this file because it contains an unexpected character in line 6 and column 47.
+7
View File
@@ -2762,3 +2762,10 @@ curves Smooth 平滑
There are too many sets: delete one first. 组太多:请先删除一个。
set name 组名称
{set} (modified) {set}(已修改)
Accept and Go to Conflict 接受并转到冲突
Changes undone. 已撤消更改。
Choose a new shortcut for this command, or leave it without one. 为此命令选择新的快捷键,或保留为无快捷键。
Put this command's shortcuts back as they were 将此命令的快捷键恢复原样
Take the shortcut from the other command and select it 从另一个命令移除该快捷键并选中它
Undo Changes 撤消更改
{shortcut} is reserved by the system and can't be assigned. {shortcut} 由系统保留,无法指定。
Can't render this file because it contains an unexpected character in line 2594 and column 53.
+7
View File
@@ -2747,3 +2747,10 @@ curves Smooth 平滑
There are too many sets: delete one first. 組合太多:請先刪除一個。
set name 組合名稱
{set} (modified) {set}(已修改)
Accept and Go to Conflict 接受並前往衝突
Changes undone. 已還原變更。
Choose a new shortcut for this command, or leave it without one. 為此指令選擇新的快速鍵,或保持沒有快速鍵。
Put this command's shortcuts back as they were 將此指令的快速鍵恢復原狀
Take the shortcut from the other command and select it 從另一個指令移除該快速鍵並選取它
Undo Changes 還原變更
{shortcut} is reserved by the system and can't be assigned. {shortcut} 由系統保留,無法指定。
Can't render this file because it contains an unexpected character in line 6 and column 47.
+77 -1
View File
@@ -784,6 +784,19 @@ pub fn shortcut_items(app: &PhotocraftApp) -> Vec<(String, String, Vec<String>,
}
/// Text of a key press for the shortcut editor (`Cmd+Shift+K`), `None` for bare modifiers.
/// Keys the system takes before the app sees them (switching apps, closing the window, force
/// quit): Edit › Keyboard Shortcuts won't assign them, as Photoshop won't. `sc` is in our
/// notation, where `Cmd` is Ctrl off the Mac.
pub fn reserved_shortcut(sc: &str) -> bool {
let Some(n) = prefs::normalize_shortcut(sc) else { return false };
let reserved: &[&str] = if cfg!(target_os = "macos") {
&["Cmd+Tab", "Cmd+Shift+Tab", "Cmd+Alt+Escape", "Cmd+`"]
} else {
&["Alt+Tab", "Alt+Shift+Tab", "Alt+F4", "Cmd+Alt+Delete", "Cmd+Escape", "Cmd+Shift+Escape"]
};
reserved.iter().filter_map(|r| prefs::normalize_shortcut(r)).any(|r| r == n)
}
pub fn shortcut_text(key: egui::Key, m: egui::Modifiers) -> Option<String> {
if is_modifier_key(key) {
return None;
@@ -1647,6 +1660,9 @@ fn shortcuts_body(app: &mut PhotocraftApp, ui: &mut egui::Ui, f: &mut Map<String
let alternates_ok = parsed_alts.as_ref().is_none_or(Result::is_ok);
let mut alt_overrides = parsed_alts.and_then(Result::ok).unwrap_or_default();
let mut capture_alt = f.get("captureAlt").and_then(Value::as_bool).unwrap_or(false);
// A key just assigned that another command holds: Photoshop's Accept and Go to Conflict /
// Undo Changes (an object: the key, the other command, and this one's keys before).
let mut conflict: Option<Value> = f.get("conflict").filter(|c| c.is_object()).cloned();
let mut hidden: Vec<String> = f.get("hidden").and_then(|v| serde_json::from_value(v.clone()).ok()).unwrap_or_default();
let mut colors: BTreeMap<String, String> = f.get("colors").and_then(|v| serde_json::from_value(v.clone()).ok()).unwrap_or_default();
let mut selected = f.get("selected").and_then(Value::as_str).unwrap_or("").to_string();
@@ -1708,8 +1724,12 @@ fn shortcuts_body(app: &mut PhotocraftApp, ui: &mut egui::Ui, f: &mut Map<String
capture = false;
message = tl!("Shortcut removed.").into();
message_warning = false;
} else if let Some(sc) = shortcut_text(key, m).filter(|sc| reserved_shortcut(sc)) {
message = crate::i18n::fmt(tl!("{shortcut} is reserved by the system and can't be assigned."), &[("shortcut", &crate::shortcuts::pretty(&sc))]);
message_warning = true;
capture = false;
} else if let Some(sc) = shortcut_text(key, m) {
let clash: Vec<String> = items
let clash_ids: Vec<&str> = items
.iter()
.filter(|(id, _, _, def)| {
let cur = eff(&overrides, id, def);
@@ -1717,11 +1737,28 @@ fn shortcuts_body(app: &mut PhotocraftApp, ui: &mut egui::Ui, f: &mut Map<String
&& (cur.as_deref().and_then(prefs::normalize_shortcut) == Some(sc.clone())
|| eff_alts(&alt_overrides, id, cur.as_deref()).contains(&sc))
})
.map(|(id, ..)| id.as_str())
.collect();
let clash: Vec<String> = items
.iter()
.filter(|(id, ..)| clash_ids.contains(&id.as_str()))
.map(|(id, label, path, _)| {
let (path, label) = shown(id, label, path);
format!("{} › {}", path.join(" › "), label.trim_end_matches('…'))
})
.collect();
// What Undo Changes puts back: the command's main key and further keys as they were.
if let Some(first) = clash_ids.first() {
conflict = Some(json!({
"shortcut": sc,
"with": first,
"command": selected,
"main": overrides.get(&selected),
"alternates": alt_overrides.get(&selected),
}));
} else {
conflict = None;
}
if capture_alt {
let def = items.iter().find(|i| i.0 == selected).and_then(|i| i.3.clone());
let cur = eff(&overrides, &selected, &def);
@@ -1883,6 +1920,44 @@ fn shortcuts_body(app: &mut PhotocraftApp, ui: &mut egui::Ui, f: &mut Map<String
if !message.is_empty() {
ui.label(RichText::new(&message).color(if message_warning { t.warning } else { t.text_dim }));
}
if tab == 0
&& let Some(c) = conflict.clone()
{
let (key, with, command) =
(c["shortcut"].as_str().unwrap_or_default(), c["with"].as_str().unwrap_or_default(), c["command"].as_str().unwrap_or_default());
ui.horizontal(|ui| {
if ui.button(tl!("Accept and Go to Conflict")).on_hover_text(tl!("Take the shortcut from the other command and select it")).clicked() {
let def = items.iter().find(|i| i.0 == with).and_then(|i| i.3.clone());
let cur = eff(&overrides, with, &def);
if cur.as_deref().and_then(prefs::normalize_shortcut).as_deref() == Some(key) {
overrides.insert(with.to_string(), String::new());
}
let keys = eff_alts(&alt_overrides, with, eff(&overrides, with, &def).as_deref());
if keys.iter().any(|k| k == key) {
alt_overrides.insert(with.to_string(), keys.into_iter().filter(|k| k != key).collect());
}
selected = with.to_string();
filter.clear();
message = tl!("Choose a new shortcut for this command, or leave it without one.").into();
message_warning = false;
conflict = None;
}
if ui.button(tl!("Undo Changes")).on_hover_text(tl!("Put this command's shortcuts back as they were")).clicked() {
match c["main"].as_str() {
Some(m) => overrides.insert(command.to_string(), m.to_string()),
None => overrides.remove(command),
};
match serde_json::from_value::<Vec<String>>(c["alternates"].clone()) {
Ok(list) => alt_overrides.insert(command.to_string(), list),
Err(_) => alt_overrides.remove(command),
};
selected = command.to_string();
message = tl!("Changes undone.").into();
message_warning = false;
conflict = None;
}
});
}
if overrides_ok {
f.insert("overrides".into(), json!(overrides));
}
@@ -1890,6 +1965,7 @@ fn shortcuts_body(app: &mut PhotocraftApp, ui: &mut egui::Ui, f: &mut Map<String
f.insert("alternates".into(), json!(alt_overrides));
}
f.insert("captureAlt".into(), json!(capture && capture_alt));
f.insert("conflict".into(), conflict.unwrap_or(Value::Null));
f.insert("hidden".into(), json!(hidden));
f.insert("colors".into(), json!(colors));
f.insert("selected".into(), json!(selected));
@@ -230,3 +230,64 @@ fn a_user_shortcut_wins_over_a_default_it_was_not_moved_from() {
let bound: Vec<String> = crate::shortcut_dispatch::bindings(&app).into_iter().filter(|(_, sc)| *sc == f7).map(|(id, _)| id).collect();
assert_eq!(bound, ["select.modify.feather"]);
}
/// Capture `k` with `m` for the selected command.
fn capture_key(h: &mut Harness<'_, PhotocraftApp>, id: u64, k: Key, m: Modifiers) {
h.state_mut().ui.dialog_mut(id).unwrap().fields.insert("capture".into(), json!(true));
h.run_steps(2);
key(h, k, true, m);
h.run_steps(2);
key(h, k, false, m);
h.run_steps(2);
}
fn click(h: &mut Harness<'_, PhotocraftApp>, label: &str) {
h.get_by_role_and_label(egui::accesskit::Role::Button, label).click();
h.run_steps(3);
}
#[test]
fn a_conflict_offers_accept_and_go_to_conflict() {
// Photoshop: the key is taken from Copy now, and Copy is selected to get a new one.
let (mut h, id) = dialog(1.0, "edit.cut", "");
capture_key(&mut h, id, Key::C, Modifiers::COMMAND);
assert_eq!(field(&h, id, "overrides")["edit.cut"], json!("Cmd+C"));
assert_eq!(field(&h, id, "conflict")["with"], json!("edit.copy"));
click(&mut h, "Accept and Go to Conflict");
assert_eq!(field(&h, id, "selected"), json!("edit.copy"));
assert_eq!(field(&h, id, "overrides")["edit.copy"], json!(""), "Copy no longer holds Cmd+C");
assert!(field(&h, id, "conflict").is_null());
crate::dialogs::confirm(h.state_mut(), id).unwrap();
assert_eq!(crate::shortcuts::effective_shortcut(h.state(), "edit.cut", Some("Cmd+X")).as_deref(), Some("Cmd+C"));
assert_eq!(crate::shortcuts::effective_shortcut(h.state(), "edit.copy", Some("Cmd+C")), None);
}
#[test]
fn undo_changes_puts_the_command_back() {
let (mut h, id) = dialog(1.0, "edit.cut", "");
capture_key(&mut h, id, Key::C, Modifiers::COMMAND);
click(&mut h, "Undo Changes");
assert!(field(&h, id, "overrides").get("edit.cut").is_none(), "{}", field(&h, id, "overrides"));
assert!(field(&h, id, "conflict").is_null());
// An alternate added with Add Shortcut is undone the same way.
h.state_mut().ui.dialog_mut(id).unwrap().fields.insert("captureAlt".into(), json!(true));
capture_key(&mut h, id, Key::C, Modifiers::COMMAND);
assert_eq!(field(&h, id, "alternates")["edit.cut"], json!(["F2", "Cmd+C"]), "beside Photoshop's F2");
click(&mut h, "Undo Changes");
assert!(field(&h, id, "alternates").get("edit.cut").is_none(), "{}", field(&h, id, "alternates"));
crate::dialogs::confirm(h.state_mut(), id).unwrap();
assert_eq!(crate::shortcuts::effective_shortcut(h.state(), "edit.copy", Some("Cmd+C")).as_deref(), Some("Cmd+C"));
}
#[test]
fn a_system_key_is_refused() {
let (k, m) = if cfg!(target_os = "macos") { (Key::Tab, Modifiers::MAC_CMD | Modifiers::COMMAND) } else { (Key::F4, Modifiers::ALT) };
let (mut h, id) = dialog(1.0, "edit.cut", "");
capture_key(&mut h, id, k, m);
assert!(field(&h, id, "overrides").get("edit.cut").is_none(), "{}", field(&h, id, "overrides"));
assert!(field(&h, id, "message").as_str().is_some_and(|s| s.contains("reserved")), "{}", field(&h, id, "message"));
assert_eq!(field(&h, id, "messageWarning"), json!(true));
assert!(crate::prefs_ui::reserved_shortcut(if cfg!(target_os = "macos") { "Cmd+Tab" } else { "Alt+F4" }));
assert!(!crate::prefs_ui::reserved_shortcut("Cmd+Shift+F4"));
assert!(!crate::prefs_ui::reserved_shortcut("garbage+"));
}