Rework [stage]

This commit is contained in:
crschnick
2026-09-03 07:19:15 +00:00
parent 0e709b6d43
commit 30c4700688
17 changed files with 78 additions and 86 deletions
@@ -95,13 +95,7 @@ public class AppLayoutModel {
if (prefs != null && prefs.getRequiresRestart().get()) {
GlobalTimer.delay(
() -> {
if (!AppOperationMode.isInShutdown()) {
var modal = ModalOverlay.of(
"prefsRestartTitle", AppDialog.dialogTextKey("prefsRestartContent"));
modal.addButton(ModalButton.cancel());
modal.addButton(new ModalButton("restart", () -> AppRestart.restart(), true, true));
modal.show();
}
showPrefsRestartDialog();
},
Duration.ofSeconds(1));
AppPrefs.get().getRequiresRestart().set(false);
@@ -120,6 +114,12 @@ public class AppLayoutModel {
}
});
AppPrefs.get().getRequiresRestart().addListener((observable, oldValue, newValue) -> {
if (newValue && !entries.get(2).equals(selected.getValue())) {
showPrefsRestartDialog();
}
});
var portraitExpanded = new SimpleBooleanProperty(true);
var toggleExpand = new AppLayoutModel.QueueEntry(
AppI18n.observable("expand"),
@@ -151,6 +151,16 @@ public class AppLayoutModel {
AppSizeBreakpoints.compactMode()));
}
private void showPrefsRestartDialog() {
if (!AppOperationMode.isInShutdown()) {
var modal = ModalOverlay.of(
"prefsRestartTitle", AppDialog.dialogTextKey("prefsRestartContent"));
modal.addButton(ModalButton.cancel());
modal.addButton(new ModalButton("restart", () -> AppRestart.restart(), true, true));
modal.show();
}
}
public static void reset() {
if (INSTANCE == null) {
return;
@@ -99,42 +99,23 @@ public class StoreCategoryConfigComp extends SimpleRegionBuilder {
: AppI18n.observable("categorySync"))
.description("categorySyncDescription")
.addComp(createToggle(sync, parentConfig.getSync()), sync)
.disable(syncDisable))
.title("connectionHandling")
.sub(new OptionsBuilder()
.nameAndDescription("categoryDontAllowScripts")
.addComp(createToggle(scripts, parentConfig.getDontAllowScripts()), scripts)
.hide(!connectionsCategory)
.nameAndDescription("categoryConfirmAllModifications")
.addComp(createToggle(confirm, parentConfig.getConfirmAllModifications()), confirm)
.hide(!connectionsCategory))
.title("connectionConfiguration")
.sub(new OptionsBuilder()
.nameAndDescription("categoryFreeze")
.addComp(createToggle(freeze, parentConfig.getFreezeConfigurations()), freeze)
.hide(!connectionsCategory)
.nameAndDescription("categoryDefaultIdentity")
.addComp(
new StoreChoiceComp<>(
null,
identityRef,
DataStore.class,
null,
StoreViewState.get().getAllIdentitiesCategory(),
DataStoreCreationCategory.IDENTITY),
identityRef)
.hide(!connectionsCategory)
.nameAndDescription("categoryDefaultGateway")
.addComp(
new StoreChoiceComp<>(
null,
gatewayRef,
DataStore.class,
null,
StoreViewState.get().getAllConnectionsCategory(),
DataStoreCreationCategory.HOST),
gatewayRef)
.hide(!connectionsCategory))
.disable(syncDisable));
if (connectionsCategory) {
options.title("connectionConfiguration").sub(new OptionsBuilder()
.nameAndDescription("categoryDefaultIdentity")
.addComp(new StoreChoiceComp<>(null, identityRef, DataStore.class, null, StoreViewState.get().getAllIdentitiesCategory(),
DataStoreCreationCategory.IDENTITY), identityRef)
.nameAndDescription("categoryDefaultGateway")
.addComp(new StoreChoiceComp<>(null, gatewayRef, DataStore.class, null, StoreViewState.get().getAllConnectionsCategory(),
DataStoreCreationCategory.HOST), gatewayRef));
options.title("connectionHandling").sub(new OptionsBuilder().nameAndDescription("categoryDontAllowScripts")
.addComp(createToggle(scripts, parentConfig.getDontAllowScripts()), scripts)
.nameAndDescription("categoryConfirmAllModifications")
.addComp(createToggle(confirm, parentConfig.getConfirmAllModifications()), confirm).nameAndDescription("categoryFreeze")
.addComp(createToggle(freeze, parentConfig.getFreezeConfigurations()), freeze));
}
options
.bind(
() -> {
return new DataStoreCategoryConfig(
@@ -43,7 +43,7 @@ public class StoreCreationModel {
ObservableValue<DataStoreEntry> entry;
BooleanProperty skippable = new SimpleBooleanProperty();
BooleanProperty connectable = new SimpleBooleanProperty();
StringProperty name;
Property<String> name;
DataStoreEntry existingEntry;
List<DataStore> existingDependencies;
boolean staticDisplay;
@@ -57,7 +57,6 @@ public class DenseStoreEntryComp extends StoreEntryComp {
grid.widthProperty()));
var notes = new StoreNotesComp(getWrapper()).build();
var templateIcon = createTemplateIcon().build();
var userIcon = createScopeIcon().build();
var pinIcon = createPinIcon().build();
var info = createInformation().build();
var active = new StoreActiveComp(getWrapper()).build();
@@ -137,7 +136,7 @@ public class DenseStoreEntryComp extends StoreEntryComp {
nameBoxEntries.add(name);
nameBoxEntries.add(new Spacer(2, Orientation.HORIZONTAL));
nameBoxEntries.add(tags);
nameBoxEntries.addAll(List.of(index, active, templateIcon, userIcon, pinIcon, notes));
nameBoxEntries.addAll(List.of(index, active, templateIcon, pinIcon, notes));
var nameBox = new HBox(nameBoxEntries.toArray(Node[]::new));
nameBox.setSpacing(4);
nameBox.setAlignment(Pos.CENTER_LEFT);
@@ -139,22 +139,6 @@ public interface StoreEntryBadge {
return of("mdi2a-account", s);
}
static StoreEntryBadge ofUsername(String s) {
if (s == null) {
return null;
}
return of("mdi2a-account", s).withCopyAction();
}
static StoreEntryBadge ofUsername(String display, String copy) {
if (display == null) {
return null;
}
return of("mdi2a-account", display).withCopyAction(copy);
}
static StoreEntryBadge ofPassword(String s) {
if (s == null) {
return null;
@@ -19,7 +19,7 @@ public class StoreNotesComp extends RegionBuilder<Button> {
var prop = new SimpleStringProperty(initial);
var md = new MarkdownEditorComp(prop, "notes-" + wrapper.getName().getValue())
.prefWidth(700)
.prefHeight(800);
.maxHeight(800);
var modal = ModalOverlay.of(new ReadOnlyStringWrapper(wrapper.getName().getValue()), md, null);
if (wrapper.getNotes().getValue() != null) {
@@ -32,7 +32,6 @@ public class StoreNotesComp extends RegionBuilder<Button> {
true,
false));
}
modal.addButton(new ModalButton("cancel", () -> {}, true, false));
modal.addButton(new ModalButton(
"apply",
() -> {
@@ -74,6 +74,11 @@ public class ErrorEventFactory {
return "Invalid file path: " + ipe.getMessage();
}
if (t instanceof UnsatisfiedLinkError ule) {
// Don't include full PATH variable in message
return ule.getMessage().split(":")[0];
}
if (t instanceof InvocationTargetException ite && ite.getCause() != null && ite.getCause() != t) {
return formatThrowableMessage(ite.getCause());
}
@@ -5,6 +5,7 @@ import io.xpipe.app.comp.SimpleRegionBuilder;
import io.xpipe.app.comp.base.*;
import io.xpipe.app.core.App;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.platform.BindingsHelper;
import io.xpipe.app.platform.DerivedObservableList;
import io.xpipe.app.platform.LabelGraphic;
@@ -54,6 +55,10 @@ public class PasswordManagerTestComp extends SimpleRegionBuilder {
this.showSettings = showSettings;
}
protected void selectFromList(PasswordManager.ListEntry entry) {
value.setValue(entry.getKey());
}
@Override
protected Region createSimple() {
var prefs = AppPrefs.get();
@@ -87,7 +92,15 @@ public class PasswordManagerTestComp extends SimpleRegionBuilder {
struc.setDisable(true);
status.set(" " + AppI18n.get("querying"));
ThreadHelper.runFailableAsync(() -> {
var list = PasswordManagerKeyList.queryList(false);
List<PasswordManager.ListEntry> list;
try {
list = PasswordManagerKeyList.queryList(false);
} catch (Exception e) {
struc.setDisable(false);
status.set(null);
ErrorEventFactory.fromThrowable(e).handle();
return;
}
Platform.runLater(() -> {
struc.setDisable(false);
@@ -134,7 +147,7 @@ public class PasswordManagerTestComp extends SimpleRegionBuilder {
var buttonName = entry.getTitle();
var entryButton = new ButtonComp(new ReadOnlyObjectWrapper<>(buttonName), () -> {
popover.hide();
value.setValue(entry.getKey());
selectFromList(entry);
});
entryButton.maxWidth(400);
entryButton.style(Styles.FLAT);
@@ -32,6 +32,8 @@ public interface DataStorageAccessHandler {
boolean isAccessRestricted();
boolean isAccessSubRestricted();
boolean isAccessible();
DataStorageAccessType getType();
@@ -132,7 +132,7 @@ public abstract class DataStorageElement {
public abstract boolean isInStorage();
public abstract Path[] getShareableFiles();
public abstract List<Path> getSyncableFiles();
public void notifyUpdate(boolean used, boolean modified) {
if (used) {
@@ -40,7 +40,7 @@ public class DataStoreAccessScopeComp extends SimpleRegionBuilder {
var handler = DataStorageAccessHandler.getInstance();
var auth = handler.getType();
if (auth != DataStorageAccessType.ROLE || !handler.isAccessible()) {
if (auth != DataStorageAccessType.ROLE || !handler.isAccessible() || !handler.isAccessSubRestricted()) {
var l = new LabelComp(AppI18n.observable("unavailable"));
var settings = new ButtonComp(null, new FontIcon("mdomz-settings"), () -> {
@@ -16,6 +16,7 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.*;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
@@ -262,8 +263,8 @@ public class DataStoreCategory extends DataStorageElement {
}
@Override
public Path[] getShareableFiles() {
return new Path[] {directory.resolve("category.json")};
public List<Path> getSyncableFiles() {
return List.of(directory.resolve("category.json"));
}
public void writeDataToDisk() throws Exception {
@@ -529,11 +529,10 @@ public class DataStoreEntry extends DataStorageElement {
}
@Override
public Path[] getShareableFiles() {
var notes = directory.resolve("notes.md");
var list = List.of(directory.resolve("store.json"), directory.resolve("entry.json"));
return Stream.concat(list.stream(), Files.exists(notes) ? Stream.of(notes) : Stream.of())
.toArray(Path[]::new);
public List<Path> getSyncableFiles() {
var list = List.of(directory.resolve("store.json"), directory.resolve("entry.json"),
directory.resolve("notes.md"), directory.resolve("notes.json"));
return list;
}
public boolean isAccessible() {
@@ -594,14 +593,14 @@ public class DataStoreEntry extends DataStorageElement {
Files.writeString(directory.resolve("entry.json"), this.entryNode.getWriteString());
}
var normalNotesFile = directory.resolve("notes.md");
var encryptedNotesFile = directory.resolve("notes.json");
Files.deleteIfExists(normalNotesFile);
Files.deleteIfExists(encryptedNotesFile);
this.notesNode = this.notesNode != null ? this.notesNode.prepareForWrite(this, false, getNotes()) : null;
if (this.notesNode != null && this.notesNode.requiresWrite()) {
var normalNotesFile = directory.resolve("notes.md");
var encryptedNotesFile = directory.resolve("notes.json");
Files.deleteIfExists(normalNotesFile);
Files.deleteIfExists(encryptedNotesFile);
var file = this.notesNode.isEncrypted() ? encryptedNotesFile : normalNotesFile;
Files.writeString(file, this.notesNode.getWriteString());
Files.writeString(file, this.notesNode.isEncrypted() ? this.notesNode.getWriteString() : this.notesNode.getValue());
}
this.storeNode = this.storeNode.prepareForWrite(this, true, getStore());
@@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
public class StandardStorage extends DataStorage {
@@ -104,7 +103,7 @@ public class StandardStorage extends DataStorage {
}
for (DataStoreCategory cat : new ArrayList<>(storeCategories)) {
if (Arrays.stream(cat.getShareableFiles()).noneMatch(Files::exists)) {
if (cat.getSyncableFiles().stream().noneMatch(Files::exists)) {
deleteStoreCategory(cat, false, false);
}
}
@@ -155,7 +154,7 @@ public class StandardStorage extends DataStorage {
selectedCategory = getStoreCategoryIfPresent(DEFAULT_CATEGORY_UUID).orElseThrow();
for (DataStoreEntry entry : new ArrayList<>(getStoreEntries())) {
if (Arrays.stream(entry.getShareableFiles()).noneMatch(Files::exists)) {
if (entry.getSyncableFiles().stream().noneMatch(Files::exists)) {
deleteStoreEntry(entry);
}
}
@@ -39,7 +39,7 @@ public class WebtopDisplayScale {
initialScale = clamped;
} else if (!initialScale.equals(clamped)) {
AppPrefs.get().uiScale.setValue(clamped);
AppRestart.restart();
AppPrefs.get().getRequiresRestart().set(true);
return true;
}
@@ -52,6 +52,6 @@ public abstract class IdentityStoreProvider implements DataStoreProvider {
var password = st.getPassword() == null || st.getPassword() instanceof SecretNoneStrategy ? null : "Password";
var key = st.getSshIdentity() == null || st.getSshIdentity() instanceof NoIdentityStrategy ? null : "Key";
return StoreEntryInformation.of(
StoreEntryBadge.ofUsername(user), StoreEntryBadge.ofPassword(password), StoreEntryBadge.ofKey(key));
StoreEntryBadge.ofAuth(user), StoreEntryBadge.ofPassword(password), StoreEntryBadge.ofKey(key));
}
}
+1 -1
View File
@@ -1 +1 @@
24.0-65
24.0-66