diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java index f26abe296e..bf1ef40fc4 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java @@ -62,7 +62,6 @@ import javafx.util.Callback; import javafx.util.Duration; import javafx.util.StringConverter; -import org.glavo.url.WebURL; import org.jackhuang.hmcl.setting.StyleSheets; import org.jackhuang.hmcl.task.CacheFileTask; import org.jackhuang.hmcl.task.Schedulers; @@ -100,10 +99,8 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.ref.WeakReference; -import java.net.HttpURLConnection; import java.net.URI; import java.net.URISyntaxException; -import java.net.URLConnection; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; @@ -1167,32 +1164,6 @@ public static Image loadImage(Path path, } } - public static Image loadImage(WebURL url) throws Exception { - URLConnection connection = NetworkUtils.createConnection(url); - if (connection instanceof HttpURLConnection httpConnection) - connection = NetworkUtils.resolveConnection(httpConnection); - - try (BufferedInputStream input = new BufferedInputStream(connection.getInputStream())) { - String contentType = Objects.requireNonNull(connection.getContentType(), ""); - Matcher matcher = ImageUtils.CONTENT_TYPE_PATTERN.matcher(contentType); - if (matcher.find()) - contentType = matcher.group("type"); - - ImageLoader loader = ImageUtils.CONTENT_TYPE_TO_LOADER.get(contentType); - if (loader == null && !ImageUtils.DEFAULT_CONTENT_TYPES.contains(contentType)) { - input.mark(ImageUtils.HEADER_BUFFER_SIZE); - byte[] headerBuffer = input.readNBytes(ImageUtils.HEADER_BUFFER_SIZE); - input.reset(); - loader = ImageUtils.guessLoader(headerBuffer); - } - - if (loader == null) - loader = ImageUtils.DEFAULT; - - return loader.load(input, 0, 0, false, false); - } - } - /** * Suppress IllegalArgumentException since the url is supposed to be correct definitely. * diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java index 4f3b060c41..542954a857 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/decorator/DecoratorController.java @@ -34,10 +34,10 @@ import javafx.scene.paint.Paint; import javafx.stage.Stage; import javafx.util.Duration; -import org.glavo.url.WebURL; import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDnD; import org.jackhuang.hmcl.setting.EnumBackgroundImage; +import org.jackhuang.hmcl.task.CacheFileTask; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.Controllers; @@ -52,7 +52,9 @@ import org.jackhuang.hmcl.ui.wizard.Refreshable; import org.jackhuang.hmcl.ui.wizard.WizardProvider; import org.jackhuang.hmcl.util.MathUtils; +import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.platform.OperatingSystem; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; @@ -71,6 +73,8 @@ import static org.jackhuang.hmcl.util.logging.Logger.LOG; public class DecoratorController { + private static final Path remoteBgCachePath = Metadata.HMCL_CURRENT_DIRECTORY.resolve("bg.png"); + private final Decorator decorator; private final Navigator navigator; @@ -169,13 +173,15 @@ public Decorator getDecorator() { @SuppressWarnings("FieldCanBeLocal") // Strong reference private final InvalidationListener changeBackgroundListener; + private volatile boolean remoteFetched = false; + private void updateBackground() { final int currentCount = ++this.changeBackgroundCount; Task.supplyAsync(Schedulers.io(), this::getBackground) .setName("Update background") .whenComplete(Schedulers.javafx(), (background, exception) -> { if (exception == null) { - if (this.changeBackgroundCount == currentCount) + if (this.changeBackgroundCount == currentCount && !remoteFetched) decorator.setContentBackground(background); } else { LOG.warning("Failed to update background", exception); @@ -184,6 +190,7 @@ private void updateBackground() { } private Background getBackground() { + remoteFetched = false; EnumBackgroundImage imageType = config().getBackgroundImageType(); if (imageType == null) imageType = EnumBackgroundImage.DEFAULT; @@ -206,7 +213,8 @@ private Background getBackground() { String backgroundImageUrl = config().getBackgroundImageUrl(); if (backgroundImageUrl != null) { try { - image = FXUtils.loadImage(WebURL.parseBrowserInput(backgroundImageUrl)); + asyncFetchRemoteImage(backgroundImageUrl); + image = tryLoadImage(remoteBgCachePath); } catch (Exception e) { LOG.warning("Couldn't load background image", e); } @@ -338,6 +346,26 @@ private Image loadDefaultBackgroundImage() { } } + private void asyncFetchRemoteImage(@NotNull String backgroundImageUrl) { + final int currentCount = this.changeBackgroundCount; + new CacheFileTask(backgroundImageUrl) + .setExecutor(Schedulers.io()) + .thenApplyAsync(Schedulers.io(), path -> { + if (this.changeBackgroundCount == currentCount) FileUtils.copyFile(path, remoteBgCachePath); + return FXUtils.loadImage(path); + }) + .whenComplete(Schedulers.javafx(), ((image, exception) -> { + if (exception == null) { + if (this.changeBackgroundCount == currentCount) { + decorator.setContentBackground(createBackgroundWithOpacity(image, config().getBackgroundImageOpacity())); + remoteFetched = true; + } + } else { + LOG.warning("Failed to load network background image from " + backgroundImageUrl, exception); + } + })).start(); + } + // ==== Navigation ==== public void navigate(Node node, AnimationProducer animationProducer, Duration duration, Interpolator interpolator) {