mirror of
https://github.com/octopusYan/alist-gui.git
synced 2024-11-21 19:56:41 +08:00
feat: 主界面启动按钮、命令执行工具
This commit is contained in:
parent
cfd7075c8f
commit
c93837a7a9
@ -6,6 +6,7 @@ import cn.octopusyan.alistgui.manager.ConfigManager;
|
||||
import cn.octopusyan.alistgui.manager.http.HttpConfig;
|
||||
import cn.octopusyan.alistgui.manager.http.HttpUtil;
|
||||
import cn.octopusyan.alistgui.manager.thread.ThreadPoolManager;
|
||||
import cn.octopusyan.alistgui.util.ProcessesUtil;
|
||||
import cn.octopusyan.alistgui.util.alert.AlertUtil;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.Scene;
|
||||
@ -92,6 +93,8 @@ public class Application extends javafx.application.Application {
|
||||
@Override
|
||||
public void stop() {
|
||||
logger.info("application stop ...");
|
||||
// 关闭所有命令
|
||||
ProcessesUtil.destroyAll();
|
||||
// 保存应用数据
|
||||
ConfigManager.save();
|
||||
// 停止所有线程
|
||||
|
@ -14,10 +14,12 @@ 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 ALIST_FILE = STR."\{BIN_DIR_PATH}\{File.separator}alist.exe";
|
||||
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";
|
||||
|
@ -1,8 +1,12 @@
|
||||
package cn.octopusyan.alistgui.controller;
|
||||
|
||||
import cn.octopusyan.alistgui.base.BaseController;
|
||||
import cn.octopusyan.alistgui.config.Context;
|
||||
import cn.octopusyan.alistgui.manager.AListManager;
|
||||
import cn.octopusyan.alistgui.manager.ConsoleLog;
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.slf4j.Logger;
|
||||
@ -22,6 +26,10 @@ public class MainController extends BaseController<VBox> {
|
||||
public VBox logArea;
|
||||
@FXML
|
||||
public ScrollPane logAreaSp;
|
||||
@FXML
|
||||
public Button statusLabel;
|
||||
@FXML
|
||||
public Button startButton;
|
||||
|
||||
@Override
|
||||
public VBox getRootPanel() {
|
||||
@ -35,11 +43,42 @@ public class MainController extends BaseController<VBox> {
|
||||
|
||||
@Override
|
||||
public void initViewStyle() {
|
||||
|
||||
AListManager.runningProperty().addListener(_ -> setStartButton(AListManager.isRunning()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initViewAction() {
|
||||
AListManager.runningProperty().addListener((_, _, running) -> setStartButton(running));
|
||||
}
|
||||
|
||||
private void setStartButton(boolean running) {
|
||||
String removeStyle = running ? "success" : "danger";
|
||||
String addStyle = running ? "danger" : "success";
|
||||
String button = Context.getLanguageBinding(STR."main.control.\{running ? "stop" : "start"}").get();
|
||||
String status = Context.getLanguageBinding(STR."main.status.label-\{running ? "running" : "stop"}").get();
|
||||
|
||||
Platform.runLater(() -> {
|
||||
startButton.getStyleClass().remove(removeStyle);
|
||||
startButton.getStyleClass().add(addStyle);
|
||||
startButton.textProperty().set(button);
|
||||
|
||||
statusLabel.getStyleClass().remove(addStyle);
|
||||
statusLabel.getStyleClass().add(removeStyle);
|
||||
statusLabel.textProperty().set(status);
|
||||
});
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void start() {
|
||||
if (AListManager.isRunning()) {
|
||||
AListManager.stop();
|
||||
} else {
|
||||
AListManager.start();
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void restart() {
|
||||
AListManager.restart();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,85 @@
|
||||
package cn.octopusyan.alistgui.manager;
|
||||
|
||||
import cn.octopusyan.alistgui.config.Constants;
|
||||
import cn.octopusyan.alistgui.config.Context;
|
||||
import cn.octopusyan.alistgui.util.ProcessesUtil;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
/**
|
||||
* AList 管理
|
||||
*
|
||||
* @author octopus_yan
|
||||
*/
|
||||
public class AListManager {
|
||||
public static final String START_COMMAND = STR."\{Constants.ALIST_FILE} server";
|
||||
private static final ProcessesUtil util;
|
||||
private static final BooleanProperty running = new SimpleBooleanProperty(false);
|
||||
|
||||
static {
|
||||
util = ProcessesUtil.init(Constants.BIN_DIR_PATH);
|
||||
}
|
||||
|
||||
public static BooleanProperty runningProperty() {
|
||||
return running;
|
||||
}
|
||||
|
||||
public static boolean isRunning() {
|
||||
return running.get();
|
||||
}
|
||||
|
||||
public static void start() {
|
||||
ConsoleLog.info(getText("alist.status.start"));
|
||||
if (running.get()) {
|
||||
ConsoleLog.warning(getText("alist.status.start.running"));
|
||||
return;
|
||||
}
|
||||
|
||||
running.set(true);
|
||||
util.exec(START_COMMAND, new ProcessesUtil.OnExecuteListener() {
|
||||
@Override
|
||||
public void onExecute(String msg) {
|
||||
if (ConsoleLog.isInit())
|
||||
ConsoleLog.msg(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExecuteSuccess(int exitValue) {
|
||||
running.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExecuteError(Exception e) {
|
||||
running.set(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void stop() {
|
||||
ConsoleLog.info(getText("alist.status.stop"));
|
||||
if (!running.get()) {
|
||||
ConsoleLog.warning(getText("alist.status.stop.stopped"));
|
||||
return;
|
||||
}
|
||||
util.destroy();
|
||||
}
|
||||
|
||||
static ChangeListener<Boolean> changeListener;
|
||||
|
||||
public static void restart() {
|
||||
stop();
|
||||
changeListener = (_, _, run) -> {
|
||||
if (run) return;
|
||||
start();
|
||||
if (changeListener != null) {
|
||||
running.removeListener(changeListener);
|
||||
}
|
||||
};
|
||||
running.addListener(changeListener);
|
||||
}
|
||||
|
||||
private static String getText(String code) {
|
||||
return Context.getLanguageBinding(code).get();
|
||||
}
|
||||
}
|
@ -1,44 +1,66 @@
|
||||
package cn.octopusyan.alistgui.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.exec.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 命令工具类
|
||||
*
|
||||
* @author octopus_yan@foxmail.com
|
||||
*/
|
||||
@Slf4j
|
||||
public class ProcessesUtil {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ProcessesUtil.class);
|
||||
private static final String NEW_LINE = System.lineSeparator();
|
||||
private static final DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler();
|
||||
|
||||
public static boolean exec(String command) {
|
||||
try {
|
||||
exec(command, msg -> {});
|
||||
handler.waitFor();
|
||||
} catch (Exception e) {
|
||||
logger.error("", e);
|
||||
}
|
||||
return 0 == handler.getExitValue();
|
||||
}
|
||||
|
||||
public static void exec(String command, OnExecuteListener listener) {
|
||||
LogOutputStream logout = new LogOutputStream() {
|
||||
private final Executor executor = DefaultExecutor.builder().get();
|
||||
private final ShutdownHookProcessDestroyer processDestroyer;
|
||||
private DefaultExecuteResultHandler handler;
|
||||
private final PumpStreamHandler streamHandler;
|
||||
private OnExecuteListener listener;
|
||||
private CommandLine commandLine;
|
||||
private final LogOutputStream logout = new LogOutputStream() {
|
||||
@Override
|
||||
protected void processLine(String line, int logLevel) {
|
||||
if (listener != null) listener.onExecute(line + NEW_LINE);
|
||||
if (listener != null)
|
||||
listener.onExecute(line + NEW_LINE);
|
||||
}
|
||||
};
|
||||
|
||||
CommandLine commandLine = CommandLine.parse(command);
|
||||
DefaultExecutor executor = DefaultExecutor.builder().get();
|
||||
executor.setStreamHandler(new PumpStreamHandler(logout, logout));
|
||||
DefaultExecuteResultHandler handler = new DefaultExecuteResultHandler() {
|
||||
private static final Set<ProcessesUtil> set = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Prevent construction.
|
||||
*/
|
||||
private ProcessesUtil(String workingDirectory) {
|
||||
streamHandler = new PumpStreamHandler(logout, logout);
|
||||
executor.setStreamHandler(streamHandler);
|
||||
executor.setWorkingDirectory(new File(workingDirectory));
|
||||
executor.setExitValue(1);
|
||||
processDestroyer = new ShutdownHookProcessDestroyer();
|
||||
executor.setProcessDestroyer(processDestroyer);
|
||||
}
|
||||
|
||||
public static ProcessesUtil init(String workingDirectory) {
|
||||
ProcessesUtil util = new ProcessesUtil(workingDirectory);
|
||||
set.add(util);
|
||||
return util;
|
||||
}
|
||||
|
||||
public boolean exec(String command) throws IOException {
|
||||
commandLine = CommandLine.parse(command);
|
||||
int execute = executor.execute(commandLine);
|
||||
return 0 == execute;
|
||||
}
|
||||
|
||||
public void exec(String command, OnExecuteListener listener) {
|
||||
this.listener = listener;
|
||||
commandLine = CommandLine.parse(command);
|
||||
handler = new DefaultExecuteResultHandler() {
|
||||
@Override
|
||||
public void onProcessComplete(int exitValue) {
|
||||
if (listener != null) {
|
||||
@ -60,15 +82,22 @@ public class ProcessesUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnExecuteListener {
|
||||
void onExecute(String msg);
|
||||
default void onExecuteSuccess(int exitValue){}
|
||||
default void onExecuteError(Exception e){}
|
||||
public void destroy() {
|
||||
if (processDestroyer.isEmpty()) return;
|
||||
processDestroyer.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent construction.
|
||||
*/
|
||||
private ProcessesUtil() {
|
||||
public static void destroyAll() {
|
||||
set.forEach(ProcessesUtil::destroy);
|
||||
}
|
||||
|
||||
public interface OnExecuteListener {
|
||||
void onExecute(String msg);
|
||||
|
||||
default void onExecuteSuccess(int exitValue) {
|
||||
}
|
||||
|
||||
default void onExecuteError(Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,10 +12,6 @@
|
||||
-fx-background-radius: 10;
|
||||
-fx-text-alignment: CENTER;
|
||||
-fx-border-radius: 10;
|
||||
-color-button-bg: -color-success-3;
|
||||
-color-button-border: -color-button-bg;
|
||||
-color-button-border-hover: -color-button-bg;
|
||||
-color-button-bg-hover: -color-button-bg;
|
||||
}
|
||||
|
||||
.control-menu, #startButton, #passwordButton, #restartButton, #moreButton {
|
||||
@ -27,12 +23,6 @@
|
||||
}
|
||||
|
||||
#startButton {
|
||||
-color-button-bg: -color-danger-4;
|
||||
-color-button-bg-hover: -color-button-bg;
|
||||
-color-button-bg-focused: -color-button-bg;
|
||||
-color-button-bg-pressed: -color-button-bg;
|
||||
-color-button-border: -color-button-bg;
|
||||
-color-button-border-hover: -color-button-bg;
|
||||
-fx-border-color: -color-button-bg;
|
||||
}
|
||||
|
||||
@ -41,8 +31,6 @@
|
||||
-color-button-bg-hover: -color-button-bg;
|
||||
-color-button-bg-focused: -color-button-bg;
|
||||
-color-button-bg-pressed: -color-button-bg;
|
||||
-color-button-border: -color-button-bg;
|
||||
-color-button-border-hover: -color-button-bg;
|
||||
-fx-border-color: -color-button-bg;
|
||||
}
|
||||
|
||||
@ -51,15 +39,16 @@
|
||||
-color-button-bg-hover: -color-button-bg;
|
||||
-color-button-bg-focused: -color-button-bg;
|
||||
-color-button-bg-pressed: -color-button-bg;
|
||||
-color-button-border: -color-button-bg;
|
||||
-color-button-border-hover: -color-button-bg;
|
||||
-fx-border-color: -color-button-bg;
|
||||
}
|
||||
|
||||
#moreButton {
|
||||
-fx-background-color: transparent;
|
||||
-fx-text-fill: -color-chart-6;
|
||||
-color-button-bg-focused: transparent;
|
||||
-color-button-bg-pressed: transparent;
|
||||
-color-button-bg-hover: -color-chart-6-alpha20;
|
||||
-color-button-border: -color-chart-6;
|
||||
-fx-border-color: -color-chart-6;
|
||||
-color-button-border-hover: -color-chart-6-alpha70;
|
||||
}
|
||||
|
||||
.logArea {
|
||||
|
@ -24,10 +24,12 @@
|
||||
<VBox.margin>
|
||||
<Insets bottom="10.0" top="10.0"/>
|
||||
</VBox.margin>
|
||||
<Button fx:id="startButton" styleClass="control-menu, danger" text="%main.control.start"/>
|
||||
<Button fx:id="passwordButton" styleClass="control-menu, success" text="%main.control.password"/>
|
||||
<Button fx:id="restartButton" styleClass="control-menu, success" text="%main.control.restart"/>
|
||||
<Button fx:id="moreButton" styleClass="control-menu" text="%main.control.more"/>
|
||||
<Button fx:id="startButton" styleClass="large, control-menu, success" onAction="#start"
|
||||
text="%main.control.start"/>
|
||||
<Button fx:id="passwordButton" styleClass="large, control-menu, success" text="%main.control.password"/>
|
||||
<Button fx:id="restartButton" styleClass="large, control-menu, success" onAction="#restart"
|
||||
text="%main.control.restart"/>
|
||||
<Button fx:id="moreButton" styleClass="large, control-menu, button-outlined" text="%main.control.more"/>
|
||||
</HBox>
|
||||
<ScrollPane fx:id="logAreaSp" fitToWidth="true" prefHeight="499.0" prefWidth="Infinity"
|
||||
styleClass="logArea" VBox.vgrow="ALWAYS">
|
||||
|
@ -6,6 +6,7 @@ root.foot.doc=\u6587\u6863
|
||||
root.foot.github=GitHub
|
||||
root.foot.sponsor=\u8D5E\u52A9 AList
|
||||
main.control.start=\u5F00\u59CB
|
||||
main.control.stop=\u505C\u6B62
|
||||
main.control.password=\u5BC6\u7801
|
||||
main.control.restart=\u91CD\u542F
|
||||
main.control.more=\u66F4\u591A
|
||||
@ -13,6 +14,10 @@ main.status.label-running=\u8FD0\u884C\u4E2D
|
||||
main.status.label-stop=\u5DF2\u505C\u6B62
|
||||
main.more.browser=\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00
|
||||
main.more.open-log=\u6253\u5F00\u65E5\u5FD7\u6587\u4EF6\u5939
|
||||
alist.status.start.running=AList \u6B63\u5728\u8FD0\u884C\u3002\u3002\u3002
|
||||
alist.status.start=\u6B63\u5728\u542F\u52A8 AList
|
||||
alist.status.stop=\u6B63\u5728\u505C\u6B62AList
|
||||
alist.status.stop.stopped=AList \u5DF2\u505C\u6B62
|
||||
setup.proxy=HTTP\u4EE3\u7406
|
||||
setup.auto-start.label=\u5F00\u673A\u81EA\u542F
|
||||
setup.silent-startup.label=\u9759\u9ED8\u542F\u52A8
|
||||
|
@ -6,6 +6,7 @@ root.foot.doc=Document
|
||||
root.foot.github=GitHub
|
||||
root.foot.sponsor=Sponsor AList
|
||||
main.control.start=Start
|
||||
main.control.stop=Stop
|
||||
main.control.password=Password
|
||||
main.control.restart=Restart
|
||||
main.control.more=More
|
||||
@ -13,6 +14,10 @@ main.status.label-running=Running
|
||||
main.status.label-stop=Stoped
|
||||
main.more.browser=Open in browser
|
||||
main.more.open-log=Open the log folder
|
||||
alist.status.start=Starting AList
|
||||
alist.status.start.running=AList is running...
|
||||
alist.status.stop=Stopping AList
|
||||
alist.status.stop.stopped=AList has stopped
|
||||
setup.proxy=HTTP PROXY
|
||||
setup.auto-start.label=Auto start with PC
|
||||
setup.silent-startup.label=Silent startup
|
||||
|
@ -6,6 +6,7 @@ root.foot.doc=\u6587\u6863
|
||||
root.foot.github=GitHub
|
||||
root.foot.sponsor=\u8D5E\u52A9 AList
|
||||
main.control.start=\u5F00\u59CB
|
||||
main.control.stop=\u505C\u6B62
|
||||
main.control.password=\u5BC6\u7801
|
||||
main.control.restart=\u91CD\u542F
|
||||
main.control.more=\u66F4\u591A
|
||||
@ -13,6 +14,10 @@ main.status.label-running=\u8FD0\u884C\u4E2D
|
||||
main.status.label-stop=\u5DF2\u505C\u6B62
|
||||
main.more.browser=\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00
|
||||
main.more.open-log=\u6253\u5F00\u65E5\u5FD7\u6587\u4EF6\u5939
|
||||
alist.status.stop.stopped=AList \u5DF2\u505C\u6B62
|
||||
alist.status.start=\u6B63\u5728\u542F\u52A8 AList
|
||||
alist.status.stop=\u6B63\u5728\u505C\u6B62AList
|
||||
alist.status.start.running=AList \u6B63\u5728\u8FD0\u884C\u3002\u3002\u3002
|
||||
setup.proxy=HTTP\u4EE3\u7406
|
||||
setup.auto-start.label=\u5F00\u673A\u81EA\u542F
|
||||
setup.silent-startup.label=\u9759\u9ED8\u542F\u52A8
|
||||
|
Loading…
Reference in New Issue
Block a user