add proper accessibility text for vault list

This commit is contained in:
Armin Schrenk
2026-01-12 23:13:15 +01:00
parent 8e68a62ab0
commit 06726303fb
3 changed files with 40 additions and 4 deletions

View File

@@ -16,6 +16,7 @@ import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.layout.HBox;
import java.util.ResourceBundle;
// unscoped because each cell needs its own controller
public class VaultListCellController implements FxController {
@@ -23,9 +24,12 @@ public class VaultListCellController implements FxController {
private static final Insets COMPACT_INSETS = new Insets(6, 12, 6, 12);
private static final Insets DEFAULT_INSETS = new Insets(12);
private final ResourceBundle resourceBundle;
private final ObjectProperty<Vault> vault = new SimpleObjectProperty<>();
private final ObservableValue<VaultState.Value> vaultState;
private final ObservableValue<FontAwesome5Icon> glyph;
private final ObservableValue<Boolean> compactMode;
private final ObservableValue<String> accessibleText;
private AutoAnimator spinAnimation;
@@ -35,17 +39,21 @@ public class VaultListCellController implements FxController {
public HBox vaultListCell;
@Inject
VaultListCellController(Settings settings) {
this.glyph = vault.flatMap(Vault::stateProperty).map(this::getGlyphForVaultState);
VaultListCellController(Settings settings, ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
this.vaultState = vault.flatMap(Vault::stateProperty);
this.glyph = vaultState.map(this::getGlyphForVaultState);
this.accessibleText = vaultState.map(this::getAccessibleTextForVaultState);
this.compactMode = settings.compactMode;
}
public void initialize() {
this.spinAnimation = AutoAnimator.animate(Animations.createDiscrete360Rotation(vaultStateView)) //
.onCondition(vault.flatMap(Vault::stateProperty).map(VaultState.Value.PROCESSING::equals).orElse(false)) //
.onCondition(vaultState.map(VaultState.Value.PROCESSING::equals).orElse(false)) //
.afterStop(() -> vaultStateView.setRotate(0)) //
.build();
this.vaultListCell.paddingProperty().bind(compactMode.map(c -> c ? COMPACT_INSETS : DEFAULT_INSETS));
this.vaultListCell.accessibleTextProperty().bind(accessibleText);
}
// TODO deduplicate w/ VaultDetailController
@@ -62,6 +70,24 @@ public class VaultListCellController implements FxController {
}
}
private String getAccessibleTextForVaultState(VaultState.Value state) {
if (state != null) {
var translationKey = switch (state) {
case LOCKED -> "vault.state.locked";
case PROCESSING -> "vault.state.processing";
case UNLOCKED -> "vault.state.unlocked";
case NEEDS_MIGRATION -> "vault.state.migrationNeeded";
case MISSING -> "vault.state.missing";
case VAULT_CONFIG_MISSING, ALL_MISSING, ERROR -> "vault.state.error";
};
var localizedState = resourceBundle.getString(translationKey);
return resourceBundle.getString("main.vaultlist.listEntry").formatted(vault.get().getDisplayName(), localizedState);
} else {
return "";
}
}
/* Getter/Setter */
public ObservableValue<FontAwesome5Icon> glyphProperty() {

View File

@@ -22,7 +22,7 @@
<VBox>
<StackPane VBox.vgrow="ALWAYS">
<VBox>
<ListView fx:id="vaultList" editable="true" fixedCellSize="${controller.cellSize}">
<ListView fx:id="vaultList" editable="true" fixedCellSize="${controller.cellSize}" accessibleText="%main.vaultlist">
<contextMenu>
<fx:include source="vault_list_contextmenu.fxml"/>
</contextMenu>

View File

@@ -18,6 +18,14 @@ generic.button.next=Next
generic.button.print=Print
generic.button.remove=Remove
## Vault state
vault.state.locked=Locked
vault.state.unlocked=Unlocked
vault.state.missing=Missing
vault.state.migrationNeeded=Migration required
vault.state.processing=Processing
vault.state.error=Error
# Error
error.message=An error occurred
error.description=Cryptomator didn't expect this to happen. You can look up existing solutions for this error. Or if it has not been reported yet, feel free to do so.
@@ -402,6 +410,8 @@ stats.access.total=Total accesses: %d
# Main Window
## Vault List
main.vaultlist=Vaults
main.vaultlist.listEntry=Vault %s. %s
main.vaultlist.emptyList.onboardingInstruction=Click here to add a vault
main.vaultlist.contextMenu.remove=Remove…
main.vaultlist.contextMenu.lock=Lock