Rework validation and browser progress

This commit is contained in:
crschnick 2024-09-21 16:54:45 +00:00
parent a146fbd936
commit ba9918e166
25 changed files with 93 additions and 98 deletions

View file

@ -21,7 +21,7 @@ public class ConnectionAddExchangeImpl extends ConnectionAddExchange {
try {
DataStorage.get().addStoreEntryInProgress(entry);
if (msg.getValidate()) {
entry.validateOrThrow(true);
entry.validateOrThrow();
}
} catch (Throwable ex) {
if (ex instanceof ValidationException) {

View file

@ -17,7 +17,7 @@ public class ConnectionRefreshExchangeImpl extends ConnectionRefreshExchange {
if (e.getStore() instanceof FixedHierarchyStore) {
DataStorage.get().refreshChildren(e, true);
} else {
e.validateOrThrow(true);
e.validateOrThrowAndClose(null);
}
return Response.builder().build();
}

View file

@ -55,7 +55,7 @@ public class BrowserStatusBarComp extends SimpleComp {
private Comp<?> createProgressEstimateStatus() {
var text = BindingsHelper.map(model.getProgress(), p -> {
if (p == null || p.done()) {
if (p == null) {
return null;
} else {
var expected = p.expectedTimeRemaining();
@ -74,7 +74,7 @@ public class BrowserStatusBarComp extends SimpleComp {
private Comp<?> createProgressStatus() {
var text = BindingsHelper.map(model.getProgress(), p -> {
if (p == null || p.done()) {
if (p == null) {
return null;
} else {
var transferred = HumanReadableFormat.progressByteCount(p.getTransferred());
@ -91,7 +91,7 @@ public class BrowserStatusBarComp extends SimpleComp {
private Comp<?> createProgressNameStatus() {
var text = BindingsHelper.map(model.getProgress(), p -> {
if (p == null || p.done()) {
if (p == null) {
return null;
} else {
return p.getName();

View file

@ -14,14 +14,6 @@ public class BrowserTransferProgress {
long total;
Instant start;
public static BrowserTransferProgress empty() {
return new BrowserTransferProgress(null, 0, 0, Instant.now());
}
static BrowserTransferProgress empty(String name, long size) {
return new BrowserTransferProgress(name, 0, size, Instant.now());
}
public static BrowserTransferProgress finished(String name, long size) {
return new BrowserTransferProgress(name, size, size, Instant.now());
}

View file

@ -102,7 +102,7 @@ public class BrowserFileTransferOperation {
public void execute() throws Exception {
if (files.isEmpty()) {
updateProgress(BrowserTransferProgress.empty());
updateProgress(null);
return;
}
@ -115,18 +115,22 @@ public class BrowserFileTransferOperation {
}
}
for (var file : files) {
if (same) {
handleSingleOnSameFileSystem(file);
} else {
handleSingleAcrossFileSystems(file);
}
}
if (!same && doesMove) {
try {
for (var file : files) {
deleteSingle(file);
if (same) {
handleSingleOnSameFileSystem(file);
} else {
handleSingleAcrossFileSystems(file);
}
}
if (!same && doesMove) {
for (var file : files) {
deleteSingle(file);
}
}
} finally {
updateProgress(null);
}
}

View file

@ -47,8 +47,7 @@ public final class OpenFileSystemModel extends BrowserSessionTab<FileSystemStore
private final OpenFileSystemHistory history = new OpenFileSystemHistory();
private final Property<ModalOverlayComp.OverlayContent> overlay = new SimpleObjectProperty<>();
private final BooleanProperty inOverview = new SimpleBooleanProperty();
private final Property<BrowserTransferProgress> progress =
new SimpleObjectProperty<>(BrowserTransferProgress.empty());
private final Property<BrowserTransferProgress> progress = new SimpleObjectProperty<>();
private FileSystem fileSystem;
private OpenFileSystemSavedState savedState;
private OpenFileSystemCache cache;
@ -73,7 +72,7 @@ public final class OpenFileSystemModel extends BrowserSessionTab<FileSystemStore
@Override
public boolean canImmediatelyClose() {
return !progress.getValue().done()
return (progress.getValue() == null || progress.getValue().done())
|| (fileSystem != null
&& fileSystem.getShell().isPresent()
&& fileSystem.getShell().get().getLock().isLocked());

View file

@ -2,13 +2,12 @@ package io.xpipe.app.comp.base;
import io.xpipe.app.comp.store.StoreEntryWrapper;
import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.impl.PrettyImageComp;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.fxcomps.impl.StackComp;
import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.resources.AppResources;
import io.xpipe.core.process.OsNameState;
import io.xpipe.core.store.FileNames;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
@ -54,7 +53,7 @@ public class OsLogoComp extends SimpleComp {
state);
var hide = BindingsHelper.map(img, s -> s != null);
return new StackComp(
List.of(new SystemStateComp(state).hide(hide), new PrettyImageComp(img, 24, 24).visible(hide)))
List.of(new SystemStateComp(state).hide(hide), PrettyImageHelper.ofFixedSize(img, 24, 24).visible(hide)))
.createRegion();
}
@ -70,7 +69,7 @@ public class OsLogoComp extends SimpleComp {
&& !path.toString().endsWith(LINUX_DEFAULT_24) && !path.toString().endsWith("-40.png"))
.map(path -> FileNames.getFileName(path.toString()))
.forEach(path -> {
var base = path.replace("-dark", "");
var base = path.replace("-dark", "").replace("-24.png", ".svg");
ICONS.put(FileNames.getBaseName(base).split("-")[0], "os/" + base);
});
}
@ -81,6 +80,6 @@ public class OsLogoComp extends SimpleComp {
.filter(e -> name.toLowerCase().contains(e.getKey()))
.findAny()
.map(e -> e.getValue())
.orElse("os/linux");
.orElse("os/linux.svg");
}
}

View file

@ -322,7 +322,10 @@ public class StoreCreationComp extends DialogComp {
try (var ignored = new BooleanScope(busy).start()) {
DataStorage.get().addStoreEntryInProgress(entry.getValue());
var context = entry.getValue().validateOrThrow(false);
var context = entry.getValue().validateAndKeepOpenOrThrowAndClose(null);
if (context == null) {
entry.getValue().validateRefreshChildrenOrThrow();
}
commit(context, true);
} catch (Throwable ex) {
if (ex instanceof ValidationException) {

View file

@ -31,11 +31,11 @@ public abstract class ScanProvider {
String nameKey;
boolean disabled;
boolean defaultSelected;
FailableRunnable<Exception> scanner;
FailableRunnable<Throwable> scanner;
String licenseFeatureId;
public ScanOperation(
String nameKey, boolean disabled, boolean defaultSelected, FailableRunnable<Exception> scanner) {
String nameKey, boolean disabled, boolean defaultSelected, FailableRunnable<Throwable> scanner) {
this.nameKey = nameKey;
this.disabled = disabled;
this.defaultSelected = defaultSelected;

View file

@ -1,19 +1,18 @@
package io.xpipe.app.storage;
import io.xpipe.app.ext.DataStoreProvider;
import io.xpipe.app.ext.DataStoreProviders;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.resources.SystemIcons;
import io.xpipe.app.util.FixedHierarchyStore;
import io.xpipe.core.store.*;
import io.xpipe.core.util.JacksonMapper;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import io.xpipe.app.ext.DataStoreProvider;
import io.xpipe.app.ext.DataStoreProviders;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.resources.SystemIcons;
import io.xpipe.app.util.FixedHierarchyStore;
import io.xpipe.core.store.*;
import io.xpipe.core.util.JacksonMapper;
import lombok.*;
import lombok.experimental.NonFinal;
import org.apache.commons.io.FileUtils;
@ -496,72 +495,72 @@ public class DataStoreEntry extends StorageElement {
dirty = true;
}
public <T extends ValidationContext<?>> void validate() {
public void validate() {
try {
validateOrThrow(true);
validateOrThrow();
} catch (Throwable ex) {
ErrorEvent.fromThrowable(ex).handle();
}
}
public <T extends ValidationContext<?>> void validate(T context) {
try {
validateOrThrow(context);
} catch (Throwable ex) {
ErrorEvent.fromThrowable(ex).handle();
public void validateOrThrow() throws Throwable {
var r = validateOrThrowAndClose(null);
if (!r) {
validateRefreshChildrenOrThrow();
}
}
@SuppressWarnings("unchecked")
public <T extends ValidationContext<?>> void validateOrThrow(T context) throws Throwable {
if (store == null) {
public void validateRefreshChildrenOrThrow() throws Throwable {
if (!(store instanceof FixedHierarchyStore h)) {
return;
}
try {
store.checkComplete();
incrementBusyCounter();
if (store instanceof ValidatableStore<?> l) {
((ValidatableStore<T>) l).validate(context);
} else if (store instanceof FixedHierarchyStore h) {
childrenCache = h.listChildren(this).stream()
.map(DataStoreEntryRef::get)
.collect(Collectors.toSet());
}
childrenCache = h.listChildren(this).stream()
.map(DataStoreEntryRef::get)
.collect(Collectors.toSet());
} finally {
decrementBusyCounter();
}
}
public boolean validateOrThrowAndClose(ValidationContext<?> existingContext) throws Throwable {
var subContext = validateAndKeepOpenOrThrowAndClose(existingContext);
if (subContext != null) {
subContext.close();
return true;
} else {
return false;
}
}
@SuppressWarnings("unchecked")
public <T> ValidationContext<?> validateOrThrow(boolean close) throws Throwable {
public <T> ValidationContext<?> validateAndKeepOpenOrThrowAndClose(ValidationContext<?> existingContext) throws Throwable {
if (store == null) {
return null;
}
if (!(store instanceof ValidatableStore<?> l)) {
return null;
}
try {
store.checkComplete();
incrementBusyCounter();
if (store instanceof ValidatableStore<?> l) {
ValidationContext<T> context = (ValidationContext<T>) l.createContext();
try {
((ValidatableStore<ValidationContext<T>>) l).validate(context);
} catch (Throwable t) {
context.close();
throw t;
}
if (close) {
context.close();
}
return context;
} else if (store instanceof FixedHierarchyStore h) {
childrenCache = h.listChildren(this).stream()
.map(DataStoreEntryRef::get)
.collect(Collectors.toSet());
return null;
} else {
ValidationContext<T> context = existingContext != null ? (ValidationContext<T>) existingContext : (ValidationContext<T>) l.createContext();
if (context == null) {
return null;
}
try {
var r = ((ValidatableStore<ValidationContext<T>>) l).validate(context);
return r;
} catch (Throwable t) {
context.close();
throw t;
}
} finally {
decrementBusyCounter();
}

View file

@ -151,7 +151,7 @@ public class ScanAlert {
try {
a.getScanner().run();
} catch (Exception ex) {
} catch (Throwable ex) {
ErrorEvent.fromThrowable(ex).handle();
}
}

View file

@ -18,16 +18,16 @@ public interface ShellStore extends DataStore, FileSystemStore, ValidatableStore
}
@Override
default void validate(ShellValidationContext context) throws Exception {
default ShellValidationContext validate(ShellValidationContext context) throws Exception {
var c = control(context.get());
if (!isInStorage()) {
c.withoutLicenseCheck();
}
try (ShellControl pc = c.start()) {}
return new ShellValidationContext(c.start());
}
@Override
default ShellValidationContext createContext() throws Exception {
return new ShellValidationContext(control().start());
return new ShellValidationContext(parentControl().start());
}
}

View file

@ -18,9 +18,7 @@ public interface ValidatableStore<T extends ValidationContext<?>> extends DataSt
*
* @throws Exception if any part of the validation went wrong
*/
default void validate(T context) throws Exception {}
T validate(T context) throws Exception;
default T createContext() throws Exception {
return null;
}
T createContext() throws Exception;
}

View file

@ -488,7 +488,7 @@ closeOtherTabs=Luk andre faner
closeAllTabs=Luk alle faner
closeLeftTabs=Luk faner til venstre
closeRightTabs=Luk faner til højre
addSerial=Seriel ...
addSerial=Seriel (eksperimentel) ...
connect=Forbind
workspaces=Arbejdsområder
manageWorkspaces=Administrer arbejdsområder

View file

@ -482,7 +482,7 @@ closeOtherTabs=Andere Tabs schließen
closeAllTabs=Alle Registerkarten schließen
closeLeftTabs=Tabs nach links schließen
closeRightTabs=Tabs nach rechts schließen
addSerial=Serielle ...
addSerial=Seriell (Experimentell) ...
connect=Verbinden
workspaces=Arbeitsbereiche
manageWorkspaces=Arbeitsbereiche verwalten

View file

@ -486,6 +486,7 @@ closeOtherTabs=Close other tabs
closeAllTabs=Close all tabs
closeLeftTabs=Close tabs to the left
closeRightTabs=Close tabs to the right
#context: Serial computer connection
addSerial=Serial (Experimental) ...
connect=Connect
workspaces=Workspaces

View file

@ -469,7 +469,7 @@ closeOtherTabs=Cerrar otras pestañas
closeAllTabs=Cerrar todas las pestañas
closeLeftTabs=Cerrar pestañas a la izquierda
closeRightTabs=Cerrar pestañas a la derecha
addSerial=Serie ...
addSerial=Serie (experimental) ...
connect=Conecta
workspaces=Espacios de trabajo
manageWorkspaces=Gestionar espacios de trabajo

View file

@ -469,7 +469,7 @@ closeOtherTabs=Fermer d'autres onglets
closeAllTabs=Fermer tous les onglets
closeLeftTabs=Ferme les onglets à gauche
closeRightTabs=Ferme les onglets à droite
addSerial=Série ...
addSerial=Série (expérimental) ...
connect=Connecter
workspaces=Espaces de travail
manageWorkspaces=Gérer les espaces de travail

View file

@ -469,7 +469,7 @@ closeOtherTabs=Chiudere altre schede
closeAllTabs=Chiudi tutte le schede
closeLeftTabs=Chiudere le schede a sinistra
closeRightTabs=Chiudere le schede a destra
addSerial=Seriale ...
addSerial=Seriale (sperimentale) ...
connect=Collegare
workspaces=Spazi di lavoro
manageWorkspaces=Gestire gli spazi di lavoro

View file

@ -469,7 +469,7 @@ closeOtherTabs=他のタブを閉じる
closeAllTabs=すべてのタブを閉じる
closeLeftTabs=タブを左に閉じる
closeRightTabs=タブを右に閉じる
addSerial=シリアル ...
addSerial=シリアル(実験)...
connect=接続する
workspaces=ワークスペース
manageWorkspaces=ワークスペースを管理する

View file

@ -469,7 +469,7 @@ closeOtherTabs=Andere tabbladen sluiten
closeAllTabs=Alle tabbladen sluiten
closeLeftTabs=Tabbladen naar links sluiten
closeRightTabs=Tabbladen naar rechts sluiten
addSerial=Serieel ...
addSerial=Serieel (Experimenteel) ...
connect=Maak verbinding met
workspaces=Werkruimten
manageWorkspaces=Werkruimten beheren

View file

@ -469,7 +469,7 @@ closeOtherTabs=Fecha outros separadores
closeAllTabs=Fecha todos os separadores
closeLeftTabs=Fecha os separadores à esquerda
closeRightTabs=Fecha os separadores à direita
addSerial=Série ...
addSerial=Série (Experimental) ...
connect=Liga-te
workspaces=Espaços de trabalho
manageWorkspaces=Gere espaços de trabalho

View file

@ -469,7 +469,7 @@ closeOtherTabs=Закрыть другие вкладки
closeAllTabs=Закрыть все вкладки
closeLeftTabs=Закрыть вкладки слева
closeRightTabs=Закрывать вкладки справа
addSerial=Серийный ...
addSerial=Последовательное (экспериментальное) ...
connect=Connect
workspaces=Рабочие пространства
manageWorkspaces=Управляй рабочими пространствами

View file

@ -470,7 +470,7 @@ closeOtherTabs=Diğer sekmeleri kapatın
closeAllTabs=Tüm sekmeleri kapat
closeLeftTabs=Sekmeleri sola doğru kapatın
closeRightTabs=Sekmeleri sağa doğru kapatın
addSerial=Seri ...
addSerial=Seri (Deneysel) ...
connect=Bağlan
workspaces=Çalışma Alanları
manageWorkspaces=Çalışma alanlarını yönetme

View file

@ -469,7 +469,7 @@ closeOtherTabs=关闭其他标签页
closeAllTabs=关闭所有标签页
closeLeftTabs=向左关闭标签
closeRightTabs=向右关闭标签页
addSerial=串行 ...
addSerial=串行(实验)...
connect=连接
workspaces=工作空间
manageWorkspaces=管理工作区