fix: do not generate thumbnail if file is being written

This commit is contained in:
Michael Aaron Murphy 2026-04-10 06:08:21 +02:00
parent 0bd20e57e7
commit 15e40461e5
No known key found for this signature in database
GPG key ID: B2732D4240C9212C
4 changed files with 67 additions and 0 deletions

View file

@ -22,6 +22,9 @@ use zip::AesMode::Aes256;
pub use self::controller::{Controller, ControllerState};
pub mod controller;
pub use notifiers::*;
mod notifiers;
pub use self::reader::OpReader;
pub mod reader;

View file

@ -0,0 +1,58 @@
// Copyright 2026 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use std::path::{Path, PathBuf};
use std::sync::{Arc, LazyLock, Mutex};
use tokio::sync::Notify;
/// Monitor files which are being written to.
pub struct FileWritingNotifier {
data: Vec<PathBuf>,
notify: Arc<Notify>,
}
static ACTIVELY_WRITING: LazyLock<Mutex<FileWritingNotifier>> = LazyLock::new(|| {
Mutex::new(FileWritingNotifier {
data: Vec::new(),
notify: Arc::new(Notify::new()),
})
});
/// Append path that is being written to.
pub fn actively_writing_add(path: PathBuf) {
ACTIVELY_WRITING.lock().unwrap().data.push(path);
}
/// Remove path to file that has finished writing and notify waiters.
pub fn actively_writing_remove(path: &Path) {
let mut guard = ACTIVELY_WRITING.lock().unwrap();
guard.data.retain(|p| p != path);
guard.notify.notify_waiters();
}
/// Wait until the actively-writing queue is empty or a file has been removed.
pub async fn actively_writing_tick() {
let notify = (|| {
let guard = ACTIVELY_WRITING.lock().unwrap();
if !guard.data.is_empty() {
return Some(guard.notify.clone());
}
None
})();
if let Some(notify) = notify {
notify.notified().await
}
}
/// Check if a file is being written to. Avoid thumbnail generation until after it is finished.
pub fn is_actively_writing_to(path: &Path) -> bool {
ACTIVELY_WRITING
.lock()
.unwrap()
.data
.iter()
.any(|p| p == path)
}

View file

@ -334,12 +334,14 @@ impl Op {
}
match self.kind {
OpKind::Copy => {
crate::operation::actively_writing_add(self.to.clone());
let result = self.copy(ctx, progress).await;
if result.is_err() {
_ = compio::fs::remove_file(&self.to).await;
}
crate::operation::actively_writing_remove(&self.to);
return result;
}
OpKind::Move { cross_device_copy } => {

View file

@ -6771,6 +6771,10 @@ impl Tab {
stream::channel(
1,
move |mut output: futures::channel::mpsc::Sender<_>| async move {
while crate::operation::is_actively_writing_to(&path) {
crate::operation::actively_writing_tick().await;
}
let message = {
let path = path.clone();