mirror of
https://github.com/octopusYan/alist-gui.git
synced 2024-11-21 19:56:41 +08:00
feat: alist 检查更次
This commit is contained in:
parent
80bda287cc
commit
cfd7075c8f
@ -9,9 +9,11 @@ import javafx.concurrent.Task;
|
||||
*/
|
||||
public abstract class BaseTask extends Task<Void> {
|
||||
private final ThreadPoolManager Executor = ThreadPoolManager.getInstance();
|
||||
protected Listener listener;
|
||||
|
||||
@Override
|
||||
protected Void call() throws Exception {
|
||||
if (listener != null) listener.onStart();
|
||||
task();
|
||||
return null;
|
||||
}
|
||||
@ -23,7 +25,8 @@ public abstract class BaseTask extends Task<Void> {
|
||||
protected abstract void task() throws Exception;
|
||||
|
||||
public void onListen(Listener listener) {
|
||||
if (listener == null) return;
|
||||
this.listener = listener;
|
||||
if (this.listener == null) return;
|
||||
|
||||
setOnRunning(_ -> listener.onRunning());
|
||||
setOnCancelled(_ -> listener.onCancelled());
|
||||
@ -36,6 +39,9 @@ public abstract class BaseTask extends Task<Void> {
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
default void onStart() {
|
||||
}
|
||||
|
||||
default void onRunning() {
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.octopusyan.alistgui.config;
|
||||
|
||||
import atlantafx.base.theme.Theme;
|
||||
import cn.octopusyan.alistgui.base.BaseController;
|
||||
import cn.octopusyan.alistgui.controller.AboutController;
|
||||
import cn.octopusyan.alistgui.controller.MainController;
|
||||
@ -36,6 +37,7 @@ public class Context {
|
||||
private static final Logger log = LoggerFactory.getLogger(Context.class);
|
||||
private static Scene scene;
|
||||
private static final IntegerProperty currentViewIndexProperty = new SimpleIntegerProperty(0);
|
||||
private static final ObjectProperty<Theme> theme = new SimpleObjectProperty<>(ConfigManager.theme());
|
||||
|
||||
/**
|
||||
* 控制器集合
|
||||
@ -82,6 +84,10 @@ public class Context {
|
||||
};
|
||||
}
|
||||
|
||||
public static ObjectProperty<Theme> themeProperty() {
|
||||
return theme;
|
||||
}
|
||||
|
||||
// 获取当前所选时区属性
|
||||
public static ObjectProperty<Locale> currentLocaleProperty() {
|
||||
return currentLocale;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.octopusyan.alistgui.controller;
|
||||
|
||||
import cn.octopusyan.alistgui.base.BaseController;
|
||||
import cn.octopusyan.alistgui.manager.ConfigManager;
|
||||
import cn.octopusyan.alistgui.viewModel.AboutViewModule;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
@ -49,6 +50,6 @@ public class AboutController extends BaseController<VBox> {
|
||||
|
||||
@FXML
|
||||
public void checkAListUpdate() {
|
||||
viewModule.checkAListUpdate();
|
||||
viewModule.checkUpdate(ConfigManager.aList());
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.octopusyan.alistgui.controller;
|
||||
|
||||
import atlantafx.base.theme.Theme;
|
||||
import cn.octopusyan.alistgui.base.BaseController;
|
||||
import cn.octopusyan.alistgui.config.Context;
|
||||
import cn.octopusyan.alistgui.enums.ProxySetup;
|
||||
@ -14,6 +15,7 @@ import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.StringConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -37,7 +39,7 @@ public class SetupController extends BaseController<VBox> implements Initializab
|
||||
@FXML
|
||||
public ComboBox<Locale> languageComboBox;
|
||||
@FXML
|
||||
public ComboBox<String> themeComboBox;
|
||||
public ComboBox<Theme> themeComboBox;
|
||||
@FXML
|
||||
public ComboBox<ProxySetup> proxySetupComboBox;
|
||||
@FXML
|
||||
@ -59,8 +61,20 @@ public class SetupController extends BaseController<VBox> implements Initializab
|
||||
@Override
|
||||
public void initData() {
|
||||
languageComboBox.setItems(FXCollections.observableList(Context.SUPPORT_LANGUAGE_LIST));
|
||||
themeComboBox.setItems(FXCollections.observableList(ConfigManager.THEME_NAME_LIST));
|
||||
themeComboBox.setItems(FXCollections.observableList(ConfigManager.THEME_LIST));
|
||||
proxySetupComboBox.setItems(FXCollections.observableList(List.of(ProxySetup.values())));
|
||||
|
||||
themeComboBox.setConverter(new StringConverter<>() {
|
||||
@Override
|
||||
public String toString(Theme object) {
|
||||
return object.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Theme fromString(String string) {
|
||||
return ConfigManager.THEME_MAP.get(string);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -71,7 +85,7 @@ public class SetupController extends BaseController<VBox> implements Initializab
|
||||
});
|
||||
|
||||
languageComboBox.getSelectionModel().select(ConfigManager.language());
|
||||
themeComboBox.getSelectionModel().select(ConfigManager.themeName());
|
||||
themeComboBox.getSelectionModel().select(ConfigManager.theme());
|
||||
proxySetupComboBox.getSelectionModel().select(ConfigManager.proxySetup());
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package cn.octopusyan.alistgui.manager;
|
||||
import atlantafx.base.theme.*;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.lang.PatternPool;
|
||||
import cn.hutool.core.net.NetUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.octopusyan.alistgui.Application;
|
||||
import cn.octopusyan.alistgui.config.Constants;
|
||||
@ -12,6 +13,7 @@ import cn.octopusyan.alistgui.model.GuiConfig;
|
||||
import cn.octopusyan.alistgui.model.ProxyInfo;
|
||||
import cn.octopusyan.alistgui.model.UpgradeConfig;
|
||||
import cn.octopusyan.alistgui.model.upgrade.AList;
|
||||
import cn.octopusyan.alistgui.model.upgrade.Gui;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||
@ -22,11 +24,14 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 客户端设置
|
||||
@ -37,22 +42,17 @@ public class ConfigManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
|
||||
public static ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
|
||||
public static final Locale DEFAULT_LANGUAGE = Locale.SIMPLIFIED_CHINESE;
|
||||
private static GuiConfig guiConfig;
|
||||
private static UpgradeConfig upgradeConfig;
|
||||
|
||||
public static final String DEFAULT_THEME = "Primer Light";
|
||||
public static List<Theme> THEME_LIST = Arrays.asList(
|
||||
public static final String DEFAULT_THEME = new PrimerLight().getName();
|
||||
public static List<Theme> THEME_LIST = List.of(
|
||||
new PrimerLight(), new PrimerDark(),
|
||||
new NordLight(), new NordDark(),
|
||||
new CupertinoLight(), new CupertinoDark(),
|
||||
new Dracula()
|
||||
);
|
||||
public static List<String> THEME_NAME_LIST = Arrays.asList(
|
||||
"Primer Light", "Primer Dark",
|
||||
"Nord Light", "Nord Dark",
|
||||
"Cupertino Light", "Cupertino Dark",
|
||||
"Dracula"
|
||||
);
|
||||
public static Map<String, Theme> THEME_MAP = THEME_LIST.stream()
|
||||
.collect(Collectors.toMap(Theme::getName, Function.identity()));
|
||||
|
||||
private static GuiConfig guiConfig;
|
||||
|
||||
static {
|
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
@ -61,7 +61,6 @@ public class ConfigManager {
|
||||
|
||||
public static void load() {
|
||||
guiConfig = loadConfig(Constants.GUI_CONFIG_PATH, GuiConfig.class);
|
||||
upgradeConfig = loadConfig(Constants.UPGRADE_PATH, UpgradeConfig.class);
|
||||
}
|
||||
|
||||
private static <T> T loadConfig(String path, Class<T> clazz) {
|
||||
@ -77,6 +76,24 @@ public class ConfigManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static <T> void checkFile(File src, Class<T> clazz) throws Exception {
|
||||
File parent = FileUtil.getParent(src, 1);
|
||||
if (!parent.exists()) {
|
||||
boolean wasSuccessful = parent.mkdirs();
|
||||
objectMapper.writeValue(src, clazz.getDeclaredConstructor().newInstance());
|
||||
if (!wasSuccessful)
|
||||
logger.error("{} 创建失败", src.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
try {
|
||||
objectMapper.writeValue(new File(Constants.GUI_CONFIG_PATH), guiConfig);
|
||||
} catch (IOException e) {
|
||||
logger.error("save config error", e);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------{ 主题 }------------------------------------------
|
||||
|
||||
public static String themeName() {
|
||||
@ -84,82 +101,15 @@ public class ConfigManager {
|
||||
}
|
||||
|
||||
public static Theme theme() {
|
||||
return THEME_LIST.get(THEME_NAME_LIST.indexOf(themeName()));
|
||||
return THEME_MAP.get(themeName());
|
||||
}
|
||||
|
||||
public static void themeName(String themeName) {
|
||||
int themeIndex = THEME_NAME_LIST.indexOf(themeName);
|
||||
if (themeIndex < 0) return;
|
||||
|
||||
guiConfig.setTheme(themeName);
|
||||
Application.setUserAgentStylesheet(theme().getUserAgentStylesheet());
|
||||
public static void theme(Theme theme) {
|
||||
Application.setUserAgentStylesheet(theme.getUserAgentStylesheet());
|
||||
guiConfig.setTheme(theme.getName());
|
||||
}
|
||||
|
||||
public static boolean hasProxy() {
|
||||
if (guiConfig == null)
|
||||
return false;
|
||||
ProxyInfo proxyInfo = getProxyInfo();
|
||||
return proxyInfo != null
|
||||
&& StringUtils.isNoneEmpty(proxyInfo.getHost())
|
||||
&& StringUtils.isNoneEmpty(proxyInfo.getPort())
|
||||
&& Integer.parseInt(proxyInfo.getPort()) > 0;
|
||||
}
|
||||
|
||||
public static ProxyInfo getProxyInfo() {
|
||||
return guiConfig.getProxyInfo();
|
||||
}
|
||||
|
||||
private static void setProxyInfo(ProxyInfo info) {
|
||||
guiConfig.setProxyInfo(info);
|
||||
}
|
||||
|
||||
public static String proxyHost() {
|
||||
if (getProxyInfo() == null) return null;
|
||||
return getProxyInfo().getHost();
|
||||
}
|
||||
|
||||
public static void proxyHost(String host) {
|
||||
final Matcher matcher = PatternPool.IPV4.matcher(host);
|
||||
if (matcher.matches()) {
|
||||
if (getProxyInfo() == null)
|
||||
setProxyInfo(new ProxyInfo());
|
||||
getProxyInfo().setHost(host);
|
||||
}
|
||||
}
|
||||
|
||||
public static String proxyPort() {
|
||||
if (getProxyInfo() == null) return null;
|
||||
return getProxyInfo().getPort();
|
||||
}
|
||||
|
||||
public static int getProxyPort() {
|
||||
return Integer.parseInt(getProxyInfo().getPort());
|
||||
}
|
||||
|
||||
public static void proxyPort(String port) {
|
||||
if (NumberUtil.isNumber(port)) {
|
||||
if (getProxyInfo() == null)
|
||||
setProxyInfo(new ProxyInfo());
|
||||
getProxyInfo().setPort(port);
|
||||
}
|
||||
}
|
||||
|
||||
public static Locale language() {
|
||||
String language = guiConfig.getLanguage();
|
||||
return LocaleUtils.toLocale(Optional.ofNullable(language).orElse(DEFAULT_LANGUAGE.toString()));
|
||||
}
|
||||
|
||||
public static void language(Locale locale) {
|
||||
guiConfig.setLanguage(locale.toString());
|
||||
}
|
||||
|
||||
public static boolean autoStart() {
|
||||
return guiConfig.getAutoStart();
|
||||
}
|
||||
|
||||
public static void autoStart(Boolean autoStart) {
|
||||
guiConfig.setAutoStart(autoStart);
|
||||
}
|
||||
// --------------------------------{ 网络代理 }------------------------------------------
|
||||
|
||||
public static ProxySetup proxySetup() {
|
||||
return ProxySetup.valueOf(StringUtils.upperCase(guiConfig.getProxySetup()));
|
||||
@ -186,6 +136,94 @@ public class ConfigManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasProxy() {
|
||||
if (guiConfig == null)
|
||||
return false;
|
||||
ProxyInfo proxyInfo = getProxyInfo();
|
||||
return proxyInfo != null
|
||||
&& StringUtils.isNoneEmpty(proxyInfo.getHost())
|
||||
&& StringUtils.isNoneEmpty(proxyInfo.getPort())
|
||||
&& Integer.parseInt(proxyInfo.getPort()) > 0;
|
||||
}
|
||||
|
||||
public static ProxyInfo getProxyInfo() {
|
||||
ProxyInfo proxyInfo = guiConfig.getProxyInfo();
|
||||
|
||||
if (proxyInfo == null)
|
||||
setProxyInfo(new ProxyInfo());
|
||||
|
||||
return guiConfig.getProxyInfo();
|
||||
}
|
||||
|
||||
private static void setProxyInfo(ProxyInfo info) {
|
||||
guiConfig.setProxyInfo(info);
|
||||
}
|
||||
|
||||
public static String proxyHost() {
|
||||
return getProxyInfo().getHost();
|
||||
}
|
||||
|
||||
public static void proxyHost(String host) {
|
||||
final Matcher matcher = PatternPool.IPV4.matcher(host);
|
||||
if (!matcher.matches()) return;
|
||||
|
||||
getProxyInfo().setHost(host);
|
||||
|
||||
checkProxy();
|
||||
}
|
||||
|
||||
public static String proxyPort() {
|
||||
return getProxyInfo().getPort();
|
||||
}
|
||||
|
||||
public static int getProxyPort() {
|
||||
return Integer.parseInt(proxyPort());
|
||||
}
|
||||
|
||||
public static void proxyPort(String port) {
|
||||
if (!NumberUtil.isNumber(port)) return;
|
||||
|
||||
getProxyInfo().setPort(port);
|
||||
|
||||
checkProxy();
|
||||
}
|
||||
|
||||
private static void checkProxy() {
|
||||
if (!hasProxy()) return;
|
||||
|
||||
try {
|
||||
InetSocketAddress address = NetUtil.createAddress(proxyHost(), getProxyPort());
|
||||
if (NetUtil.isOpen(address, 2000)) {
|
||||
HttpUtil.getInstance().proxy(proxySetup(), ConfigManager.getProxyInfo());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(STR."host=\{proxyHost()},port=\{proxyPort()}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------{ 语言 }------------------------------------------
|
||||
|
||||
public static Locale language() {
|
||||
String language = guiConfig.getLanguage();
|
||||
return LocaleUtils.toLocale(Optional.ofNullable(language).orElse(DEFAULT_LANGUAGE.toString()));
|
||||
}
|
||||
|
||||
public static void language(Locale locale) {
|
||||
guiConfig.setLanguage(locale.toString());
|
||||
}
|
||||
|
||||
// --------------------------------{ 开机自启 }------------------------------------------
|
||||
|
||||
public static boolean autoStart() {
|
||||
return guiConfig.getAutoStart();
|
||||
}
|
||||
|
||||
public static void autoStart(Boolean autoStart) {
|
||||
guiConfig.setAutoStart(autoStart);
|
||||
}
|
||||
|
||||
// --------------------------------{ 静默启动 }------------------------------------------
|
||||
|
||||
public static boolean silentStartup() {
|
||||
return guiConfig.getSilentStartup();
|
||||
}
|
||||
@ -194,35 +232,33 @@ public class ConfigManager {
|
||||
guiConfig.setSilentStartup(startup);
|
||||
}
|
||||
|
||||
// --------------------------------{ 版本检查 }------------------------------------------
|
||||
|
||||
public static UpgradeConfig upgradeConfig() {
|
||||
return guiConfig.getUpgradeConfig();
|
||||
}
|
||||
|
||||
public static AList aList() {
|
||||
return upgradeConfig.getAList();
|
||||
return upgradeConfig().getAList();
|
||||
}
|
||||
|
||||
public static String aListVersion() {
|
||||
return upgradeConfig.getAList().getVersion();
|
||||
return aList().getVersion();
|
||||
}
|
||||
|
||||
public static void aListVersion(String version) {
|
||||
upgradeConfig.getAList().setVersion(version);
|
||||
aList().setVersion(version);
|
||||
}
|
||||
|
||||
|
||||
private static <T> void checkFile(File src, Class<T> clazz) throws Exception {
|
||||
File parent = FileUtil.getParent(src, 1);
|
||||
if (!parent.exists()) {
|
||||
boolean wasSuccessful = parent.mkdirs();
|
||||
objectMapper.writeValue(src, clazz.getDeclaredConstructor().newInstance());
|
||||
if (!wasSuccessful)
|
||||
logger.error("{} 创建失败", src.getAbsolutePath());
|
||||
}
|
||||
public static Gui gui() {
|
||||
return upgradeConfig().getGui();
|
||||
}
|
||||
|
||||
public static void save() {
|
||||
try {
|
||||
objectMapper.writeValue(new File(Constants.GUI_CONFIG_PATH), guiConfig);
|
||||
objectMapper.writeValue(new File(Constants.UPGRADE_PATH), upgradeConfig);
|
||||
} catch (IOException e) {
|
||||
logger.error("save config error", e);
|
||||
}
|
||||
public static String guiVersion() {
|
||||
return gui().getVersion();
|
||||
}
|
||||
|
||||
public static void guiVersion(String version) {
|
||||
gui().setVersion(version);
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,22 @@
|
||||
package cn.octopusyan.alistgui.manager;
|
||||
|
||||
import atlantafx.base.util.BBCodeParser;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 模拟控制台输出
|
||||
@ -19,18 +26,14 @@ import java.util.Date;
|
||||
public class ConsoleLog {
|
||||
public static final String format = "yyyy/MM/dd hh:mm:ss";
|
||||
private volatile static ConsoleLog log;
|
||||
private final ScrollPane logAreaSp;
|
||||
private final VBox textArea;
|
||||
private final static String CONSOLE_COLOR_PREFIX = "^\033\\[(\\d+)m(.*)\033\\[0m(.*)$";
|
||||
private final static String CONSOLE_COLOR_SUFFIX = "\033[0m";
|
||||
|
||||
private ConsoleLog(ScrollPane logAreaSp, VBox textArea) {
|
||||
this.textArea = textArea;
|
||||
this.logAreaSp = logAreaSp;
|
||||
|
||||
textArea.maxWidthProperty().bind(logAreaSp.prefWidthProperty());
|
||||
|
||||
textArea.heightProperty().subscribe(() -> {
|
||||
logAreaSp.vvalueProperty().setValue(1);
|
||||
});
|
||||
textArea.heightProperty().subscribe(() -> logAreaSp.vvalueProperty().setValue(1));
|
||||
}
|
||||
|
||||
public static ConsoleLog getInstance() {
|
||||
@ -63,41 +66,120 @@ public class ConsoleLog {
|
||||
}
|
||||
|
||||
public static void info(String tag, String message, Object... param) {
|
||||
printLog(tag, "INFO", message, param);
|
||||
printLog(tag, Level.INFO, message, param);
|
||||
}
|
||||
|
||||
public static void warning(String tag, String message, Object... param) {
|
||||
printLog(tag, "[color=-color-chart-2]WARN[/color]", message, param);
|
||||
printLog(tag, Level.WARN, message, param);
|
||||
}
|
||||
|
||||
public static void error(String tag, String message, Object... param) {
|
||||
printLog(tag, "[color=-color-chart-3]ERROR[/color]", message, param);
|
||||
printLog(tag, Level.ERROR, message, param);
|
||||
}
|
||||
|
||||
public static void msg(String message, Object... param) {
|
||||
Node text = BBCodeParser.createFormattedText(STR."\{StrUtil.format(message, param)}\n\n");
|
||||
if (message.contains("\033[")) {
|
||||
message = resetConsoleColor(message);
|
||||
}
|
||||
|
||||
Node text = BBCodeParser.createFormattedText(STR."\{StrUtil.format(message, param)}");
|
||||
Platform.runLater(() -> log.textArea.getChildren().add(text));
|
||||
}
|
||||
|
||||
public static void printLog(String tag, String level, String message, Object... param) {
|
||||
public static void printLog(String tag, Level level, String message, Object... param) {
|
||||
|
||||
String time = DateFormatUtils.format(new Date(), format);
|
||||
time = STR."[color=-color-accent-emphasis]\{time}[/color]";
|
||||
|
||||
String levelStr = StringUtils.substringBetween(level, "]", "[");
|
||||
if (levelStr == null) levelStr = level;
|
||||
level = StringUtils.replace(level, levelStr, StringUtils.center(levelStr, 5));
|
||||
String levelStr = resetLevelColor(level);
|
||||
|
||||
tag = StringUtils.isEmpty(tag) ? "" : STR."\{tag}: ";
|
||||
|
||||
String msg = STR."[color=-color-fg-muted]\{StrUtil.format(message, param)}[/color]";
|
||||
message = STR."[color=-color-fg-muted]\{StrUtil.format(message, param)}[/color]";
|
||||
|
||||
Node text;
|
||||
if (msg.contains("\n")) {
|
||||
text = BBCodeParser.createLayout(STR."\{time} \{level} \{tag}\{msg}");
|
||||
String input = STR."\{time} \{levelStr} \{tag}\{message}";
|
||||
|
||||
if (input.contains("\n")) {
|
||||
text = BBCodeParser.createLayout(input);
|
||||
} else {
|
||||
text = BBCodeParser.createFormattedText(STR."\{time} \{level} \{tag}\{msg}");
|
||||
text = BBCodeParser.createFormattedText(input);
|
||||
}
|
||||
Platform.runLater(() -> log.textArea.getChildren().add(text));
|
||||
}
|
||||
|
||||
//============================{ 私有方法 }================================
|
||||
|
||||
/**
|
||||
* 控制台输出颜色
|
||||
*
|
||||
* @param msg alist 输出消息
|
||||
* @return bbcode 颜色文本
|
||||
*/
|
||||
private static String resetConsoleColor(String msg) {
|
||||
try {
|
||||
String colorCode = ReUtil.get(CONSOLE_COLOR_PREFIX, msg, 1);
|
||||
String color = StringUtils.lowerCase(Color.valueOf(Integer.parseInt(colorCode)).getColor());
|
||||
String colorMsg = ReUtil.get(CONSOLE_COLOR_PREFIX, msg, 2);
|
||||
msg = ReUtil.get(CONSOLE_COLOR_PREFIX, msg, 3);
|
||||
return color(color, colorMsg) + msg;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param level 级别
|
||||
* @return bbcode 颜色
|
||||
*/
|
||||
private static String resetLevelColor(Level level) {
|
||||
return color(level.getColor(), level.getCode());
|
||||
}
|
||||
|
||||
private static String color(String color, String msg) {
|
||||
String PREFIX = STR."\{StringUtils.isEmpty(color) ? "" : STR."[color=\{color}]"}";
|
||||
String SUFFIX = STR."\{StringUtils.isEmpty(color) ? "" : "[/color]"}";
|
||||
return STR."\{PREFIX}\{msg}\{SUFFIX}";
|
||||
}
|
||||
|
||||
//============================{ 枚举 }================================
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum Level {
|
||||
INFO("INFO", null),
|
||||
WARN("WARN", "color=-color-chart-2"),
|
||||
ERROR("ERROR", "color=-color-chart-3"),
|
||||
;
|
||||
|
||||
private final String code;
|
||||
private final String color;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
enum Color {
|
||||
BLACK(30, "-color-fg-default"),
|
||||
RED(31, "-color-danger-fg"),
|
||||
GREEN(32, "-color-success-fg"),
|
||||
YELLOW(33, "-color-warning-emphasis"),
|
||||
BLUE(34, "-color-accent-fg"),
|
||||
PINKISH_RED(35, "-color-danger-4"),
|
||||
CYAN(36, "-color-accent-emphasis"),
|
||||
WHITE(37, "-color-bg-default");
|
||||
|
||||
private final int code;
|
||||
private final String color;
|
||||
|
||||
public static final Map<String, Color> NAME_CODE = Arrays.stream(Color.values())
|
||||
.collect(Collectors.toMap(Color::name, Function.identity()));
|
||||
|
||||
public static final Map<Integer, Color> CODE_NAME = Arrays.stream(Color.values())
|
||||
.collect(Collectors.toMap(Color::getCode, Function.identity()));
|
||||
|
||||
public static Color valueOf(int code) {
|
||||
return CODE_NAME.get(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cn.octopusyan.alistgui.enums.ProxySetup;
|
||||
import cn.octopusyan.alistgui.model.ProxyInfo;
|
||||
import cn.octopusyan.alistgui.util.JsonUtil;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
@ -25,6 +26,7 @@ import java.util.Optional;
|
||||
*/
|
||||
public class HttpUtil {
|
||||
private volatile static HttpUtil util;
|
||||
@Getter
|
||||
private volatile HttpClient httpClient;
|
||||
private final HttpConfig httpConfig;
|
||||
|
||||
|
@ -2,6 +2,7 @@ package cn.octopusyan.alistgui.model;
|
||||
|
||||
import cn.octopusyan.alistgui.enums.ProxySetup;
|
||||
import cn.octopusyan.alistgui.manager.ConfigManager;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -17,9 +18,13 @@ public class GuiConfig {
|
||||
|
||||
private Boolean autoStart = false;
|
||||
private Boolean silentStartup = false;
|
||||
@JsonProperty("proxy")
|
||||
private ProxyInfo proxyInfo;
|
||||
@JsonProperty("proxy.testUrl")
|
||||
private String proxyTestUrl = "http://";
|
||||
private String proxySetup = ProxySetup.NO_PROXY.getName();
|
||||
private String language = ConfigManager.DEFAULT_LANGUAGE.toString();
|
||||
private String theme = ConfigManager.DEFAULT_THEME;
|
||||
private String proxyTestUrl = "http://";
|
||||
@JsonProperty("upgrade")
|
||||
private UpgradeConfig upgradeConfig = new UpgradeConfig();
|
||||
}
|
||||
|
@ -11,8 +11,6 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
public class UpgradeConfig {
|
||||
public static final String RELEASE_API = "https://api.github.com/repos/{}/{}/releases/latest";
|
||||
public static final String DOWNLOAD_API = "https://github.com/{}/{}/releases/download/{}/{}";
|
||||
private AList aList = new AList();
|
||||
private Gui gui = new Gui();
|
||||
}
|
||||
|
@ -1,9 +1,21 @@
|
||||
package cn.octopusyan.alistgui.model.upgrade;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
/**
|
||||
* @author octopus_yan
|
||||
*/
|
||||
public interface UpgradeApp {
|
||||
@JsonIgnore
|
||||
default String getReleaseApi() {
|
||||
return STR."https://api.github.com/repos/\{getOwner()}/\{getRepo()}/releases/latest";
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
default String getDownloadUrl(String version) {
|
||||
return STR."https://github.com/\{getOwner()}/\{getRepo()}/releases/download/\{version}/\{getReleaseFile()}";
|
||||
}
|
||||
|
||||
String getOwner();
|
||||
|
||||
String getRepo();
|
||||
|
158
src/main/java/cn/octopusyan/alistgui/task/DownloadTask.java
Normal file
158
src/main/java/cn/octopusyan/alistgui/task/DownloadTask.java
Normal file
@ -0,0 +1,158 @@
|
||||
package cn.octopusyan.alistgui.task;
|
||||
|
||||
import cn.octopusyan.alistgui.base.BaseTask;
|
||||
import cn.octopusyan.alistgui.config.Constants;
|
||||
import cn.octopusyan.alistgui.manager.http.HttpUtil;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.OpenOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.concurrent.Flow;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* TODO 下载任务
|
||||
*
|
||||
* @author octopus_yan
|
||||
*/
|
||||
@Slf4j
|
||||
public class DownloadTask extends BaseTask {
|
||||
private final String downloadUrl;
|
||||
|
||||
public DownloadTask(String downloadUrl) {
|
||||
this.downloadUrl = downloadUrl;
|
||||
log.info(STR."downlaod url : \{downloadUrl}");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void task() throws Exception {
|
||||
HttpClient client = HttpUtil.getInstance().getHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(downloadUrl)).build();
|
||||
|
||||
// 检查bin目录
|
||||
File binDir = new File(Constants.BIN_DIR_PATH);
|
||||
if (!binDir.exists()) {
|
||||
log.debug(STR."dir [\{Constants.BIN_DIR_PATH}] not exists");
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
binDir.mkdirs();
|
||||
log.debug(STR."created dir [\{Constants.BIN_DIR_PATH}]");
|
||||
}
|
||||
|
||||
// 下载处理器
|
||||
var handler = BodyHandler.create(
|
||||
Path.of(Constants.BIN_DIR_PATH),
|
||||
StandardOpenOption.CREATE, StandardOpenOption.WRITE
|
||||
);
|
||||
|
||||
// 下载监听
|
||||
handler.listener((total, progress) -> {
|
||||
// 输出进度
|
||||
if (listener != null && listener instanceof Listener lis)
|
||||
lis.onProgress(total, progress);
|
||||
});
|
||||
|
||||
log.info("download start");
|
||||
HttpResponse<Path> response = client.send(request, handler);
|
||||
log.info("download success");
|
||||
}
|
||||
|
||||
public interface Listener extends BaseTask.Listener {
|
||||
void onProgress(Long total, Long progress);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义下载返回处理
|
||||
*/
|
||||
private static class BodyHandler implements HttpResponse.BodyHandler<Path> {
|
||||
private final HttpResponse.BodyHandler<Path> handler;
|
||||
private BiConsumer<Long, Long> consumer;
|
||||
|
||||
private BodyHandler(HttpResponse.BodyHandler<Path> handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public static BodyHandler create(Path directory, OpenOption... openOptions) {
|
||||
return new BodyHandler(HttpResponse.BodyHandlers.ofFileDownload(directory, openOptions));
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpResponse.BodySubscriber<Path> apply(HttpResponse.ResponseInfo responseInfo) {
|
||||
AtomicLong length = new AtomicLong(-1);
|
||||
// 获取文件大小
|
||||
Optional<String> string = responseInfo.headers().firstValue("content-length");
|
||||
string.ifPresentOrElse(s -> {
|
||||
length.set(Long.parseLong(s));
|
||||
log.debug(STR."========={content-length = \{s}}=========");
|
||||
}, () -> {
|
||||
String msg = "response not has header [content-length]";
|
||||
log.error(msg);
|
||||
});
|
||||
|
||||
BodySubscriber subscriber = new BodySubscriber(handler.apply(responseInfo));
|
||||
subscriber.setConsumer(progress -> consumer.accept(length.get(), progress));
|
||||
|
||||
return subscriber;
|
||||
}
|
||||
|
||||
public void listener(BiConsumer<Long, Long> consumer) {
|
||||
this.consumer = consumer;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BodySubscriber implements HttpResponse.BodySubscriber<Path> {
|
||||
private final HttpResponse.BodySubscriber<Path> subscriber;
|
||||
private final AtomicLong progress = new AtomicLong(0);
|
||||
@Setter
|
||||
private Consumer<Long> consumer;
|
||||
|
||||
public BodySubscriber(HttpResponse.BodySubscriber<Path> subscriber) {
|
||||
this.subscriber = subscriber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionStage<Path> getBody() {
|
||||
return subscriber.getBody();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Flow.Subscription subscription) {
|
||||
subscriber.onSubscribe(subscription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(List<ByteBuffer> item) {
|
||||
subscriber.onNext(item);
|
||||
|
||||
// 记录进度
|
||||
for (ByteBuffer byteBuffer : item) {
|
||||
progress.addAndGet(byteBuffer.limit());
|
||||
}
|
||||
consumer.accept(progress.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
subscriber.onError(throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
subscriber.onComplete();
|
||||
|
||||
consumer.accept(progress.get());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
package cn.octopusyan.alistgui.task;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.octopusyan.alistgui.base.BaseTask;
|
||||
import cn.octopusyan.alistgui.manager.http.HttpUtil;
|
||||
import cn.octopusyan.alistgui.model.UpgradeConfig;
|
||||
import cn.octopusyan.alistgui.model.upgrade.AList;
|
||||
import cn.octopusyan.alistgui.model.upgrade.UpgradeApp;
|
||||
import cn.octopusyan.alistgui.util.JsonUtil;
|
||||
import cn.octopusyan.alistgui.viewModel.AboutViewModule;
|
||||
@ -16,31 +15,30 @@ import org.apache.commons.lang3.StringUtils;
|
||||
* @author octopus_yan
|
||||
*/
|
||||
public class UpgradeTask extends BaseTask {
|
||||
private final AboutViewModule vm;
|
||||
private final AboutViewModule viewModule;
|
||||
private final UpgradeApp app;
|
||||
|
||||
public UpgradeTask(AboutViewModule viewModel, UpgradeApp app) {
|
||||
this.vm = viewModel;
|
||||
this.viewModule = viewModel;
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void task() throws Exception {
|
||||
String releaseApi = StrUtil.format(UpgradeConfig.RELEASE_API, app.getOwner(), app.getRepo());
|
||||
String responseStr = HttpUtil.getInstance().get(releaseApi, null, null);
|
||||
String responseStr = HttpUtil.getInstance().get(app.getReleaseApi(), null, null);
|
||||
JsonNode response = JsonUtil.parseJsonObject(responseStr);
|
||||
|
||||
// TODO 校验返回内容
|
||||
String newVersion = response.get("tag_name").asText();
|
||||
String downloadUrl = StrUtil.format(UpgradeConfig.DOWNLOAD_API,
|
||||
app.getOwner(),
|
||||
app.getRepo(),
|
||||
newVersion,
|
||||
app.getReleaseFile()
|
||||
);
|
||||
|
||||
runLater(() -> {
|
||||
vm.aListUpgradeProperty().setValue(StringUtils.equals(app.getVersion(), newVersion));
|
||||
vm.aListNewVersionProperty().setValue(newVersion);
|
||||
if (app instanceof AList) {
|
||||
viewModule.aListUpgradeProperty().setValue(!StringUtils.equals(app.getVersion(), newVersion));
|
||||
viewModule.aListNewVersionProperty().setValue(newVersion);
|
||||
} else {
|
||||
viewModule.guiUpgradeProperty().setValue(!StringUtils.equals(app.getVersion(), newVersion));
|
||||
viewModule.guiNewVersionProperty().setValue(newVersion);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,11 @@ public class AlertBuilder extends BaseBuilder<AlertBuilder, Alert> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public AlertBuilder buttons(ButtonType... buttons) {
|
||||
dialog.getButtonTypes().addAll(buttons);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AlertBuilder exception(Exception ex) {
|
||||
dialog.setTitle("Exception Dialog");
|
||||
dialog.setHeaderText(ex.getClass().getSimpleName());
|
||||
@ -71,8 +76,9 @@ public class AlertBuilder extends BaseBuilder<AlertBuilder, Alert> {
|
||||
|
||||
return Arrays.stream(buttons).map((type) -> {
|
||||
ButtonBar.ButtonData buttonData = ButtonBar.ButtonData.OTHER;
|
||||
if ("cancel".equals(StringUtils.lowerCase(type)) || "取消".equals(type))
|
||||
buttonData = ButtonBar.ButtonData.CANCEL_CLOSE;
|
||||
if ("cancel".equals(StringUtils.lowerCase(type)) || "取消".equals(type)) {
|
||||
return ButtonType.CANCEL;
|
||||
}
|
||||
return new ButtonType(type, buttonData);
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
@ -53,6 +53,10 @@ public class AlertUtil {
|
||||
return confirm().buttons(buttons);
|
||||
}
|
||||
|
||||
public static AlertBuilder confirm(ButtonType... buttons) {
|
||||
return confirm().buttons(buttons);
|
||||
}
|
||||
|
||||
public static AlertBuilder alert(Alert.AlertType type) {
|
||||
return new AlertBuilder(mOwner, type);
|
||||
}
|
||||
@ -77,7 +81,8 @@ public class AlertUtil {
|
||||
public interface OnChoseListener {
|
||||
void confirm();
|
||||
|
||||
void cancelOrClose(ButtonType buttonType);
|
||||
default void cancelOrClose(ButtonType buttonType) {
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnClickListener {
|
||||
|
@ -1,14 +1,8 @@
|
||||
package cn.octopusyan.alistgui.util.alert;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.control.Dialog;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.Window;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author octopus_yan
|
||||
*/
|
||||
@ -17,7 +11,6 @@ public abstract class BaseBuilder<T extends BaseBuilder<T, ?>, D extends Dialog<
|
||||
|
||||
public BaseBuilder(D dialog, Window mOwner) {
|
||||
this.dialog = dialog;
|
||||
icon("/assets/logo.png");
|
||||
if (mOwner != null)
|
||||
this.dialog.initOwner(mOwner);
|
||||
}
|
||||
@ -37,18 +30,6 @@ public abstract class BaseBuilder<T extends BaseBuilder<T, ?>, D extends Dialog<
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T icon(String path) {
|
||||
return icon(new Image(Objects.requireNonNull(this.getClass().getResource(path)).toString()));
|
||||
}
|
||||
|
||||
public T icon(Image image) {
|
||||
ObservableList<Image> icons = getStage().getIcons();
|
||||
if (icons.isEmpty()) {
|
||||
Platform.runLater(() -> icons.add(image));
|
||||
}
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public D getDialog() {
|
||||
return dialog;
|
||||
}
|
||||
@ -61,8 +42,4 @@ public abstract class BaseBuilder<T extends BaseBuilder<T, ?>, D extends Dialog<
|
||||
if (dialog.isShowing())
|
||||
dialog.close();
|
||||
}
|
||||
|
||||
private Stage getStage() {
|
||||
return (Stage) dialog.getDialogPane().getScene().getWindow();
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public class ProgressBuilder extends BaseBuilder<ProgressBuilder, Dialog<Void>>
|
||||
HBox hBox = new HBox();
|
||||
hBox.setPrefWidth(350);
|
||||
hBox.setAlignment(Pos.CENTER);
|
||||
hBox.setPadding(new Insets(0, 0, 0, 0));
|
||||
hBox.setPadding(new Insets(10, 0, 10, 0));
|
||||
|
||||
// 取消按钮
|
||||
Button cancel = new Button(Context.getLanguageBinding("label.cancel").get());
|
||||
|
@ -1,14 +1,28 @@
|
||||
package cn.octopusyan.alistgui.viewModel;
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.octopusyan.alistgui.base.BaseTask;
|
||||
import cn.octopusyan.alistgui.config.Constants;
|
||||
import cn.octopusyan.alistgui.config.Context;
|
||||
import cn.octopusyan.alistgui.manager.ConfigManager;
|
||||
import cn.octopusyan.alistgui.manager.ConsoleLog;
|
||||
import cn.octopusyan.alistgui.model.upgrade.AList;
|
||||
import cn.octopusyan.alistgui.model.upgrade.UpgradeApp;
|
||||
import cn.octopusyan.alistgui.task.DownloadTask;
|
||||
import cn.octopusyan.alistgui.task.UpgradeTask;
|
||||
import cn.octopusyan.alistgui.util.alert.AlertBuilder;
|
||||
import cn.octopusyan.alistgui.util.alert.AlertUtil;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.*;
|
||||
import javafx.scene.control.ButtonType;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
* 关于
|
||||
*
|
||||
@ -19,6 +33,9 @@ public class AboutViewModule {
|
||||
private final StringProperty aListVersion = new SimpleStringProperty(ConfigManager.aListVersion());
|
||||
private final StringProperty aListNewVersion = new SimpleStringProperty("");
|
||||
private final BooleanProperty aListUpgrade = new SimpleBooleanProperty(false);
|
||||
private final StringProperty guiVersion = new SimpleStringProperty(ConfigManager.guiVersion());
|
||||
private final StringProperty guiNewVersion = new SimpleStringProperty("");
|
||||
private final BooleanProperty guiUpgrade = new SimpleBooleanProperty(false);
|
||||
|
||||
public AboutViewModule() {
|
||||
aListVersion.addListener((_, _, newValue) -> ConfigManager.aListVersion(newValue));
|
||||
@ -36,38 +53,173 @@ public class AboutViewModule {
|
||||
return aListNewVersion;
|
||||
}
|
||||
|
||||
public StringProperty guiVersionProperty() {
|
||||
return guiVersion;
|
||||
}
|
||||
|
||||
public StringProperty guiNewVersionProperty() {
|
||||
return guiNewVersion;
|
||||
}
|
||||
|
||||
public BooleanProperty guiUpgradeProperty() {
|
||||
return guiUpgrade;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查alist更新
|
||||
* 检查更新
|
||||
*/
|
||||
public void checkAListUpdate() {
|
||||
var task = new UpgradeTask(this, ConfigManager.aList());
|
||||
task.onListen(new BaseTask.Listener() {
|
||||
@Override
|
||||
public void onSucceeded() {
|
||||
AlertUtil.confirm()
|
||||
public void checkUpdate(UpgradeApp app) {
|
||||
|
||||
// 检查任务
|
||||
startUpgrade(app, () -> {
|
||||
// 判断 检查的应用
|
||||
boolean tag = app instanceof AList;
|
||||
|
||||
boolean upgrade = tag ? aListUpgrade.get() : guiUpgrade.get();
|
||||
String version = tag ? aListVersion.get() : guiVersion.get();
|
||||
String newVersion = tag ? aListNewVersion.get() : guiNewVersion.get();
|
||||
String title = Context.getLanguageBinding(STR."about.\{tag ? "alist" : "app"}.update").getValue();
|
||||
String currentLabel = Context.getLanguageBinding("update.current").get();
|
||||
String newLabel = Context.getLanguageBinding("update.remote").get();
|
||||
String header = Context.getLanguageBinding(STR."update.upgrade.\{upgrade ? "new" : "not"}").get();
|
||||
|
||||
String msg = STR."\{app.getRepo()}\{upgrade ? "" : STR." \{version}"} \{header} \{upgrade ? newVersion : ""}";
|
||||
log.info(msg);
|
||||
ConsoleLog.info(msg);
|
||||
|
||||
AlertBuilder builder = upgrade ? AlertUtil.confirm() : AlertUtil.info();
|
||||
builder.title(title)
|
||||
.header(header)
|
||||
.content(STR."""
|
||||
当前版本 : \{aListVersion.get()}
|
||||
最新版本 : \{aListNewVersion.get()}
|
||||
\{currentLabel} : \{version}
|
||||
\{newLabel} : \{newVersion}
|
||||
""")
|
||||
.title(Context.getLanguageBinding("about.alist.update").getValue())
|
||||
.show(new AlertUtil.OnChoseListener() {
|
||||
.show(() -> {
|
||||
if (upgrade) startDownload(app, newVersion);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void startUpgrade(UpgradeApp app, Runnable runnable) {
|
||||
// 检查更新的任务
|
||||
var task = new UpgradeTask(this, app);
|
||||
|
||||
// 加载弹窗
|
||||
final var progress = AlertUtil.progress();
|
||||
progress.title(Context.getLanguageBinding("proxy.test.title").get());
|
||||
progress.onCancel(task::cancel);
|
||||
|
||||
// 任务监听
|
||||
task.onListen(new BaseTask.Listener() {
|
||||
|
||||
@Override
|
||||
public void confirm() {
|
||||
log.info("========confirm==========");
|
||||
public void onStart() {
|
||||
String msg = STR."start update \{app.getRepo()}...";
|
||||
log.info(msg);
|
||||
ConsoleLog.info(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelOrClose(ButtonType buttonType) {
|
||||
log.info("========cancelOrClose==========");
|
||||
public void onRunning() {
|
||||
progress.show();
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
public void onSucceeded() {
|
||||
progress.close();
|
||||
if (runnable != null) runnable.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed(Throwable throwable) {
|
||||
String msg = STR."\{app.getRepo()} check version error";
|
||||
log.error(msg, throwable);
|
||||
ConsoleLog.error(STR."\{msg} : \{throwable.getMessage()}");
|
||||
AlertUtil.exception(new Exception(throwable)).show();
|
||||
}
|
||||
});
|
||||
// 执行任务
|
||||
task.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
*
|
||||
* @param app 应用
|
||||
* @param version 下载版本
|
||||
*/
|
||||
private void startDownload(UpgradeApp app, String version) {
|
||||
DownloadTask downloadTask = new DownloadTask(app.getDownloadUrl(version));
|
||||
downloadTask.onListen(new DownloadTask.Listener() {
|
||||
|
||||
private volatile int lastProgress = 0;
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
String msg = STR."download \{app.getRepo()} start";
|
||||
log.info(msg);
|
||||
ConsoleLog.info(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(Long total, Long progress) {
|
||||
int a = (int) (((double) progress / total) * 100);
|
||||
if (a % 10 == 0) {
|
||||
if (a != lastProgress) {
|
||||
lastProgress = a;
|
||||
String msg = STR."\{app.getRepo()} \{a} %";
|
||||
log.info(STR."download \{msg}");
|
||||
ConsoleLog.info(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSucceeded() {
|
||||
String msg = STR."download \{app.getRepo()} success";
|
||||
log.info(msg);
|
||||
ConsoleLog.info(msg);
|
||||
|
||||
// 解压并删除文件
|
||||
unzip(app);
|
||||
|
||||
Platform.runLater(() -> aListVersion.setValue(aListNewVersion.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed(Throwable throwable) {
|
||||
log.error("下载失败", throwable);
|
||||
ConsoleLog.error(STR."下载失败 => \{throwable.getMessage()}");
|
||||
}
|
||||
});
|
||||
downloadTask.execute();
|
||||
}
|
||||
|
||||
private void unzip(UpgradeApp app) {
|
||||
File file = new File(Constants.BIN_DIR_PATH + File.separator + app.getReleaseFile());
|
||||
ZipFile zipFile = ZipUtil.toZipFile(file, CharsetUtil.defaultCharset());
|
||||
ZipUtil.read(zipFile, zipEntry -> {
|
||||
String path = zipEntry.getName();
|
||||
if (FileUtil.isWindows()) {
|
||||
// Win系统下
|
||||
path = StrUtil.replace(path, "*", "_");
|
||||
}
|
||||
|
||||
final File outItemFile = FileUtil.file(Constants.BIN_DIR_PATH, path);
|
||||
if (zipEntry.isDirectory()) {
|
||||
// 目录
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
outItemFile.mkdirs();
|
||||
} else {
|
||||
InputStream in = ZipUtil.getStream(zipFile, zipEntry);
|
||||
// 文件
|
||||
FileUtil.writeFromStream(in, outItemFile, false);
|
||||
|
||||
log.info(STR."unzip ==> \{outItemFile.getAbsoluteFile()}");
|
||||
}
|
||||
});
|
||||
|
||||
// 解压完成后删除
|
||||
FileUtil.del(file);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.octopusyan.alistgui.viewModel;
|
||||
|
||||
import atlantafx.base.theme.Theme;
|
||||
import cn.octopusyan.alistgui.base.BaseTask;
|
||||
import cn.octopusyan.alistgui.config.Context;
|
||||
import cn.octopusyan.alistgui.enums.ProxySetup;
|
||||
@ -22,7 +23,7 @@ import java.util.Locale;
|
||||
public class SetupViewModel {
|
||||
private final BooleanProperty autoStart = new SimpleBooleanProperty(ConfigManager.autoStart());
|
||||
private final BooleanProperty silentStartup = new SimpleBooleanProperty(ConfigManager.silentStartup());
|
||||
private final StringProperty theme = new SimpleStringProperty(ConfigManager.themeName());
|
||||
private final ObjectProperty<Theme> theme = new SimpleObjectProperty<>(ConfigManager.theme());
|
||||
private final StringProperty proxyHost = new SimpleStringProperty(ConfigManager.proxyHost());
|
||||
private final StringProperty proxyPort = new SimpleStringProperty(ConfigManager.proxyPort());
|
||||
private final ObjectProperty<Locale> language = new SimpleObjectProperty<>(ConfigManager.language());
|
||||
@ -31,7 +32,8 @@ public class SetupViewModel {
|
||||
|
||||
|
||||
public SetupViewModel() {
|
||||
theme.addListener((_, _, newValue) -> ConfigManager.themeName(newValue));
|
||||
theme.bindBidirectional(Context.themeProperty());
|
||||
theme.addListener((_, _, newValue) -> ConfigManager.theme(newValue));
|
||||
autoStart.addListener((_, _, newValue) -> ConfigManager.autoStart(newValue));
|
||||
silentStartup.addListener((_, _, newValue) -> ConfigManager.silentStartup(newValue));
|
||||
proxySetup.addListener((_, _, newValue) -> ConfigManager.proxySetup(newValue));
|
||||
@ -41,7 +43,7 @@ public class SetupViewModel {
|
||||
language.addListener((_, _, newValue) -> Context.setLanguage(newValue));
|
||||
}
|
||||
|
||||
public StringProperty themeProperty() {
|
||||
public ObjectProperty<Theme> themeProperty() {
|
||||
return theme;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,6 @@
|
||||
<Label styleClass="shield-name" text="%about.app.version"/>
|
||||
<Label styleClass="shield-version" text="v${project.version}"/>
|
||||
</HBox>
|
||||
<Button fx:id="checkAppVersion" text="%about.app.update"/>
|
||||
<Button fx:id="checkAListVersion" onAction="#checkAListUpdate" text="%about.alist.update"/>
|
||||
<Button fx:id="checkAppVersion" styleClass="flat" text="%about.app.update"/>
|
||||
<Button fx:id="checkAListVersion" styleClass="flat" onAction="#checkAListUpdate" text="%about.alist.update"/>
|
||||
</VBox>
|
||||
|
@ -32,5 +32,10 @@ about.app.version=GUI \u7248\u672C
|
||||
about.alist.update=\u68C0\u67E5 AList \u7248\u672C
|
||||
about.app.update=\u68C0\u67E5 GUI \u7248\u672C
|
||||
setup.theme=\u4E3B\u9898
|
||||
update.current=\u5F53\u524D
|
||||
update.remote=\u6700\u65B0
|
||||
update.upgrade.not=\u5DF2\u662F\u6700\u65B0\u7248\u672C
|
||||
update.upgrade.new=\u68C0\u67E5\u5230\u65B0\u7248\u672C
|
||||
|
||||
|
||||
|
||||
|
@ -32,5 +32,9 @@ about.app.version=GUI Version
|
||||
about.alist.update=Check AList Version
|
||||
about.app.update=Check GUI Version
|
||||
setup.theme=Theme
|
||||
update.current=Current
|
||||
update.remote=Latest
|
||||
update.upgrade.not=It is already the latest version
|
||||
update.upgrade.new=Detected a new version
|
||||
|
||||
|
||||
|
@ -32,5 +32,9 @@ about.app.version=GUI \u7248\u672C
|
||||
about.alist.update=\u68C0\u67E5 AList \u7248\u672C
|
||||
about.app.update=\u68C0\u67E5 GUI \u7248\u672C
|
||||
setup.theme=\u4E3B\u9898
|
||||
update.current=\u5F53\u524D
|
||||
update.remote=\u6700\u65B0
|
||||
update.upgrade.not=\u5DF2\u662F\u6700\u65B0\u7248\u672C
|
||||
update.upgrade.new=\u68C0\u67E5\u5230\u65B0\u7248\u672C
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user