This commit is contained in:
Armin Schrenk 2023-11-29 18:45:52 +01:00
parent 7d281e2878
commit b895ac69fb
No known key found for this signature in database
GPG Key ID: 8F2992163CBBA7FC
2 changed files with 61 additions and 14 deletions

View File

@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Named;
import javafx.application.Platform;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
@ -34,10 +35,9 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.concurrent.ExecutorService;
@AddVaultWizardScoped
public class CreateNewVaultLocationController implements FxController {
@ -49,13 +49,14 @@ public class CreateNewVaultLocationController implements FxController {
private final Stage window;
private final Lazy<Scene> chooseNameScene;
private final Lazy<Scene> chooseExpertSettingsScene;
private final List<RadioButton> locationPresetBtns;
private final ObjectProperty<Path> vaultPath;
private final StringProperty vaultName;
private final ExecutorService backgroundExecutor;
private final ResourceBundle resourceBundle;
private final ObservableValue<VaultPathStatus> vaultPathStatus;
private final ObservableValue<Boolean> validVaultPath;
private final BooleanProperty usePresetPath;
private final BooleanProperty loadingPresetLocations = new SimpleBooleanProperty(false);
private Path customVaultPath = DEFAULT_CUSTOM_VAULT_PATH;
@ -73,25 +74,18 @@ public class CreateNewVaultLocationController implements FxController {
@FxmlScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS) Lazy<Scene> chooseExpertSettingsScene, //
ObjectProperty<Path> vaultPath, //
@Named("vaultName") StringProperty vaultName, //
ResourceBundle resourceBundle) {
ExecutorService backgroundExecutor, ResourceBundle resourceBundle) {
this.window = window;
this.chooseNameScene = chooseNameScene;
this.chooseExpertSettingsScene = chooseExpertSettingsScene;
this.vaultPath = vaultPath;
this.vaultName = vaultName;
this.backgroundExecutor = backgroundExecutor;
this.resourceBundle = resourceBundle;
this.vaultPathStatus = ObservableUtil.mapWithDefault(vaultPath, this::validatePath, new VaultPathStatus(false, "error.message"));
this.validVaultPath = ObservableUtil.mapWithDefault(vaultPathStatus, VaultPathStatus::valid, false);
this.vaultPathStatus.addListener(this::updateStatusLabel);
this.usePresetPath = new SimpleBooleanProperty();
this.locationPresetBtns = LocationPresetsProvider.loadAll(LocationPresetsProvider.class) //
.flatMap(LocationPresetsProvider::getLocations) //
.sorted(Comparator.comparing(LocationPreset::name)) //
.map(preset -> { //
var btn = new RadioButton(preset.name());
btn.setUserData(preset.path());
return btn;
}).toList();
}
private VaultPathStatus validatePath(Path p) throws NullPointerException {
@ -137,12 +131,51 @@ public class CreateNewVaultLocationController implements FxController {
@FXML
public void initialize() {
radioButtonVBox.getChildren().addAll(1, locationPresetBtns); //first item is the list header
locationPresetsToggler.getToggles().addAll(locationPresetBtns);
backgroundExecutor.submit(this::loadLocationPresets);
locationPresetsToggler.selectedToggleProperty().addListener(this::togglePredefinedLocation);
usePresetPath.bind(locationPresetsToggler.selectedToggleProperty().isNotEqualTo(customRadioButton));
}
private void loadLocationPresets() {
Platform.runLater(() -> loadingPresetLocations.set(true));
LocationPresetsProvider.loadAll(LocationPresetsProvider.class) //
.flatMap(LocationPresetsProvider::getLocations) //we do not use sorted(), because it evaluates the stream elements, blocking until all elements are gathered
.forEach(this::createRadioButtonFor);
Platform.runLater(() -> loadingPresetLocations.set(false));
}
private void createRadioButtonFor(LocationPreset preset) {
Platform.runLater(() -> {
var btn = new RadioButton(preset.name());
btn.setUserData(preset.path());
//in place sorting
var vboxElements = radioButtonVBox.getChildren();
boolean added = false;
int listIndex = 0; //first item of vbox is the list header
while (listIndex < vboxElements.size()) {
listIndex++;
if (vboxElements.get(listIndex) instanceof RadioButton rb) {
//another radio button
if (rb.getText().compareTo(preset.name()) > 0) {
vboxElements.add(listIndex, btn);
added = true;
break;
}
} else {
//end of all radiobuttons
break;
}
}
if (!added) {
vboxElements.add(listIndex, btn);
}
locationPresetsToggler.getToggles().add(btn);
});
}
private void togglePredefinedLocation(@SuppressWarnings("unused") ObservableValue<? extends Toggle> observable, @SuppressWarnings("unused") Toggle oldValue, Toggle newValue) {
var storagePath = Optional.ofNullable((Path) newValue.getUserData()).orElse(customVaultPath);
vaultPath.set(storagePath.resolve(vaultName.get()));
@ -200,6 +233,14 @@ public class CreateNewVaultLocationController implements FxController {
return validVaultPath.getValue();
}
public boolean isLoadingPresetLocations() {
return loadingPresetLocations.getValue();
}
public BooleanProperty loadingPresetLocationsProperty() {
return loadingPresetLocations;
}
public BooleanProperty usePresetPathProperty() {
return usePresetPath;
}

View File

@ -11,6 +11,7 @@
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<?import org.cryptomator.ui.controls.FontAwesome5Spinner?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.addvaultwizard.CreateNewVaultLocationController"
@ -40,6 +41,11 @@
</graphic>
</Button>
</HBox>
<Label wrapText="true" text="Checking local filesystem for default cloud storage directories..." visible="${controller.loadingPresetLocations}" managed="${controller.loadingPresetLocations}">
<graphic>
<FontAwesome5Spinner />
</graphic>
</Label>
</VBox>
<Region prefHeight="12" VBox.vgrow="NEVER"/>