add update checker (not configurable yet)

This commit is contained in:
Wirlaburla 2024-07-12 05:56:18 -05:00
parent 4a2a992b04
commit bfcb21769e
4 changed files with 289 additions and 1 deletions

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="Ernie">
<grid id="27dc6" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1" binding="frameContainer">
<margin top="10" left="5" bottom="5" right="5"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="b5829" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="A new update for Firestar is available!"/>
</properties>
</component>
<grid id="6bf91" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="5" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="61273" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="56086" class="javax.swing.JButton" binding="notnowbtn">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="2" indent="0" use-parent-layout="false">
<minimum-size width="150" height="-1"/>
<preferred-size width="150" height="-1"/>
<maximum-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<text value="No Thanks"/>
</properties>
</component>
<component id="a3535" class="javax.swing.JButton" binding="surebtn">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="2" indent="0" use-parent-layout="false">
<minimum-size width="150" height="-1"/>
<preferred-size width="150" height="-1"/>
<maximum-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<text value="Open in Browser"/>
</properties>
</component>
<vspacer id="9f407">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
<component id="6acad" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="If you want to stay on this version,"/>
</properties>
</component>
<component id="a73c6" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="you can disable this notification in the Options."/>
</properties>
</component>
</children>
</grid>
<scrollpane id="1a774">
<constraints>
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="1efd0" class="javax.swing.JEditorPane" binding="changelogDisplay">
<constraints/>
<properties/>
</component>
</children>
</scrollpane>
</children>
</grid>
</form>

View File

