Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 0 additions & 29 deletions HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorDnD;
import org.jackhuang.hmcl.setting.EnumBackgroundImage;
import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.ui.Controllers;
Expand All @@ -51,14 +52,20 @@
import org.jackhuang.hmcl.ui.construct.Navigator;
import org.jackhuang.hmcl.ui.wizard.Refreshable;
import org.jackhuang.hmcl.ui.wizard.WizardProvider;
import org.jackhuang.hmcl.util.CacheRepository;
import org.jackhuang.hmcl.util.DigestUtils;
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;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HexFormat;
import java.util.Locale;
import java.util.Random;
import java.util.stream.Collectors;
Expand All @@ -71,6 +78,8 @@
import static org.jackhuang.hmcl.util.logging.Logger.LOG;

public class DecoratorController {
private static final Path remoteBgCacheDir = Metadata.HMCL_CURRENT_DIRECTORY.resolve("bg_cache");

private final Decorator decorator;
private final Navigator navigator;

Expand Down Expand Up @@ -169,13 +178,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);
Expand All @@ -184,6 +195,7 @@ private void updateBackground() {
}

private Background getBackground() {
remoteFetched = false;
EnumBackgroundImage imageType = config().getBackgroundImageType();
if (imageType == null)
imageType = EnumBackgroundImage.DEFAULT;
Expand All @@ -206,7 +218,8 @@ private Background getBackground() {
String backgroundImageUrl = config().getBackgroundImageUrl();
if (backgroundImageUrl != null) {
try {
image = FXUtils.loadImage(WebURL.parseBrowserInput(backgroundImageUrl));
asyncFetchRemoteImage(backgroundImageUrl);
image = tryLoadImage(remoteBgCacheDir.resolve(generateFileName(backgroundImageUrl)));
} catch (Exception e) {
LOG.warning("Couldn't load background image", e);
}
Expand Down Expand Up @@ -338,6 +351,28 @@ private Image loadDefaultBackgroundImage() {
}
}

private void asyncFetchRemoteImage(@NotNull String backgroundImageUrl) {
final int[] currentCount = new int[1];
final Path path = remoteBgCacheDir.resolve(generateFileName(backgroundImageUrl));
Task.runAsync(Schedulers.javafx(), () -> currentCount[0] = this.changeBackgroundCount)
.thenComposeAsync(new FileDownloadTask(backgroundImageUrl, path).setExecutor(Schedulers.io()))
.thenApplyAsync(Schedulers.io(), (__) -> tryLoadImage(path))
.whenComplete(Schedulers.javafx(), ((image, exception) -> {
if (exception == null && image != null) {
if (this.changeBackgroundCount == currentCount[0]) {
decorator.setContentBackground(createBackgroundWithOpacity(image, config().getBackgroundImageOpacity()));
remoteFetched = true;
}
} else {
LOG.warning("Failed to load network background image from " + backgroundImageUrl, exception);
}
})).start();
}

private static String generateFileName(@NotNull String url) {
return HexFormat.of().formatHex(DigestUtils.digest(CacheRepository.SHA1, url.getBytes(StandardCharsets.UTF_8))) + "." + FileUtils.getExtension(WebURL.parse(url).getPath());
}

// ==== Navigation ====

public void navigate(Node node, AnimationProducer animationProducer, Duration duration, Interpolator interpolator) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,9 @@ protected EnumCheckETag shouldCheckETag() {
LOG.warning("Failed to copy cache files", e);
}
}
return EnumCheckETag.NOT_CHECK_E_TAG;
} else {
return EnumCheckETag.CHECK_E_TAG;
} else {
return EnumCheckETag.NOT_CHECK_E_TAG;
}
}

Expand Down