Added checking for new releases
This commit is contained in:
parent
40c522ec8f
commit
ff6f5b70bc
6 changed files with 290 additions and 28 deletions
|
@ -48,6 +48,7 @@ public class FTLModManager {
|
||||||
config.setProperty( "use_default_ui", "false" );
|
config.setProperty( "use_default_ui", "false" );
|
||||||
config.setProperty( "remember_geometry", "true" );
|
config.setProperty( "remember_geometry", "true" );
|
||||||
// "update_catalog" doesn't have a default.
|
// "update_catalog" doesn't have a default.
|
||||||
|
// "update_app" doesn't have a default.
|
||||||
// "manager_geometry" doesn't have a default.
|
// "manager_geometry" doesn't have a default.
|
||||||
|
|
||||||
// Read the config file.
|
// Read the config file.
|
||||||
|
@ -128,19 +129,30 @@ public class FTLModManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prompt if update_catalog is invalid or hasn't been set.
|
// Prompt if update_catalog is invalid or hasn't been set.
|
||||||
|
boolean askAboutUpdates = false;
|
||||||
|
String catalogUpdateInterval = config.getProperty( "update_catalog" );
|
||||||
|
String appUpdateInterval = config.getProperty( "update_app" );
|
||||||
|
|
||||||
String updateCatalog = config.getProperty( "update_catalog" );
|
if ( catalogUpdateInterval == null || !catalogUpdateInterval.matches("^\\d+$") )
|
||||||
if ( updateCatalog == null || !updateCatalog.matches("^true|false$") ) {
|
askAboutUpdates = true;
|
||||||
|
if ( appUpdateInterval == null || !appUpdateInterval.matches("^\\d+$") )
|
||||||
|
askAboutUpdates = true;
|
||||||
|
|
||||||
|
if ( askAboutUpdates ) {
|
||||||
String message = "";
|
String message = "";
|
||||||
message += "Would you like Slipstream to periodically\n";
|
message += "Would you like Slipstream to periodically\n";
|
||||||
message += "download descriptions for the latest mods?\n\n";
|
message += "check for updates and download descriptions\n";
|
||||||
|
message += "for the latest mods?\n\n";
|
||||||
message += "You can change this later in modman.cfg.";
|
message += "You can change this later in modman.cfg.";
|
||||||
|
|
||||||
int response = JOptionPane.showConfirmDialog(null, message, "Catalog Updates", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
int response = JOptionPane.showConfirmDialog(null, message, "Updates", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
|
||||||
if ( response == JOptionPane.YES_OPTION )
|
if ( response == JOptionPane.YES_OPTION ) {
|
||||||
config.setProperty( "update_catalog", "true" );
|
config.setProperty( "update_catalog", "7" );
|
||||||
else
|
config.setProperty( "update_app", "4" );
|
||||||
config.setProperty( "update_catalog", "false" );
|
} else {
|
||||||
|
config.setProperty( "update_catalog", "0" );
|
||||||
|
config.setProperty( "update_app", "0" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
45
src/main/java/net/vhati/modmanager/core/AutoUpdateInfo.java
Normal file
45
src/main/java/net/vhati/modmanager/core/AutoUpdateInfo.java
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
package net.vhati.modmanager.core;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import net.vhati.modmanager.core.ComparableVersion;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds info about available updates.
|
||||||
|
*/
|
||||||
|
public class AutoUpdateInfo {
|
||||||
|
private ComparableVersion latestVersion = null;
|
||||||
|
private Map<String,String> latestURLs = new TreeMap<String,String>();
|
||||||
|
private Map<ComparableVersion,List<String>> changelog = new TreeMap<ComparableVersion,List<String>>( Collections.reverseOrder() );
|
||||||
|
|
||||||
|
|
||||||
|
public void setLatestVersion( ComparableVersion version ) {
|
||||||
|
latestVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComparableVersion getLatestVersion() {
|
||||||
|
return latestVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void putLatestURL( String os, String url ) {
|
||||||
|
latestURLs.put( os, url );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putChanges( ComparableVersion version, List<String> changeList ) {
|
||||||
|
changelog.put( version, changeList );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Map<String,String> getLatestURLs() {
|
||||||
|
return latestURLs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<ComparableVersion,List<String>> getChangelog() {
|
||||||
|
return changelog;
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,6 +29,14 @@ public class SlipstreamConfig {
|
||||||
return config.setProperty( key, value );
|
return config.setProperty( key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getPropertyAsInt( String key, int defaultValue ) {
|
||||||
|
String s = config.getProperty( key );
|
||||||
|
if ( s != null && s.matches("^\\d+$") )
|
||||||
|
return Integer.parseInt( s );
|
||||||
|
else
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
public String getProperty( String key, String defaultValue ) {
|
public String getProperty( String key, String defaultValue ) {
|
||||||
return config.getProperty( key, defaultValue );
|
return config.getProperty( key, defaultValue );
|
||||||
}
|
}
|
||||||
|
@ -48,7 +56,8 @@ public class SlipstreamConfig {
|
||||||
configComments += " allow_zip - Sets whether to treat .zip files as .ftl files. Default: false.\n";
|
configComments += " allow_zip - Sets whether to treat .zip files as .ftl files. Default: false.\n";
|
||||||
configComments += " ftl_dats_path - The path to FTL's resources folder. If invalid, you'll be prompted.\n";
|
configComments += " ftl_dats_path - The path to FTL's resources folder. If invalid, you'll be prompted.\n";
|
||||||
configComments += " never_run_ftl - If true, there will be no offer to run FTL after patching. Default: false.\n";
|
configComments += " never_run_ftl - If true, there will be no offer to run FTL after patching. Default: false.\n";
|
||||||
configComments += " update_catalog - If true, periodically download descriptions for the latest mods.\n";
|
configComments += " update_catalog - If a number greater than 0, check for new mod descriptions every N days.\n";
|
||||||
|
configComments += " update_app - If a number greater than 0, check for new app version every N days.\n";
|
||||||
configComments += " use_default_ui - If true, no attempt will be made to resemble a native GUI. Default: false.\n";
|
configComments += " use_default_ui - If true, no attempt will be made to resemble a native GUI. Default: false.\n";
|
||||||
configComments += " remember_geometry - If true, window geometry will be saved on exit and restored on startup.\n";
|
configComments += " remember_geometry - If true, window geometry will be saved on exit and restored on startup.\n";
|
||||||
configComments += "\n";
|
configComments += "\n";
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package net.vhati.modmanager.json;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.vhati.modmanager.core.AutoUpdateInfo;
|
||||||
|
import net.vhati.modmanager.core.ComparableVersion;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
|
||||||
|
public class JacksonAutoUpdateReader {
|
||||||
|
|
||||||
|
private static final Logger log = LogManager.getLogger(JacksonAutoUpdateReader.class);
|
||||||
|
|
||||||
|
|
||||||
|
public static AutoUpdateInfo parse( File jsonFile ) {
|
||||||
|
AutoUpdateInfo aui = new AutoUpdateInfo();
|
||||||
|
|
||||||
|
Exception exception = null;
|
||||||
|
try {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
mapper.configure( JsonParser.Feature.ALLOW_SINGLE_QUOTES, true );
|
||||||
|
mapper.setVisibility( PropertyAccessor.FIELD, Visibility.ANY );
|
||||||
|
|
||||||
|
JsonNode rootNode = mapper.readTree( jsonFile );
|
||||||
|
JsonNode historiesNode = rootNode.get( "history_versions" );
|
||||||
|
JsonNode historyNode = historiesNode.get( "1" );
|
||||||
|
|
||||||
|
JsonNode latestNode = historyNode.get( "latest" );
|
||||||
|
aui.setLatestVersion( new ComparableVersion( latestNode.get( "version" ).textValue() ) );
|
||||||
|
|
||||||
|
Iterator<Map.Entry<String,JsonNode>> fieldIt = latestNode.get( "urls" ).fields();
|
||||||
|
while ( fieldIt.hasNext() ) {
|
||||||
|
Map.Entry<String,JsonNode> entry = fieldIt.next();
|
||||||
|
aui.putLatestURL( entry.getKey(), entry.getValue().textValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode changelogNode = historyNode.get( "changelog" );
|
||||||
|
|
||||||
|
for ( JsonNode releaseNode : changelogNode ) {
|
||||||
|
String releaseVersion = releaseNode.get( "version" ).textValue();
|
||||||
|
|
||||||
|
List<String> changeList = new ArrayList<String>( releaseNode.get( "changes" ).size() );
|
||||||
|
for ( JsonNode changeNode : releaseNode.get( "changes" ) ) {
|
||||||
|
changeList.add( changeNode.textValue() );
|
||||||
|
}
|
||||||
|
aui.putChanges( new ComparableVersion( releaseVersion ), changeList );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( JsonProcessingException e ) {
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
catch ( IOException e ) {
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
if ( exception != null ) {
|
||||||
|
log.error( exception );
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aui;
|
||||||
|
}
|
||||||
|
}
|
|
@ -76,7 +76,7 @@ public class URLFetcher {
|
||||||
int responseCode = httpConn.getResponseCode();
|
int responseCode = httpConn.getResponseCode();
|
||||||
|
|
||||||
if ( responseCode == HttpURLConnection.HTTP_NOT_MODIFIED ) {
|
if ( responseCode == HttpURLConnection.HTTP_NOT_MODIFIED ) {
|
||||||
log.debug( String.format( "The server's \"%s\" has not been modified since the previous check.", httpConn.getURL().getFile() ) );
|
log.debug( String.format( "No need to update \"%s\", the server's copy has not been modified since the previous check.", localFile.getName() ) );
|
||||||
|
|
||||||
// Update the local file's timestamp as if it had downloaded.
|
// Update the local file's timestamp as if it had downloaded.
|
||||||
localFile.setLastModified( new Date().getTime() );
|
localFile.setLastModified( new Date().getTime() );
|
||||||
|
@ -98,7 +98,7 @@ public class URLFetcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log.error( String.format( "Download request failed: HTTP Code %d (%s).", responseCode, httpConn.getResponseMessage() ) );
|
log.error( String.format( "Download request failed for \"%s\": HTTP Code %d (%s).", httpConn.getURL(), responseCode, httpConn.getResponseMessage() ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import java.util.HashMap;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
|
@ -59,6 +60,7 @@ import javax.swing.event.ListSelectionListener;
|
||||||
import javax.swing.table.DefaultTableModel;
|
import javax.swing.table.DefaultTableModel;
|
||||||
|
|
||||||
import net.vhati.ftldat.FTLDat;
|
import net.vhati.ftldat.FTLDat;
|
||||||
|
import net.vhati.modmanager.core.AutoUpdateInfo;
|
||||||
import net.vhati.modmanager.core.ComparableVersion;
|
import net.vhati.modmanager.core.ComparableVersion;
|
||||||
import net.vhati.modmanager.core.FTLUtilities;
|
import net.vhati.modmanager.core.FTLUtilities;
|
||||||
import net.vhati.modmanager.core.HashObserver;
|
import net.vhati.modmanager.core.HashObserver;
|
||||||
|
@ -72,6 +74,7 @@ import net.vhati.modmanager.core.ModUtilities;
|
||||||
import net.vhati.modmanager.core.Report;
|
import net.vhati.modmanager.core.Report;
|
||||||
import net.vhati.modmanager.core.Report.ReportFormatter;
|
import net.vhati.modmanager.core.Report.ReportFormatter;
|
||||||
import net.vhati.modmanager.core.SlipstreamConfig;
|
import net.vhati.modmanager.core.SlipstreamConfig;
|
||||||
|
import net.vhati.modmanager.json.JacksonAutoUpdateReader;
|
||||||
import net.vhati.modmanager.json.JacksonGrognakCatalogReader;
|
import net.vhati.modmanager.json.JacksonGrognakCatalogReader;
|
||||||
import net.vhati.modmanager.json.URLFetcher;
|
import net.vhati.modmanager.json.URLFetcher;
|
||||||
import net.vhati.modmanager.ui.ChecklistTableModel;
|
import net.vhati.modmanager.ui.ChecklistTableModel;
|
||||||
|
@ -92,26 +95,30 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
private static final Logger log = LogManager.getLogger(ManagerFrame.class);
|
private static final Logger log = LogManager.getLogger(ManagerFrame.class);
|
||||||
|
|
||||||
public static final String CATALOG_URL = "https://raw.github.com/Vhati/Slipstream-Mod-Manager/master/skel_common/backup/current_catalog.json";
|
public static final String CATALOG_URL = "https://raw.github.com/Vhati/Slipstream-Mod-Manager/master/skel_common/backup/current_catalog.json";
|
||||||
public static final String AUTOUPDATE_URL = "https://raw.github.com/Vhati/Slipstream-Mod-Manager/master/auto-update.json";
|
public static final String APP_UPDATE_URL = "https://raw.github.com/Vhati/Slipstream-Mod-Manager/master/auto_update.json";
|
||||||
|
|
||||||
private File backupDir = new File( "./backup/" );
|
private File backupDir = new File( "./backup/" );
|
||||||
private File modsDir = new File( "./mods/" );
|
private File modsDir = new File( "./mods/" );
|
||||||
|
|
||||||
private int catalogFetchInterval = 7; // Days.
|
|
||||||
private File catalogFile = new File( backupDir, "current_catalog.json" );
|
private File catalogFile = new File( backupDir, "current_catalog.json" );
|
||||||
private File catalogETagFile = new File( backupDir, "current_catalog_etag.txt" );
|
private File catalogETagFile = new File( backupDir, "current_catalog_etag.txt" );
|
||||||
|
|
||||||
|
private File appUpdateFile = new File( backupDir, "auto_update.json" );
|
||||||
|
private File appUpdateETagFile = new File( backupDir, "auto_update_etag.txt" );
|
||||||
|
|
||||||
private SlipstreamConfig appConfig;
|
private SlipstreamConfig appConfig;
|
||||||
private String appName;
|
private String appName;
|
||||||
private ComparableVersion appVersion;
|
private ComparableVersion appVersion;
|
||||||
private String appURL;
|
private String appURL;
|
||||||
private String appAuthor;
|
private String appAuthor;
|
||||||
|
|
||||||
private NerfListener nerfListener = new NerfListener( this );
|
|
||||||
|
|
||||||
private HashMap<File,String> modFileHashes = new HashMap<File,String>();
|
private HashMap<File,String> modFileHashes = new HashMap<File,String>();
|
||||||
private ModDB modDB = new ModDB();
|
private ModDB modDB = new ModDB();
|
||||||
|
|
||||||
|
private AutoUpdateInfo appUpdateInfo = null;
|
||||||
|
|
||||||
|
private NerfListener nerfListener = new NerfListener( this );
|
||||||
|
|
||||||
private ChecklistTableModel<ModFileInfo> localModsTableModel;
|
private ChecklistTableModel<ModFileInfo> localModsTableModel;
|
||||||
private JTable localModsTable;
|
private JTable localModsTable;
|
||||||
|
|
||||||
|
@ -128,6 +135,7 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
private JButton toggleAllBtn;
|
private JButton toggleAllBtn;
|
||||||
private JButton validateBtn;
|
private JButton validateBtn;
|
||||||
private JButton modsFolderBtn;
|
private JButton modsFolderBtn;
|
||||||
|
private JButton updateBtn;
|
||||||
private JSplitPane splitPane;
|
private JSplitPane splitPane;
|
||||||
private ModInfoArea infoArea;
|
private ModInfoArea infoArea;
|
||||||
|
|
||||||
|
@ -198,9 +206,16 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
modsFolderBtn.setEnabled( Desktop.isDesktopSupported() );
|
modsFolderBtn.setEnabled( Desktop.isDesktopSupported() );
|
||||||
modActionsPanel.add( modsFolderBtn );
|
modActionsPanel.add( modsFolderBtn );
|
||||||
|
|
||||||
|
updateBtn = new JButton("Update");
|
||||||
|
updateBtn.setMargin( actionInsets );
|
||||||
|
updateBtn.addMouseListener( new StatusbarMouseListener( this, String.format( "Show info about the latest version of %s.", appName ) ) );
|
||||||
|
updateBtn.addActionListener(this);
|
||||||
|
updateBtn.setEnabled( false );
|
||||||
|
modActionsPanel.add( updateBtn );
|
||||||
|
|
||||||
topPanel.add( modActionsPanel, BorderLayout.EAST );
|
topPanel.add( modActionsPanel, BorderLayout.EAST );
|
||||||
|
|
||||||
JButton[] actionBtns = new JButton[] {patchBtn, toggleAllBtn, validateBtn, modsFolderBtn };
|
JButton[] actionBtns = new JButton[] {patchBtn, toggleAllBtn, validateBtn, modsFolderBtn, updateBtn };
|
||||||
int actionBtnWidth = Integer.MIN_VALUE;
|
int actionBtnWidth = Integer.MIN_VALUE;
|
||||||
int actionBtnHeight = Integer.MIN_VALUE;
|
int actionBtnHeight = Integer.MIN_VALUE;
|
||||||
for ( JButton btn : actionBtns ) {
|
for ( JButton btn : actionBtns ) {
|
||||||
|
@ -402,6 +417,7 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
List<String> preferredOrder = loadModOrder();
|
List<String> preferredOrder = loadModOrder();
|
||||||
rescanMods( preferredOrder );
|
rescanMods( preferredOrder );
|
||||||
|
|
||||||
|
int catalogUpdateInterval = appConfig.getPropertyAsInt( "update_catalog", 0 );
|
||||||
boolean needNewCatalog = false;
|
boolean needNewCatalog = false;
|
||||||
|
|
||||||
if ( catalogFile.exists() ) {
|
if ( catalogFile.exists() ) {
|
||||||
|
@ -409,15 +425,17 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
ModDB currentDB = JacksonGrognakCatalogReader.parse( catalogFile );
|
ModDB currentDB = JacksonGrognakCatalogReader.parse( catalogFile );
|
||||||
if ( currentDB != null ) modDB = currentDB;
|
if ( currentDB != null ) modDB = currentDB;
|
||||||
|
|
||||||
// Check if the downloaded catalog is stale.
|
if ( catalogUpdateInterval > 0 ) {
|
||||||
Date catalogDate = new Date( catalogFile.lastModified() );
|
// Check if the downloaded catalog is stale.
|
||||||
Calendar cal = Calendar.getInstance();
|
Date catalogDate = new Date( catalogFile.lastModified() );
|
||||||
cal.add( Calendar.DATE, catalogFetchInterval * -1 );
|
Calendar cal = Calendar.getInstance();
|
||||||
if ( catalogDate.before( cal.getTime() ) ) {
|
cal.add( Calendar.DATE, catalogUpdateInterval * -1 );
|
||||||
log.debug( String.format( "Catalog is older than %d days.", catalogFetchInterval ) );
|
if ( catalogDate.before( cal.getTime() ) ) {
|
||||||
needNewCatalog = true;
|
log.debug( String.format( "Catalog is older than %d days.", catalogUpdateInterval ) );
|
||||||
} else {
|
needNewCatalog = true;
|
||||||
log.debug( "Catalog isn't stale yet." );
|
} else {
|
||||||
|
log.debug( "Catalog isn't stale yet." );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -426,8 +444,7 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't update if the user doesn't want to.
|
// Don't update if the user doesn't want to.
|
||||||
String updatesAllowed = appConfig.getProperty( "update_catalog", "false" );
|
if ( catalogUpdateInterval <= 0 ) needNewCatalog = false;
|
||||||
if ( !updatesAllowed.equals("true") ) needNewCatalog = false;
|
|
||||||
|
|
||||||
if ( needNewCatalog ) {
|
if ( needNewCatalog ) {
|
||||||
Runnable fetchTask = new Runnable() {
|
Runnable fetchTask = new Runnable() {
|
||||||
|
@ -441,11 +458,56 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
Thread fetchThread = new Thread( fetchTask );
|
Thread fetchThread = new Thread( fetchTask );
|
||||||
fetchThread.start();
|
fetchThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int appUpdateInterval = appConfig.getPropertyAsInt( "update_app", 0 );
|
||||||
|
boolean needAppUpdate = false;
|
||||||
|
|
||||||
|
if ( appUpdateFile.exists() ) {
|
||||||
|
// Load the info first, before downloading.
|
||||||
|
AutoUpdateInfo aui = JacksonAutoUpdateReader.parse( appUpdateFile );
|
||||||
|
if ( aui != null ) {
|
||||||
|
appUpdateInfo = aui;
|
||||||
|
updateBtn.setEnabled( appVersion.compareTo(appUpdateInfo.getLatestVersion()) < 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( appUpdateInterval > 0 ) {
|
||||||
|
// Check if the app update info is stale.
|
||||||
|
Date catalogDate = new Date( appUpdateFile.lastModified() );
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.add( Calendar.DATE, catalogUpdateInterval * -1 );
|
||||||
|
if ( catalogDate.before( cal.getTime() ) ) {
|
||||||
|
log.debug( String.format( "App update info is older than %d days.", appUpdateInterval ) );
|
||||||
|
needAppUpdate = true;
|
||||||
|
} else {
|
||||||
|
log.debug( "App update info isn't stale yet." );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// App update file doesn't exist.
|
||||||
|
needAppUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't update if the user doesn't want to.
|
||||||
|
if ( appUpdateInterval <= 0 ) needAppUpdate = false;
|
||||||
|
|
||||||
|
if ( needAppUpdate ) {
|
||||||
|
Runnable fetchTask = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
boolean fetched = URLFetcher.refetchURL( APP_UPDATE_URL, appUpdateFile, appUpdateETagFile );
|
||||||
|
|
||||||
|
if ( fetched ) reloadAppUpdateInfo();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Thread fetchThread = new Thread( fetchTask );
|
||||||
|
fetchThread.start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reparses and replace the downloaded ModDB catalog. (thread-safe)
|
* Reparses and replaces the downloaded ModDB catalog. (thread-safe)
|
||||||
*/
|
*/
|
||||||
public void reloadCatalog() {
|
public void reloadCatalog() {
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@ -459,6 +521,24 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reparses info about available app updates. (thread-safe)
|
||||||
|
*/
|
||||||
|
public void reloadAppUpdateInfo() {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if ( appUpdateFile.exists() ) {
|
||||||
|
AutoUpdateInfo aui = JacksonAutoUpdateReader.parse( appUpdateFile );
|
||||||
|
if ( aui != null ) {
|
||||||
|
appUpdateInfo = aui;
|
||||||
|
updateBtn.setEnabled( appVersion.compareTo(appUpdateInfo.getLatestVersion()) < 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a mod list with names sorted in a preferred order.
|
* Returns a mod list with names sorted in a preferred order.
|
||||||
|
@ -579,6 +659,42 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
infoArea.setDescription( appName, appAuthor, appVersion.toString(), appURL, body );
|
infoArea.setDescription( appName, appAuthor, appVersion.toString(), appURL, body );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showAppUpdateInfo() {
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
|
||||||
|
for ( Map.Entry<ComparableVersion,List<String>> entry : appUpdateInfo.getChangelog().entrySet() ) {
|
||||||
|
if ( appVersion.compareTo( entry.getKey() ) >= 0 ) break;
|
||||||
|
|
||||||
|
if ( buf.length() > 0 ) buf.append( "\n" );
|
||||||
|
buf.append( entry.getKey() ).append( ":\n" );
|
||||||
|
|
||||||
|
for ( String change : entry.getValue() ) {
|
||||||
|
buf.append( " - " ).append( change ).append( "\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
infoArea.clear();
|
||||||
|
infoArea.appendTitleText( "What's New\n" );
|
||||||
|
infoArea.appendRegularText( String.format( "Version %s: ", appUpdateInfo.getLatestVersion().toString() ) );
|
||||||
|
boolean first = true;
|
||||||
|
for ( Map.Entry<String,String> entry : appUpdateInfo.getLatestURLs().entrySet() ) {
|
||||||
|
if ( !first ) infoArea.appendRegularText( " " );
|
||||||
|
infoArea.appendRegularText( "[" );
|
||||||
|
infoArea.appendLinkText( entry.getValue(), entry.getKey() );
|
||||||
|
infoArea.appendRegularText( "]" );
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
infoArea.appendRegularText( "\n" );
|
||||||
|
infoArea.appendRegularText( "\n" );
|
||||||
|
infoArea.appendRegularText( buf.toString() );
|
||||||
|
infoArea.setCaretPosition( 0 );
|
||||||
|
}
|
||||||
|
catch ( Exception e ) {
|
||||||
|
log.error( "Error filling info text area.", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows info about a local mod in the text area.
|
* Shows info about a local mod in the text area.
|
||||||
*/
|
*/
|
||||||
|
@ -720,6 +836,9 @@ public class ManagerFrame extends JFrame implements ActionListener, HashObserver
|
||||||
log.error( "Error opening mods/ folder.", f );
|
log.error( "Error opening mods/ folder.", f );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ( source == updateBtn ) {
|
||||||
|
showAppUpdateInfo();
|
||||||
|
}
|
||||||
else if ( source == rescanMenuItem ) {
|
else if ( source == rescanMenuItem ) {
|
||||||
setStatusText( "" );
|
setStatusText( "" );
|
||||||
if ( rescanMenuItem.isEnabled() == false ) return;
|
if ( rescanMenuItem.isEnabled() == false ) return;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue