This commit is contained in:
crschnick
2025-07-30 14:28:51 +00:00
parent d507e72a11
commit 1ca0c433c4
8 changed files with 173 additions and 1 deletions
@@ -38,6 +38,7 @@ public class AppProperties {
boolean debugThreads;
Path dataDir;
Path defaultDataDir;
Path dataBinDir;
boolean showcase;
AppVersion canonicalVersion;
boolean locatePtb;
@@ -124,6 +125,7 @@ public class AppProperties {
return p;
})
.orElse(defaultDataDir);
dataBinDir = dataDir.resolve("bin");
showcase = Optional.ofNullable(System.getProperty("io.xpipe.app.showcase"))
.map(Boolean::parseBoolean)
.orElse(false);
@@ -0,0 +1,32 @@
package io.xpipe.app.core;
import io.xpipe.core.OsType;
import java.nio.file.Files;
import java.nio.file.Path;
public class AppSystemInfo {
public static class Windows {
}
public static Linux linux() {
if (OsType.getLocal() != OsType.LINUX) {
throw new IllegalStateException();
}
return new Linux();
}
public static class Linux {
public boolean isDebianBased() {
return Files.exists(Path.of("/etc/debian_version"));
}
}
public static class MacOS {
}
}
@@ -0,0 +1,38 @@
package io.xpipe.app.ext;
import io.xpipe.app.util.LabelGraphic;
import io.xpipe.core.ModuleLayerLoader;
import java.util.*;
public interface SetupProvider {
List<SetupProvider> ALL = new ArrayList<>();
static Optional<SetupProvider> byId(String id) {
return ALL.stream().filter(d -> d.getId().equalsIgnoreCase(id)).findAny();
}
class Loader implements ModuleLayerLoader {
@Override
public void init(ModuleLayer layer) {
ALL.addAll(ServiceLoader.load(layer, SetupProvider.class).stream()
.sorted(Comparator.comparing(p -> p.type().getModule().getName()))
.map(p -> p.get())
.toList());
}
}
String getId();
String getNameKey();
LabelGraphic getGraphic();
boolean checkInstalled() throws Exception;
void execute() throws Exception;
ScanProvider getScan();
}
@@ -0,0 +1,59 @@
package io.xpipe.app.ext;
import io.xpipe.app.action.AbstractAction;
import io.xpipe.app.action.ActionProvider;
import io.xpipe.app.comp.base.ModalOverlay;
import io.xpipe.app.core.window.AppDialog;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.process.ShellScript;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry;
import lombok.SneakyThrows;
import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;
import java.util.LinkedHashMap;
import java.util.Map;
public class SetupToolActionProvider implements ActionProvider {
@Override
public String getId() {
return "setupTool";
}
@Jacksonized
@SuperBuilder
public static class Action extends AbstractAction {
private final String type;
@Override
@SneakyThrows
public void executeImpl() throws Exception {
var provider = SetupProvider.byId(type);
if (provider.isEmpty()) {
throw ErrorEventFactory.expected(new IllegalArgumentException("Setup action not found: " + type));
}
if (!provider.get().checkInstalled()) {
provider.get().execute();
}
var local = DataStorage.get().local();
var sc = ((ShellStore) local.getStore()).getOrStartSession();
var op = provider.get().getScan().create(local, sc);
if (op != null && !op.isDisabled()) {
provider.get().getScan().scan(local, sc);
}
}
@Override
public Map<String, String> toDisplayMap() {
var map = new LinkedHashMap<String, String>();
map.put("Action", getDisplayName());
map.put("Type", type);
return map;
}
}
}
@@ -5,6 +5,8 @@ import io.xpipe.app.comp.base.PrettyImageHelper;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.ext.DataStoreCreationCategory;
import io.xpipe.app.ext.DataStoreProviders;
import io.xpipe.app.ext.SetupProvider;
import io.xpipe.app.ext.SetupToolActionProvider;
import io.xpipe.app.util.ScanDialog;
import javafx.application.Platform;
@@ -93,6 +95,8 @@ public class StoreCreationMenu {
menu.getItems().add(categoryMenu("addSerial", "mdi2s-serial-port", DataStoreCreationCategory.SERIAL, "serial"));
menu.getItems().add(actionMenu);
menu.getItems().add(setupMenu());
}
private static Menu categoryMenu(
@@ -144,4 +148,24 @@ public class StoreCreationMenu {
}
return menu;
}
private static Menu setupMenu() {
var menu = new Menu();
menu.setGraphic(new FontIcon("mdi2t-toy-brick-plus-outline"));
menu.textProperty().bind(AppI18n.observable("addCloud"));
for (var p : SetupProvider.ALL) {
var item = new MenuItem();
item.textProperty().bind(AppI18n.observable(p.getNameKey()));
item.setGraphic(p.getGraphic().createGraphicNode());
item.setOnAction(event -> {
var action = SetupToolActionProvider.Action.builder().type(p.getId()).build();
action.executeAsync();
event.consume();
});
menu.getItems().add(item);
}
return menu;
}
}
@@ -1,5 +1,6 @@
package io.xpipe.app.util;
import io.xpipe.app.process.CommandBuilder;
import io.xpipe.core.JacksonMapper;
import java.io.IOException;
@@ -34,6 +35,18 @@ public class GithubReleaseDownloader {
return temp;
}
public static void extractTarEntry(Path tarFile, String path, Path target) throws Exception {
var c = CommandBuilder.of().add("tar");
c.add("-C").addFile(target);
var gz = tarFile.getFileName().toString().endsWith(".gz");
c.add("-x").addIf(gz, "-z").add("-f");
c.addFile(tarFile);
c.addFile(path);
Files.createDirectories(target.getParent());
LocalShell.getShell().command(c).execute();
}
private static String getDownloadUrl(String repository, Predicate<String> filter) throws Exception {
var request = HttpRequest.newBuilder()
.GET()
+4 -1
View File
@@ -119,8 +119,10 @@ open module io.xpipe.app {
uses DataStorageExtensionProvider;
uses ProcessControlProvider;
uses ShellDialect;
uses SetupProvider;
provides ActionProvider with
SetupToolActionProvider,
XPipeUrlProvider,
OpenHubMenuLeafProvider,
EditHubLeafProvider,
@@ -198,7 +200,8 @@ open module io.xpipe.app {
PrefsProvider.Loader,
LicenseProvider.Loader,
ScanProvider.Loader,
ShellDialects.Loader;
ShellDialects.Loader,
SetupProvider.Loader;
provides SLF4JServiceProvider with
AppLogs.Slf4jProvider;
provides EventHandler with
+1
View File
@@ -1574,3 +1574,4 @@ metrics=Metrics
publicKey=Public key identifier
publicKeyDescription=The optional public key to force the agent to only offer the matching private key
openInVsCode=Open in VsCode
addCloud=Cloud ...