diff --git a/app/src/main/java/io/xpipe/app/browser/FileBrowserComp.java b/app/src/main/java/io/xpipe/app/browser/FileBrowserComp.java index f0710ee45..4d3054a21 100644 --- a/app/src/main/java/io/xpipe/app/browser/FileBrowserComp.java +++ b/app/src/main/java/io/xpipe/app/browser/FileBrowserComp.java @@ -3,11 +3,13 @@ package io.xpipe.app.browser; import atlantafx.base.controls.RingProgressIndicator; import atlantafx.base.controls.Spacer; import atlantafx.base.theme.Styles; +import io.xpipe.app.browser.icon.FileIconManager; import io.xpipe.app.fxcomps.SimpleComp; import io.xpipe.app.fxcomps.impl.PrettyImageComp; import io.xpipe.app.fxcomps.util.PlatformThread; import io.xpipe.app.storage.DataStorage; import io.xpipe.app.util.BusyProperty; +import io.xpipe.app.util.ThreadHelper; import io.xpipe.core.store.FileSystem; import javafx.beans.binding.Bindings; import javafx.beans.property.SimpleBooleanProperty; @@ -37,6 +39,10 @@ public class FileBrowserComp extends SimpleComp { @Override protected Region createSimple() { + ThreadHelper.runAsync( () -> { + FileIconManager.loadIfNecessary(); + }); + var bookmarksList = new BookmarkList(model).createRegion(); VBox.setVgrow(bookmarksList, Priority.ALWAYS); var localDownloadStage = new LocalFileTransferComp(model.getLocalTransfersStage()).hide(Bindings.createBooleanBinding(() -> { diff --git a/app/src/main/java/io/xpipe/app/browser/FileListComp.java b/app/src/main/java/io/xpipe/app/browser/FileListComp.java index 8e44dbcc8..d510f7fc5 100644 --- a/app/src/main/java/io/xpipe/app/browser/FileListComp.java +++ b/app/src/main/java/io/xpipe/app/browser/FileListComp.java @@ -250,7 +250,12 @@ final class FileListComp extends AnchorPane { var currentDirectory = fileList.getFileSystemModel().getCurrentDirectory(); if (!Objects.equals(lastDir.get(), currentDirectory)) { - table.scrollTo(0); + TableViewSkin skin = (TableViewSkin) table.getSkin(); + VirtualFlow flow = (VirtualFlow) skin.getChildren().get(1); + ScrollBar vbar = (ScrollBar) flow.getChildrenUnmodifiable().get(2); + if (vbar.getValue() != 0.0) { + table.scrollTo(0); + } } lastDir.setValue(currentDirectory); }); @@ -310,7 +315,9 @@ final class FileListComp extends AnchorPane { text.setValue(fullPath); if (empty || getTableRow() == null || getTableRow().getItem() == null) { - img.set(null); + // Don't set image as that would trigger image comp update + // and cells are emptied on each change, leading to unnecessary changes + // img.set(null); setGraphic(null); } else { var isDirectory = getTableRow().getItem().isDirectory(); diff --git a/app/src/main/java/io/xpipe/app/browser/icon/FileIconManager.java b/app/src/main/java/io/xpipe/app/browser/icon/FileIconManager.java index cbb4dbef5..b05dae00d 100644 --- a/app/src/main/java/io/xpipe/app/browser/icon/FileIconManager.java +++ b/app/src/main/java/io/xpipe/app/browser/icon/FileIconManager.java @@ -2,23 +2,24 @@ package io.xpipe.app.browser.icon; import io.xpipe.app.core.AppImages; import io.xpipe.app.core.AppResources; +import io.xpipe.app.fxcomps.impl.SvgCache; import io.xpipe.core.store.FileSystem; +import javafx.scene.image.Image; import java.io.BufferedReader; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; public class FileIconManager { private static final List factories = new ArrayList<>(); private static final List folderFactories = new ArrayList<>(); + private static SvgCache svgCache; private static boolean loaded; - static { + private static void loadDefinitions() { AppResources.with(AppResources.XPIPE_MODULE, "browser_icons/file_list.txt", path -> { try (var reader = new BufferedReader(new InputStreamReader(Files.newInputStream(path), StandardCharsets.UTF_8))) { @@ -87,8 +88,27 @@ public class FileIconManager { }); } - private static void loadIfNecessary() { + private static void createCache() { + svgCache = new SvgCache() { + + private final Map hits = new HashMap<>(); + private final Map images = new HashMap<>(); + + @Override + public Optional getCached(String image) { + var hitCount = hits.computeIfAbsent(image, s -> 1); + if (hitCount > 5) { + //images.computeIfAbsent(image, s -> AppImages.image()) + } + + return Optional.empty(); + } + }; + } + + public static synchronized void loadIfNecessary() { if (!loaded) { + loadDefinitions(); AppImages.loadDirectory(AppResources.XPIPE_MODULE, "browser_icons"); loaded = true; } diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/SvgCache.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/SvgCache.java new file mode 100644 index 000000000..fd67704d8 --- /dev/null +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/SvgCache.java @@ -0,0 +1,10 @@ +package io.xpipe.app.fxcomps.impl; + +import javafx.scene.image.Image; + +import java.util.Optional; + +public interface SvgCache { + + Optional getCached(String image); +} diff --git a/app/src/main/java/io/xpipe/app/fxcomps/impl/SvgComp.java b/app/src/main/java/io/xpipe/app/fxcomps/impl/SvgComp.java index fee04858f..3447a0beb 100644 --- a/app/src/main/java/io/xpipe/app/fxcomps/impl/SvgComp.java +++ b/app/src/main/java/io/xpipe/app/fxcomps/impl/SvgComp.java @@ -96,6 +96,7 @@ public class SvgComp { var wv = new WebView(); wv.setPageFill(Color.TRANSPARENT); wv.setDisable(true); + wv.getEngine().setJavaScriptEnabled(false); wv.getEngine().loadContent(getHtml(svgContent.getValue())); svgContent.addListener((c, o, n) -> {