This commit is contained in:
crschnick
2026-03-11 22:30:25 +00:00
parent cb4eeee6dd
commit 230969ec4a
12 changed files with 99 additions and 10 deletions
@@ -8,6 +8,7 @@ import io.xpipe.app.comp.RegionDescriptor;
import io.xpipe.app.comp.SimpleRegionBuilder;
import io.xpipe.app.comp.base.IconButtonComp;
import io.xpipe.app.comp.base.InputGroupComp;
import io.xpipe.app.core.AppFontSizes;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.AppOpenArguments;
import io.xpipe.app.platform.PlatformThread;
@@ -20,6 +21,7 @@ import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Region;
import javafx.stage.PopupWindow;
import lombok.val;
import java.util.List;
import java.util.Objects;
@@ -54,18 +56,25 @@ public class StoreFilterFieldComp extends SimpleRegionBuilder {
}
});
var clearButton = new IconButtonComp("mdi2c-close", () -> {
field.clear();
}).build();
clearButton.setCursor(Cursor.DEFAULT);
AppFontSizes.sm(clearButton);
var searchButton = new IconButtonComp("mdi2m-magnify", () -> {
if (state.open()) {
field.clear();
}
}).build();
searchButton.setCursor(Cursor.DEFAULT);
AppFontSizes.sm(searchButton);
var launchButton = new IconButtonComp("mdi2p-play", () -> {
if (state.open()) {
field.clear();
}
}).build();
launchButton.setCursor(Cursor.DEFAULT);
AppFontSizes.sm(launchButton);
field.setMinHeight(0);
field.setMaxHeight(20000);
@@ -75,7 +84,7 @@ public class StoreFilterFieldComp extends SimpleRegionBuilder {
.bind(Bindings.createObjectBinding(
() -> {
if (!field.isFocused()) {
return null;
return state.getEffectiveFilter().get() != null ? clearButton : null;
}
if (state.getIsQuickConnectString().get() || state.getIsUrlString().get()) {
@@ -1089,8 +1089,8 @@ public abstract class DataStorage {
}
private DataStoreCategory getFallbackCategory(DataStoreCategory cat) {
var parent = getStoreCategoryIfPresent(cat.getParentCategory()).orElseThrow();
if (parent.getParentCategory() != null) {
var parent = getStoreCategoryIfPresent(cat.getParentCategory()).orElse(null);
if (parent != null && parent.getParentCategory() != null) {
return parent;
}
@@ -5,4 +5,9 @@
-fx-padding: 0.5em;
-fx-border-radius: 4px;
-fx-background-radius: 4px;
}
.root:nord .data-store-list-choice-comp .entry {
-fx-border-radius: 0;
-fx-background-radius: 0;
}
@@ -7,7 +7,7 @@
}
.store-filter-comp {
-fx-padding: 0.3em 0.5em 0.3em 0.5em;
-fx-padding: 0.3em 0.0em 0.3em 0.5em;
}
.bar {
@@ -26,6 +26,11 @@
-fx-border-color: -color-neutral-emphasis;
}
.root:nord .edit-button.icon-button-comp {
-fx-background-radius: 0;
-fx-border-radius: 0;
}
.scan-list {
-fx-background-radius: 4px;
-fx-border-width: 1;
@@ -6,6 +6,7 @@
.root:nord .tile-button-comp {
-fx-background-radius: 0;
-fx-border-radius: 0;
}
.tile-button-comp:hover:armed {
@@ -28,6 +28,10 @@
-fx-padding: 0.7em;
}
.root:windows:nord .toggle-switch-comp > .thumb {
-fx-background-radius: 0em;
}
.root:macos .toggle-switch-comp > .thumb-area {
-fx-padding: 0.8em 1.4em;
}
@@ -38,6 +42,10 @@
-fx-padding: 0.8em;
}
.root:macos:nord .toggle-switch-comp > .thumb {
-fx-background-radius: 0em;
}
.root:light .toggle-switch-comp > .thumb {
-fx-background-color: -color-neutral-emphasis;
}
@@ -0,0 +1,8 @@
package io.xpipe.ext.base.store;
import io.xpipe.app.ext.DataStore;
public interface RestartableStore extends DataStore {
void restart() throws Exception;
}
@@ -28,7 +28,7 @@ public class StoreRestartActionProvider implements HubLeafProvider<DataStore>, B
@Override
public boolean isApplicable(DataStoreEntryRef<DataStore> o) {
return o.getStore() instanceof StartableStore && o.getStore() instanceof StoppableStore;
return o.getStore() instanceof RestartableStore || (o.getStore() instanceof StartableStore && o.getStore() instanceof StoppableStore);
}
@Override
@@ -63,7 +63,7 @@ public class StoreRestartActionProvider implements HubLeafProvider<DataStore>, B
@Override
public String getId() {
return "restartStore";
return "restartAction";
}
@Jacksonized
@@ -72,8 +72,12 @@ public class StoreRestartActionProvider implements HubLeafProvider<DataStore>, B
@Override
public void executeImpl() throws Exception {
((StoppableStore) ref.getStore()).stop();
((StartableStore) ref.getStore()).start();
if (ref.getStore() instanceof RestartableStore r) {
r.restart();
} else {
((StoppableStore) ref.getStore()).stop();
((StartableStore) ref.getStore()).start();
}
}
@Override
@@ -30,6 +30,11 @@ public class PodmanCmdStore
this.host = host;
}
@Override
public boolean removeLeftovers() {
return false;
}
@Override
public List<DataStoreEntryRef<?>> getDependencies() {
return DataStoreDependencies.of(host);
@@ -3,10 +3,12 @@ package io.xpipe.ext.system.podman;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.process.*;
import io.xpipe.core.OsType;
import lombok.NonNull;
import lombok.Value;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
public class PodmanCommandView extends CommandViewBase {
@@ -67,6 +69,16 @@ public class PodmanCommandView extends CommandViewBase {
public class Container extends CommandView {
public Optional<String> queryLabel(String container, String label) throws Exception {
var command = build(b -> b.add("inspect")
.add(sc -> {
var quote = ShellDialects.isPowershell(sc) ? "'" : "\"";
return "--format=" + quote + "{{index (index .Config.Labels \\\"" + label + "\\\")}}" + quote;
})
.addQuoted(container));
return command.readStdoutIfPossible().filter(s -> !s.isBlank());
}
public String queryState(String container) throws Exception {
return build(commandBuilder -> commandBuilder.add(
"ls", "-a", "-f", "name=\"^" + container + "$\"", "--format=\"{{.Status}}\""))
@@ -145,6 +157,18 @@ public class PodmanCommandView extends CommandViewBase {
.execute();
}
public void restart(String container) throws Exception {
if (shellControl.getOsType() == OsType.LINUX) {
var systemd = queryLabel(container, "PODMAN_SYSTEMD_UNIT");
if (systemd.isPresent()) {
shellControl.command(CommandBuilder.of().add("systemctl", "restart", "--user").addQuoted(systemd.get())).execute();
return;
}
}
build(commandBuilder -> commandBuilder.add("restart").addQuoted(container)).execute();
}
public String port(String container) throws Exception {
return build(commandBuilder -> commandBuilder.add("port").addQuoted(container))
.readStdoutOrThrow();
@@ -9,6 +9,7 @@ import io.xpipe.app.util.Validators;
import io.xpipe.ext.base.service.AbstractServiceStore;
import io.xpipe.ext.base.service.FixedServiceCreatorStore;
import io.xpipe.ext.base.service.MappedServiceStore;
import io.xpipe.ext.base.store.RestartableStore;
import io.xpipe.ext.base.store.StartableStore;
import io.xpipe.ext.base.store.StoppableStore;
@@ -28,7 +29,7 @@ import java.util.regex.Pattern;
@Value
public class PodmanContainerStore
implements StartableStore,
StoppableStore,
StoppableStore, RestartableStore,
ShellStore,
InternalCacheDataStore,
FixedChildStore,
@@ -77,6 +78,8 @@ public class PodmanContainerStore
refreshContainerState(sc);
}
@Override
public List<? extends DataStoreEntryRef<? extends AbstractServiceStore>> createFixedServices() throws Exception {
return findServices().stream()
@@ -160,13 +163,30 @@ public class PodmanContainerStore
};
}
private void refreshContainerState(ShellControl sc) throws Exception {
private boolean refreshContainerState(ShellControl sc) throws Exception {
var state = getState();
var view = new PodmanCommandView(sc).container();
var displayState = view.queryState(containerName);
if (displayState.isEmpty()) {
var newState =
state.toBuilder().containerState("Removed").running(false).build();
setState(newState);
return false;
}
var running = displayState.startsWith("Up");
var newState =
state.toBuilder().containerState(displayState).running(running).build();
setState(newState);
return true;
}
@Override
public void restart() throws Exception {
stopSessionIfNeeded();
var sc = getCmd().getStore().getHost().getStore().getOrStartSession();
var view = commandView(sc);
view.restart(containerName);
refreshContainerState(sc);
}
}