From b1218e9122e290e74822afebdea87fe234e0950b Mon Sep 17 00:00:00 2001 From: octopus_yan Date: Sun, 8 Sep 2024 02:03:01 +0800 Subject: [PATCH] =?UTF-8?q?todo:=20alist=E6=A3=80=E6=9F=A5=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E3=80=81=E4=BB=A3=E7=90=86=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 60 ++++-- .../cn/octopusyan/alistgui/base/BaseTask.java | 50 +++++ .../alistgui/config/ConfigManager.java | 127 ------------ .../{AppConstant.java => Constants.java} | 10 +- .../octopusyan/alistgui/config/Context.java | 33 ++-- .../alistgui/controller/RootController.java | 32 ++-- .../alistgui/controller/SetupController.java | 46 ++--- .../alistgui/manager/ConfigManager.java | 181 ++++++++++++++++++ .../octopusyan/alistgui/model/GuiConfig.java | 52 +---- .../alistgui/model/UpgradeConfig.java | 18 ++ .../alistgui/model/upgrade/AList.java | 18 ++ .../alistgui/model/upgrade/Gui.java | 27 +++ .../alistgui/model/upgrade/UpgradeApp.java | 14 ++ .../octopusyan/alistgui/task/UpgradeTask.java | 46 +++++ .../alistgui/viewModel/SetupViewModel.java | 72 ++++--- src/main/java/module-info.java | 2 + src/main/resources/css/main-view.scss | 1 - src/main/resources/fxml/setup-view.fxml | 65 +++---- .../resources/language/language.properties | 7 +- .../resources/language/language_en.properties | 7 +- .../resources/language/language_zh.properties | 7 +- 21 files changed, 551 insertions(+), 324 deletions(-) create mode 100644 src/main/java/cn/octopusyan/alistgui/base/BaseTask.java delete mode 100644 src/main/java/cn/octopusyan/alistgui/config/ConfigManager.java rename src/main/java/cn/octopusyan/alistgui/config/{AppConstant.java => Constants.java} (57%) create mode 100644 src/main/java/cn/octopusyan/alistgui/manager/ConfigManager.java create mode 100644 src/main/java/cn/octopusyan/alistgui/model/UpgradeConfig.java create mode 100644 src/main/java/cn/octopusyan/alistgui/model/upgrade/AList.java create mode 100644 src/main/java/cn/octopusyan/alistgui/model/upgrade/Gui.java create mode 100644 src/main/java/cn/octopusyan/alistgui/model/upgrade/UpgradeApp.java create mode 100644 src/main/java/cn/octopusyan/alistgui/task/UpgradeTask.java diff --git a/pom.xml b/pom.xml index 2728439..01ca524 100644 --- a/pom.xml +++ b/pom.xml @@ -18,21 +18,21 @@ AList windows gui - 17 - 17 - 17 + 21 + 21 + 21 UTF-8 UTF-8 5.10.0 - 17.0.6 + 21.0.4 2.0.16 1.4.14 5.8.32 3.16.0 - 1.4.0 1.18.32 + 2.15.4 12.3.1 1.0.1 @@ -50,6 +50,7 @@ ${javafx.version} + io.github.mkpaz atlantafx-base @@ -127,7 +128,7 @@ com.fasterxml.jackson.dataformat jackson-dataformat-yaml - 2.15.4 + ${jackson.version} @@ -183,8 +184,9 @@ maven-compiler-plugin 3.13.0 - 17 - 17 + 21 + 21 + --enable-preview @@ -196,11 +198,45 @@ exe dll - ttf + scss + + + us.hebi.sass + sass-cli-maven-plugin + 1.0.3 + + 1.78.0 + + + ${project.basedir}/src/main/resources/css/root.scss:${project.basedir}/target/classes/css/root.css + + + ${project.basedir}/src/main/resources/css/root-view.scss:${project.basedir}/target/classes/css/root-view.css + + + ${project.basedir}/src/main/resources/css/main-view.scss:${project.basedir}/target/classes/css/main-view.css + + + ${project.basedir}/src/main/resources/css/setup-view.scss:${project.basedir}/target/classes/css/setup-view.css + + --no-source-map + + + + + sass-exec + generate-resources + + run + + + + + org.openjfx javafx-maven-plugin @@ -210,8 +246,7 @@ default-cli - cn.octopusyan.alistgui/cn.octopusyan.alistgui.AppLuncher - + cn.octopusyan.alistgui/cn.octopusyan.alistgui.AppLauncher launcher app app @@ -223,13 +258,14 @@ + io.github.fvarrui javapackager 1.7.7-SNAPSHOT true - cn.octopusyan.alistgui.AppLuncher + cn.octopusyan.alistgui.AppLauncher false diff --git a/src/main/java/cn/octopusyan/alistgui/base/BaseTask.java b/src/main/java/cn/octopusyan/alistgui/base/BaseTask.java new file mode 100644 index 0000000..13e87e4 --- /dev/null +++ b/src/main/java/cn/octopusyan/alistgui/base/BaseTask.java @@ -0,0 +1,50 @@ +package cn.octopusyan.alistgui.base; + +import cn.octopusyan.alistgui.manager.thread.ThreadPoolManager; +import javafx.application.Platform; +import javafx.concurrent.Task; + +/** + * @author octopus_yan + */ +public abstract class BaseTask extends Task { + private final ThreadPoolManager Executor = ThreadPoolManager.getInstance(); + + @Override + protected Void call() throws Exception { + task(); + return null; + } + + protected void runLater(Runnable runnable) { + Platform.runLater(runnable); + } + + protected abstract void task() throws Exception; + + public void onListen(Listener listener) { + if (listener == null) return; + + setOnRunning(_ -> listener.onRunning()); + setOnCancelled(_ -> listener.onCancelled()); + setOnFailed(_ -> listener.onFailed(getException())); + setOnSucceeded(_ -> listener.onSucceeded()); + } + + public void execute() { + Executor.execute(this); + } + + public interface Listener { + default void onRunning() { + } + + default void onCancelled() { + } + + default void onFailed(Throwable throwable) { + } + + void onSucceeded(); + } +} diff --git a/src/main/java/cn/octopusyan/alistgui/config/ConfigManager.java b/src/main/java/cn/octopusyan/alistgui/config/ConfigManager.java deleted file mode 100644 index 4c155a6..0000000 --- a/src/main/java/cn/octopusyan/alistgui/config/ConfigManager.java +++ /dev/null @@ -1,127 +0,0 @@ -package cn.octopusyan.alistgui.config; - -import cn.hutool.core.lang.PatternPool; -import cn.hutool.core.util.NumberUtil; -import cn.octopusyan.alistgui.enums.ProxySetup; -import cn.octopusyan.alistgui.manager.http.HttpUtil; -import cn.octopusyan.alistgui.model.GuiConfig; -import cn.octopusyan.alistgui.model.ProxyInfo; -import org.apache.commons.lang3.LocaleUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.Locale; -import java.util.Optional; -import java.util.regex.Matcher; - -/** - * 客户端设置 - * - * @author octopus_yan@foxmail.com - */ -public class ConfigManager { - private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class); - public static final Locale DEFAULT_LANGUAGE = Locale.CHINESE; - private static GuiConfig guiConfig; - - public static void load() { - try { - guiConfig = GuiConfig.getInstance(); - } catch (IOException e) { - logger.error("load config error", e); - } - } - - public static boolean hasProxy() { - if (guiConfig == null) - return false; - ProxyInfo proxyInfo = guiConfig.getProxyInfo(); - return proxyInfo != null - && StringUtils.isNoneEmpty(proxyInfo.getHost()) - && StringUtils.isNoneEmpty(proxyInfo.getPort()) - && Integer.parseInt(proxyInfo.getPort()) > 0; - } - - public static ProxyInfo getProxyInfo() { - return guiConfig.getProxyInfo(); - } - - public static String proxyHost() { - return guiConfig.getProxyInfo().getHost(); - } - - public static void proxyHost(String host) { - final Matcher matcher = PatternPool.IPV4.matcher(host); - if (matcher.matches()) { - guiConfig.getProxyInfo().setHost(host); - } - } - - public static String proxyPort() { - return guiConfig.getProxyInfo().getPort(); - } - - public static int getProxyPort() { - return Integer.parseInt(guiConfig.getProxyInfo().getPort()); - } - - public static void proxyPort(String port) { - if (NumberUtil.isNumber(port)) - guiConfig.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())); - } - - public static void proxySetup(ProxySetup setup) { - guiConfig.setProxySetup(setup.getName()); - - if (!ProxySetup.NO_PROXY.equals(setup) && hasProxy()) { - HttpUtil.getInstance().proxy(setup, ConfigManager.getProxyInfo()); - } - } - - public static boolean silentStartup() { - return guiConfig.getSilentStartup(); - } - - public static void silentStartup(Boolean startup) { - guiConfig.setSilentStartup(startup); - } - - public static String aListVersion() { - return guiConfig.getAListVersion(); - } - - public static void aListVersion(String version) { - guiConfig.setAListVersion(version); - } - - public static void save() { - try { - guiConfig.save(); - } catch (IOException e) { - logger.error("save config error", e); - } - } -} diff --git a/src/main/java/cn/octopusyan/alistgui/config/AppConstant.java b/src/main/java/cn/octopusyan/alistgui/config/Constants.java similarity index 57% rename from src/main/java/cn/octopusyan/alistgui/config/AppConstant.java rename to src/main/java/cn/octopusyan/alistgui/config/Constants.java index 95ab185..245eb4c 100644 --- a/src/main/java/cn/octopusyan/alistgui/config/AppConstant.java +++ b/src/main/java/cn/octopusyan/alistgui/config/Constants.java @@ -10,13 +10,15 @@ import java.nio.file.Paths; * * @author octopus_yan@foxmail.com */ -public class AppConstant { +public class Constants { public static final String APP_TITLE = PropertiesUtils.getInstance().getProperty("app.title"); public static final String APP_NAME = PropertiesUtils.getInstance().getProperty("app.name"); public static final String APP_VERSION = PropertiesUtils.getInstance().getProperty("app.version"); public static final String DATA_DIR_PATH = Paths.get(".").toFile().getAbsolutePath(); + public static final String BIN_DIR_PATH = STR."\{DATA_DIR_PATH}\{File.separator}bin"; + public static final String UPGRADE_PATH = STR."\{BIN_DIR_PATH}\{File.separator}upgrade.yaml"; public static final String TMP_DIR_PATH = System.getProperty("java.io.tmpdir") + APP_NAME; - public static final String CONFIG_DIR_PATH = DATA_DIR_PATH + File.separator + "config"; - public static final String GUI_CONFIG_PATH = CONFIG_DIR_PATH + File.separator + "gui.yaml"; - public static final String BAK_FILE_PATH = AppConstant.TMP_DIR_PATH + File.separator + "bak"; + public static final String CONFIG_DIR_PATH = STR."\{DATA_DIR_PATH}\{File.separator}config"; + public static final String GUI_CONFIG_PATH = STR."\{CONFIG_DIR_PATH}\{File.separator}gui.yaml"; + public static final String BAK_FILE_PATH = STR."\{Constants.TMP_DIR_PATH}\{File.separator}bak"; } diff --git a/src/main/java/cn/octopusyan/alistgui/config/Context.java b/src/main/java/cn/octopusyan/alistgui/config/Context.java index cf14ca4..dca5cee 100644 --- a/src/main/java/cn/octopusyan/alistgui/config/Context.java +++ b/src/main/java/cn/octopusyan/alistgui/config/Context.java @@ -65,14 +65,17 @@ public class Context { // 获取控制工厂 public static Callback, Object> getControlFactory() { return type -> { - if (type.equals(RootController.class)) { - return new RootController(); - } else if (type.equals(MainController.class)) { - return new MainController(); - } else if (type.equals(SetupController.class)) { - return new SetupController(); + try { + return switch (type.getDeclaredConstructor().newInstance()) { + case RootController root -> root; + case MainController main -> main; + case SetupController setup -> setup; + default -> throw new IllegalStateException(STR."Unexpected value: \{type}"); + }; + } catch (Exception e) { + log.error("", e); + return null; } - throw new IllegalStateException("Unexpected value: " + type); }; } @@ -130,15 +133,13 @@ public class Context { * 初始化 语言 */ private static void initI18n() { - currentLocaleProperty().addListener((observable, oldValue, newValue) -> { - Platform.runLater(() -> { - try { - loadScene(); - } catch (IOException e) { - log.error("", e); - } - }); - }); + currentLocaleProperty().addListener((_, _, _) -> Platform.runLater(() -> { + try { + loadScene(); + } catch (IOException e) { + log.error("", e); + } + })); } /** diff --git a/src/main/java/cn/octopusyan/alistgui/controller/RootController.java b/src/main/java/cn/octopusyan/alistgui/controller/RootController.java index ae4ff99..408b5d7 100644 --- a/src/main/java/cn/octopusyan/alistgui/controller/RootController.java +++ b/src/main/java/cn/octopusyan/alistgui/controller/RootController.java @@ -47,6 +47,7 @@ public class RootController extends BaseController { public Button github; @FXML public Button sponsor; + /** * 获取根布局 * @@ -71,12 +72,19 @@ public class RootController extends BaseController { @Override public void initViewStyle() { // 设置图标 - ImageView book = EmojiImageUtils.emojiView(EmojiData.emojiFromShortName("book").get(), 25); - document.setGraphic(book); - ImageView githubIcon = EmojiImageUtils.emojiView(EmojiData.emojiFromShortName("cat").get(), 25); - github.setGraphic(githubIcon); - ImageView juice = EmojiImageUtils.emojiView(EmojiData.emojiFromShortName("tropical_drink").get(), 25); - sponsor.setGraphic(juice); + EmojiData.emojiFromShortName("book").ifPresent(icon -> { + ImageView book = EmojiImageUtils.emojiView(icon, 25); + document.setGraphic(book); + }); + EmojiData.emojiFromShortName("cat").ifPresent(icon -> { + ImageView githubIcon = EmojiImageUtils.emojiView(icon, 25); + github.setGraphic(githubIcon); + + }); + EmojiData.emojiFromShortName("tropical_drink").ifPresent(icon -> { + ImageView juice = EmojiImageUtils.emojiView(icon, 25); + sponsor.setGraphic(juice); + }); } /** @@ -84,9 +92,9 @@ public class RootController extends BaseController { */ @Override public void initViewAction() { - closeIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> getWindow().close()); - minimizeIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> getWindow().setIconified(true)); - alwaysOnTopIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { + closeIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, _ -> getWindow().close()); + minimizeIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, _ -> getWindow().setIconified(true)); + alwaysOnTopIcon.addEventHandler(MouseEvent.MOUSE_CLICKED, _ -> { boolean newVal = !getWindow().isAlwaysOnTop(); alwaysOnTopIcon.pseudoClassStateChanged(PseudoClass.getPseudoClass("always-on-top"), newVal); getWindow().setAlwaysOnTop(newVal); @@ -101,8 +109,8 @@ public class RootController extends BaseController { getWindow().setY(event.getScreenY() + yOffset); }); - tabPane.getSelectionModel().selectedIndexProperty().addListener((observable, oldValue, newValue) -> { - Context.setCurrentViewIndex(newValue); - }); + tabPane.getSelectionModel() + .selectedIndexProperty() + .addListener((_, _, newValue) -> Context.setCurrentViewIndex(newValue)); } } diff --git a/src/main/java/cn/octopusyan/alistgui/controller/SetupController.java b/src/main/java/cn/octopusyan/alistgui/controller/SetupController.java index a8687a8..4fded3a 100644 --- a/src/main/java/cn/octopusyan/alistgui/controller/SetupController.java +++ b/src/main/java/cn/octopusyan/alistgui/controller/SetupController.java @@ -1,15 +1,15 @@ package cn.octopusyan.alistgui.controller; import cn.octopusyan.alistgui.base.BaseController; -import cn.octopusyan.alistgui.config.ConfigManager; import cn.octopusyan.alistgui.config.Context; import cn.octopusyan.alistgui.enums.ProxySetup; +import cn.octopusyan.alistgui.manager.ConfigManager; import cn.octopusyan.alistgui.viewModel.SetupViewModel; import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.*; -import javafx.scene.layout.GridPane; +import javafx.scene.layout.AnchorPane; import javafx.scene.layout.Pane; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,11 +22,11 @@ import java.util.Locale; * * @author octopus_yan */ -public class SetupController extends BaseController implements Initializable { +public class SetupController extends BaseController implements Initializable { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); @FXML - public GridPane setupView; + public AnchorPane setupView; @FXML public CheckBox autoStartCheckBox; @FXML @@ -35,26 +35,23 @@ public class SetupController extends BaseController implements Initial public ComboBox languageComboBox; @FXML public ComboBox proxySetupComboBox; -// @FXML -// public RadioButton noProxy; -// @FXML -// public RadioButton systemProxy; -// @FXML -// public RadioButton manualProxy; @FXML public Pane proxySetupPane; @FXML + public Button proxyCheck; + @FXML public TextField proxyHost; @FXML public TextField proxyPort; @FXML - public Label alistVersion; + public Label aListVersion; + @FXML + public Button checkAppVersion; private final SetupViewModel setupViewModel = new SetupViewModel(); - private final ToggleGroup proxySetupGroup = new ToggleGroup(); @Override - public GridPane getRootPanel() { + public AnchorPane getRootPanel() { return setupView; } @@ -63,18 +60,13 @@ public class SetupController extends BaseController implements Initial languageComboBox.setItems(FXCollections.observableList(Context.SUPPORT_LANGUAGE_LIST)); proxySetupComboBox.setItems(FXCollections.observableList(List.of(ProxySetup.values()))); -// noProxy.setToggleGroup(proxySetupGroup); -// systemProxy.setToggleGroup(proxySetupGroup); -// manualProxy.setToggleGroup(proxySetupGroup); } @Override public void initViewStyle() { - proxySetupComboBox.getSelectionModel().selectedItemProperty().addListener(observable -> { - proxySetupPane.setVisible(ProxySetup.MANUAL.equals(setupViewModel.proxySetupProperty().get())); - }); - proxySetupComboBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + proxySetupComboBox.getSelectionModel().selectedItemProperty().addListener((_, _, newValue) -> { proxySetupPane.setVisible(ProxySetup.MANUAL.equals(newValue)); + proxyCheck.setVisible(!ProxySetup.NO_PROXY.equals(newValue)); }); languageComboBox.getSelectionModel().select(ConfigManager.language()); @@ -85,15 +77,19 @@ public class SetupController extends BaseController implements Initial public void initViewAction() { autoStartCheckBox.selectedProperty().bindBidirectional(setupViewModel.autoStartProperty()); silentStartupCheckBox.selectedProperty().bindBidirectional(setupViewModel.silentStartupProperty()); - proxySetupComboBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { - setupViewModel.proxySetupProperty().set(newValue); - }); + proxySetupComboBox.getSelectionModel().selectedItemProperty() + .addListener((_, _, newValue) -> setupViewModel.proxySetupProperty().set(newValue)); proxyHost.textProperty().bindBidirectional(setupViewModel.proxyHostProperty()); proxyPort.textProperty().bindBidirectional(setupViewModel.proxyPortProperty()); - languageComboBox.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> { + languageComboBox.getSelectionModel().selectedItemProperty().addListener((_, _, newValue) -> { setupViewModel.languageProperty().set(newValue); logger.info("language changed to {}", newValue); }); - alistVersion.textProperty().bindBidirectional(setupViewModel.aListVersionProperty()); + aListVersion.textProperty().bindBidirectional(setupViewModel.aListVersionProperty()); + } + + @FXML + public void checkAListUpdate() { + setupViewModel.checkAListUpdate(); } } diff --git a/src/main/java/cn/octopusyan/alistgui/manager/ConfigManager.java b/src/main/java/cn/octopusyan/alistgui/manager/ConfigManager.java new file mode 100644 index 0000000..90a3269 --- /dev/null +++ b/src/main/java/cn/octopusyan/alistgui/manager/ConfigManager.java @@ -0,0 +1,181 @@ +package cn.octopusyan.alistgui.manager; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.lang.PatternPool; +import cn.hutool.core.util.NumberUtil; +import cn.octopusyan.alistgui.config.Constants; +import cn.octopusyan.alistgui.enums.ProxySetup; +import cn.octopusyan.alistgui.manager.http.HttpUtil; +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 com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import org.apache.commons.lang3.LocaleUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import java.util.Optional; +import java.util.regex.Matcher; + +/** + * 客户端设置 + * + * @author octopus_yan@foxmail.com + */ +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.CHINESE; + private static GuiConfig guiConfig; + private static UpgradeConfig upgradeConfig; + + static { + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); + } + + public static void load() { + guiConfig = loadConfig(Constants.GUI_CONFIG_PATH, GuiConfig.class); + upgradeConfig = loadConfig(Constants.UPGRADE_PATH, UpgradeConfig.class); + } + + private static T loadConfig(String path, Class clazz) { + File src = new File(path); + try { + if (!src.exists()) { + checkFile(src, clazz); + } + return objectMapper.readValue(src, clazz); + } catch (Exception e) { + logger.error(String.format("load %s error", clazz.getSimpleName()), e); + } + return null; + } + + 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; + } + + private 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())); + } + + public static void proxySetup(ProxySetup setup) { + guiConfig.setProxySetup(setup.getName()); + + if (ProxySetup.NO_PROXY.equals(setup)) { + HttpUtil.getInstance().clearProxy(); + } else if (hasProxy()) { + HttpUtil.getInstance().proxy(setup, ConfigManager.getProxyInfo()); + } + } + + public static boolean silentStartup() { + return guiConfig.getSilentStartup(); + } + + public static void silentStartup(Boolean startup) { + guiConfig.setSilentStartup(startup); + } + + public static AList aList() { + return upgradeConfig.getAList(); + } + + public static String aListVersion() { + return upgradeConfig.getAList().getVersion(); + } + + public static void aListVersion(String version) { + upgradeConfig.getAList().setVersion(version); + } + + + private static void checkFile(File src, Class 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); + objectMapper.writeValue(new File(Constants.UPGRADE_PATH), upgradeConfig); + } catch (IOException e) { + logger.error("save config error", e); + } + } +} diff --git a/src/main/java/cn/octopusyan/alistgui/model/GuiConfig.java b/src/main/java/cn/octopusyan/alistgui/model/GuiConfig.java index ac8fa1d..2fc31c3 100644 --- a/src/main/java/cn/octopusyan/alistgui/model/GuiConfig.java +++ b/src/main/java/cn/octopusyan/alistgui/model/GuiConfig.java @@ -1,71 +1,23 @@ package cn.octopusyan.alistgui.model; -import cn.hutool.core.io.FileUtil; -import cn.octopusyan.alistgui.config.AppConstant; -import cn.octopusyan.alistgui.config.ConfigManager; import cn.octopusyan.alistgui.enums.ProxySetup; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import cn.octopusyan.alistgui.manager.ConfigManager; import lombok.Data; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.IOException; - /** * GUI配置信息 - * 通过Jackson 写入yaml * * @author octopus_yan */ @Data public class GuiConfig { private static final Logger log = LoggerFactory.getLogger(GuiConfig.class); - public static GuiConfig INSTANCE; - public static ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory()); private Boolean autoStart = false; private Boolean silentStartup = false; - private ProxyInfo proxyInfo = new ProxyInfo(); + private ProxyInfo proxyInfo; private String proxySetup = ProxySetup.NO_PROXY.getName(); private String language = ConfigManager.DEFAULT_LANGUAGE.toString(); - @JsonProperty("aListVersion") - private String aListVersion = "unknown"; - - static { - objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); - } - - private GuiConfig() { - - } - - public static GuiConfig getInstance() throws IOException { - File src = new File(AppConstant.GUI_CONFIG_PATH); - if (INSTANCE == null) { - if (!src.exists()) { - checkFile(src); - } - INSTANCE = objectMapper.readValue(src, GuiConfig.class); - } - return INSTANCE; - } - - private static void checkFile(File src) throws IOException { - File parent = FileUtil.getParent(src, 1); - if (!parent.exists()) { - boolean wasSuccessful = parent.mkdirs(); - objectMapper.writeValue(src, new GuiConfig()); - if (!wasSuccessful) - log.error("{} 创建失败", src.getAbsolutePath()); - } - } - - public void save() throws IOException { - objectMapper.writeValue(new File(AppConstant.GUI_CONFIG_PATH), INSTANCE); - } } diff --git a/src/main/java/cn/octopusyan/alistgui/model/UpgradeConfig.java b/src/main/java/cn/octopusyan/alistgui/model/UpgradeConfig.java new file mode 100644 index 0000000..146692b --- /dev/null +++ b/src/main/java/cn/octopusyan/alistgui/model/UpgradeConfig.java @@ -0,0 +1,18 @@ +package cn.octopusyan.alistgui.model; + +import cn.octopusyan.alistgui.model.upgrade.AList; +import cn.octopusyan.alistgui.model.upgrade.Gui; +import lombok.Data; + +/** + * 更新配置 + * + * @author octopus_yan + */ +@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(); +} diff --git a/src/main/java/cn/octopusyan/alistgui/model/upgrade/AList.java b/src/main/java/cn/octopusyan/alistgui/model/upgrade/AList.java new file mode 100644 index 0000000..9fa79b5 --- /dev/null +++ b/src/main/java/cn/octopusyan/alistgui/model/upgrade/AList.java @@ -0,0 +1,18 @@ +package cn.octopusyan.alistgui.model.upgrade; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @author octopus_yan + */ +@Data +public class AList implements UpgradeApp { + @JsonIgnore + private final String owner = "alist-org"; + @JsonIgnore + private final String repo = "alist"; + + private String releaseFile = "alist-windows-amd64.zip"; + private String version = "unknown"; +} diff --git a/src/main/java/cn/octopusyan/alistgui/model/upgrade/Gui.java b/src/main/java/cn/octopusyan/alistgui/model/upgrade/Gui.java new file mode 100644 index 0000000..0dac232 --- /dev/null +++ b/src/main/java/cn/octopusyan/alistgui/model/upgrade/Gui.java @@ -0,0 +1,27 @@ +package cn.octopusyan.alistgui.model.upgrade; + +import cn.octopusyan.alistgui.util.PropertiesUtils; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +/** + * @author octopus_yan + */ +@Data +public class Gui implements UpgradeApp { + @JsonIgnore + private final String owner = "alist-org"; + @JsonIgnore + private final String repo = "alist"; + + private String releaseFile = "alist-gui-{version}-windows.zip"; + private String version = PropertiesUtils.getInstance().getProperty("app.version"); + + public String getReleaseFile() { + return getReleaseFile(version); + } + + public String getReleaseFile(String version) { + return releaseFile.replace("{version}", version); + } +} diff --git a/src/main/java/cn/octopusyan/alistgui/model/upgrade/UpgradeApp.java b/src/main/java/cn/octopusyan/alistgui/model/upgrade/UpgradeApp.java new file mode 100644 index 0000000..ad09c3d --- /dev/null +++ b/src/main/java/cn/octopusyan/alistgui/model/upgrade/UpgradeApp.java @@ -0,0 +1,14 @@ +package cn.octopusyan.alistgui.model.upgrade; + +/** + * @author octopus_yan + */ +public interface UpgradeApp { + String getOwner(); + + String getRepo(); + + String getReleaseFile(); + + String getVersion(); +} diff --git a/src/main/java/cn/octopusyan/alistgui/task/UpgradeTask.java b/src/main/java/cn/octopusyan/alistgui/task/UpgradeTask.java new file mode 100644 index 0000000..bc97ef2 --- /dev/null +++ b/src/main/java/cn/octopusyan/alistgui/task/UpgradeTask.java @@ -0,0 +1,46 @@ +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.UpgradeApp; +import cn.octopusyan.alistgui.util.JsonUtil; +import cn.octopusyan.alistgui.viewModel.SetupViewModel; +import com.fasterxml.jackson.databind.JsonNode; +import org.apache.commons.lang3.StringUtils; + +/** + * 检查更新任务 + * + * @author octopus_yan + */ +public class UpgradeTask extends BaseTask { + private final SetupViewModel vm; + private final UpgradeApp app; + + public UpgradeTask(SetupViewModel viewModel, UpgradeApp app) { + this.vm = 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); + JsonNode response = JsonUtil.parseJsonObject(responseStr); + + 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); + }); + } +} diff --git a/src/main/java/cn/octopusyan/alistgui/viewModel/SetupViewModel.java b/src/main/java/cn/octopusyan/alistgui/viewModel/SetupViewModel.java index b931ae9..6435772 100644 --- a/src/main/java/cn/octopusyan/alistgui/viewModel/SetupViewModel.java +++ b/src/main/java/cn/octopusyan/alistgui/viewModel/SetupViewModel.java @@ -1,12 +1,12 @@ package cn.octopusyan.alistgui.viewModel; -import cn.hutool.core.lang.Validator; -import cn.hutool.core.net.url.UrlBuilder; -import cn.octopusyan.alistgui.config.ConfigManager; +import cn.octopusyan.alistgui.base.BaseTask; import cn.octopusyan.alistgui.config.Context; import cn.octopusyan.alistgui.enums.ProxySetup; +import cn.octopusyan.alistgui.manager.ConfigManager; +import cn.octopusyan.alistgui.task.UpgradeTask; +import cn.octopusyan.alistgui.util.alert.AlertUtil; import javafx.beans.property.*; -import org.apache.commons.lang3.StringUtils; import java.util.Locale; @@ -20,19 +20,21 @@ public class SetupViewModel { private final BooleanProperty silentStartup = new SimpleBooleanProperty(ConfigManager.silentStartup()); private final StringProperty proxyHost = new SimpleStringProperty(ConfigManager.proxyHost()); private final StringProperty proxyPort = new SimpleStringProperty(ConfigManager.proxyPort()); - private final BooleanProperty proxyVerify = new SimpleBooleanProperty(false); private final ObjectProperty language = new SimpleObjectProperty<>(ConfigManager.language()); private final ObjectProperty proxySetup = new SimpleObjectProperty<>(ConfigManager.proxySetup()); - private final SimpleStringProperty aListVersion = new SimpleStringProperty(ConfigManager.aListVersion()); + private final StringProperty aListVersion = new SimpleStringProperty(ConfigManager.aListVersion()); + private final StringProperty aListNewVersion = new SimpleStringProperty(""); + private final BooleanProperty aListUpgrade = new SimpleBooleanProperty(false); + public SetupViewModel() { - aListVersion.addListener((observable, oldValue, newValue) -> ConfigManager.aListVersion(newValue)); - autoStart.addListener((observable, oldValue, newValue) -> ConfigManager.autoStart(newValue)); - silentStartup.addListener((observable, oldValue, newValue) -> ConfigManager.silentStartup(newValue)); - proxySetup.addListener((observable, oldValue, newValue) -> ConfigManager.proxySetup(newValue)); - proxyHost.addListener((observable, oldValue, newValue) -> ConfigManager.proxyHost(newValue)); - proxyPort.addListener((observable, oldValue, newValue) -> ConfigManager.proxyPort(newValue)); - language.addListener((observable, oldValue, newValue) -> Context.setLanguage(newValue)); + aListVersion.addListener((_, _, newValue) -> ConfigManager.aListVersion(newValue)); + autoStart.addListener((_, _, newValue) -> ConfigManager.autoStart(newValue)); + silentStartup.addListener((_, _, newValue) -> ConfigManager.silentStartup(newValue)); + proxySetup.addListener((_, _, newValue) -> ConfigManager.proxySetup(newValue)); + proxyHost.addListener((_, _, newValue) -> ConfigManager.proxyHost(newValue)); + proxyPort.addListener((_, _, newValue) -> ConfigManager.proxyPort(newValue)); + language.addListener((_, _, newValue) -> Context.setLanguage(newValue)); } public BooleanProperty autoStartProperty() { @@ -63,25 +65,35 @@ public class SetupViewModel { return aListVersion; } + public BooleanProperty aListUpgradeProperty() { + return aListUpgrade; + } + + public StringProperty aListNewVersionProperty() { + return aListNewVersion; + } + /** - * 验证代理地址 - * - * @param address 新的代理地址 - * @return UrlBuilder, 验证失败时为null + * 检查alist更新 */ - public UrlBuilder validateAddress(String address) { - if (StringUtils.isEmpty(address)) - return null; + public void checkAListUpdate() { + var task = new UpgradeTask(this, ConfigManager.aList()); + task.onListen(new BaseTask.Listener() { + @Override + public void onSucceeded() { + AlertUtil.info(STR.""" + 当前版本 : \{aListVersion.get()} + 最新版本 : \{aListNewVersion.get()} + """) + .title("AList 更新提示") + .show(); + } - // 验证 URL 的可用性 - UrlBuilder ub = UrlBuilder.of(address); - boolean isUrlValid = Validator.isUrl(address) && ub.getPort() > 0; - - // 设置 proxyVerify 和 proxyVerifyMsg - proxyVerify.setValue(isUrlValid); - - if (isUrlValid) - return ub; - else return null; + @Override + public void onFailed(Throwable throwable) { + AlertUtil.exception(new Exception(throwable)).show(); + } + }); + task.execute(); } } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index e2051d9..29e5401 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -21,4 +21,6 @@ module cn.octopusyan.alistgui { opens cn.octopusyan.alistgui to javafx.fxml; opens cn.octopusyan.alistgui.model to com.fasterxml.jackson.databind; opens cn.octopusyan.alistgui.controller to javafx.fxml; + opens cn.octopusyan.alistgui.base to com.fasterxml.jackson.databind; + opens cn.octopusyan.alistgui.model.upgrade to com.fasterxml.jackson.databind; } \ No newline at end of file diff --git a/src/main/resources/css/main-view.scss b/src/main/resources/css/main-view.scss index 6b1db7d..8bea96d 100644 --- a/src/main/resources/css/main-view.scss +++ b/src/main/resources/css/main-view.scss @@ -50,7 +50,6 @@ -fx-background-color: transparent; -fx-text-fill: #9254d1; -fx-border-color: #9254d1; - -fx-border-width: 2; } #logArea { diff --git a/src/main/resources/fxml/setup-view.fxml b/src/main/resources/fxml/setup-view.fxml index 809822d..1d02484 100644 --- a/src/main/resources/fxml/setup-view.fxml +++ b/src/main/resources/fxml/setup-view.fxml @@ -3,59 +3,48 @@ - + - - - - - - - - + + +