This commit is contained in:
crschnick
2025-01-27 01:22:07 +00:00
parent 00af8406ef
commit aa53bfea4b
7 changed files with 66 additions and 13 deletions

View File

@@ -14,7 +14,7 @@ XPipe fully integrates with your tools such as your favourite text/code editors,
It currently supports:
- [SSH](https://www.ssh.com/academy/ssh/protocol) connections, config files, and tunnels
- [Docker](https://www.docker.com/), [Podman](https://podman.io/), LXD](https://linuxcontainers.org/lxd/introduction/), and [incus](https://linuxcontainers.org/incus/) container instances located on any host
- [Docker](https://www.docker.com/), [Podman](https://podman.io/), [LXD](https://linuxcontainers.org/lxd/introduction/), and [incus](https://linuxcontainers.org/incus/) container instances located on any host
- [Proxmox PVE](https://www.proxmox.com/en/proxmox-virtual-environment/overview) virtual machines and containers
- [Hyper-V](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/about/), [KVM/QEMU](https://linux-kvm.org/page/Main_Page), [VMware Player/Workstation/Fusion](https://www.vmware.com/products/desktop-hypervisor/workstation-and-fusion) virtual machines
- [Kubernetes](https://kubernetes.io/) clusters, pods, and containers

View File

@@ -134,6 +134,7 @@ public class BaseMode extends OperationMode {
PlatformInit.init(true);
AppImages.init();
imagesLoaded.countDown();
storageLoaded.await();
SystemIconManager.init();
},
() -> {

View File

@@ -4,6 +4,7 @@ import io.xpipe.app.core.AppProperties;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.resources.AppImages;
import io.xpipe.app.storage.DataStorage;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -16,6 +17,19 @@ public class SystemIconManager {
private static final Map<SystemIconSource, SystemIconSourceData> LOADED = new HashMap<>();
private static final Set<SystemIcon> ICONS = new HashSet<>();
public static List<SystemIconSource> getEffectiveSources() {
var prefs = AppPrefs.get().getIconSources().getValue();
var all = new ArrayList<SystemIconSource>();
all.add(SystemIconSource.Directory.builder().path(DataStorage.get().getIconsDir()).id("custom").build());
all.add(SystemIconSource.GitRepository.builder().remote("https://github.com/selfhst/icons").id("selfhst").build());
for (var pref : prefs) {
if (!all.contains(pref)) {
all.add(pref);
}
}
return all;
}
public static Map<SystemIconSource, SystemIconSourceData> getSources() {
return LOADED;
}
@@ -38,7 +52,7 @@ public class SystemIconManager {
Files.createDirectories(DIRECTORY);
LOADED.clear();
for (var source : AppPrefs.get().getIconSources().getValue()) {
for (var source : getEffectiveSources()) {
LOADED.put(source,SystemIconSourceData.of(source));
}
@@ -54,7 +68,7 @@ public class SystemIconManager {
public static void reloadImages() {
AppImages.remove(s -> s.startsWith("icons/"));
try {
for (var source : AppPrefs.get().getIconSources().getValue()) {
for (var source : getEffectiveSources()) {
AppImages.loadRasterImages(SystemIconCache.getDirectory(source), "icons/" + source.getId());
}
} catch (Exception e) {
@@ -64,7 +78,7 @@ public class SystemIconManager {
public static synchronized void reload() throws Exception {
Files.createDirectories(DIRECTORY);
for (var source : AppPrefs.get().getIconSources().getValue()) {
for (var source : getEffectiveSources()) {
source.refresh();
}
reloadSources();

View File

@@ -7,6 +7,7 @@ import io.xpipe.app.ext.ProcessControlProvider;
import io.xpipe.app.util.DesktopHelper;
import io.xpipe.app.util.Hyperlinks;
import io.xpipe.core.process.CommandBuilder;
import io.xpipe.core.store.FileNames;
import lombok.Builder;
import lombok.Value;
import lombok.extern.jackson.Jacksonized;
@@ -32,7 +33,9 @@ public interface SystemIconSource {
String id;
@Override
public void refresh() throws Exception {}
public void refresh() throws Exception {
Files.createDirectories(path);
}
@Override
public Path getPath() {
@@ -44,6 +47,11 @@ public interface SystemIconSource {
return "mdi2f-folder";
}
@Override
public String getDisplayName() {
return path.getFileName().toString();
}
@Override
public String getDescription() {
return path.toString();
@@ -51,6 +59,7 @@ public interface SystemIconSource {
@Override
public void open() throws Exception {
Files.createDirectories(path);
DesktopHelper.browsePathLocal(path);
}
}
@@ -86,6 +95,11 @@ public interface SystemIconSource {
return "mdi2g-git";
}
@Override
public String getDisplayName() {
return FileNames.getFileName(remote);
}
@Override
public String getDescription() {
return "Git repository " + remote;
@@ -105,6 +119,8 @@ public interface SystemIconSource {
String getIcon();
String getDisplayName();
String getDescription();
void open() throws Exception;

View File

@@ -80,8 +80,7 @@ public class AppPrefs {
final BooleanProperty clearTerminalOnInit =
mapLocal(new SimpleBooleanProperty(true), "clearTerminalOnInit", Boolean.class, false);
final Property<List<SystemIconSource>> iconSources = map(Mapping.builder()
.property(new SimpleObjectProperty<>(new ArrayList<>(List.of(
SystemIconSource.GitRepository.builder().remote("https://github.com/selfhst/icons").id("selfhst").build()))))
.property(new SimpleObjectProperty<>(new ArrayList<>()))
.key("iconSources")
.valueType(TypeFactory.defaultInstance().constructType(new TypeReference<List<SystemIconSource>>() {}))
.build());

View File

@@ -24,6 +24,7 @@ import javafx.scene.control.TextField;
import org.kordamp.ikonli.javafx.FontIcon;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -49,9 +50,9 @@ public class IconsCategory extends AppPrefsCategory {
private Comp<?> createOverview() {
var sources = FXCollections.<SystemIconSource>observableArrayList();
AppPrefs.get().getIconSources().subscribe((newValue) -> {
sources.setAll(newValue);
sources.setAll(SystemIconManager.getEffectiveSources());
});
var box = new ListBoxViewComp<>(sources, sources, s -> createSourceEntry(s), true);
var box = new ListBoxViewComp<>(sources, sources, s -> createSourceEntry(s, sources), true);
var busy = new SimpleBooleanProperty(false);
var refreshButton = new TileButtonComp("refreshSources", "refreshSourcesDescription", "mdi2r-refresh", e -> {
@@ -81,7 +82,12 @@ public class IconsCategory extends AppPrefsCategory {
}
var source = SystemIconSource.GitRepository.builder().remote(remote.get()).id(UUID.randomUUID().toString()).build();
sources.add(source);
if (!sources.contains(source)) {
sources.add(source);
var nl = new ArrayList<>(AppPrefs.get().getIconSources().getValue());
nl.add(source);
AppPrefs.get().iconSources.setValue(nl);
}
});
modal.show();
e.consume();
@@ -99,7 +105,12 @@ public class IconsCategory extends AppPrefsCategory {
}
var source = SystemIconSource.Directory.builder().path(Path.of(dir.get())).id(UUID.randomUUID().toString()).build();
sources.add(source);
if (!sources.contains(source)) {
sources.add(source);
var nl = new ArrayList<>(AppPrefs.get().getIconSources().getValue());
nl.add(source);
AppPrefs.get().iconSources.setValue(nl);
}
});
modal.show();
e.consume();
@@ -111,17 +122,25 @@ public class IconsCategory extends AppPrefsCategory {
return vbox;
}
private Comp<?> createSourceEntry(SystemIconSource source) {
private Comp<?> createSourceEntry(SystemIconSource source, List<SystemIconSource> sources) {
var delete = new IconButtonComp(new LabelGraphic.IconGraphic("mdal-delete_outline"), () -> {
if (!AppDialog.confirm("iconSourceDeletion")) {
return;
}
var nl = new ArrayList<>(AppPrefs.get().getIconSources().getValue());
nl.remove(source);
AppPrefs.get().iconSources.setValue(nl);
sources.remove(source);
});
var buttons = new HorizontalComp(List.of(delete));
buttons.spacing(5);
if (!AppPrefs.get().getIconSources().getValue().contains(source)) {
buttons.disable(new SimpleBooleanProperty(true));
}
var tile = new TileButtonComp(
new SimpleStringProperty(source.getId()),
new SimpleStringProperty(AppPrefs.get().getIconSources().getValue().contains(source) ? source.getDisplayName() : source.getId()),
new SimpleStringProperty(source.getDescription()),
new SimpleObjectProperty<>(source.getIcon()),
actionEvent -> {

View File

@@ -252,6 +252,10 @@ public abstract class DataStorage {
return dir.resolve("data");
}
public Path getIconsDir() {
return dir.resolve("icons");
}
protected Path getCategoriesDir() {
return dir.resolve("categories");
}