More rework

This commit is contained in:
crschnick 2024-06-10 18:51:37 +00:00
parent b4800bdecd
commit 02b9ba6062
10 changed files with 77 additions and 53 deletions

View file

@ -103,7 +103,7 @@ public class DenseStoreEntryComp extends StoreEntryComp {
grid.getColumnConstraints().addAll(infoCC, custom);
var cr = content != null ? content.createRegion() : new Region();
var bb = createButtonBar().createRegion();
var bb = createButtonBar();
var controls = new HBox(cr, bb);
controls.setFillHeight(true);
controls.setAlignment(Pos.CENTER_RIGHT);

View file

@ -51,7 +51,7 @@ public class StandardStoreEntryComp extends StoreEntryComp {
var custom = new ColumnConstraints(0, customSize, customSize);
custom.setHalignment(HPos.RIGHT);
var cr = content != null ? content.createRegion() : new Region();
var bb = createButtonBar().createRegion();
var bb = createButtonBar();
var controls = new HBox(cr, bb);
controls.setFillHeight(true);
HBox.setHgrow(cr, Priority.ALWAYS);

View file

@ -1,5 +1,6 @@
package io.xpipe.app.comp.store;
import atlantafx.base.layout.InputGroup;
import atlantafx.base.theme.Styles;
import io.xpipe.app.comp.base.LoadingOverlayComp;
import io.xpipe.app.core.*;
@ -9,8 +10,12 @@ import io.xpipe.app.fxcomps.SimpleComp;
import io.xpipe.app.fxcomps.SimpleCompStructure;
import io.xpipe.app.fxcomps.augment.ContextMenuAugment;
import io.xpipe.app.fxcomps.augment.GrowAugment;
import io.xpipe.app.fxcomps.impl.*;
import io.xpipe.app.fxcomps.impl.IconButtonComp;
import io.xpipe.app.fxcomps.impl.LabelComp;
import io.xpipe.app.fxcomps.impl.PrettyImageHelper;
import io.xpipe.app.fxcomps.impl.TooltipAugment;
import io.xpipe.app.fxcomps.util.BindingsHelper;
import io.xpipe.app.fxcomps.util.DerivedObservableList;
import io.xpipe.app.fxcomps.util.PlatformThread;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.storage.DataStorage;
@ -199,40 +204,27 @@ public abstract class StoreEntryComp extends SimpleComp {
return stack;
}
protected Comp<?> createButtonBar() {
var list = new ArrayList<Comp<?>>();
for (var p : wrapper.getActionProviders()) {
var def = p.getDefaultDataStoreCallSite();
if (def != null && def.equals(wrapper.getDefaultActionProvider().getValue())) {
continue;
}
protected Region createButtonBar() {
var list = new DerivedObservableList<>(wrapper.getActionProviders(), false);
var buttons = list.mapped(actionProvider -> {
var button = buildButton(actionProvider);
return button != null ? button.createRegion() : null;
}).filtered(region -> region != null).getList();
var button = buildButton(p);
if (button != null) {
list.add(button);
}
}
var settingsButton = createSettingsButton();
list.add(settingsButton);
if (list.size() > 1) {
list.getFirst().styleClass(Styles.LEFT_PILL);
for (int i = 1; i < list.size() - 1; i++) {
list.get(i).styleClass(Styles.CENTER_PILL);
}
list.getLast().styleClass(Styles.RIGHT_PILL);
}
list.forEach(comp -> {
comp.apply(struc -> {
struc.get().getStyleClass().remove(Styles.FLAT);
});
});
return new HorizontalComp(list)
.apply(struc -> {
struc.get().setAlignment(Pos.CENTER_RIGHT);
struc.get().setPadding(new Insets(5));
})
.styleClass("button-bar");
var ig = new InputGroup();
Runnable update = () -> {
var l = new ArrayList<Node>(buttons);
var settingsButton = createSettingsButton().createRegion();
l.add(settingsButton);
l.forEach(o -> o.getStyleClass().remove(Styles.FLAT));
ig.getChildren().setAll(l);
};
buttons.subscribe(update);
update.run();
ig.setAlignment(Pos.CENTER_RIGHT);
ig.setPadding(new Insets(5));
ig.getStyleClass().add("button-bar");
return ig;
}
private Comp<?> buildButton(ActionProvider p) {

View file

@ -10,6 +10,7 @@ import io.xpipe.app.storage.DataStoreColor;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.util.ThreadHelper;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import lombok.Getter;
import java.time.Duration;
@ -25,8 +26,8 @@ public class StoreEntryWrapper {
private final BooleanProperty disabled = new SimpleBooleanProperty();
private final BooleanProperty busy = new SimpleBooleanProperty();
private final Property<DataStoreEntry.Validity> validity = new SimpleObjectProperty<>();
private final List<ActionProvider> actionProviders;
private final Property<ActionProvider.DefaultDataStoreCallSite<?>> defaultActionProvider;
private final ListProperty<ActionProvider> actionProviders = new SimpleListProperty<>(FXCollections.observableArrayList());
private final Property<ActionProvider> defaultActionProvider = new SimpleObjectProperty<>();
private final BooleanProperty deletable = new SimpleBooleanProperty();
private final BooleanProperty expanded = new SimpleBooleanProperty();
private final Property<Object> persistentState = new SimpleObjectProperty<>();
@ -40,7 +41,6 @@ public class StoreEntryWrapper {
this.entry = entry;
this.name = new SimpleStringProperty(entry.getName());
this.lastAccess = new SimpleObjectProperty<>(entry.getLastAccess().minus(Duration.ofMillis(500)));
this.actionProviders = new ArrayList<>();
ActionProvider.ALL.stream()
.filter(dataStoreActionProvider -> {
return !entry.isDisabled()
@ -55,7 +55,6 @@ public class StoreEntryWrapper {
.forEach(dataStoreActionProvider -> {
actionProviders.add(dataStoreActionProvider);
});
this.defaultActionProvider = new SimpleObjectProperty<>();
this.notes = new SimpleObjectProperty<>(new StoreNotes(entry.getNotes(), entry.getNotes()));
setupListeners();
}
@ -162,22 +161,21 @@ public class StoreEntryWrapper {
.isAssignableFrom(entry.getStore().getClass())
&& e.getDefaultDataStoreCallSite().isApplicable(entry.ref()))
.findFirst()
.map(ActionProvider::getDefaultDataStoreCallSite)
.orElse(null);
this.defaultActionProvider.setValue(defaultProvider);
this.actionProviders.clear();
try {
ActionProvider.ALL.stream()
var newProviders = ActionProvider.ALL.stream()
.filter(dataStoreActionProvider -> {
return showActionProvider(dataStoreActionProvider);
return !dataStoreActionProvider.equals(defaultProvider) && showActionProvider(dataStoreActionProvider);
})
.sorted(Comparator.comparing(
actionProvider -> actionProvider.getLeafDataStoreCallSite() != null &&
actionProvider.getLeafDataStoreCallSite().isSystemAction()))
.forEach(dataStoreActionProvider -> {
actionProviders.add(dataStoreActionProvider);
});
.toList();
if (!actionProviders.equals(newProviders)) {
actionProviders.setAll(newProviders);
}
} catch (Exception ex) {
ErrorEvent.fromThrowable(ex).handle();
}
@ -224,7 +222,7 @@ public class StoreEntryWrapper {
var found = getDefaultActionProvider().getValue();
entry.notifyUpdate(true, false);
if (found != null) {
found.createAction(entry.ref()).execute();
found.getDefaultDataStoreCallSite().createAction(entry.ref()).execute();
} else {
entry.setExpanded(!entry.isExpanded());
}

View file

@ -171,7 +171,7 @@ public class AppPrefs {
new SshCategory(),
new LocalShellCategory(),
new SecurityCategory(),
new HttpServerCategory(),
new HttpApiCategory(),
new TroubleshootCategory(),
new DeveloperCategory())
.filter(appPrefsCategory -> appPrefsCategory.show())

View file

@ -4,11 +4,11 @@ import io.xpipe.app.beacon.AppBeaconServer;
import io.xpipe.app.fxcomps.Comp;
import io.xpipe.app.util.OptionsBuilder;
public class HttpServerCategory extends AppPrefsCategory {
public class HttpApiCategory extends AppPrefsCategory {
@Override
protected String getId() {
return "httpServer";
return "httpApi";
}
@Override

View file

@ -440,6 +440,7 @@ public abstract class DataStorage {
}
}
});
refreshEntries();
saveAsync();
toAdd.forEach(dataStoreEntryRef -> dataStoreEntryRef.get().getProvider().onChildrenRefresh(dataStoreEntryRef.getEntry()));
toUpdate.forEach(dataStoreEntryRef -> dataStoreEntryRef.getKey().getProvider().onChildrenRefresh(dataStoreEntryRef.getKey()));

View file

@ -238,6 +238,35 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
.addFile(configuration.getScriptFile());
}
};
ExternalTerminalType FOOT = new SimplePathType("app.foot", "foot", true) {
@Override
public String getWebsite() {
return "https://codeberg.org/dnkl/foot";
}
@Override
public boolean supportsTabs() {
return false;
}
@Override
public boolean isRecommended() {
return false;
}
@Override
public boolean supportsColoredTitle() {
return true;
}
@Override
protected CommandBuilder toCommand(LaunchConfiguration configuration) {
return CommandBuilder.of()
.add("--title")
.addQuoted(configuration.getColoredTitle())
.addFile(configuration.getScriptFile());
}
};
ExternalTerminalType ELEMENTARY = new SimplePathType("app.elementaryTerminal", "io.elementary.terminal", true) {
@Override
@ -262,7 +291,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
@Override
protected CommandBuilder toCommand(LaunchConfiguration configuration) {
return CommandBuilder.of().add("--new-tab").add("-e").addFile(configuration.getColoredTitle());
return CommandBuilder.of().add("--new-tab").add("-e").addFile(configuration.getScriptFile());
}
};
ExternalTerminalType TILIX = new SimplePathType("app.tilix", "tilix", true) {
@ -641,6 +670,7 @@ public interface ExternalTerminalType extends PrefsChoiceValue {
TILDA,
XTERM,
DEEPIN_TERMINAL,
FOOT,
Q_TERMINAL);
List<ExternalTerminalType> MACOS_TERMINALS = List.of(
KittyTerminalType.KITTY_MACOS,

View file

@ -34,7 +34,7 @@ If you have existing scripts, they will have to be manually adjusted by setting
The docker integration has been updated to support docker contexts. The UI has also been streamlined to make common actions more easily accessible.
There's also now support for Windows containers running on HyperV.
There's also now support for Windows docker containers running on HyperV.
Note that old docker container connections will be removed as they are incompatible with the new version.
@ -51,3 +51,5 @@ You can now order connections relative to other sibling connections. This orderi
- The Linux builds now list socat as a dependency such that the kitty terminal integration will work without issues
- Searching for connections has been improved to show children as well
- The welcome screen will now also contain the option to straight up jump to the synchronization settings
- Add support for foot terminal
- Fix elementary terminal not launching correctly

View file

@ -474,3 +474,4 @@ storeIntroImportDescription=Already using XPipe on another system? Synchronize y
importConnections=Sync connections
importConnectionsTitle=Import Connections
showAllChildren=Show all children
httpApi=HTTP API