diff --git a/src/main/java/org/qortal/api/model/NodeStatus.java b/src/main/java/org/qortal/api/model/NodeStatus.java new file mode 100644 index 00000000..3ab0f873 --- /dev/null +++ b/src/main/java/org/qortal/api/model/NodeStatus.java @@ -0,0 +1,15 @@ +package org.qortal.api.model; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; + +@XmlAccessorType(XmlAccessType.FIELD) +public class NodeStatus { + + public boolean isMintingPossible; + public boolean isSynchronizing; + + public NodeStatus() { + } + +} diff --git a/src/main/java/org/qortal/api/resource/AdminResource.java b/src/main/java/org/qortal/api/resource/AdminResource.java index abf1f37b..5277bedf 100644 --- a/src/main/java/org/qortal/api/resource/AdminResource.java +++ b/src/main/java/org/qortal/api/resource/AdminResource.java @@ -45,6 +45,7 @@ import org.qortal.api.ApiExceptionFactory; import org.qortal.api.Security; import org.qortal.api.model.ActivitySummary; import org.qortal.api.model.NodeInfo; +import org.qortal.api.model.NodeStatus; import org.qortal.block.BlockChain; import org.qortal.controller.Controller; import org.qortal.controller.Synchronizer.SynchronizationResult; @@ -120,6 +121,27 @@ public class AdminResource { return nodeInfo; } + @GET + @Path("/status") + @Operation( + summary = "Fetch node status", + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = NodeStatus.class)) + ) + } + ) + public NodeStatus status() { + Security.checkApiCallAllowed(request); + + NodeStatus nodeStatus = new NodeStatus(); + + nodeStatus.isMintingPossible = Controller.getInstance().isMintingPossible(); + nodeStatus.isSynchronizing = Controller.getInstance().isSynchronizing(); + + return nodeStatus; + } + @GET @Path("/stop") @Operation( diff --git a/src/main/java/org/qortal/controller/Controller.java b/src/main/java/org/qortal/controller/Controller.java index 8419a11f..94fa0c28 100644 --- a/src/main/java/org/qortal/controller/Controller.java +++ b/src/main/java/org/qortal/controller/Controller.java @@ -133,6 +133,9 @@ public class Controller extends Thread { /** Whether we can mint new blocks, as reported by BlockMinter. */ private volatile boolean isMintingPossible = false; + /** Whether we are attempting to synchronize. */ + private volatile boolean isSynchronizing = false; + /** Latest block signatures from other peers that we know are on inferior chains. */ List inferiorChainSignatures = new ArrayList<>(); @@ -245,6 +248,15 @@ public class Controller extends Thread { return isStopping; } + // For API use + public boolean isMintingPossible() { + return this.isMintingPossible; + } + + public boolean isSynchronizing() { + return this.isSynchronizing; + } + // Entry point public static void main(String[] args) { @@ -497,7 +509,13 @@ public class Controller extends Thread { int index = new SecureRandom().nextInt(peers.size()); Peer peer = peers.get(index); + isSynchronizing = true; + updateSysTray(); + actuallySynchronize(peer, false); + + isSynchronizing = false; + requestSysTrayUpdate = true; } public SynchronizationResult actuallySynchronize(Peer peer, boolean force) throws InterruptedException { @@ -601,9 +619,17 @@ public class Controller extends Thread { String connectionsText = Translator.INSTANCE.translate("SysTray", numberOfPeers != 1 ? "CONNECTIONS" : "CONNECTION"); String heightText = Translator.INSTANCE.translate("SysTray", "BLOCK_HEIGHT"); - String mintingText = Translator.INSTANCE.translate("SysTray", isMintingPossible ? "MINTING_ENABLED" : "MINTING_DISABLED"); - String tooltip = String.format("%s - %d %s - %s %d", mintingText, numberOfPeers, connectionsText, heightText, height); + String actionKey; + if (isMintingPossible) + actionKey = "MINTING_ENABLED"; + else if (isSynchronizing) + actionKey = "SYNCHRONIZING_BLOCKCHAIN"; + else + actionKey = "MINTING_DISABLED"; + String actionText = Translator.INSTANCE.translate("SysTray", actionKey); + + String tooltip = String.format("%s - %d %s - %s %d", actionText, numberOfPeers, connectionsText, heightText, height); SysTray.getInstance().setToolTipText(tooltip); } diff --git a/src/main/resources/i18n/SysTray_en.properties b/src/main/resources/i18n/SysTray_en.properties index 9dd826e9..8d805a36 100644 --- a/src/main/resources/i18n/SysTray_en.properties +++ b/src/main/resources/i18n/SysTray_en.properties @@ -26,4 +26,6 @@ OPEN_UI = Open UI SYNCHRONIZE_CLOCK = Synchronize clock +SYNCHRONIZING_BLOCKCHAIN = Synchronizing + SYNCHRONIZING_CLOCK = Synchronizing clock diff --git a/src/main/resources/i18n/SysTray_zh.properties b/src/main/resources/i18n/SysTray_zh.properties index 2f1a8abc..bb2e1426 100644 --- a/src/main/resources/i18n/SysTray_zh.properties +++ b/src/main/resources/i18n/SysTray_zh.properties @@ -26,4 +26,6 @@ OPEN_UI = \u5F00\u542F\u754C\u9762 SYNCHRONIZE_CLOCK = \u540C\u6B65\u65F6\u949F +SYNCHRONIZING_BLOCKCHAIN = \u540C\u6B65\u533A\u5757\u94FE + SYNCHRONIZING_CLOCK = \u540C\u6B65\u7740\u65F6\u949F