mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
GUI: added old what's new page (build-in window on startup);
This commit is contained in:
parent
e04306c51f
commit
8f7abe2dc5
12 changed files with 540 additions and 24 deletions
|
|
@ -144,6 +144,24 @@
|
||||||
<version>1.17</version>
|
<version>1.17</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- svg support END -->
|
<!-- svg support END -->
|
||||||
|
|
||||||
|
<!-- JavaFX support (build-in browser) START -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjfx</groupId>
|
||||||
|
<artifactId>javafx-controls</artifactId>
|
||||||
|
<version>11.0.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjfx</groupId>
|
||||||
|
<artifactId>javafx-swing</artifactId>
|
||||||
|
<version>11.0.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjfx</groupId>
|
||||||
|
<artifactId>javafx-web</artifactId>
|
||||||
|
<version>11.0.2</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- JavaFX support (build-in browser) END -->
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<!-- to get the reference to local repository with com\googlecode\jspf\jspf-core\0.9.1\ -->
|
<!-- to get the reference to local repository with com\googlecode\jspf\jspf-core\0.9.1\ -->
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,8 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
@ -109,6 +111,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
||||||
private static CallbackClient callbackClient;
|
private static CallbackClient callbackClient;
|
||||||
private static final Preferences PREFS = Preferences.userNodeForPackage(MageFrame.class);
|
private static final Preferences PREFS = Preferences.userNodeForPackage(MageFrame.class);
|
||||||
private final JPanel fakeTopPanel;
|
private final JPanel fakeTopPanel;
|
||||||
|
private WhatsNewDialog whatsNewDialog; // can be null
|
||||||
private JLabel title;
|
private JLabel title;
|
||||||
private Rectangle titleRectangle;
|
private Rectangle titleRectangle;
|
||||||
private static final MageVersion VERSION = new MageVersion(MageFrame.class);
|
private static final MageVersion VERSION = new MageVersion(MageFrame.class);
|
||||||
|
|
@ -306,6 +309,15 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
||||||
errorDialog.setLocation(100, 100);
|
errorDialog.setLocation(100, 100);
|
||||||
desktopPane.add(errorDialog, JLayeredPane.MODAL_LAYER);
|
desktopPane.add(errorDialog, JLayeredPane.MODAL_LAYER);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.whatsNewDialog = new WhatsNewDialog();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
// example: JavaFX is not supported on old MacOS with OpenJDK
|
||||||
|
// https://bugs.openjdk.java.net/browse/JDK-8202132
|
||||||
|
LOGGER.error("JavaFX is not supported by your system. What's new page will be disabled.", e);
|
||||||
|
this.whatsNewDialog = null;
|
||||||
|
}
|
||||||
|
|
||||||
PING_SENDER_EXECUTOR.scheduleAtFixedRate(SessionHandler::ping, TablesPanel.PING_SERVER_SECS, TablesPanel.PING_SERVER_SECS, TimeUnit.SECONDS);
|
PING_SENDER_EXECUTOR.scheduleAtFixedRate(SessionHandler::ping, TablesPanel.PING_SERVER_SECS, TablesPanel.PING_SERVER_SECS, TimeUnit.SECONDS);
|
||||||
|
|
||||||
updateMemUsageTask = new UpdateMemUsageTask(jMemUsageLabel);
|
updateMemUsageTask = new UpdateMemUsageTask(jMemUsageLabel);
|
||||||
|
|
@ -384,6 +396,11 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
||||||
}
|
}
|
||||||
setWindowTitle();
|
setWindowTitle();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// run what's new checks (loading in background)
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
showWhatsNewDialog(false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bootstrapSetsAndFormats() {
|
private void bootstrapSetsAndFormats() {
|
||||||
|
|
@ -1861,8 +1878,14 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
|
||||||
updateTooltipContainerSizes();
|
updateTooltipContainerSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void showWhatsNewDialog() {
|
public void showWhatsNewDialog(boolean forceToShowPage) {
|
||||||
AppUtil.openUrlInBrowser("https://jaydi85.github.io/xmage-web-news/news.html");
|
if (whatsNewDialog != null) {
|
||||||
|
// build-in browser
|
||||||
|
whatsNewDialog.checkUpdatesAndShow(forceToShowPage);
|
||||||
|
} else {
|
||||||
|
// system browser
|
||||||
|
AppUtil.openUrlInSystemBrowser(WhatsNewDialog.WHATS_NEW_PAGE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGameFrameActive(UUID gameId) {
|
public boolean isGameFrameActive(UUID gameId) {
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ public class AboutDialog extends MageDialog {
|
||||||
}//GEN-LAST:event_btnOkActionPerformed
|
}//GEN-LAST:event_btnOkActionPerformed
|
||||||
|
|
||||||
private void btnWhatsNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnWhatsNewActionPerformed
|
private void btnWhatsNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnWhatsNewActionPerformed
|
||||||
MageFrame.showWhatsNewDialog();
|
MageFrame.getInstance().showWhatsNewDialog(true);
|
||||||
}//GEN-LAST:event_btnWhatsNewActionPerformed
|
}//GEN-LAST:event_btnWhatsNewActionPerformed
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import mage.utils.StreamUtils;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
|
|
@ -739,11 +738,11 @@ public class ConnectDialog extends MageDialog {
|
||||||
}//GEN-LAST:event_btnFlagSearchActionPerformed
|
}//GEN-LAST:event_btnFlagSearchActionPerformed
|
||||||
|
|
||||||
private void btnCheckStatusActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheckStatusActionPerformed
|
private void btnCheckStatusActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheckStatusActionPerformed
|
||||||
AppUtil.openUrlInBrowser("http://xmage.today/servers/");
|
AppUtil.openUrlInSystemBrowser("http://xmage.today/servers/");
|
||||||
}//GEN-LAST:event_btnCheckStatusActionPerformed
|
}//GEN-LAST:event_btnCheckStatusActionPerformed
|
||||||
|
|
||||||
private void btnWhatsNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnWhatsNewActionPerformed
|
private void btnWhatsNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnWhatsNewActionPerformed
|
||||||
MageFrame.showWhatsNewDialog();
|
MageFrame.getInstance().showWhatsNewDialog(true);
|
||||||
}//GEN-LAST:event_btnWhatsNewActionPerformed
|
}//GEN-LAST:event_btnWhatsNewActionPerformed
|
||||||
|
|
||||||
private void btnFindMainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFindMainActionPerformed
|
private void btnFindMainActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFindMainActionPerformed
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ public class ErrorDialog extends MageDialog {
|
||||||
CardUtil.urlEncode(title),
|
CardUtil.urlEncode(title),
|
||||||
CardUtil.urlEncode(body)
|
CardUtil.urlEncode(body)
|
||||||
);
|
);
|
||||||
AppUtil.openUrlInBrowser(url);
|
AppUtil.openUrlInSystemBrowser(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This method is called from within the constructor to
|
/** This method is called from within the constructor to
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo">
|
||||||
|
<SyntheticProperties>
|
||||||
|
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||||
|
</SyntheticProperties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="panelData" max="32767" attributes="0"/>
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Component id="buttonRefresh" min="-2" pref="100" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="32767" attributes="0"/>
|
||||||
|
<Component id="buttonCancel" min="-2" pref="100" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="panelData" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
|
<Component id="buttonCancel" alignment="3" min="-2" pref="30" max="-2" attributes="0"/>
|
||||||
|
<Component id="buttonRefresh" alignment="3" min="-2" pref="30" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JButton" name="buttonCancel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" value="Close"/>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonCancelActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="buttonRefresh">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" value="Refresh"/>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonRefreshActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JPanel" name="panelData">
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
||||||
411
Mage.Client/src/main/java/mage/client/dialog/WhatsNewDialog.java
Normal file
411
Mage.Client/src/main/java/mage/client/dialog/WhatsNewDialog.java
Normal file
|
|
@ -0,0 +1,411 @@
|
||||||
|
package mage.client.dialog;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.value.ChangeListener;
|
||||||
|
import javafx.beans.value.ObservableValue;
|
||||||
|
import javafx.concurrent.Worker;
|
||||||
|
import javafx.embed.swing.JFXPanel;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.web.WebEngine;
|
||||||
|
import javafx.scene.web.WebView;
|
||||||
|
import mage.client.MageFrame;
|
||||||
|
import mage.client.remote.XmageURLConnection;
|
||||||
|
import mage.client.util.AppUtil;
|
||||||
|
import mage.client.util.GUISizeHelper;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.w3c.dom.events.EventListener;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.net.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App GUI: what's new dialog with latest news.
|
||||||
|
* Uses system browser. Shows on app's start after page ready.
|
||||||
|
*
|
||||||
|
* @author JayDi85
|
||||||
|
*/
|
||||||
|
public class WhatsNewDialog extends MageDialog {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(WhatsNewDialog.class);
|
||||||
|
|
||||||
|
// cookies store tester: https://setcookie.net/
|
||||||
|
public static final String WHATS_NEW_PAGE = "https://jaydi85.github.io/xmage-web-news/news.html";
|
||||||
|
private static final String WHATS_NEW_VERSION_PAGE = "https://jaydi85.github.io/xmage-web-news/news_version.html"; // increment version=123 to auto-shown for all users
|
||||||
|
private static final int WHATS_NEW_MAX_LOAD_TIMEOUT_SECS = 20; // timeout for page loading (example: no network)
|
||||||
|
private static final boolean WHATS_NEW_DEBUG_ENABLE_CONTROLS = false; // default: false, enable it for debug/test
|
||||||
|
|
||||||
|
private final JFXPanel fxPanel;
|
||||||
|
private WebView webView;
|
||||||
|
private WebEngine engine;
|
||||||
|
private boolean isPageReady = false;
|
||||||
|
|
||||||
|
private SwingWorker<Void, Void> lastWaitingWorker = null;
|
||||||
|
|
||||||
|
public WhatsNewDialog() {
|
||||||
|
initComponents();
|
||||||
|
this.setDefaultCloseOperation(HIDE_ON_CLOSE);
|
||||||
|
|
||||||
|
fxPanel = new JFXPanel();
|
||||||
|
panelData.add(fxPanel);
|
||||||
|
webView = null;
|
||||||
|
engine = null;
|
||||||
|
|
||||||
|
createWebView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showDialog() {
|
||||||
|
this.setModal(true);
|
||||||
|
this.setResizable(true);
|
||||||
|
|
||||||
|
getRootPane().setDefaultButton(buttonCancel);
|
||||||
|
this.setSize(GUISizeHelper.dialogGuiScaleSize(new Dimension(800, 600)));
|
||||||
|
|
||||||
|
// windows settings
|
||||||
|
MageFrame.getDesktop().remove(this);
|
||||||
|
if (this.isModal()) {
|
||||||
|
MageFrame.getDesktop().add(this, JLayeredPane.MODAL_LAYER);
|
||||||
|
} else {
|
||||||
|
MageFrame.getDesktop().add(this, JLayeredPane.PALETTE_LAYER);
|
||||||
|
}
|
||||||
|
this.makeWindowCentered();
|
||||||
|
|
||||||
|
// Close on "ESC"
|
||||||
|
registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
|
||||||
|
|
||||||
|
this.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final SwingWorker<Void, Void> checkUpdatesWorker = new SwingWorker<Void, Void>() {
|
||||||
|
private String newVersion = "";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void doInBackground() {
|
||||||
|
// download version
|
||||||
|
String newsVersion = XmageURLConnection.downloadText(WHATS_NEW_VERSION_PAGE);
|
||||||
|
if (newsVersion.startsWith("version=")) {
|
||||||
|
newVersion = newsVersion.substring("version=".length());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void done() {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
String oldVersion = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEWS_PAGE_LAST_VERSION, "1");
|
||||||
|
|
||||||
|
boolean isHaveUpdates = newVersion.isEmpty() || !newVersion.equals(oldVersion);
|
||||||
|
if (isHaveUpdates) {
|
||||||
|
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEWS_PAGE_LAST_VERSION, newVersion);
|
||||||
|
startBrowser(WHATS_NEW_PAGE);
|
||||||
|
startWaitingWorker();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private void startWaitingWorker() {
|
||||||
|
// wait page ready and open it on complete
|
||||||
|
if (this.lastWaitingWorker != null) {
|
||||||
|
this.lastWaitingWorker.cancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastWaitingWorker = new SwingWorker<Void, Void>() {
|
||||||
|
@Override
|
||||||
|
public Void doInBackground() {
|
||||||
|
// waiting page loading
|
||||||
|
int waitedSecs = 0;
|
||||||
|
while (!isPageReady && waitedSecs <= WHATS_NEW_MAX_LOAD_TIMEOUT_SECS) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
waitedSecs++;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void done() {
|
||||||
|
if (isPageReady) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
showDialog();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.lastWaitingWorker.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkUpdatesAndShow(boolean forceToShowPage) {
|
||||||
|
// lazy loading in background
|
||||||
|
// shows it on page ready or by force
|
||||||
|
|
||||||
|
if (!forceToShowPage) {
|
||||||
|
// checks version -> start loading -> show on isPageReady
|
||||||
|
checkUpdatesWorker.execute();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// direct open
|
||||||
|
if (isPageReady) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
showDialog();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
checkUpdatesWorker.cancel(true);
|
||||||
|
startBrowser(WHATS_NEW_PAGE);
|
||||||
|
startWaitingWorker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store cookies in preferences
|
||||||
|
*/
|
||||||
|
private static class PersistentCookieStore implements CookieStore, Runnable {
|
||||||
|
private final CookieStore store;
|
||||||
|
|
||||||
|
public PersistentCookieStore() {
|
||||||
|
// improved store with save/load feature
|
||||||
|
store = new CookieManager().getCookieStore();
|
||||||
|
|
||||||
|
// load on startup
|
||||||
|
loadFromPrefs();
|
||||||
|
|
||||||
|
// save on app close
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveToPrefs() {
|
||||||
|
// convert cookie to version 1, so it will get full data before save
|
||||||
|
// example: xxx
|
||||||
|
List<String> v1Cookies = store.getCookies().stream()
|
||||||
|
.peek(c -> c.setVersion(1))
|
||||||
|
.map(HttpCookie::toString)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
PreferencesDialog.saveValue(PreferencesDialog.KEY_NEWS_PAGE_COOKIES, new Gson().toJson(v1Cookies));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadFromPrefs() {
|
||||||
|
Type type = new TypeToken<List<String>>() {
|
||||||
|
}.getType();
|
||||||
|
try {
|
||||||
|
String savedData = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEWS_PAGE_COOKIES, "");
|
||||||
|
List<String> savedCookies = new Gson().fromJson(savedData, type);
|
||||||
|
if (savedCookies != null) {
|
||||||
|
savedCookies.forEach(savedCookie -> {
|
||||||
|
// load as version 1, but convert back to version 0 for compatibility
|
||||||
|
List<HttpCookie> v1Cookies = HttpCookie.parse("set-cookie2:" + savedCookie.replace("$", ""));
|
||||||
|
v1Cookies.forEach(realCookie -> {
|
||||||
|
realCookie.setVersion(0);
|
||||||
|
store.add(URI.create(realCookie.getDomain()), realCookie);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("News page: catch broken cookies", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
saveToPrefs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(URI uri, HttpCookie cookie) {
|
||||||
|
store.add(uri, cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HttpCookie> get(URI uri) {
|
||||||
|
return store.get(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HttpCookie> getCookies() {
|
||||||
|
return store.getCookies();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<URI> getURIs() {
|
||||||
|
return store.getURIs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(URI uri, HttpCookie cookie) {
|
||||||
|
return store.remove(uri, cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll() {
|
||||||
|
return store.removeAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createWebView() {
|
||||||
|
|
||||||
|
// init web engine and events
|
||||||
|
// https://docs.oracle.com/javafx/2/swing/swing-fx-interoperability.htm
|
||||||
|
|
||||||
|
// workaround for empty dialog on 2+ opens - keep jfx thread alive (by default it exits on parent window close)
|
||||||
|
// see https://stackoverflow.com/a/32104851
|
||||||
|
Platform.setImplicitExit(false);
|
||||||
|
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
webView = new WebView();
|
||||||
|
engine = webView.getEngine();
|
||||||
|
engine.setJavaScriptEnabled(true);
|
||||||
|
engine.setUserAgent(engine.getUserAgent() + " " + XmageURLConnection.getDefaultUserAgent()); // keep system user-agent too
|
||||||
|
if (!WHATS_NEW_DEBUG_ENABLE_CONTROLS) {
|
||||||
|
webView.contextMenuEnabledProperty().setValue(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
CookieManager cookieManager = new CookieManager(new PersistentCookieStore(), CookiePolicy.ACCEPT_ALL);
|
||||||
|
CookieHandler.setDefault(cookieManager);
|
||||||
|
|
||||||
|
// on error
|
||||||
|
engine.getLoadWorker().exceptionProperty().addListener(new ChangeListener<Throwable>() {
|
||||||
|
@Override
|
||||||
|
public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {
|
||||||
|
if (engine.getLoadWorker().getState() == Worker.State.FAILED
|
||||||
|
|| engine.getLoadWorker().getState() == Worker.State.CANCELLED) {
|
||||||
|
LOGGER.error("News page: can't load page", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// on completed
|
||||||
|
engine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
|
||||||
|
@Override
|
||||||
|
public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) {
|
||||||
|
if (newState != Worker.State.SUCCEEDED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WHATS_NEW_DEBUG_ENABLE_CONTROLS) {
|
||||||
|
// 1. open all page links in real browser, not build-in window
|
||||||
|
EventListener listener = new EventListener() {
|
||||||
|
@Override
|
||||||
|
public void handleEvent(org.w3c.dom.events.Event ev) {
|
||||||
|
String href = ((org.w3c.dom.Element) ev.getTarget()).getAttribute("href");
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
// open browser (must check href on null anyway)
|
||||||
|
if (href != null && href.startsWith("http")) {
|
||||||
|
SwingUtilities.invokeLater(() -> AppUtil.openUrlInSystemBrowser(href));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
org.w3c.dom.Document doc = engine.getDocument();
|
||||||
|
org.w3c.dom.NodeList listA = doc.getElementsByTagName("a");
|
||||||
|
for (int i = 0; i < listA.getLength(); i++) {
|
||||||
|
((org.w3c.dom.events.EventTarget) listA.item(i)).addEventListener("click", listener, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. all done, build-in browser ready to show
|
||||||
|
isPageReady = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fxPanel.setScene(new Scene(webView));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startBrowser(final String startingUrl) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
String link = startingUrl;
|
||||||
|
if (!link.startsWith("http")) {
|
||||||
|
link = "http://" + link;
|
||||||
|
}
|
||||||
|
engine.load(link);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onCancel() {
|
||||||
|
this.hideDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
buttonCancel = new JButton();
|
||||||
|
buttonRefresh = new JButton();
|
||||||
|
panelData = new JPanel();
|
||||||
|
|
||||||
|
buttonCancel.setText("Close");
|
||||||
|
buttonCancel.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
buttonCancelActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonRefresh.setText("Refresh");
|
||||||
|
buttonRefresh.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
buttonRefreshActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
panelData.setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
GroupLayout layout = new GroupLayout(getContentPane());
|
||||||
|
getContentPane().setLayout(layout);
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(panelData, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addComponent(buttonRefresh, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addComponent(buttonCancel, GroupLayout.PREFERRED_SIZE, 100, GroupLayout.PREFERRED_SIZE)))
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addComponent(panelData, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||||
|
.addComponent(buttonCancel, GroupLayout.PREFERRED_SIZE, 30, GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addComponent(buttonRefresh, GroupLayout.PREFERRED_SIZE, 30, GroupLayout.PREFERRED_SIZE))
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
|
||||||
|
pack();
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed
|
||||||
|
onCancel();
|
||||||
|
}//GEN-LAST:event_buttonCancelActionPerformed
|
||||||
|
|
||||||
|
private void buttonRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonRefreshActionPerformed
|
||||||
|
startBrowser(WHATS_NEW_PAGE);
|
||||||
|
}//GEN-LAST:event_buttonRefreshActionPerformed
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private JButton buttonCancel;
|
||||||
|
private JButton buttonRefresh;
|
||||||
|
private JPanel panelData;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
||||||
|
|
@ -141,10 +141,13 @@ public class XmageURLConnection {
|
||||||
this.connection.setRequestProperty("Accept-Encoding", "gzip");
|
this.connection.setRequestProperty("Accept-Encoding", "gzip");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.connection.setRequestProperty("User-Agent", getDefaultUserAgent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDefaultUserAgent() {
|
||||||
// user agent due standard notation User-Agent: <product> / <product-version> <comment>
|
// user agent due standard notation User-Agent: <product> / <product-version> <comment>
|
||||||
// warning, dot not add os, language and other details
|
// warning, dot not add os, language and other details
|
||||||
this.connection.setRequestProperty("User-Agent", String.format("XMage/%s build: %s",
|
return String.format("XMage/%s build: %s", version.toString(false), version.getBuildTime());
|
||||||
version.toString(false), version.getBuildTime()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1752,7 +1752,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
}//GEN-LAST:event_btnStateFinishedActionPerformed
|
}//GEN-LAST:event_btnStateFinishedActionPerformed
|
||||||
|
|
||||||
private void buttonWhatsNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonWhatsNewActionPerformed
|
private void buttonWhatsNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonWhatsNewActionPerformed
|
||||||
MageFrame.showWhatsNewDialog();
|
MageFrame.getInstance().showWhatsNewDialog(true);
|
||||||
}//GEN-LAST:event_buttonWhatsNewActionPerformed
|
}//GEN-LAST:event_buttonWhatsNewActionPerformed
|
||||||
|
|
||||||
private void btnQuickStart2PlayerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartDuelActionPerformed
|
private void btnQuickStart2PlayerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartDuelActionPerformed
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ public class AppUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void openUrlInBrowser(String url) {
|
public static void openUrlInSystemBrowser(String url) {
|
||||||
Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
|
Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
|
||||||
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
|
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
package mage.client.util;
|
package mage.client.util;
|
||||||
|
|
||||||
import java.awt.Desktop;
|
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
|
|
@ -48,14 +44,7 @@ public class URLHandler {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.getClickCount() > 0) {
|
if (e.getClickCount() > 0) {
|
||||||
if (Desktop.isDesktopSupported()) {
|
AppUtil.openUrlInSystemBrowser(url);
|
||||||
Desktop desktop = Desktop.getDesktop();
|
|
||||||
try {
|
|
||||||
URI uri = new URI(url);
|
|
||||||
desktop.browse(uri);
|
|
||||||
} catch (IOException | URISyntaxException ignore) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
2
pom.xml
2
pom.xml
|
|
@ -343,7 +343,7 @@
|
||||||
<!-- json support -->
|
<!-- json support -->
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.8.8</version>
|
<version>2.11.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<!-- extended lib from google (collections, io, etc) -->
|
<!-- extended lib from google (collections, io, etc) -->
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue