xpipe/app/src/main/java/io/xpipe/app/browser/BrowserTransferModel.java

175 lines
5.8 KiB
Java
Raw Normal View History

2023-03-31 07:56:18 +13:00
package io.xpipe.app.browser;
2024-04-14 04:23:09 +12:00
import io.xpipe.app.browser.file.FileSystemHelper;
import io.xpipe.app.browser.fs.OpenFileSystemModel;
import io.xpipe.app.browser.session.BrowserSessionModel;
import io.xpipe.app.issue.ErrorEvent;
2023-09-27 13:47:51 +13:00
import io.xpipe.app.util.BooleanScope;
import io.xpipe.app.util.ShellTemp;
2023-10-05 03:34:03 +13:00
import io.xpipe.core.store.FileNames;
2023-03-31 07:56:18 +13:00
import io.xpipe.core.store.FileSystem;
import javafx.beans.binding.Bindings;
2023-03-31 07:56:18 +13:00
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.Property;
2023-03-31 07:56:18 +13:00
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableBooleanValue;
2023-03-31 07:56:18 +13:00
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import lombok.Value;
import org.apache.commons.io.FileUtils;
import java.io.File;
2023-07-17 13:03:12 +12:00
import java.io.IOException;
import java.nio.file.Files;
2023-03-31 07:56:18 +13:00
import java.nio.file.Path;
2023-07-17 13:03:12 +12:00
import java.util.ArrayList;
2023-03-31 07:56:18 +13:00
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
2023-03-31 07:56:18 +13:00
@Value
2023-05-21 01:49:58 +12:00
public class BrowserTransferModel {
2023-03-31 07:56:18 +13:00
private static final Path TEMP = ShellTemp.getLocalTempDataDirectory("download");
2023-03-31 07:56:18 +13:00
ExecutorService executor = Executors.newSingleThreadExecutor(r -> {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
t.setName("file downloader");
return t;
});
2024-04-14 04:23:09 +12:00
BrowserSessionModel browserSessionModel;
2023-03-31 07:56:18 +13:00
ObservableList<Item> items = FXCollections.observableArrayList();
BooleanProperty downloading = new SimpleBooleanProperty();
2023-07-17 13:03:12 +12:00
BooleanProperty allDownloaded = new SimpleBooleanProperty();
private void cleanDirectory() {
if (!Files.isDirectory(TEMP)) {
return;
}
try (var ls = Files.list(TEMP)) {
var list = ls.toList();
for (Path path : list) {
FileUtils.forceDelete(path.toFile());
}
2023-07-17 13:03:12 +12:00
} catch (IOException e) {
ErrorEvent.fromThrowable(e).handle();
}
}
public void clear() {
cleanDirectory();
2023-07-17 13:03:12 +12:00
items.clear();
}
2023-03-31 07:56:18 +13:00
public void drop(OpenFileSystemModel model, List<FileSystem.FileEntry> entries) {
2023-03-31 07:56:18 +13:00
entries.forEach(entry -> {
var name = FileNames.getFileName(entry.getPath());
if (items.stream().anyMatch(item -> item.getName().equals(name))) {
return;
}
Path file = TEMP.resolve(name);
var item = new Item(model, name, entry, file);
2023-03-31 07:56:18 +13:00
items.add(item);
2023-07-17 13:03:12 +12:00
allDownloaded.set(false);
});
}
public void dropLocal(List<File> entries) {
if (entries.isEmpty()) {
return;
}
var empty = items.isEmpty();
try {
var paths = entries.stream().map(File::toPath).filter(Files::exists).toList();
for (Path path : paths) {
var entry = FileSystemHelper.getLocal(path);
var name = entry.getName();
if (items.stream().anyMatch(item -> item.getName().equals(name))) {
return;
}
var item = new Item(null, name, entry, path);
item.progress.setValue(BrowserTransferProgress.finished(entry.getName(), entry.getSize()));
items.add(item);
}
} catch (Exception ex) {
ErrorEvent.fromThrowable(ex).handle();
}
if (empty) {
allDownloaded.set(true);
}
}
2023-07-17 13:03:12 +12:00
public void download() {
executor.submit(() -> {
try {
FileUtils.forceMkdir(TEMP.toFile());
} catch (IOException e) {
ErrorEvent.fromThrowable(e).handle();
return;
}
for (Item item : new ArrayList<>(items)) {
if (item.downloadFinished().get()) {
continue;
}
if (item.getOpenFileSystemModel() != null
&& item.getOpenFileSystemModel().isClosed()) {
2023-07-19 00:46:47 +12:00
continue;
}
try {
2023-09-27 13:47:51 +13:00
try (var b = new BooleanScope(downloading).start()) {
2023-07-17 13:03:12 +12:00
FileSystemHelper.dropFilesInto(
2024-03-05 06:47:13 +13:00
FileSystemHelper.getLocal(TEMP),
List.of(item.getFileEntry()),
true,
false,
progress -> {
item.getProgress().setValue(progress);
item.getOpenFileSystemModel().getProgress().setValue(progress);
});
}
} catch (Throwable t) {
ErrorEvent.fromThrowable(t).handle();
2023-06-14 20:54:00 +12:00
items.remove(item);
2023-03-31 07:56:18 +13:00
}
2023-07-17 13:03:12 +12:00
}
allDownloaded.set(true);
2023-03-31 07:56:18 +13:00
});
}
@Value
public static class Item {
OpenFileSystemModel openFileSystemModel;
String name;
FileSystem.FileEntry fileEntry;
Path localFile;
Property<BrowserTransferProgress> progress;
public Item(
OpenFileSystemModel openFileSystemModel, String name, FileSystem.FileEntry fileEntry, Path localFile) {
this.openFileSystemModel = openFileSystemModel;
this.name = name;
this.fileEntry = fileEntry;
this.localFile = localFile;
2024-03-03 02:23:40 +13:00
this.progress = new SimpleObjectProperty<>();
}
public ObservableBooleanValue downloadFinished() {
return Bindings.createBooleanBinding(
() -> {
2024-03-05 06:47:13 +13:00
return progress.getValue() != null
&& progress.getValue().done();
},
progress);
}
}
2023-03-31 07:56:18 +13:00
}