mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-09-25 18:05:39 +00:00
Rework
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user