mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-07-08 11:30:42 +00:00
Rework identities
This commit is contained in:
@@ -56,7 +56,7 @@ public class ActionConfigComp extends SimpleRegionBuilder {
|
||||
});
|
||||
|
||||
var choice = new StoreListChoiceComp<>(
|
||||
listProp, DataStore.class, null, StoreViewState.get().getAllConnectionsCategory(), null, null);
|
||||
listProp, DataStore.class, null, StoreViewState.get().getAllConnectionsCategory(), null);
|
||||
choice.hide(listProp.emptyProperty());
|
||||
choice.maxHeight(450);
|
||||
return choice;
|
||||
|
||||
@@ -54,7 +54,7 @@ public class ActionConfirmComp extends SimpleRegionBuilder {
|
||||
}
|
||||
|
||||
var choice = new StoreListChoiceComp<>(
|
||||
listProp, DataStore.class, null, StoreViewState.get().getAllConnectionsCategory(), null, null);
|
||||
listProp, DataStore.class, null, StoreViewState.get().getAllConnectionsCategory(), null);
|
||||
choice.maxHeight(450);
|
||||
choice.setEditable(false);
|
||||
choice.hide(listProp.emptyProperty());
|
||||
|
||||
@@ -24,8 +24,10 @@ import javafx.scene.layout.Region;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -36,6 +38,9 @@ public class StoreChoiceComp<T extends DataStore> extends SimpleRegionBuilder {
|
||||
|
||||
private StoreChoicePopover<T> popover;
|
||||
|
||||
@Setter
|
||||
private boolean editable = true;
|
||||
|
||||
public StoreChoiceComp(
|
||||
DataStoreEntry self,
|
||||
ObjectProperty<DataStoreEntryRef<T>> selected,
|
||||
@@ -200,7 +205,12 @@ public class StoreChoiceComp<T extends DataStore> extends SimpleRegionBuilder {
|
||||
}, selected));
|
||||
editButton.describe(d -> d.nameKey("edit"));
|
||||
|
||||
var box = new InputGroupComp(List.of(RegionBuilder.of(() -> pane).hgrow(), editButton));
|
||||
var l = new ArrayList<BaseRegionBuilder<?,?>>();
|
||||
l.add(RegionBuilder.of(() -> pane).hgrow());
|
||||
if (editable) {
|
||||
l.add(editButton);
|
||||
}
|
||||
var box = new InputGroupComp(l);
|
||||
box.setMainReference(0);
|
||||
box.style("store-choice-comp");
|
||||
return box.build();
|
||||
|
||||
@@ -572,6 +572,7 @@ public class StoreEntryWrapper {
|
||||
}
|
||||
l.add(information.getValue());
|
||||
l.add(summary.getValue());
|
||||
l.add(notes.getValue());
|
||||
l.addAll(tags);
|
||||
return filter.matches(l);
|
||||
}
|
||||
|
||||
@@ -7,14 +7,17 @@ import io.xpipe.app.comp.base.*;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.ext.DataStore;
|
||||
import io.xpipe.app.ext.DataStoreCreationCategory;
|
||||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.ListProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.int4.fx.builders.common.AbstractRegionBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -22,12 +25,11 @@ import java.util.function.Predicate;
|
||||
|
||||
public class StoreListChoiceComp<T extends DataStore> extends SimpleRegionBuilder {
|
||||
|
||||
private final ListProperty<DataStoreEntryRef<T>> selectedList;
|
||||
protected final ListProperty<DataStoreEntryRef<T>> selectedList;
|
||||
private final Class<T> storeClass;
|
||||
private final Predicate<DataStoreEntryRef<T>> applicableCheck;
|
||||
private final StoreCategoryWrapper initialCategory;
|
||||
private final DataStoreCreationCategory creationCategory;
|
||||
private final Predicate<DataStoreEntryRef<T>> activeCheck;
|
||||
private boolean editable;
|
||||
|
||||
public StoreListChoiceComp(
|
||||
@@ -35,14 +37,13 @@ public class StoreListChoiceComp<T extends DataStore> extends SimpleRegionBuilde
|
||||
Class<T> storeClass,
|
||||
Predicate<DataStoreEntryRef<T>> applicableCheck,
|
||||
StoreCategoryWrapper initialCategory,
|
||||
DataStoreCreationCategory creationCategory, Predicate<DataStoreEntryRef<T>> activeCheck
|
||||
DataStoreCreationCategory creationCategory
|
||||
) {
|
||||
this.selectedList = selectedList;
|
||||
this.storeClass = storeClass;
|
||||
this.applicableCheck = applicableCheck;
|
||||
this.initialCategory = initialCategory;
|
||||
this.creationCategory = creationCategory;
|
||||
this.activeCheck = activeCheck;
|
||||
this.editable = true;
|
||||
}
|
||||
|
||||
@@ -51,6 +52,18 @@ public class StoreListChoiceComp<T extends DataStore> extends SimpleRegionBuilde
|
||||
return this;
|
||||
}
|
||||
|
||||
protected ObservableValue<String> getName(DataStoreEntryRef<T> ref) {
|
||||
var labelName = Bindings.createStringBinding(() -> {
|
||||
var base = ref.get().getName();
|
||||
return base;
|
||||
}, selectedList, AppI18n.activeLanguage());
|
||||
return labelName;
|
||||
}
|
||||
|
||||
protected BaseRegionBuilder<?, ?> buildCustomButtons(DataStoreEntryRef<T> ref) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Region createSimple() {
|
||||
var listBox = new ListBoxViewComp<>(
|
||||
@@ -61,12 +74,7 @@ public class StoreListChoiceComp<T extends DataStore> extends SimpleRegionBuilde
|
||||
return null;
|
||||
}
|
||||
|
||||
var labelName = Bindings.createStringBinding(() -> {
|
||||
var base = t.get().getName();
|
||||
var active = activeCheck != null && activeCheck.test(t);
|
||||
return base + (active ? " (" + AppI18n.get("active") + ")" : "");
|
||||
}, selectedList, AppI18n.activeLanguage());
|
||||
|
||||
var labelName = getName(t);
|
||||
var label = new LabelComp(labelName).apply(struc -> {
|
||||
struc.setGraphic(PrettyImageHelper.ofFixedSizeSquare(
|
||||
t.get().getEffectiveIconFile(), 16)
|
||||
@@ -82,6 +90,7 @@ public class StoreListChoiceComp<T extends DataStore> extends SimpleRegionBuilde
|
||||
selectedList.get().add(prior, t);
|
||||
}
|
||||
});
|
||||
up.describe(d -> d.nameKey("moveUp"));
|
||||
up.disable(Bindings.createBooleanBinding(
|
||||
() -> {
|
||||
return selectedList.get().indexOf(t) == 0;
|
||||
@@ -96,6 +105,7 @@ public class StoreListChoiceComp<T extends DataStore> extends SimpleRegionBuilde
|
||||
selectedList.get().add(next, t);
|
||||
}
|
||||
});
|
||||
down.describe(d -> d.nameKey("moveDown"));
|
||||
down.disable(Bindings.createBooleanBinding(
|
||||
() -> {
|
||||
return selectedList.get().indexOf(t) == selectedList.size() - 1;
|
||||
@@ -105,10 +115,20 @@ public class StoreListChoiceComp<T extends DataStore> extends SimpleRegionBuilde
|
||||
var delete = new IconButtonComp("mdal-delete_outline", () -> {
|
||||
selectedList.remove(t);
|
||||
});
|
||||
var row = editable
|
||||
? new HorizontalComp(List.of(label, RegionBuilder.hspacer(), up, down, delete))
|
||||
.spacing(5)
|
||||
: new HorizontalComp(List.of(label, RegionBuilder.hspacer()));
|
||||
delete.describe(d -> d.nameKey("delete"));
|
||||
var l = new ArrayList<BaseRegionBuilder<?, ?>>();
|
||||
l.add(label);
|
||||
l.add(RegionBuilder.hspacer());
|
||||
var custom = buildCustomButtons(t);
|
||||
if (custom != null) {
|
||||
l.add(custom);
|
||||
}
|
||||
if (editable) {
|
||||
l.add(up);
|
||||
l.add(down);
|
||||
l.add(delete);
|
||||
}
|
||||
var row = new HorizontalComp(l).spacing(5);
|
||||
return row.style("entry");
|
||||
},
|
||||
false)
|
||||
@@ -117,6 +137,7 @@ public class StoreListChoiceComp<T extends DataStore> extends SimpleRegionBuilde
|
||||
.apply(struc -> ((VBox) struc.getContent()).setSpacing(5));
|
||||
var selected = new SimpleObjectProperty<DataStoreEntryRef<T>>();
|
||||
var add = new StoreChoiceComp<>(null, selected, storeClass, applicableCheck, initialCategory, creationCategory);
|
||||
add.setEditable(false);
|
||||
selected.addListener((observable, oldValue, newValue) -> {
|
||||
if (newValue != null) {
|
||||
if (!selectedList.contains(newValue) && (applicableCheck == null || applicableCheck.test(newValue))) {
|
||||
|
||||
@@ -362,6 +362,7 @@ public abstract class DataStorage {
|
||||
|
||||
finalizeWithDependencies(entry);
|
||||
|
||||
var flatChildren = getStoreChildren(entry);
|
||||
var children = getDeepStoreChildren(entry);
|
||||
if (!sameParent) {
|
||||
var toRemove = Stream.concat(Stream.of(entry), children.stream()).toArray(DataStoreEntry[]::new);
|
||||
@@ -407,6 +408,12 @@ public abstract class DataStorage {
|
||||
listeners.forEach(storageListener -> storageListener.onStoreListUpdate());
|
||||
}
|
||||
|
||||
entry.setChildrenCache(null);
|
||||
var newFlatChildren = getStoreChildren(entry);
|
||||
if (!flatChildren.equals(newFlatChildren)) {
|
||||
listeners.forEach(storageListener -> storageListener.onStoreListUpdate());
|
||||
}
|
||||
|
||||
if (userScopeChanged) {
|
||||
updateUserScope(entry);
|
||||
}
|
||||
|
||||
Vendored
+1
@@ -46,6 +46,7 @@ The latest release of the [apple container runtime](https://github.com/apple/con
|
||||
- Add support for the wayland versions of freerdp
|
||||
- You can now configure additional custom launch arguments/options for Remmina and FreeRDP in the settings menu
|
||||
- Improve key mapping settings for Hashicorp Vault and OpenBao
|
||||
- The search filter now also checks for any associated connection notes
|
||||
|
||||
## Fixes
|
||||
|
||||
|
||||
@@ -82,7 +82,11 @@ public class IdentityApplyHubLeafProvider implements HubLeafProvider<IdentitySto
|
||||
&& !(ref.getStore().getSshIdentity() instanceof NoIdentityStrategy)
|
||||
&& ref.getStore().getSshIdentity().getPublicKeyStrategy() == null) {
|
||||
AppDialog.confirm("identityApplyMissingPublicKey");
|
||||
StoreCreationDialog.showEdit(ref.get());
|
||||
var toEdit = ref.getStore().getCustomEditTarget();
|
||||
if (toEdit == null) {
|
||||
toEdit = ref;
|
||||
}
|
||||
StoreCreationDialog.showEdit(toEdit.get());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@ public class IdentitySelectComp extends RegionBuilder<HBox> {
|
||||
null,
|
||||
selectedReference,
|
||||
IdentityStore.class,
|
||||
null,
|
||||
ref -> !MultiIdentityStore.isExclusivelyHeld(ref),
|
||||
StoreViewState.get().getAllIdentitiesCategory(),
|
||||
null,
|
||||
true,
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.xpipe.app.ext.SelfReferentialStore;
|
||||
import io.xpipe.app.ext.ValidationException;
|
||||
import io.xpipe.app.secret.SecretRetrievalStrategy;
|
||||
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
@@ -18,6 +19,8 @@ import lombok.experimental.SuperBuilder;
|
||||
@Getter
|
||||
public abstract class IdentityStore implements SelfReferentialStore, DataStore {
|
||||
|
||||
public abstract DataStoreEntryRef<IdentityStore> getCustomEditTarget();
|
||||
|
||||
public abstract UsernameStrategy getUsername();
|
||||
|
||||
public abstract SecretRetrievalStrategy getPassword();
|
||||
|
||||
@@ -4,6 +4,8 @@ import io.xpipe.app.comp.BaseRegionBuilder;
|
||||
import io.xpipe.app.ext.*;
|
||||
import io.xpipe.app.hub.comp.StoreSection;
|
||||
import io.xpipe.app.hub.comp.SystemStateComp;
|
||||
import io.xpipe.app.storage.DataStoreEntry;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
import io.xpipe.app.util.DocumentationLink;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
@@ -14,6 +16,11 @@ import java.util.List;
|
||||
|
||||
public abstract class IdentityStoreProvider implements DataStoreProvider {
|
||||
|
||||
@Override
|
||||
public DataStoreEntry getDisplayParent(DataStoreEntry store) {
|
||||
return MultiIdentityStore.getExclusiveHolder(store.ref()).map(DataStoreEntryRef::get).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocumentationLink getHelpLink() {
|
||||
return DocumentationLink.IDENTITIES;
|
||||
|
||||
@@ -27,6 +27,11 @@ public class LocalIdentityStore extends IdentityStore {
|
||||
EncryptedValue<SecretRetrievalStrategy> password;
|
||||
EncryptedValue<SshIdentityStrategy> sshIdentity;
|
||||
|
||||
@Override
|
||||
public DataStoreEntryRef<IdentityStore> getCustomEditTarget() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public UsernameStrategy.Fixed getUsername() {
|
||||
return new UsernameStrategy.Fixed(username);
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@ import io.xpipe.app.cred.SshIdentityStrategy;
|
||||
import io.xpipe.app.cred.UsernameStrategy;
|
||||
import io.xpipe.app.ext.StatefulDataStore;
|
||||
import io.xpipe.app.ext.UserScopeStore;
|
||||
import io.xpipe.app.ext.ValidationException;
|
||||
import io.xpipe.app.issue.ErrorEventFactory;
|
||||
import io.xpipe.app.secret.SecretRetrievalStrategy;
|
||||
import io.xpipe.app.storage.DataStorage;
|
||||
import io.xpipe.app.storage.DataStoreEntryRef;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import io.xpipe.app.util.Validators;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import lombok.Value;
|
||||
@@ -29,8 +31,20 @@ import java.util.UUID;
|
||||
public class MultiIdentityStore extends IdentityStore
|
||||
implements StatefulDataStore<MultiIdentityStoreState>, UserScopeStore {
|
||||
|
||||
public static boolean isExclusivelyHeld(DataStoreEntryRef<IdentityStore> ref) {
|
||||
return getExclusiveHolder(ref).isPresent();
|
||||
}
|
||||
|
||||
public static Optional<DataStoreEntryRef<MultiIdentityStore>> getExclusiveHolder(DataStoreEntryRef<IdentityStore> ref) {
|
||||
var exclusiveHolder = DataStorage.get().getStoreEntries().stream()
|
||||
.filter(entry -> entry.getValidity().isUsable() && entry.getStore() instanceof MultiIdentityStore m &&
|
||||
m.getExclusive() != null && m.getExclusive() && m.getAvailableIdentities().contains(ref)).findFirst();
|
||||
return exclusiveHolder.map(entry -> entry.ref());
|
||||
}
|
||||
|
||||
List<UUID> identities;
|
||||
boolean perUser;
|
||||
Boolean exclusive;
|
||||
Boolean perUser;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -87,14 +101,19 @@ public class MultiIdentityStore extends IdentityStore
|
||||
|
||||
@Override
|
||||
public List<DataStoreEntryRef<?>> getDependencies() {
|
||||
return List.of();
|
||||
return getAvailableIdentities().stream().<DataStoreEntryRef<?>>map(DataStoreEntryRef::asNeeded).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkComplete() {
|
||||
public void checkComplete() throws ValidationException {
|
||||
getSelectedOrThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataStoreEntryRef<IdentityStore> getCustomEditTarget() {
|
||||
return getSelected().orElse(null);
|
||||
}
|
||||
|
||||
public UsernameStrategy getUsername() {
|
||||
return getSelectedOrThrow().getStore().getUsername();
|
||||
}
|
||||
@@ -113,4 +132,9 @@ public class MultiIdentityStore extends IdentityStore
|
||||
public Class<MultiIdentityStoreState> getStateClass() {
|
||||
return MultiIdentityStoreState.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPerUser() {
|
||||
return perUser != null && perUser;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package io.xpipe.ext.base.identity;
|
||||
|
||||
import io.xpipe.app.comp.BaseRegionBuilder;
|
||||
import io.xpipe.app.comp.RegionBuilder;
|
||||
import io.xpipe.app.comp.base.HorizontalComp;
|
||||
import io.xpipe.app.comp.base.IconButtonComp;
|
||||
import io.xpipe.app.core.AppI18n;
|
||||
import io.xpipe.app.ext.DataStore;
|
||||
import io.xpipe.app.ext.DataStoreCreationCategory;
|
||||
@@ -10,9 +14,13 @@ import io.xpipe.app.hub.comp.StoreViewState;
|
||||
import io.xpipe.app.platform.OptionsBuilder;
|
||||
import io.xpipe.app.storage.*;
|
||||
|
||||
import io.xpipe.app.util.ObservableSubscriber;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleListProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.FXCollections;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -43,22 +51,52 @@ public class MultiIdentityStoreProvider extends IdentityStoreProvider {
|
||||
uuid, DataStorage.DEFAULT_CATEGORY_UUID, AppI18n.get("unknown"), null)));
|
||||
}
|
||||
}
|
||||
var perUser = new SimpleBooleanProperty(st.isPerUser());
|
||||
var exclusive = new SimpleObjectProperty<>(st.getExclusive());
|
||||
var perUser = new SimpleObjectProperty<>(st.getPerUser());
|
||||
|
||||
return new OptionsBuilder()
|
||||
var listUpdate = new ObservableSubscriber();
|
||||
var selected = new SimpleObjectProperty<DataStoreEntryRef<IdentityStore>>(st.getSelected().orElse(null));
|
||||
identities.addListener((observable, oldValue, newValue) -> {
|
||||
var hasActive = identities.contains(selected.get());
|
||||
if (!hasActive) {
|
||||
selected.set(identities.stream().filter(ref -> ref.get().getValidity().isUsable()).findFirst().orElse(null));
|
||||
listUpdate.trigger();
|
||||
}
|
||||
});
|
||||
|
||||
var choice = new StoreListChoiceComp<>(identities, IdentityStore.class,
|
||||
ref -> !(ref.get().equals(model.getExistingEntry())) && !identities.contains(ref) && !MultiIdentityStore.isExclusivelyHeld(ref),
|
||||
StoreViewState.get().getAllIdentitiesCategory(),
|
||||
DataStoreCreationCategory.IDENTITY) {
|
||||
|
||||
@Override
|
||||
protected ObservableValue<String> getName(DataStoreEntryRef<IdentityStore> ref) {
|
||||
var labelName = Bindings.createStringBinding(() -> {
|
||||
var base = ref.get().getName();
|
||||
var active = ref.equals(selected.get());
|
||||
return base + (active ? " (" + AppI18n.get("active") + ")" : "");
|
||||
}, selectedList, AppI18n.activeLanguage(), listUpdate);
|
||||
return labelName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseRegionBuilder<?, ?> buildCustomButtons(DataStoreEntryRef<IdentityStore> ref) {
|
||||
var select = new IconButtonComp("mdi2i-image-filter-center-focus", () -> {
|
||||
st.select(ref);
|
||||
selected.set(ref);
|
||||
listUpdate.trigger();
|
||||
});
|
||||
select.disable(ref.get().getProvider() == null);
|
||||
select.describe(d -> d.nameKey("makeActive"));
|
||||
return new HorizontalComp(List.of(select, RegionBuilder.hspacer(5)));
|
||||
}
|
||||
};
|
||||
var options = new OptionsBuilder()
|
||||
.nameAndDescription("multiIdentityList")
|
||||
.addComp(
|
||||
new StoreListChoiceComp<>(
|
||||
identities,
|
||||
IdentityStore.class,
|
||||
ref -> !(ref.getStore() instanceof MultiIdentityStore) && !identities.contains(ref),
|
||||
StoreViewState.get().getAllIdentitiesCategory(),
|
||||
DataStoreCreationCategory.IDENTITY,
|
||||
ref -> {
|
||||
var l = identities.stream().filter(r -> r.getStore() != null).toList();
|
||||
return l.size() > 0 && l.getFirst() == ref;
|
||||
}),
|
||||
.addComp(choice,
|
||||
identities)
|
||||
.nameAndDescription("multiIdentityExclusive")
|
||||
.addToggle(exclusive)
|
||||
.nameAndDescription(
|
||||
DataStorageUserHandler.getInstance().getActiveUser() != null
|
||||
? "identityPerUser"
|
||||
@@ -75,6 +113,7 @@ public class MultiIdentityStoreProvider extends IdentityStoreProvider {
|
||||
return MultiIdentityStore.builder()
|
||||
.identities(st.getIdentities())
|
||||
.perUser(perUser.get())
|
||||
.exclusive(exclusive.get())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -85,11 +124,16 @@ public class MultiIdentityStoreProvider extends IdentityStoreProvider {
|
||||
|
||||
return MultiIdentityStore.builder()
|
||||
.identities(all)
|
||||
.exclusive(exclusive.get())
|
||||
.perUser(perUser.get())
|
||||
.build();
|
||||
},
|
||||
store)
|
||||
.buildDialog();
|
||||
store);
|
||||
var dialog = new GuiDialog(options, entry -> {
|
||||
var finalStore = (MultiIdentityStore) entry.getStore();
|
||||
finalStore.select(selected.get());
|
||||
});
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -117,6 +117,11 @@ public class PasswordManagerIdentityStore extends IdentityStore
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataStoreEntryRef<IdentityStore> getCustomEditTarget() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public UsernameStrategy getUsername() {
|
||||
return new UsernameStrategy.Dynamic(() -> {
|
||||
var r = retrieve();
|
||||
|
||||
@@ -38,6 +38,11 @@ public class SyncedIdentityStore extends IdentityStore implements UserScopeStore
|
||||
return getSelfEntry().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataStoreEntryRef<IdentityStore> getCustomEditTarget() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public UsernameStrategy.Fixed getUsername() {
|
||||
return new UsernameStrategy.Fixed(username);
|
||||
}
|
||||
|
||||
@@ -152,8 +152,7 @@ public class ScriptStoreProvider implements DataStoreProvider {
|
||||
scriptStore -> !scriptStore.get().equals(model.getExistingEntry())
|
||||
&& !others.contains(scriptStore),
|
||||
StoreViewState.get().getAllScriptsCategory(),
|
||||
DataStoreCreationCategory.SCRIPT,
|
||||
null),
|
||||
DataStoreCreationCategory.SCRIPT),
|
||||
others)
|
||||
.bind(
|
||||
() -> {
|
||||
|
||||
Generated
+5
@@ -2361,3 +2361,8 @@ webtopQrCodeTitle=Scan the code for $NAME$ with the XPipe app
|
||||
done=Done
|
||||
webtopConnectHostChoice=Host address
|
||||
webtopConnectHostChoiceDescription=The externally reachable hostname/IP and the webtop container SSH port
|
||||
moveDown=Move down
|
||||
moveUp=Move up
|
||||
makeActive=Make active
|
||||
multiIdentityExclusive=Make identities exclusive
|
||||
multiIdentityExclusiveDescription=Show all contained identities as children of this multi identity for better organization
|
||||
|
||||
Reference in New Issue
Block a user