Merge pull request #1858 from SiboVG/issue-1768

[#1768] Add welcome dialog
This commit is contained in:
Sibo Van Gool 2022-12-12 15:10:18 +01:00 committed by GitHub
commit cb4fda112d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 602 additions and 114 deletions

View File

@ -1,6 +1,20 @@
<!--
!! NOTE: This HTML formatting is required for the welcome info dialog.
Always encapsulate each release with a <div> tag and the correct id.
-->
<body>
<div>
Release Notes
=============
</div>
<div id="22.02.beta.05">
OpenRocket 22.02.beta.05 (2022-09-28)
------------------------
(through PR1688)
@ -66,6 +80,10 @@ OpenRocket 22.02.beta.05 (2022-09-28)
* Fixed overlapping labels in motor selection diameter filter slider (fixes #1643)
* More Russian translation updates
</div>
<div id="22.02.beta.04">
OpenRocket 22.02.beta.04 (2022-06-17)
------------------------
(through PR1456)
@ -102,6 +120,9 @@ However, the JAR file will still allow Java 11 *or* 17, so if you want to keep e
* Updated guided tours
* Improved Russian translation
</div>
<div id="22.02.beta.03">
OpenRocket 22.02.beta.03 (2022-05-18)
------------------------
@ -131,6 +152,10 @@ OpenRocket 22.02.beta.03 (2022-05-18)
* Improved time step selection for descent
* Java 17 is now included in the packaged installers and supported by the JAR file.
</div>
<div id="22.02.beta.02">
OpenRocket 22.02.beta.02 (2022-03-26)
------------------------
(through PR1261)
@ -161,6 +186,9 @@ NOTE: Tube fin simulation is currently broken, and will be fixed in a future bet
* Set default color for all components to #BBBBBB, with Shine=30 (closes issue 1192)
* Update Mac installer style to more standard "drag app to Applications folder"
</div>
<div id="22.02.beta.01">
OpenRocket 22.02.beta.01 (2022-02-25)
------------------------
@ -239,6 +267,10 @@ OpenRocket 22.02.beta.01 (2022-02-25)
..._plus many, many additional bug fixes and refinements_
</div>
<div id="15.03">
OpenRocket 15.03 (2015-03-28)
-----------------------------
@ -258,6 +290,10 @@ Bug Fixes
* Always use the correct filename extension when saving
</div>
<div id="14.11">
OpenRocket 14.11 (2014-11-02)
-----------------------------
@ -269,6 +305,10 @@ Bug Fixes
* Fixed a couple of bugs.
</div>
<div id="14.06">
OpenRocket 14.06 (2014-06-25)
-----------------------------
@ -282,6 +322,10 @@ Bug Fixes
* Fixed annoying IndexOutOfBounds bug in tables.
</div>
<div id="14.05">
OpenRocket 14.05 (2014-05-21)
-----------------------------
@ -296,6 +340,10 @@ Bug Fixes
* Updated thrustcurves
* Updated 3d libraries to 2.1.5
</div>
<div id="14.03">
OpenRocket 14.03 (2014-03-20)
-----------------------------
@ -308,6 +356,10 @@ Bug Fixes
* Fixes to the flight configuration tab and motor selection dialog
* Updated thrustcurves
</div>
<div id="13.11.2">
OpenRocket 13.11.2 (2014-01-01)
-------------------------------
@ -318,6 +370,10 @@ Bug Fixes
* Fix couple of layout issues
* Updated Spanish, French and Chinese translations
</div>
<div id="13.11.1">
OpenRocket 13.11.1 (2013-11-15)
-------------------------------
@ -329,6 +385,10 @@ Bug Fixes
* Fixed various exceptions in flight configuration tables due to column reordering
* Fixed NPE when deleting a configuration
</div>
<div id="13.11">
OpenRocket 13.11 (2013-11-08)
------------------------------
@ -343,6 +403,10 @@ Bug Fixes
* Updated jogl to correct 3d problems on various platforms
* Fixed NPE introduced by changes in Java 1.7.0_45-b18
</div>
<div id="13.09.1">
OpenRocket 13.09.1 (2013-10-05)
-------------------------------
@ -350,6 +414,9 @@ This release contains a number of bug fixes, updated 3D JOGL
libraries. Added preliminary thrustcurves for Aerotech C3 and D2 18mm
reloads.
</div>
<div id="13.09">
OpenRocket 13.09 (2013-09-08)
-----------------------------
@ -357,6 +424,9 @@ OpenRocket 13.09 (2013-09-08)
This release contains a number of bug fixes, updated 3D JOGL
libraries, and separates simulation edit and plot dialogs.
</div>
<div id="13.05">
OpenRocket 13.05 (2013-05-04)
-----------------------------
@ -384,6 +454,9 @@ New Features
scroll with mouse wheel. If the alt key is used with either of these, only the domain is zoomed. Richard
contributed a more logical mouse controlled zoom - right click and drag will zoom (either domain, range or both).
</div>
<div id="12.09.1">
OpenRocket 12.09.1 (2012-06-28)
-------------------------------
@ -392,6 +465,9 @@ Bug-fix release for 12.09, fixing numerous bugs. Only new feature is
the possiblity to automatically open the latest design file on startup
(in Edit -> Preferences -> Options).
</div>
<div id="12.09">
OpenRocket 12.09 (2012-09-16)
------------------------------
@ -411,6 +487,9 @@ Numerous new features by many contributors
- Calibration rulers added to printed templates
- Translations in Czech and Polish, numerous updates
</div>
<div id="12.03">
OpenRocket 12.03 (2012-03-17)
------------------------------
@ -430,6 +509,9 @@ release you can open files and examine existing simulations, stability
data and motor files. The Android port is thanks to work by Kevin
Ruland.
</div>
<div id="1.1.9">
OpenRocket 1.1.9 (2011-11-24)
------------------------------
@ -440,6 +522,9 @@ to work by Richard Graham. Printing of transitions, nose cone
profiles and fin marking guides is available thanks to Doug Pedrick.
It also contains some usability features and bug fixes.
</div>
<div id="1.1.8">
OpenRocket 1.1.8 (2011-08-25)
------------------------------
@ -448,6 +533,9 @@ This release contains bug fixes to the optimization methods.
It also contains a workaround to a JRE bug that prevents running
OpenRocket on Java 7.
</div>
<div id="1.1.7">
OpenRocket 1.1.7 (2011-08-12)
------------------------------
@ -456,6 +544,9 @@ This release contains automatic rocket design optimization
functionality. However, be cautious when using it and take the
results with a grain of salt.
</div>
<div id="1.1.6">
OpenRocket 1.1.6 (2011-07-22)
------------------------------
@ -465,6 +556,9 @@ translations by Tripoli Spain, Tripoli France and Stefan Lobas
(ERIG e.V.). The release also contains rocket design scaling support
and numerous bug fixes.
</div>
<div id="1.1.5">
OpenRocket 1.1.5 (2011-06-10)
------------------------------
@ -473,12 +567,18 @@ Removed native printing support. Printing is now handled via PDF
viewer, which should make printing much more reliable and less
bug-prone.
</div>
<div id="1.1.4">
OpenRocket 1.1.4 (2011-03-05)
------------------------------
Initial printing support by Doug Pedrick, and various bug fixes.
</div>
<div id="1.1.3">
OpenRocket 1.1.3 (2010-10-06)
------------------------------
@ -486,12 +586,18 @@ OpenRocket 1.1.3 (2010-10-06)
Support for drag-drop moving and copying of components. Fixes a
severe bug in the undo system.
</div>
<div id="1.1.2">
OpenRocket 1.1.2 (2010-09-07)
------------------------------
Fixes a severe bug that prevented adding stages to rockets.
</div>
<div id="1.1.1">
OpenRocket 1.1.1 (2010-09-03)
------------------------------
@ -501,6 +607,9 @@ curve loading and selection, faster startup time and bug fixes.
Old simulation listeners are incompatible with this release.
</div>
<div id="1.1.0">
OpenRocket 1.1.0 (2010-03-21)
------------------------------
@ -508,6 +617,9 @@ OpenRocket 1.1.0 (2010-03-21)
Support for loading RockSim rocket design files (.rkt) thanks to
Doug Pedrick.
</div>
<div id="1.0.0">
OpenRocket 1.0.0 (2010-03-10)
------------------------------
@ -515,6 +627,9 @@ OpenRocket 1.0.0 (2010-03-10)
Added numerous new motor thrustcurves from thrustcurve.org, and fixed
a few more bugs.
</div>
<div id="0.9.6">
OpenRocket 0.9.6 (2010-02-17)
------------------------------
@ -523,6 +638,9 @@ Updated aerodynamic calculation methods to be more in line with the
Barrowman method and enhanced simulation time step selection. Fixed
numerous bugs.
</div>
<div id="0.9.5">
OpenRocket 0.9.5 (2009-11-28)
------------------------------
@ -530,6 +648,9 @@ OpenRocket 0.9.5 (2009-11-28)
Fixed a serious defect which prevented adding a tube coupler and
centering ring on the same body tube. Other minor improvements.
</div>
<div id="0.9.4">
OpenRocket 0.9.4 (2009-11-24)
------------------------------
@ -538,6 +659,9 @@ Added through-the-wall fin tabs, attaching components to tube
couplers, material editing and automatic update checks, and fixed
numerous of the most commonly occurring bugs.
</div>
<div id="0.9.3">
OpenRocket 0.9.3 (2009-09-01)
------------------------------
@ -546,6 +670,9 @@ Numerous bug fixes and enhancements including data exporting, showing
flight events in plots, example rocket designs, splitting clustered
inner tubes and automated bug reporting.
</div>
<div id="0.9.2">
OpenRocket 0.9.2 (2009-07-13)
------------------------------
@ -554,6 +681,9 @@ Fixed imperial unit conversions. Significant UI enhancements to the
motor configuration edit dialog, motor selection dialog and file
open/save.
</div>
<div id="0.9.1">
OpenRocket 0.9.1 (2009-06-09)
------------------------------
@ -561,8 +691,14 @@ OpenRocket 0.9.1 (2009-06-09)
Bug fixes to file dialog and saving; initial support for cut/copy/paste
of simulations.
</div>
<div id="0.9.0">
OpenRocket 0.9.0 (2009-05-24)
------------------------------
Initial release.
</div>
</body>

View File

@ -1,7 +1,8 @@
<project name="OpenRocket-Core" basedir=".">
<property file="resources/build.properties" />
<property name="root.dir" value=".."/> <!-- Root directory -->
<property name="src.dir" value="${basedir}/src"/> <!-- Source directory -->
<property name="src-test.dir" value="${basedir}/test"/> <!-- Test directory -->
<property name="build.dir" value="${basedir}/build"/> <!-- Build directory -->
@ -34,6 +35,7 @@
<pathelement location="${build-test.dir}"/>
<pathelement location="${classes.dir}"/>
<pathelement location="${src-test.dir}"/>
<pathelement location="${root.dir}"/>
<fileset dir="${libtest.dir}/" includes="*.jar"/>
</path>

View File

@ -356,6 +356,13 @@ generalprefs.lbl.language = Interface language
generalprefs.languages.default = System default
generalprefs.lbl.languageEffect = The language will change the next time you start OpenRocket.
! Welcome dialog
welcome.dlg.title = Welcome to OpenRocket
welcome.dlg.lbl.thankYou = Thank you for downloading OpenRocket
welcome.dlg.lbl.seeReleaseNotes = See the release notes below to find what's new.
welcome.dlg.checkbox.dontShowAgain = Don't show this dialog again
welcome.dlg.btn.close.ttip = Cool! Now leave me alone\u2026
! Software update checker
update.dlg.error.title = Unable to retrieve update information
update.dlg.error = An error occurred while communicating with the server.
@ -366,6 +373,8 @@ update.dlg.newerVersion.title = Newer version detected
update.dlg.newerVersion = You are either running a test/unofficial release of OpenRocket, or you have a time machine and are running an official release from the future.\n\nYour version: %s\nLatest official release: %s
update.dlg.updateAvailable.title = Update available
update.dlg.updateAvailable.lbl.title = A new version of OpenRocket is available!
update.dlg.btn.remindMeLater = Remind Me Later
update.dlg.checkbox.skipThisVersion = Skip This Version
update.dlg.updateAvailable.lbl.yourVersion = OpenRocket %s is available! \u2015 you have %s. Would you like to download it now?
update.dlg.updateAvailable.lbl.releaseNotes = Release notes:
update.dlg.updateAvailable.txtPane.readMore = Read more on GitHub

View File

@ -9,7 +9,7 @@ public abstract class Communicator {
protected static final String BUG_REPORT_URL;
protected static final String UPDATE_URL;
protected static final String UPDATE_ADDITIONAL_URL; // Extra URL needed for the update checker
protected static final String UPDATE_URL_LATEST; // Extra URL needed for the latest GitHub release
static {
String url;
@ -21,10 +21,10 @@ public abstract class Communicator {
url = System.getProperty("openrocket.debug.updateurl");
if (url == null) {
url = "https://api.github.com/repos/openrocket/openrocket/releases";
UPDATE_ADDITIONAL_URL = "https://api.github.com/repos/openrocket/openrocket/releases/latest";
UPDATE_URL_LATEST = "https://api.github.com/repos/openrocket/openrocket/releases/latest";
}
else {
UPDATE_ADDITIONAL_URL = null;
UPDATE_URL_LATEST = null;
}
UPDATE_URL = url;
}

View File

@ -0,0 +1,112 @@
package net.sf.openrocket.communication;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.json.Json;
import javax.json.JsonReader;
import javax.json.stream.JsonParsingException;
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Map;
/**
* Utility functions for the GitHub API.
*/
public class GitHubAPIUtil {
private static final Logger log = LoggerFactory.getLogger(GitHubAPIUtil.class);
private static final Translator trans = Application.getTranslator();
/**
* Generate a URL with a set of parameters included.
* E.g. url = github.com/openrocket/openrocket/releases, params = {"lorem", "ipsum"}
* => formatted url: github.com/openrocket/openrocket/releases?lorem=ipsum
* @param url base URL
* @param params parameters to include
* @return formatted URL (= base URL with parameters)
*/
public static String generateUrlWithParameters(String url, Map<String, String> params) {
StringBuilder formattedUrl = new StringBuilder(url);
formattedUrl.append("?"); // Identifier for start of query string (for parameters)
// Append the parameters to the URL
int idx = 0;
for (Map.Entry<String, String> e : params.entrySet()) {
formattedUrl.append(String.format("%s=%s", e.getKey(), e.getValue()));
if (idx < params.size() - 1) {
formattedUrl.append("&"); // Identifier for more parameters
}
idx++;
}
return formattedUrl.toString();
}
/**
* Fetches the JSON info from the specified GitHub API URL.
* @param urlLink GitHub API link of the desired releases
* @return JSON-formatted string (can be a JSON-array or JSON-object)
* @throws Exception if an error occurred (e.g. no internet connection)
*/
public static String fetchPageInfo(String urlLink) throws Exception {
HttpsURLConnection connection = null;
try {
// Set up connection info to the GitHub release page
URL url = new URL(urlLink);
connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/json");
connection.setUseCaches(false);
connection.setAllowUserInteraction(false);
connection.setConnectTimeout(Communicator.CONNECTION_TIMEOUT);
connection.setReadTimeout(Communicator.CONNECTION_TIMEOUT);
// Connect to the GitHub page and get the status response code
connection.connect();
int status = connection.getResponseCode();
log.debug("Update checker response code: " + status);
// Invalid response code
if (status != 200) {
log.warn(String.format("Bad response code from server: %d", status));
throw new Exception(String.format(trans.get("update.fetcher.badResponse"), status));
}
// Read the response JSON data into a StringBuilder
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
br.close();
return sb.toString();
} catch (UnknownHostException | SocketTimeoutException | ConnectException e) {
log.warn(String.format("Could not connect to URL: %s. Please check your internet connection.", urlLink));
throw new Exception(trans.get("update.fetcher.badConnection"));
} catch (MalformedURLException e) {
log.warn("Malformed URL: " + urlLink);
throw new Exception(String.format(trans.get("update.fetcher.malformedURL"), urlLink));
} catch (IOException e) {
throw new Exception(String.format("Exception - %s: %s", e, e.getMessage()));
} finally { // Close the connection to the release page
if (connection != null) {
try {
connection.disconnect();
} catch (Exception ex) {
log.warn("Could not disconnect update checker connection");
}
}
}
}
}

View File

@ -0,0 +1,56 @@
package net.sf.openrocket.communication;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.simplesax.AbstractElementHandler;
import net.sf.openrocket.file.simplesax.ElementHandler;
import net.sf.openrocket.file.simplesax.PlainTextHandler;
import org.xml.sax.SAXException;
import java.util.HashMap;
import java.util.Objects;
/**
* Class that parses ReleaseNotes.md.
* <p>
* Releases are stored in an HTML <div> object with as id attribute the release version.
* E.g. <div id="15.03">...</div>
* The content of the div is the release notes for that version.
*/
public class ReleaseNotesHandler extends AbstractElementHandler {
private final String buildVersion;
private String releaseNotes = null;
/**
* @param buildVersion the build version to search the release notes for (e.g. "22.02")
*/
public ReleaseNotesHandler(String buildVersion) {
this.buildVersion = buildVersion;
}
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes, WarningSet warnings) throws SAXException {
if (element.equals("body")) { // The release notes are encapsulated in a root <body> tag (required for XML parsing)
return this;
}
if (element.equals("div") && Objects.equals(attributes.get("id"), this.buildVersion)) {
return PlainTextHandler.INSTANCE;
}
return null;
}
@Override
public void closeElement(String element, HashMap<String, String> attributes, String content, WarningSet warnings) throws SAXException {
super.closeElement(element, attributes, content, warnings);
if (element.equals("div")) {
this.releaseNotes = content.trim();
}
}
/**
* @return the release notes for the build version
*/
public String getReleaseNotes() {
return releaseNotes;
}
}

View File

@ -1,14 +1,6 @@
package net.sf.openrocket.communication;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -31,7 +23,6 @@ import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.stream.JsonParsingException;
import javax.net.ssl.HttpsURLConnection;
/**
* Class that initiates fetching software update information.
@ -79,7 +70,7 @@ public class UpdateInfoRetriever {
*/
public boolean isRunning() {
if (this.fetcher == null) {
throw new IllegalStateException("startFetchUpdateInfo() has not been called");
throw new IllegalStateException("Fetcher has not been called yet");
}
return this.fetcher.isAlive();
}
@ -100,7 +91,7 @@ public class UpdateInfoRetriever {
*/
public UpdateInfo getUpdateInfo() {
if (this.fetcher == null) {
throw new IllegalStateException("startFetchUpdateInfo() has not been called");
throw new IllegalStateException("Fetcher has not been called yet");
}
return this.fetcher.info;
}
@ -175,15 +166,15 @@ public class UpdateInfoRetriever {
// Get release tags from release page
String relUrl = Communicator.UPDATE_URL;
relUrl = generateUrlWithParameters(relUrl, params);
relUrl = GitHubAPIUtil.generateUrlWithParameters(relUrl, params);
JsonArray arr1 = retrieveReleaseJSONArr(relUrl);
if (arr1 == null) return null;
if (Communicator.UPDATE_ADDITIONAL_URL == null) return arr1;
if (Communicator.UPDATE_URL_LATEST == null) return arr1;
// Get release tags from latest release page
String latestRelUrl = Communicator.UPDATE_ADDITIONAL_URL;
latestRelUrl = generateUrlWithParameters(latestRelUrl, params);
String latestRelUrl = Communicator.UPDATE_URL_LATEST;
latestRelUrl = GitHubAPIUtil.generateUrlWithParameters(latestRelUrl, params);
JsonArray arr2 = retrieveReleaseJSONArr(latestRelUrl);
if (arr2 == null) return null;
@ -209,72 +200,25 @@ public class UpdateInfoRetriever {
* @throws UpdateCheckerException if an error occurred (e.g. no internet connection)
*/
private JsonArray retrieveReleaseJSONArr(String urlLink) throws UpdateCheckerException {
JsonArray jsonArr;
HttpsURLConnection connection = null;
try {
// Set up connection info to the GitHub release page
URL url = new URL(urlLink);
connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/json");
connection.setUseCaches(false);
connection.setAllowUserInteraction(false);
connection.setConnectTimeout(Communicator.CONNECTION_TIMEOUT);
connection.setReadTimeout(Communicator.CONNECTION_TIMEOUT);
String pageInfo = GitHubAPIUtil.fetchPageInfo(urlLink);
// Connect to the GitHub page and get the status response code
connection.connect();
int status = connection.getResponseCode();
log.debug("Update checker response code: " + status);
// Invalid response code
if (status != 200) {
log.warn(String.format("Bad response code from server: %d", status));
throw new UpdateCheckerException(String.format(trans.get("update.fetcher.badResponse"), status));
}
// Read the response JSON data into a StringBuilder
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
br.close();
// Read the release page as a JSON array
JsonReader reader = Json.createReader(new StringReader(sb.toString()));
// Read the release page as a JSON object
JsonReader reader = Json.createReader(new StringReader(pageInfo));
// The reader-content can be a JSON array or just a JSON object
try { // Case: JSON array
jsonArr = reader.readArray();
return reader.readArray();
} catch (JsonParsingException e) { // Case: JSON object
JsonArrayBuilder builder = Json.createArrayBuilder();
reader = Json.createReader(new StringReader(sb.toString()));
reader = Json.createReader(new StringReader(pageInfo));
JsonObject obj = reader.readObject();
builder.add(obj);
jsonArr = builder.build();
}
} catch (UnknownHostException | SocketTimeoutException | ConnectException e) {
log.warn(String.format("Could not connect to URL: %s. Please check your internet connection.", urlLink));
throw new UpdateCheckerException(trans.get("update.fetcher.badConnection"));
} catch (MalformedURLException e) {
log.warn("Malformed URL: " + urlLink);
throw new UpdateCheckerException(String.format(trans.get("update.fetcher.malformedURL"), urlLink));
} catch (IOException e) {
throw new UpdateCheckerException(String.format("Exception - %s: %s", e, e.getMessage()));
} finally { // Close the connection to the release page
if (connection != null) {
try {
connection.disconnect();
} catch (Exception ex) {
log.warn("Could not disconnect update checker connection");
}
return builder.build();
}
} catch (Exception e) {
throw new UpdateCheckerException(e);
}
return jsonArr;
}
/**
@ -494,30 +438,6 @@ public class UpdateInfoRetriever {
}
}
/**
* Generate a URL with a set of parameters included.
* E.g. url = github.com/openrocket/openrocket/releases, params = {"lorem", "ipsum"}
* => formatted url: github.com/openrocket/openrocket/releases?lorem=ipsum
* @param url base URL
* @param params parameters to include
* @return formatted URL (= base URL with parameters)
*/
private String generateUrlWithParameters(String url, Map<String, String> params) {
StringBuilder formattedUrl = new StringBuilder(url);
formattedUrl.append("?"); // Identifier for start of query string (for parameters)
// Append the parameters to the URL
int idx = 0;
for (Map.Entry<String, String> e : params.entrySet()) {
formattedUrl.append(String.format("%s=%s", e.getKey(), e.getValue()));
if (idx < params.size() - 1) {
formattedUrl.append("&"); // Identifier for more parameters
}
idx++;
}
return formattedUrl.toString();
}
/**
* Exception for the update checker
*/
@ -525,6 +445,10 @@ public class UpdateInfoRetriever {
public UpdateCheckerException(String message) {
super(message);
}
public UpdateCheckerException(Throwable cause) {
super(cause);
}
}
}
}

View File

@ -0,0 +1,47 @@
package net.sf.openrocket.communication;
import net.sf.openrocket.aerodynamics.WarningSet;
import net.sf.openrocket.file.simplesax.SimpleSAX;
import net.sf.openrocket.util.BuildProperties;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public abstract class WelcomeInfoRetriever {
/**
* Retrieves the release notes of the current build version from the ReleaseNotes.md file.
* @param version the build version to search the release notes for (e.g. "22.02")
* @return the release notes of the current build version
* @throws IOException if the file could not be read
*/
public static String retrieveWelcomeInfo(String version) throws IOException {
ClassLoader cl = WelcomeInfoRetriever.class.getClassLoader();
InputStream in = cl.getResourceAsStream("ReleaseNotes.md");
if (in == null) {
throw new FileNotFoundException("ReleaseNotes.md not found");
}
InputSource source = new InputSource(new InputStreamReader(in));
ReleaseNotesHandler handler = new ReleaseNotesHandler(version);
WarningSet warnings = new WarningSet();
try {
SimpleSAX.readXML(source, handler, warnings);
return handler.getReleaseNotes();
} catch (SAXException e) {
throw new IOException(e.getMessage(), e);
}
}
/**
* Retrieves the release notes of the current build version from the ReleaseNotes.md file.
* @return the release notes of the current build version
* @throws IOException if the file could not be read
*/
public static String retrieveWelcomeInfo() throws IOException {
return retrieveWelcomeInfo(BuildProperties.getVersion());
}
}

View File

@ -55,10 +55,12 @@ public abstract class Preferences implements ChangeSource {
public static final String USER_LOCAL = "locale";
public static final String PLOT_SHOW_POINTS = "ShowPlotPoints";
private static final String IGNORE_WELCOME = "IgnoreWelcome";
private static final String CHECK_UPDATES = "CheckUpdates";
private static final String IGNORE_VERSIONS = "IgnoreVersions";
private static final String IGNORE_UPDATE_VERSIONS = "IgnoreUpdateVersions";
private static final String CHECK_BETA_UPDATES = "CheckBetaUpdates";
public static final String MOTOR_DIAMETER_FILTER = "MotorDiameterMatch";
@ -141,9 +143,31 @@ public abstract class Preferences implements ChangeSource {
public abstract void putString(String directory, String key, String value);
public abstract java.util.prefs.Preferences getNode(String nodeName);
/*
* ******************************************************************************************
* Welcome dialog
*/
/**
* Sets to ignore opening the welcome dialog for the supplied OpenRocket build version.
* @param version build version to ignore opening the welcome dialog for (e.g. "22.02")
* @param ignore true to ignore, false to show the welcome dialog
*/
public final void setIgnoreWelcome(String version, boolean ignore) {
this.putBoolean(IGNORE_WELCOME + "_" + version, ignore);
}
/**
* Returns whether to ignore opening the welcome dialog for the supplied OpenRocket build version.
* @param version build version (e.g. "22.02")
* @return true if no welcome dialog should be opened for the supplied version
*/
public final boolean getIgnoreWelcome(String version) {
return this.getBoolean(IGNORE_WELCOME + "_" + version, false);
}
/*
* Software updater
*/
public final boolean getCheckUpdates() {
return this.getBoolean(CHECK_UPDATES, BuildProperties.getDefaultCheckUpdates());
@ -153,12 +177,12 @@ public abstract class Preferences implements ChangeSource {
this.putBoolean(CHECK_UPDATES, check);
}
public final List<String> getIgnoreVersions() {
return List.of(this.getString(IGNORE_VERSIONS, "").split("\n"));
public final List<String> getIgnoreUpdateVersions() {
return List.of(this.getString(IGNORE_UPDATE_VERSIONS, "").split("\n"));
}
public final void setIgnoreVersions(List<String> versions) {
this.putString(IGNORE_VERSIONS, String.join("\n", versions));
public final void setIgnoreUpdateVersions(List<String> versions) {
this.putString(IGNORE_UPDATE_VERSIONS, String.join("\n", versions));
}
public final boolean getCheckBetaUpdates() {
@ -168,6 +192,11 @@ public abstract class Preferences implements ChangeSource {
public final void setCheckBetaUpdates(boolean check) {
this.putBoolean(CHECK_BETA_UPDATES, check);
}
/*
* ******************************************************************************************
*/
public final boolean getConfirmSimDeletion() {
return this.getBoolean(CONFIRM_DELETE_SIMULATION, true);

View File

@ -0,0 +1,27 @@
package net.sf.openrocket.communication;
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class WelcomeInfoTest extends BaseTestCase {
/**
* Note: this unit test will fail if you don't run it using 'ant unittest', because otherwise
* it can't load the ReleaseNotes.md file.
*/
@Test
public void testWelcomeInfo() throws Exception {
// Test the welcome info for the current build version
String welcomeInfo = WelcomeInfoRetriever.retrieveWelcomeInfo();
assertNotNull(welcomeInfo);
assertTrue(welcomeInfo.length() > 0);
// Test the release info for a bogus release version
welcomeInfo = WelcomeInfoRetriever.retrieveWelcomeInfo("bogus release");
assertNull(welcomeInfo);
}
}

View File

@ -30,7 +30,6 @@ import net.sf.openrocket.communication.AssetHandler.UpdatePlatform;
import net.sf.openrocket.communication.ReleaseInfo;
import net.sf.openrocket.communication.UpdateInfo;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.configdialog.CommonStrings;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.gui.util.Icons;
import net.sf.openrocket.gui.util.SwingPreferences;
@ -58,6 +57,7 @@ public class UpdateInfoDialog extends JDialog {
JPanel panel = new JPanel(new MigLayout("insets n n 8px n, fill"));
// OpenRocket logo on the left
panel.add(new JLabel(Icons.getScaledIcon(Icons.loadImageIcon("pix/icon/icon-about.png", "OpenRocket"), 0.6)),
"spany, top, gapright 20px, cell 0 0");
@ -124,7 +124,7 @@ public class UpdateInfoDialog extends JDialog {
// Lower row buttons
//// Remind me later button
JButton btnLater = new SelectColorButton("Remind Me Later");
JButton btnLater = new SelectColorButton(trans.get("update.dlg.btn.remindMeLater"));
btnLater.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@ -134,15 +134,15 @@ public class UpdateInfoDialog extends JDialog {
panel.add(btnLater, "skip 1, split 2");
//// Skip this version button
JButton btnSkip = new SelectColorButton("Skip This Version");
JButton btnSkip = new SelectColorButton(trans.get("update.dlg.checkbox.skipThisVersion"));
btnSkip.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
List<String> ignoreVersions = new ArrayList<>(preferences.getIgnoreVersions());
List<String> ignoreVersions = new ArrayList<>(preferences.getIgnoreUpdateVersions());
String ignore = release.getReleaseName();
if (!ignoreVersions.contains(ignore)) {
ignoreVersions.add(ignore);
preferences.setIgnoreVersions(ignoreVersions);
preferences.setIgnoreUpdateVersions(ignoreVersions);
}
UpdateInfoDialog.this.dispose();
}

View File

@ -0,0 +1,115 @@
package net.sf.openrocket.gui.dialogs;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.util.GUIUtil;
import net.sf.openrocket.gui.util.Icons;
import net.sf.openrocket.gui.widgets.SelectColorButton;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BuildProperties;
import net.sf.openrocket.util.MarkdownUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Dialog that opens when you start up OpenRocket. It will display the release notes of the current version.
*/
public class WelcomeDialog extends JDialog {
private static final Translator trans = Application.getTranslator();
private static final Logger log = LoggerFactory.getLogger(WelcomeDialog.class);
/**
* @param releaseNotes the release notes to display for the current version
*/
public WelcomeDialog(String releaseNotes) {
super(null, trans.get("welcome.dlg.title"), ModalityType.APPLICATION_MODAL);
JPanel panel = new JPanel(new MigLayout("insets n n 8px n, fill"));
// OpenRocket logo on the left
panel.add(new JLabel(Icons.getScaledIcon(Icons.loadImageIcon("pix/icon/icon-about.png", "OpenRocket"), 0.6)),
"spany, top, gapright 20px, cell 0 0");
// Thank you for downloading!
panel.add(new StyledLabel(trans.get("welcome.dlg.lbl.thankYou") + " " + BuildProperties.getVersion() + "!",
2, StyledLabel.Style.BOLD), "spanx, wrap");
// See the release notes below for what's new
panel.add(new StyledLabel(trans.get("welcome.dlg.lbl.seeReleaseNotes"),
1, StyledLabel.Style.PLAIN), "skip 1, spanx, wrap para");
// Release notes
final JTextPane textPane = new JTextPane();
textPane.setEditable(false);
textPane.setContentType("text/html");
textPane.setMargin(new Insets(10, 10, 10, 10));
textPane.putClientProperty(JTextPane.HONOR_DISPLAY_PROPERTIES, true);
String sb = "<html>" +
MarkdownUtil.toHtml(releaseNotes) + "<br><br>" +
"</html>";
textPane.addHyperlinkListener(new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
Desktop desktop = Desktop.getDesktop();
try {
desktop.browse(e.getURL().toURI());
} catch (Exception ex) {
log.warn("Exception hyperlink: " + ex.getMessage());
}
}
}
});
textPane.setText(sb);
textPane.setCaretPosition(0); // Scroll to the top
panel.add(new JScrollPane(textPane), "skip 1, left, spanx, grow, push, gapbottom 6px, wrap");
// Don't show this dialog again
JCheckBox dontShowAgain = new JCheckBox(trans.get("welcome.dlg.checkbox.dontShowAgain"));
dontShowAgain.setSelected(Application.getPreferences().getIgnoreWelcome(BuildProperties.getVersion())); // Normally this should never be true, but just in case
panel.add(dontShowAgain, "skip 1");
dontShowAgain.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Application.getPreferences().setIgnoreWelcome(BuildProperties.getVersion(), dontShowAgain.isSelected());
}
});
// Close button
JButton closeBtn = new SelectColorButton(trans.get("button.close"));
closeBtn.setToolTipText(trans.get("welcome.dlg.btn.close.ttip"));
closeBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
WelcomeDialog.this.dispose();
}
});
panel.add(closeBtn, "pushx, right, wrap");
panel.setPreferredSize(new Dimension(800, 600));
this.add(panel);
this.pack();
this.setLocationRelativeTo(null);
GUIUtil.setDisposableDialogOptions(this, closeBtn);
}
}

View File

@ -342,7 +342,7 @@ public class GeneralPreferencesPanel extends PreferencesPanel {
ReleaseInfo release = info.getLatestRelease();
// Do nothing if the release is part of the ignore versions
if (preferences.getIgnoreVersions().contains(release.getReleaseName())) {
if (preferences.getIgnoreUpdateVersions().contains(release.getReleaseName())) {
return;
}

View File

@ -4,6 +4,7 @@ import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.stream.IntStream;
@ -19,10 +20,11 @@ import net.sf.openrocket.arch.SystemInfo.Platform;
import net.sf.openrocket.communication.UpdateInfo;
import net.sf.openrocket.communication.UpdateInfoRetriever;
import net.sf.openrocket.communication.UpdateInfoRetriever.ReleaseStatus;
import net.sf.openrocket.communication.WelcomeInfoRetriever;
import net.sf.openrocket.database.Databases;
import net.sf.openrocket.gui.dialogs.UpdateInfoDialog;
import net.sf.openrocket.gui.dialogs.WelcomeDialog;
import net.sf.openrocket.gui.main.BasicFrame;
import net.sf.openrocket.gui.main.MRUDesignFile;
import net.sf.openrocket.gui.main.Splash;
import net.sf.openrocket.gui.main.SwingExceptionHandler;
import net.sf.openrocket.gui.util.GUIUtil;
@ -217,6 +219,7 @@ public class SwingStartup {
if (!handleCommandLine(args)) {
BasicFrame startupFrame = BasicFrame.reopen();
BasicFrame.setStartupFrame(startupFrame);
showWelcomeDialog();
}
// Check whether update info has been fetched or whether it needs more time
@ -277,7 +280,7 @@ public class SwingStartup {
// Only display something when an update is found
if (info != null && info.getException() == null && info.getReleaseStatus() == ReleaseStatus.OLDER &&
!preferences.getIgnoreVersions().contains(info.getLatestRelease().getReleaseName())) {
!preferences.getIgnoreUpdateVersions().contains(info.getLatestRelease().getReleaseName())) {
UpdateInfoDialog infoDialog = new UpdateInfoDialog(info);
infoDialog.setVisible(true);
}
@ -290,6 +293,34 @@ public class SwingStartup {
timer.addActionListener(listener);
timer.start();
}
/**
* Shows a welcome dialog displaying the release notes for this build version.
*/
public static void showWelcomeDialog() {
// Don't show if this build version is ignored
if (Application.getPreferences().getIgnoreWelcome(BuildProperties.getVersion())) {
log.debug("Welcome dialog ignored");
return;
}
// Fetch this version's release notes
String releaseNotes;
try {
releaseNotes = WelcomeInfoRetriever.retrieveWelcomeInfo();
} catch (IOException e) {
log.error("Error retrieving welcome info", e);
return;
}
if (releaseNotes == null) {
log.debug("No release notes found");
return;
}
// Show the dialog
WelcomeDialog dialog = new WelcomeDialog(releaseNotes);
dialog.setVisible(true);
}
/**
* Handles arguments passed from the command line. This may be used either