@ -0,0 +1,166 @@
/*
* Firestar Mod Manager
* Copyright (C) 2024 bonkmaykr
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
import java.awt.Desktop;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.WindowConstants;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class Ernie implements ActionListener, Runnable {
// Base URL for Gitea API
public static final String gitapi = "https://git.worlio.com/api/v1/repos/bonkmaykr/firestar";
public static final String changelog = "https://bonkmaykr.worlio.com/http/firestar/changelog.htm";
private HttpURLConnection httpConn;
private int contentLength;
private InputStream inputStream;
private JFrame frame = new JFrame();
private JPanel frameContainer;
private JEditorPane changelogDisplay;
private JButton notnowbtn;
private JButton surebtn;
public boolean backgroundDone = false;
public void run() {
byte[] urlraw = new Ernie().getFile(gitapi+"/releases?draft=false&pre-release=false");
if (urlraw.length <= 0) {
JOptionPane.showMessageDialog(frame, "Internal Error: Couldn't check for updates.", "Fatal Error", JOptionPane.ERROR_MESSAGE);
} else {
try {
JSONArray releases = new JSONArray(new String(urlraw, Charset.forName("utf-8")));
if (releases.length() >= 1 && ((JSONObject)releases.get(0)).get("tag_name") != Main.vtag) {
frame.add(frameContainer);
notnowbtn.addActionListener(this);
surebtn.addActionListener(this);
changelogDisplay.setEditable(false);
changelogDisplay.setPage(changelog);
frame.setTitle("An update is available!");
frame.setSize(450, 400);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setAlwaysOnTop(true);
frame.setVisible(true);
} else { System.out.println("Problem??"); }
} catch (IOException ex) {
Logger.getLogger(Ernie.class.getName()).log(Level.SEVERE, null, ex);
} catch (JSONException ex) {
Logger.getLogger(Ernie.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
if (actionEvent.getSource() == notnowbtn) {frame.dispose();} else
if (actionEvent.getSource() == surebtn) {
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
String releasepage = "https://git.worlio.com/bonkmaykr/firestar/releases";
try {
Desktop.getDesktop().browse(new URI(releasepage));
} catch (Exception ex) {
JOptionPane.showMessageDialog(frame, "Couldn't open your web browser!\nYou can check out the latest release at the URL below:\n"+releasepage, "Error", JOptionPane.ERROR_MESSAGE);
}
}
}
}
byte[] getFile(String url) {
try {
URL fileURL = new URL(url);
httpConn = (HttpURLConnection) fileURL.openConnection();
int response = httpConn.getResponseCode();
if (response == HttpURLConnection.HTTP_OK) {
contentLength = httpConn.getContentLength();
inputStream = httpConn.getInputStream();
} else if (response == 404) {
throw new IOException(
"File missing from remote server.");
} else {
throw new IOException(
"Unexpected response; Server replied with " + response);
}
ErnieDownloader ed = new ErnieDownloader(this, url, httpConn.getContentLength());
ed.doInBackground();
while (!backgroundDone) {}
inputStream.close();
httpConn.disconnect();
frame.dispose();
return ed.output;
} catch (MalformedURLException e) {
JOptionPane.showMessageDialog(frame, "Internal Error: URL given to Ernie is not valid.\nGet a programmer!", "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.dispose();
return new byte[]{};
} catch (Exception e) {
JOptionPane.showMessageDialog(frame, "Error: " + e.getMessage(), "Fatal Error", JOptionPane.ERROR_MESSAGE);
frame.dispose();
return new byte[]{};
}
}
}
class ErnieDownloader extends SwingWorker<Void, Void> {
private static final int BUFFER_SIZE = 4096;
private String downloadURL;
private final Ernie gui;
public byte[] output;
public ErnieDownloader(Ernie gui, String downloadURL, long size) {
this.gui = gui;
this.downloadURL = downloadURL;
}
@Override
protected Void doInBackground() throws Exception {
BufferedInputStream in = new BufferedInputStream(new URL(downloadURL).openStream());
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] data = new byte[16384];
int x;
while ((x = in.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, x);
}
output = buffer.toByteArray();
in.close();
gui.backgroundDone = true;
return null;
}
}

View File

@ -31,6 +31,7 @@ public class Main {
// Build Information // Build Information
public static final String vstr = "Release 1.3"; public static final String vstr = "Release 1.3";
public static final String vcode = "Tetsuo"; public static final String vcode = "Tetsuo";
public static final String vtag = "tetsuo-1.3";
public static final int vint = 1; public static final int vint = 1;
// User Settings // User Settings
@ -41,6 +42,7 @@ public class Main {
public static boolean repatch; //are we in compat mode? public static boolean repatch; //are we in compat mode?
public static boolean windows; //True = windows public static boolean windows; //True = windows
public static int confvint = vint; public static int confvint = vint;
public static boolean checkUpdates;
//public static String psarc; //sdk location //public static String psarc; //sdk location
public enum ArcTarget { // install target for 2048, type used by downloader public enum ArcTarget { // install target for 2048, type used by downloader
@ -136,6 +138,7 @@ public class Main {
container.put("HDpath", "TODO"); // proposed hd/fury support for ps3, will use very simplified Fast Mode due to less difficulty installing container.put("HDpath", "TODO"); // proposed hd/fury support for ps3, will use very simplified Fast Mode due to less difficulty installing
container.put("safemode", repatch); container.put("safemode", repatch);
container.put("isWin32", windows); container.put("isWin32", windows);
container.put("checkUpdates", checkUpdates);
container.put("currentPlaylist", "TODO"); // proposed feature: store separate mod lists in lists/ to load/save later? container.put("currentPlaylist", "TODO"); // proposed feature: store separate mod lists in lists/ to load/save later?
try { try {
@ -153,6 +156,11 @@ public class Main {
outpath = container.get("2048path").toString(); outpath = container.get("2048path").toString();
repatch = (boolean) container.get("safemode"); repatch = (boolean) container.get("safemode");
windows = (boolean) container.get("isWin32"); windows = (boolean) container.get("isWin32");
try {
checkUpdates = (boolean) container.get("checkUpdates");
} catch (JSONException e) {
checkUpdates = true;
}
} catch (IOException e) { } catch (IOException e) {
System.out.println("ERROR: Failed to load firestar.conf"); System.out.println("ERROR: Failed to load firestar.conf");
System.out.println(e.getMessage()); System.out.println(e.getMessage());
@ -167,6 +175,11 @@ public class Main {
outpath = container.get("2048path").toString(); outpath = container.get("2048path").toString();
repatch = (boolean) container.get("safemode"); repatch = (boolean) container.get("safemode");
windows = (boolean) container.get("isWin32"); windows = (boolean) container.get("isWin32");
try {
checkUpdates = (boolean) container.get("checkUpdates");
} catch (JSONException e) {
checkUpdates = true;
}
} catch (Exception e) { } catch (Exception e) {
JOptionPane.showMessageDialog(w.frame, "Firestar couldn't load your config file. Tread lightly.\n\n" + e.getMessage(), "Critical Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(w.frame, "Firestar couldn't load your config file. Tread lightly.\n\n" + e.getMessage(), "Critical Error", JOptionPane.ERROR_MESSAGE);
System.out.println("ERROR: Failed to load firestar.conf"); System.out.println("ERROR: Failed to load firestar.conf");

View File

@ -113,6 +113,7 @@ public class MissPiggy implements ActionListener {
helpMenu.add(new JMenuItem("Source Code")); //replace with Website 'screwgravity.net' and 'Issue Tracker' gitea later helpMenu.add(new JMenuItem("Source Code")); //replace with Website 'screwgravity.net' and 'Issue Tracker' gitea later
helpMenu.add(new JMenuItem("License")); helpMenu.add(new JMenuItem("License"));
helpMenu.add(new JSeparator()); helpMenu.add(new JSeparator());
helpMenu.add(new JMenuItem("Check for Updates"));
helpMenu.add(new JMenuItem("About Firestar")); helpMenu.add(new JMenuItem("About Firestar"));
menuBar.add(fileMenu); menuBar.add(fileMenu);
@ -138,6 +139,7 @@ public class MissPiggy implements ActionListener {
helpMenu.getItem(2).addActionListener(this); helpMenu.getItem(2).addActionListener(this);
helpMenu.getItem(3).addActionListener(this); helpMenu.getItem(3).addActionListener(this);
helpMenu.getItem(5).addActionListener(this); helpMenu.getItem(5).addActionListener(this);
helpMenu.getItem(6).addActionListener(this);
deployButton.addActionListener(this); deployButton.addActionListener(this);
importButton.addActionListener(this); importButton.addActionListener(this);
@ -181,6 +183,8 @@ public class MissPiggy implements ActionListener {
frame.setLayout(new GridLayout()); frame.setLayout(new GridLayout());
frame.setLocationRelativeTo(null); frame.setLocationRelativeTo(null);
if (Main.checkUpdates) { StartErnie(); }
frame.setVisible(true); frame.setVisible(true);
} }
@ -307,6 +311,11 @@ public class MissPiggy implements ActionListener {
createSelectionEventListener(); createSelectionEventListener();
} }
private void StartErnie() {
Ernie e = new Ernie();
new Thread(e).start();
}
private ListSelectionListener whenItemSelected() { private ListSelectionListener whenItemSelected() {
return null; return null;
} }
@ -356,7 +365,8 @@ public class MissPiggy implements ActionListener {
JOptionPane.showMessageDialog(frame, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(frame, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
} }
} else } else
if (actionEvent.getSource() == helpMenu.getItem(5)) {new Rowlf().displayAboutScreen();} if (actionEvent.getSource() == helpMenu.getItem(5)) {StartErnie();} else
if (actionEvent.getSource() == helpMenu.getItem(6)) {new Rowlf().displayAboutScreen();}
} }
// Will likely split the below functions into separate classes to work with intellij GUI designer. // Will likely split the below functions into separate classes to work with intellij GUI designer.