diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5eebf8b..dfb4238 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -52,6 +52,7 @@ dependencies { // https://mvnrepository.com/artifact/com.melloware/jintellitype implementation(libs.jintelitype) implementation(libs.gh.api) + implementation(libs.okhttp) // test dependencies diff --git a/app/src/main/java/io/github/hizumiaoba/mctimemachine/MainController.java b/app/src/main/java/io/github/hizumiaoba/mctimemachine/MainController.java index a96f3fc..4b7d684 100644 --- a/app/src/main/java/io/github/hizumiaoba/mctimemachine/MainController.java +++ b/app/src/main/java/io/github/hizumiaoba/mctimemachine/MainController.java @@ -5,9 +5,11 @@ import io.github.hizumiaoba.mctimemachine.MainController.GlobalShortcutKeyListener.Shortcut; import io.github.hizumiaoba.mctimemachine.api.Config; import io.github.hizumiaoba.mctimemachine.api.ExceptionPopup; +import io.github.hizumiaoba.mctimemachine.api.Version; import io.github.hizumiaoba.mctimemachine.internal.ApplicationConfig; import io.github.hizumiaoba.mctimemachine.internal.concurrent.ConcurrentThreadFactory; import io.github.hizumiaoba.mctimemachine.internal.fs.BackupUtils; +import io.github.hizumiaoba.mctimemachine.internal.version.VersionObj; import java.awt.Desktop; import java.io.File; import java.io.IOException; @@ -26,7 +28,10 @@ import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; import javafx.scene.control.CheckBox; import javafx.scene.control.Spinner; import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory; @@ -403,18 +408,31 @@ void onSpecialBackupNowBtnClick() { } @FXML - private Button checkVersionUpdateBtn; - - @FXML - void onCheckVersionUpdateBtnClick() throws IOException { - log.trace("Checking the latest version..."); - // open new dialog with `update.fxml` - FXMLLoader loader = new FXMLLoader( - MineCraftTimeMachineApplication.class.getResource("update.fxml")); - Stage updateDialogStage = new Stage(); - updateDialogStage.setScene(new Scene(loader.load())); - updateDialogStage.initModality(Modality.APPLICATION_MODAL); - updateDialogStage.showAndWait(); + void onOpenReleasePageOnWebBtnClick() { + runConcurrentTask(es, () -> { + final String url = "https://github.com/hizumiaoba/MineCraftTimeMachine/releases"; + Platform.runLater(() -> { + Alert alert = new Alert(AlertType.CONFIRMATION); + alert.initModality(Modality.APPLICATION_MODAL); + alert.setTitle("リリースページを開きますか?"); + alert.setHeaderText("既定のブラウザでリリースページを開きます。よろしいですか?"); + alert.setContentText(String.format("現在のバージョン: v%s", VersionObj.parse(MineCraftTimeMachineApplication.class.getAnnotation(Version.class)).asStringNotation())); + alert.getButtonTypes().setAll(ButtonType.OK, ButtonType.CANCEL); + alert.showAndWait().ifPresent(response -> { + if(response == ButtonType.OK) { + try { + Desktop.getDesktop().browse(URI.create(url)); + } catch (IOException e) { + ExceptionPopup popup = new ExceptionPopup(e, "リリースページを開けませんでした。", + "MainController#onOpenReleasePageOnWebBtnClick()$lambda"); + popup.pop(); + } + } else { + log.trace("User canceled to open the release page."); + } + }); + }); + }); } private void runConcurrentTask(ExecutorService service, Runnable task) { diff --git a/app/src/main/java/io/github/hizumiaoba/mctimemachine/UpdateDialogController.java b/app/src/main/java/io/github/hizumiaoba/mctimemachine/UpdateDialogController.java deleted file mode 100644 index 23e6a3b..0000000 --- a/app/src/main/java/io/github/hizumiaoba/mctimemachine/UpdateDialogController.java +++ /dev/null @@ -1,87 +0,0 @@ -package io.github.hizumiaoba.mctimemachine; - -import io.github.hizumiaoba.mctimemachine.api.ExceptionPopup; -import io.github.hizumiaoba.mctimemachine.api.Version; -import io.github.hizumiaoba.mctimemachine.internal.version.VersionHelper; -import io.github.hizumiaoba.mctimemachine.internal.version.VersionObj; -import java.awt.Desktop; -import java.io.IOException; -import java.net.URI; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.control.CheckBox; -import javafx.scene.control.Label; -import javafx.scene.control.ProgressBar; -import javafx.stage.Stage; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class UpdateDialogController { - - @FXML - private CheckBox chkIncludePrerelease; - - @FXML - private ProgressBar updateProgressBar; - - @FXML - private Label labelUpdateMessage; - - private VersionObj remoteLatest; - - @FXML - void onCheckUpdateBtnClick() { - log.info("Check update button clicked."); - chkIncludePrerelease.setDisable(true); - updateProgressBar.setProgress(0.0); - log.trace("Fetching remote latest version..."); - VersionObj clientVersion = VersionObj.parse(MineCraftTimeMachineApplication.class.getAnnotation( - Version.class)); - updateProgressBar.setProgress(0.15); - VersionHelper helper = new VersionHelper(clientVersion); - try { - this.remoteLatest = VersionHelper.getLatestRemoteVersion(chkIncludePrerelease.isSelected()); - updateProgressBar.setProgress(0.33); - log.info("Remote latest version: {}", remoteLatest.asStringNotation()); - log.trace("Client version: {}", clientVersion.asStringNotation()); - updateProgressBar.setProgress(0.67); - if (helper.checkLatest(remoteLatest, false)) { - log.info("Client is up-to-date."); - } else { - log.info("Client is outdated."); - } - } catch (IOException e) { - ExceptionPopup p = new ExceptionPopup(e, "最新バージョンを取得できませんでした。", - "UpdateDialogController#onCheckUpdateBtnClick"); - p.pop(); - } finally { - chkIncludePrerelease.setDisable(false); - updateProgressBar.setProgress(1.0); - labelUpdateMessage.setText(helper.constructUpdateMessage(remoteLatest, false)); - } - } - - @FXML - void onOpenReleasePageBtnClick() { - log.info("Open release page button clicked."); - try { - // construct GitHub release page URL with remoteLatest - URI uri = URI.create( - String.format("https://github.com/hizumiaoba/MineCraftTimeMachine/releases/tag/v%s", - remoteLatest.asStringNotation())); - log.info("Opening release page: {}", uri); - Desktop.getDesktop().browse(uri); - } catch (IOException e) { - ExceptionPopup p = new ExceptionPopup(e, "リリースページを開けませんでした。", - "UpdateDialogController#onOpenReleasePageBtnClick"); - p.pop(); - } - } - - @FXML - void onCloseBtnClick(ActionEvent e) { - log.info("Close button clicked."); - Stage stage = (Stage) updateProgressBar.getScene().getWindow(); - stage.close(); - } -} diff --git a/app/src/main/java/io/github/hizumiaoba/mctimemachine/internal/version/VersionHelper.java b/app/src/main/java/io/github/hizumiaoba/mctimemachine/internal/version/VersionHelper.java deleted file mode 100644 index 0c77b64..0000000 --- a/app/src/main/java/io/github/hizumiaoba/mctimemachine/internal/version/VersionHelper.java +++ /dev/null @@ -1,79 +0,0 @@ -package io.github.hizumiaoba.mctimemachine.internal.version; - -import io.github.hizumiaoba.mctimemachine.MineCraftTimeMachineApplication; -import io.github.hizumiaoba.mctimemachine.api.Version; -import java.io.IOException; -import java.util.List; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.kohsuke.github.GHRelease; -import org.kohsuke.github.GitHub; - -@RequiredArgsConstructor -@Slf4j -public class VersionHelper { - - private final VersionObj clientVersion; - - public boolean checkLatest(VersionObj remoteVersion, boolean ignoreSuffix) { - return getUpdateType(remoteVersion, ignoreSuffix).equals("latest"); - } - - private String getUpdateType(VersionObj remoteVersion, boolean ignoreSuffix) { - final boolean isMajorSame = clientVersion.getMajor() == remoteVersion.getMajor(); - final boolean isMinorSame = clientVersion.getMinor() == remoteVersion.getMinor(); - final boolean isPatchSame = clientVersion.getPatch() == remoteVersion.getPatch(); - final boolean isSuffixSame = - ignoreSuffix || clientVersion.getSuffix().equals(remoteVersion.getSuffix()); - if (isMajorSame && isMinorSame && isPatchSame && isSuffixSame) { - return "latest"; - } else if (isMajorSame && isMinorSame && isPatchSame) { - return "suffix"; - } else if (isMajorSame && isMinorSame) { - return "patch"; - } else if (isMajorSame) { - return "minor"; - } else { - return "major"; - } - } - - public static VersionObj getLatestRemoteVersion(boolean includePrerelease) throws IOException { - GitHub gh = GitHub.connectAnonymously(); - List releases = gh.getRepository("hizumiaoba/MineCraftTimeMachine") - .listReleases() - .toList() - .parallelStream().filter(r -> includePrerelease || !r.isPrerelease()) - .toList(); - if (releases.isEmpty()) { - // fall back client version so that no update prompt will be shown - log.warn( - "No available releases found with required precondition. Fallback to client version."); - return VersionObj.parse(MineCraftTimeMachineApplication.class.getAnnotation(Version.class)); - } - log.debug("Found {} releases", releases.size()); - log.trace("Latest release: {}", releases.get(0).getTagName()); - return VersionObj.parse(releases.get(0).getTagName()); - } - - public String constructUpdateMessage(VersionObj remoteVersion, boolean ignoreSuffix) { - final String updateType = getUpdateType(remoteVersion, ignoreSuffix); - final String remoteVersionString = remoteVersion.asStringNotation(); - final String clientVersionString = clientVersion.asStringNotation(); - final String clientVersionNotice = "現在のバージョンは" + clientVersionString + "です。"; - return switch (updateType) { - case "latest" -> "現在最新バージョンのソフトウェアを使用中です!最新こそ正義!"; - case "suffix" -> "新しい試験運用版のソフトウェアが利用可能です!未知への冒険へ、出発です! \n最新バージョン: " - + remoteVersionString + "。 " + clientVersionNotice; - case "patch" -> "新しいパッチリリースのソフトウェアが利用可能です!バグ修正などが含まれています! \n最新バージョン: " - + remoteVersionString + "。 " + clientVersionNotice; - case "minor" -> "新しいマイナーリリースのソフトウェアが利用可能です!新機能や小規模な機能の挙動改善が含まれています! \n最新バージョン: " - + remoteVersionString + "。 " + clientVersionNotice; - case "major" -> - "新しいメジャーリリースのソフトウェアが利用可能です!大規模な機能追加や大幅な仕様変更が含まれています!更新の際には互換性にご注意ください! \n最新バージョン: " - + remoteVersionString + "。 " + clientVersionNotice; - default -> - "更新の種類を特定できません。直接アップデートを確認してください。" + clientVersionNotice; - }; - } -} diff --git a/app/src/main/java/module-info.java b/app/src/main/java/module-info.java index 7f8f889..32a9074 100644 --- a/app/src/main/java/module-info.java +++ b/app/src/main/java/module-info.java @@ -3,6 +3,7 @@ requires javafx.fxml; requires kotlin.stdlib; requires java.desktop; + requires java.security.sasl; requires org.xerial.sqlitejdbc; requires org.slf4j; requires ch.qos.logback.classic; @@ -11,6 +12,8 @@ requires annotations; requires jintellitype; requires org.kohsuke.github.api; + requires org.apache.commons.lang3; + requires okhttp3; requires com.fasterxml.jackson.core; requires com.fasterxml.jackson.databind; diff --git a/app/src/main/resources/io/github/hizumiaoba/mctimemachine/main.fxml b/app/src/main/resources/io/github/hizumiaoba/mctimemachine/main.fxml index 68f0273..7216e0e 100644 --- a/app/src/main/resources/io/github/hizumiaoba/mctimemachine/main.fxml +++ b/app/src/main/resources/io/github/hizumiaoba/mctimemachine/main.fxml @@ -114,8 +114,8 @@ prefHeight="40.0" prefWidth="170.0" text="各種フォルダを開く" fx:id="openRelatedFolderBtn"/>