mirror of
https://github.com/storytold/lightcraft.git
synced 2026-11-02 06:27:53 -06:00
LRC-LIB-CATALOG-SWITCH: files waiting for a library wait for a running import instead of being dropped (#2779)
This commit is contained in:
@@ -2407,6 +2407,7 @@
|
||||
"Dropped Files": "Přetažené soubory",
|
||||
"Import dropped files without review": "Importovat přetažené soubory bez kontroly",
|
||||
"An import is running": "Import už běží",
|
||||
"The photos are imported once it ends": "Fotky se naimportují potom",
|
||||
"An import is running. Drop photos when it has finished": "Import už běží. Fotky přetáhněte, až skončí",
|
||||
"Finish Lightroom catalog import before adding photos": "Dokončete import katalogu Lightroom, než přidáte fotky"
|
||||
}
|
||||
|
||||
@@ -3439,6 +3439,7 @@
|
||||
"Dropped Files": "Abgelegte Dateien",
|
||||
"Import dropped files without review": "Abgelegte Dateien ohne Prüfung importieren",
|
||||
"An import is running": "Ein Import läuft",
|
||||
"The photos are imported once it ends": "Die Fotos werden danach importiert",
|
||||
"An import is running. Drop photos when it has finished": "Ein Import läuft. Lege die Fotos ab, wenn er fertig ist",
|
||||
"Finish Lightroom catalog import before adding photos": "Schließe den Import des Lightroom-Katalogs ab, bevor du Fotos hinzufügst"
|
||||
}
|
||||
|
||||
@@ -2357,6 +2357,7 @@
|
||||
"Dropped Files": "Archivos soltados",
|
||||
"Import dropped files without review": "Importar los archivos soltados sin revisión",
|
||||
"An import is running": "Hay una importación en curso",
|
||||
"The photos are imported once it ends": "Las fotos se importarán después",
|
||||
"An import is running. Drop photos when it has finished": "Hay una importación en curso. Suelta las fotos cuando termine",
|
||||
"Finish Lightroom catalog import before adding photos": "Termina la importación del catálogo de Lightroom antes de añadir fotos"
|
||||
}
|
||||
|
||||
@@ -2320,6 +2320,7 @@
|
||||
"Mask Pins": "Maskin nastat",
|
||||
"Photo Counts": "Kuvamäärät",
|
||||
"An import is running": "Tuonti on käynnissä",
|
||||
"The photos are imported once it ends": "Kuvat tuodaan sen jälkeen",
|
||||
"An import is running. Drop photos when it has finished": "Tuonti on käynnissä. Pudota kuvat, kun se on valmis",
|
||||
"Close the open dialog to drop files here": "Sulje avoin valintaikkuna pudottaaksesi tiedostot tähän",
|
||||
"Close the open dialog, then drop the files again": "Sulje avoin valintaikkuna ja pudota tiedostot sitten uudelleen",
|
||||
|
||||
@@ -2353,6 +2353,7 @@
|
||||
"Dropped Files": "Fichiers déposés",
|
||||
"Import dropped files without review": "Importer les fichiers déposés sans vérification",
|
||||
"An import is running": "Une importation est en cours",
|
||||
"The photos are imported once it ends": "Les photos seront importées ensuite",
|
||||
"An import is running. Drop photos when it has finished": "Une importation est en cours. Déposez les photos quand elle sera terminée",
|
||||
"Finish Lightroom catalog import before adding photos": "Terminez l'importation du catalogue Lightroom avant d'ajouter des photos",
|
||||
"The library is empty: the catalog's photos, collections and edits become its first.": "La bibliothèque est vide : les photos, collections et retouches du catalogue seront les premières.",
|
||||
|
||||
@@ -2332,6 +2332,7 @@
|
||||
"Mask Pins": "Pin masker",
|
||||
"Photo Counts": "Jumlah foto",
|
||||
"An import is running": "Impor sedang berjalan",
|
||||
"The photos are imported once it ends": "Foto diimpor setelah selesai",
|
||||
"An import is running. Drop photos when it has finished": "Impor sedang berjalan. Jatuhkan foto setelah selesai",
|
||||
"Close the open dialog to drop files here": "Tutup dialog yang terbuka untuk menjatuhkan file di sini",
|
||||
"Close the open dialog, then drop the files again": "Tutup dialog yang terbuka, lalu jatuhkan file lagi",
|
||||
|
||||
@@ -2360,6 +2360,7 @@
|
||||
"Dropped Files": "File rilasciati",
|
||||
"Import dropped files without review": "Importa i file rilasciati senza revisione",
|
||||
"An import is running": "Un'importazione è in corso",
|
||||
"The photos are imported once it ends": "Le foto verranno importate dopo",
|
||||
"An import is running. Drop photos when it has finished": "Un'importazione è in corso. Trascina le foto quando è finita",
|
||||
"Finish Lightroom catalog import before adding photos": "Termina l'importazione del catalogo Lightroom prima di aggiungere foto"
|
||||
}
|
||||
|
||||
@@ -2355,6 +2355,7 @@
|
||||
"Dropped Files": "ドロップしたファイル",
|
||||
"Import dropped files without review": "ドロップしたファイルを確認せずに読み込む",
|
||||
"An import is running": "読み込み中です",
|
||||
"The photos are imported once it ends": "終わりしだい写真を読み込みます",
|
||||
"An import is running. Drop photos when it has finished": "読み込み中です。完了してから写真をドロップしてください",
|
||||
"Finish Lightroom catalog import before adding photos": "写真を追加する前に Lightroom カタログの読み込みを完了してください"
|
||||
}
|
||||
|
||||
@@ -2733,6 +2733,7 @@
|
||||
"Dropped Files": "ჩაგდებული ფაილები",
|
||||
"Import dropped files without review": "ჩაგდებული ფაილების იმპორტი გადახედვის გარეშე",
|
||||
"An import is running": "იმპორტი მიმდინარეობს",
|
||||
"The photos are imported once it ends": "ფოტოები ამის შემდეგ შემოიტანება",
|
||||
"An import is running. Drop photos when it has finished": "იმპორტი მიმდინარეობს. ფოტოები ჩააგდეთ, როცა დასრულდება",
|
||||
"Finish Lightroom catalog import before adding photos": "ფოტოების დამატებამდე დაასრულეთ Lightroom-ის კატალოგის იმპორტი"
|
||||
}
|
||||
|
||||
@@ -2282,6 +2282,7 @@
|
||||
"Dropped Files": "Upuszczone pliki",
|
||||
"Import dropped files without review": "Importuj upuszczone pliki bez przeglądu",
|
||||
"An import is running": "Import jest w toku",
|
||||
"The photos are imported once it ends": "Zdjęcia zostaną zaimportowane potem",
|
||||
"An import is running. Drop photos when it has finished": "Import jest w toku. Upuść zdjęcia, gdy się zakończy",
|
||||
"Finish Lightroom catalog import before adding photos": "Zakończ import katalogu Lightrooma, zanim dodasz zdjęcia"
|
||||
}
|
||||
|
||||
@@ -2201,6 +2201,7 @@
|
||||
"Dropped Files": "Arquivos soltos",
|
||||
"Import dropped files without review": "Importar arquivos soltos sem revisão",
|
||||
"An import is running": "Uma importação está em andamento",
|
||||
"The photos are imported once it ends": "As fotos serão importadas depois",
|
||||
"An import is running. Drop photos when it has finished": "Uma importação está em andamento. Solte as fotos quando ela terminar",
|
||||
"Finish Lightroom catalog import before adding photos": "Conclua a importação do catálogo do Lightroom antes de adicionar fotos"
|
||||
}
|
||||
|
||||
@@ -2348,6 +2348,7 @@
|
||||
"Dropped Files": "Перетащенные файлы",
|
||||
"Import dropped files without review": "Импортировать перетащенные файлы без проверки",
|
||||
"An import is running": "Импорт уже выполняется",
|
||||
"The photos are imported once it ends": "Фото будут импортированы после этого",
|
||||
"An import is running. Drop photos when it has finished": "Импорт уже выполняется. Перетащите фото, когда он закончится",
|
||||
"Finish Lightroom catalog import before adding photos": "Завершите импорт каталога Lightroom, прежде чем добавлять фото"
|
||||
}
|
||||
|
||||
@@ -2422,6 +2422,7 @@
|
||||
"Mask Pins": "Masknålar",
|
||||
"Photo Counts": "Antal foton",
|
||||
"An import is running": "En import pågår",
|
||||
"The photos are imported once it ends": "Bilderna importeras efteråt",
|
||||
"An import is running. Drop photos when it has finished": "En import pågår. Släpp fotona när den är klar",
|
||||
"Close the open dialog to drop files here": "Stäng den öppna dialogrutan för att släppa filer här",
|
||||
"Close the open dialog, then drop the files again": "Stäng den öppna dialogrutan och släpp sedan filerna igen",
|
||||
|
||||
@@ -2353,6 +2353,7 @@
|
||||
"Dropped Files": "Перетягнуті файли",
|
||||
"Import dropped files without review": "Імпортувати перетягнуті файли без перегляду",
|
||||
"An import is running": "Імпорт уже виконується",
|
||||
"The photos are imported once it ends": "Фото буде імпортовано після цього",
|
||||
"An import is running. Drop photos when it has finished": "Імпорт уже виконується. Перетягніть фото, коли він завершиться",
|
||||
"Finish Lightroom catalog import before adding photos": "Завершіть імпорт каталогу Lightroom, перш ніж додавати фото"
|
||||
}
|
||||
|
||||
@@ -2228,6 +2228,7 @@
|
||||
"Mask Pins": "Ghim mặt nạ",
|
||||
"Photo Counts": "Số lượng ảnh",
|
||||
"An import is running": "Đang có một lần nhập chạy",
|
||||
"The photos are imported once it ends": "Ảnh sẽ được nhập khi việc đó kết thúc",
|
||||
"An import is running. Drop photos when it has finished": "Đang có một lần nhập chạy. Hãy thả ảnh khi nó hoàn tất",
|
||||
"Close the open dialog to drop files here": "Hãy đóng hộp thoại đang mở để thả tệp vào đây",
|
||||
"Close the open dialog, then drop the files again": "Hãy đóng hộp thoại đang mở, rồi thả lại các tệp",
|
||||
|
||||
@@ -2199,6 +2199,7 @@
|
||||
"Dropped Files": "拖入的文件",
|
||||
"Import dropped files without review": "不经检查直接导入拖入的文件",
|
||||
"An import is running": "正在导入",
|
||||
"The photos are imported once it ends": "结束后即导入这些照片",
|
||||
"An import is running. Drop photos when it has finished": "正在导入。导入完成后再拖放照片",
|
||||
"Finish Lightroom catalog import before adding photos": "添加照片前,请先完成 Lightroom 目录的导入"
|
||||
}
|
||||
|
||||
@@ -2156,6 +2156,7 @@
|
||||
"Dropped Files": "拖放的檔案",
|
||||
"Import dropped files without review": "不經檢查直接匯入拖放的檔案",
|
||||
"An import is running": "正在匯入",
|
||||
"The photos are imported once it ends": "結束後即匯入這些照片",
|
||||
"An import is running. Drop photos when it has finished": "正在匯入。匯入完成後再拖放照片",
|
||||
"Finish Lightroom catalog import before adding photos": "新增照片前,請先完成 Lightroom 目錄的匯入"
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@ impl LightcraftApp {
|
||||
merge: merge::MergeState::default(),
|
||||
import: None,
|
||||
scan: None,
|
||||
waiting_import: Default::default(),
|
||||
sync: None,
|
||||
sync_owns_changes: false,
|
||||
sync_run: None,
|
||||
|
||||
@@ -298,6 +298,8 @@ pub struct LightcraftApp {
|
||||
pub import: Option<import::ImportTask>,
|
||||
/// A folder scan in progress (feeds the import review).
|
||||
pub scan: Option<import::ScanTask>,
|
||||
/// Files that waited for a library and wait for the running import or Synchronize Folder too.
|
||||
pub waiting_import: panels::library_problem::WaitingImport,
|
||||
/// A Synchronize Folder scan in progress (feeds its dialog).
|
||||
pub sync: Option<sync::SyncTask>,
|
||||
/// `session.folder_changes` came from the Synchronize Folder dialog (and goes with it).
|
||||
|
||||
@@ -327,6 +327,16 @@ pub struct Chooser {
|
||||
pub over: Option<u64>,
|
||||
}
|
||||
|
||||
/// Files that waited for a library (the command line, drops on the launch list) and found another
|
||||
/// import or a Synchronize Folder running when one opened: kept, and imported once it ends instead
|
||||
/// of being lost (issue #2779).
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct WaitingImport {
|
||||
pub files: Vec<String>,
|
||||
/// The toast already said why they wait.
|
||||
told: bool,
|
||||
}
|
||||
|
||||
/// A library that failed to open (set by the host at launch).
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct LibraryProblem {
|
||||
@@ -783,12 +793,7 @@ fn open(app: &mut LightcraftApp, path: Option<String>) {
|
||||
Ok(serde_json::Value::Null) => {} // folder dialog cancelled
|
||||
Ok(_) => {
|
||||
let files = app.library_problem.take().map(|p| p.pending_import).unwrap_or_default();
|
||||
// in the background, like files dropped on the window (issue #374)
|
||||
if !files.is_empty()
|
||||
&& let Err(e) = crate::import::start_paths(app, files)
|
||||
{
|
||||
log::warn!("import: {e}");
|
||||
}
|
||||
app.waiting_import.files.extend(files);
|
||||
}
|
||||
Err(e) => {
|
||||
// a failed switch reopens the library that was open behind the launch list
|
||||
@@ -816,6 +821,26 @@ fn open(app: &mut LightcraftApp, path: Option<String>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Import the files that waited for a library, in the background like files dropped on the window
|
||||
/// (issue #374). While another import or a Synchronize Folder runs they keep waiting, and a toast
|
||||
/// says why once (issue #2779).
|
||||
fn import_waiting(app: &mut LightcraftApp, ctx: &egui::Context) {
|
||||
if app.waiting_import.files.is_empty() {
|
||||
return;
|
||||
}
|
||||
let files = std::mem::take(&mut app.waiting_import.files);
|
||||
match crate::import::start_paths(app, files.clone()) {
|
||||
Ok(_) => app.waiting_import = WaitingImport::default(),
|
||||
Err(e) => {
|
||||
if !app.waiting_import.told {
|
||||
app.toast(ctx, format!("{e}. {}", crate::i18n::tr("The photos are imported once it ends")));
|
||||
}
|
||||
app.waiting_import = WaitingImport { files, told: true };
|
||||
ctx.request_repaint_after(std::time::Duration::from_millis(250));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear the problem once a library is open (e.g. through Settings → Open Library…) — another
|
||||
/// one than the launch list was opened over; offer the list when Alt/Option is held as the window
|
||||
/// appears; and the list's keys.
|
||||
@@ -827,12 +852,9 @@ pub fn logic(app: &mut LightcraftApp, ctx: &egui::Context) {
|
||||
// files from the command line go into the library opened another way (New Library…,
|
||||
// File ▸ Open Library…), as through the window's own buttons
|
||||
let files = app.library_problem.take().map(|p| p.pending_import).unwrap_or_default();
|
||||
if !files.is_empty()
|
||||
&& let Err(e) = crate::import::start_paths(app, files)
|
||||
{
|
||||
log::warn!("import: {e}");
|
||||
}
|
||||
app.waiting_import.files.extend(files);
|
||||
}
|
||||
import_waiting(app, ctx);
|
||||
let batch_in_flight = app.synthetic_in_flight;
|
||||
alt_at_launch(app, ctx);
|
||||
// Alt/Option can create the launch list here, after the frame's input was accepted. Drop
|
||||
@@ -1111,12 +1133,7 @@ fn act(app: &mut LightcraftApp, choice: Choice) {
|
||||
p.dismissed = true;
|
||||
}
|
||||
let files = app.library_problem.as_mut().map(|p| std::mem::take(&mut p.pending_import)).unwrap_or_default();
|
||||
// in the background, like files dropped on the window (issue #374)
|
||||
if !files.is_empty()
|
||||
&& let Err(e) = crate::import::start_paths(app, files)
|
||||
{
|
||||
log::warn!("import: {e}");
|
||||
}
|
||||
app.waiting_import.files.extend(files);
|
||||
}
|
||||
Choice::Quit => app.ui.quit = true,
|
||||
}
|
||||
|
||||
@@ -804,3 +804,42 @@ fn typing_reaches_the_launch_lists_own_new_library_prompt() {
|
||||
assert_eq!(command, "app.newLibrary");
|
||||
assert_eq!(value, "Fresh", "typing reaches the launch list's own text prompt");
|
||||
}
|
||||
|
||||
/// Issue #2779: files waiting for a library (the command line, drops on the launch list) that
|
||||
/// find another import running when a library opens are kept, with a toast saying why, and
|
||||
/// imported once that import ends instead of being dropped.
|
||||
#[test]
|
||||
fn waiting_files_wait_for_a_running_import_instead_of_being_dropped() {
|
||||
let dir = std::env::temp_dir().join(format!("lightcraft-waiting-import-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let png = |v: u8| {
|
||||
let img = lightcraft_raster::Rgba8 { width: 8, height: 8, data: vec![[v, 3, 9, 255]; 64] };
|
||||
lightcraft_codecs::encode_png(&lightcraft_codecs::EncodeImage::rgba8(&img), &lightcraft_codecs::EncodeMeta::default()).unwrap()
|
||||
};
|
||||
let (busy, waiting) = (dir.join("busy.png"), dir.join("waiting.png"));
|
||||
std::fs::write(&busy, png(10)).unwrap();
|
||||
std::fs::write(&waiting, png(200)).unwrap();
|
||||
|
||||
let app = LightcraftApp::new(lightcraft_engine::Session::new().with_fs(), Services { png: None, ..Default::default() });
|
||||
let mut h = Headless::new(app, [1300.0, 900.0], 1.0);
|
||||
let lib = dir.join("lib");
|
||||
h.app.library_problem = Some(LibraryProblem {
|
||||
pending_import: vec![waiting.to_string_lossy().to_string()],
|
||||
..LibraryProblem::new(lib.to_string_lossy(), "a test error")
|
||||
});
|
||||
h.step();
|
||||
// a library opens another way (File ▸ Open Library…) while an import is running
|
||||
h.app.session.open_library(&lib, false).unwrap();
|
||||
crate::import::start_paths(&mut h.app, vec![busy.to_string_lossy().to_string()]).unwrap();
|
||||
h.step();
|
||||
assert!(h.app.library_problem.is_none(), "the problem is over");
|
||||
assert_eq!(h.app.waiting_import.files, vec![waiting.to_string_lossy().to_string()], "the waiting file is kept");
|
||||
let toast = h.app.ui.toast.as_ref().map(|t| t.0.clone()).unwrap_or_default();
|
||||
assert!(toast.contains("An import is running") && toast.contains("once it ends"), "{toast}");
|
||||
|
||||
assert!(h.step_until(T, |h| h.app.import.is_none() && h.app.session.catalog.len() == 2), "{} photos", h.app.session.catalog.len());
|
||||
assert!(h.app.waiting_import.files.is_empty());
|
||||
let _ = h.app.session.close_library();
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# What's new in LightCraft
|
||||
|
||||
## 2026-10-30
|
||||
|
||||
### Photos waiting for a library wait for a running import too
|
||||
- Photos given on the command line or dropped on the launch list are imported once a library opens. If another import
|
||||
or a Synchronize Folder is still running then, they now wait for it to end instead of being dropped, and a message
|
||||
says so (issue #2779).
|
||||
|
||||
## 2026-10-24
|
||||
|
||||
### Relative-date filters and smart albums follow the clock
|
||||
|
||||
Reference in New Issue
Block a user