GUI: reworked error dialog:

* added client version and improved stack trace;
* added copy to clipboard button;
* added button to create new issue on github (with prefilled form fields like error text);
* added GUI size settings support;
* some old errors now use new error dialog instead message box;
This commit is contained in:
Oleg Agafonov 2024-07-05 17:42:36 +04:00
parent 2631b31b8a
commit 6c0f7ebb90
11 changed files with 284 additions and 125 deletions

View file

@ -1,6 +1,7 @@
package mage.client;
import mage.MageException;
import mage.cards.RateCard;
import mage.cards.action.ActionCallback;
import mage.cards.decks.Deck;
import mage.cards.repository.CardRepository;
@ -38,7 +39,6 @@ import mage.client.util.stats.UpdateMemUsageTask;
import mage.components.ImagePanel;
import mage.components.ImagePanelStyle;
import mage.constants.PlayerAction;
import mage.cards.RateCard;
import mage.interfaces.MageClient;
import mage.interfaces.callback.CallbackClient;
import mage.interfaces.callback.ClientCallback;
@ -72,14 +72,13 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.prefs.Preferences;
import java.util.stream.Collectors;
/**
* Client app
@ -1356,11 +1355,52 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
userRequestDialog.showDialog(userRequestMessage);
}
public void showErrorDialog(final String title, final String message) {
public void showErrorDialog(String errorType, Exception e) {
String errorMessage = e.getMessage();
if (errorMessage == null || errorMessage.isEmpty() || errorMessage.equals("Null")) {
errorMessage = e.getClass().getSimpleName() + " - look at server or client logs for more details";
}
int maxLines = 10;
String newLine = "\n";
// main error
String mainError = Arrays.stream(e.getStackTrace())
.map(StackTraceElement::toString)
.limit(maxLines)
.collect(Collectors.joining(newLine));
if (e.getStackTrace().length > maxLines) {
mainError += newLine + "and other " + (e.getStackTrace().length - maxLines) + " lines";
}
// root error
String rootError = "";
Throwable root = ThreadUtils.findRootException(e);
if (root != e) {
rootError = Arrays.stream(root.getStackTrace())
.map(StackTraceElement::toString)
.limit(maxLines)
.collect(Collectors.joining(newLine));
if (root.getStackTrace().length > maxLines) {
rootError += newLine + "and other " + (root.getStackTrace().length - maxLines) + " lines";
}
}
String allErrors = mainError;
if (!rootError.isEmpty()) {
allErrors += newLine + "Root caused by:" + newLine + rootError;
}
showErrorDialog(errorType,
e.getClass().getSimpleName(),
errorMessage + newLine + newLine + "Stack trace:" + newLine + allErrors
);
}
public void showErrorDialog(String errorType, String errorTitle, String errorText) {
if (SwingUtilities.isEventDispatchThread()) {
errorDialog.showDialog(title, message);
errorDialog.showDialog(errorType, errorTitle, errorText);
} else {
SwingUtilities.invokeLater(() -> errorDialog.showDialog(title, message));
SwingUtilities.invokeLater(() -> errorDialog.showDialog(errorType, errorTitle, errorText));
}
}
@ -1587,7 +1627,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
.filter(Component::isVisible)
.filter(p -> p instanceof MagePane)
.map(p -> (MagePane) p)
.filter(p-> !onlyActive || p.isActiveTable())
.filter(p -> !onlyActive || p.isActiveTable())
.count();
}
@ -1813,21 +1853,14 @@ public class MageFrame extends javax.swing.JFrame implements MageClient {
}
}
this.connectDialog.changeGUISize();
this.errorDialog.changeGUISize();
updateTooltipContainerSizes();
}
public static void showWhatsNewDialog() {
try {
URI newsURI = new URI("https://jaydi85.github.io/xmage-web-news/news.html");
Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
desktop.browse(newsURI);
}
} catch (URISyntaxException e) {
LOGGER.error("URI Syntax error when creating news link", e);
} catch (IOException e) {
LOGGER.error("IOException while loading news page", e);
}
AppUtil.openUrlInBrowser("https://jaydi85.github.io/xmage-web-news/news.html");
}
public boolean isGameFrameActive(UUID gameId) {

View file

@ -6,6 +6,7 @@ import mage.client.dialog.PreferencesDialog;
import mage.client.util.gui.ColorsChooser;
import mage.client.util.gui.FastSearchUtil;
import mage.client.util.sets.ConstructedFormats;
import org.apache.log4j.Logger;
import javax.swing.*;
import javax.swing.border.CompoundBorder;
@ -25,6 +26,8 @@ import static mage.cards.decks.DeckFormats.XMAGE;
*/
public class DeckGeneratorDialog {
private static final Logger logger = Logger.getLogger(DeckGeneratorDialog.class);
private static JDialog dlg;
private static String selectedColors;
private static JComboBox cbSets, cbDeckSize, cbCMC;
@ -332,7 +335,8 @@ public class DeckGeneratorDialog {
cleanUp();
return tmp.getAbsolutePath();
} catch (Exception e) {
MageFrame.getInstance().showError("Couldn't generate deck. Try again.");
logger.error("Can't generate deck due " + e, e);
MageFrame.getInstance().showErrorDialog("CLIENT - error on random deck save", e);
}
return null;
}

View file

@ -5,10 +5,9 @@ import mage.cards.decks.DeckFormats;
import mage.cards.decks.exporter.DeckExporter;
import mage.client.MageFrame;
import mage.client.dialog.MageDialog;
import mage.client.util.AppUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyEvent;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
@ -62,15 +61,6 @@ public class DeckExportClipboardDialog extends MageDialog {
this.setVisible(true);
}
private void setClipboardStringData(String text) {
try {
StringSelection data = new StringSelection(text);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(data, data);
} catch (HeadlessException e) {
//e.printStackTrace();
}
}
private void onOK() {
onCopyToClipboard();
this.removeDialog();
@ -95,7 +85,7 @@ public class DeckExportClipboardDialog extends MageDialog {
}
private void onCopyToClipboard() {
setClipboardStringData(editData.getText());
AppUtil.setClipboardData(editData.getText());
}
/**

View file

@ -5,6 +5,7 @@ import mage.choices.ChoiceImpl;
import mage.client.MageFrame;
import mage.client.SessionHandler;
import mage.client.preference.MagePreferences;
import mage.client.util.AppUtil;
import mage.client.util.ClientDefaultSettings;
import mage.client.util.gui.countryBox.CountryItemEditor;
import mage.remote.Connection;
@ -738,13 +739,7 @@ public class ConnectDialog extends MageDialog {
}//GEN-LAST:event_btnFlagSearchActionPerformed
private void btnCheckStatusActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCheckStatusActionPerformed
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
try {
Desktop.getDesktop().browse(new URI("http://xmage.today/servers/"));
} catch (Exception e) {
//
}
}
AppUtil.openUrlInBrowser("http://xmage.today/servers/");
}//GEN-LAST:event_btnCheckStatusActionPerformed
private void btnWhatsNewActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnWhatsNewActionPerformed

View file

@ -1,4 +1,4 @@
<?xml version="1.1" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JInternalFrameFormInfo">
<Properties>
@ -26,19 +26,17 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane2" pref="647" max="32767" attributes="1"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane1" pref="647" max="32767" attributes="1"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Component id="pnlInfo" alignment="0" max="32767" attributes="1"/>
<Component id="pnlError" alignment="0" max="32767" attributes="1"/>
<Group type="102" alignment="1" attributes="0">
<Component id="btnOK" min="-2" pref="60" max="-2" attributes="0"/>
<Component id="btnCopyToClipboard" min="-2" pref="202" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="btnOpenGithub" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="btnOK" min="-2" pref="96" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -46,11 +44,15 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<Component id="jScrollPane2" pref="43" max="32767" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="237" max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="btnOK" min="-2" max="-2" attributes="0"/>
<Component id="pnlInfo" min="-2" pref="73" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="pnlError" pref="225" max="32767" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="btnOK" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnCopyToClipboard" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="btnOpenGithub" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
</Group>
</Group>
@ -59,26 +61,32 @@
<SubComponents>
<Component class="javax.swing.JButton" name="btnOK">
<Properties>
<Property name="text" type="java.lang.String" value="OK"/>
<Property name="text" type="java.lang.String" value="Close"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[59, 33]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[59, 33]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[59, 33]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnOKActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Container class="javax.swing.JScrollPane" name="pnlError">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="lblMessage">
<Component class="javax.swing.JTextArea" name="textError">
<Properties>
<Property name="columns" type="int" value="20"/>
<Property name="editable" type="boolean" value="false"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Arial" size="10" style="0"/>
</Property>
<Property name="columns" type="int" value="20"/>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="5"/>
<Property name="wrapStyleWord" type="boolean" value="true"/>
@ -86,25 +94,43 @@
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<Container class="javax.swing.JScrollPane" name="pnlInfo">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="jTextArea1">
<Component class="javax.swing.JTextArea" name="textInfo">
<Properties>
<Property name="columns" type="int" value="20"/>
<Property name="editable" type="boolean" value="false"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Arial" size="10" style="0"/>
</Property>
<Property name="rows" type="int" value="2"/>
<Property name="text" type="java.lang.String" value="An error has occurred on the MAGE server. Your last action will be rollbacked.&#xa;Please post the following report here: http://www.slightlymagic.net/forum/posting.php?mode=reply&amp;f=70&amp;t=3116"/>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value="[bug report instructions]"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="btnCopyToClipboard">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/buttons/copy_24.png"/>
</Property>
<Property name="text" type="java.lang.String" value="Copy error to clipboard"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnCopyToClipboardActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="btnOpenGithub">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/buttons/search_24.png"/>
</Property>
<Property name="text" type="java.lang.String" value="Open github and create bug report"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnOpenGithubActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>

View file

@ -1,21 +1,40 @@
package mage.client.dialog;
import mage.client.MageFrame;
import mage.client.util.AppUtil;
import mage.client.util.GUISizeHelper;
import mage.util.CardUtil;
/**
* Game GUI: error dialog
* GUI: error dialog with copyable error message
*
* @author BetaSteward_at_googlemail.com
* @author JayDi85
*/
public class ErrorDialog extends MageDialog {
/** Creates new form ErrorDialog */
private final String GITHUB_ISSUES_PAGE = "https://github.com/magefree/mage/issues";
public ErrorDialog() {
initComponents();
}
public void showDialog(String title, String message) {
this.setTitle(title);
this.lblMessage.setText(message);
this.lblMessage.setCaretPosition(0);
public void showDialog(String errorType, String errorTitle, String errorText) {
this.textInfo.setText("You can report bugs and create new feature requests at github: " + GITHUB_ISSUES_PAGE);
this.textInfo.setCaretPosition(0);
String fullTitle = errorType + " - " + errorTitle;
this.setTitle(fullTitle);
// add additional info
String fullError = "Error type: " + fullTitle + "\n"
+ "Client version: " + MageFrame.getInstance().getVersion().toString() + "\n"
+ "\n"
+ errorText;
this.textError.setText(fullError);
this.textError.setCaretPosition(0);
this.changeGUISize();
this.pack();
this.revalidate();
this.repaint();
@ -23,6 +42,31 @@ public class ErrorDialog extends MageDialog {
this.setVisible(true);
}
@Override
public void changeGUISize() {
super.changeGUISize();
this.textError.setFont(GUISizeHelper.menuFont);
this.textInfo.setFont(GUISizeHelper.menuFont);
this.btnCopyToClipboard.setFont(GUISizeHelper.menuFont);
this.btnOpenGithub.setFont(GUISizeHelper.menuFont);
this.btnOK.setFont(GUISizeHelper.menuFont);
}
private void openGithub() {
// create new issue on github with predefined fields
String title = this.getTitle();
String body = this.textError.getText();
String labels = "bug";
String url = String.format("%s/new?labels=%s&title=%s&body=%s",
GITHUB_ISSUES_PAGE,
CardUtil.urlEncode(labels),
CardUtil.urlEncode(title),
CardUtil.urlEncode(body)
);
AppUtil.openUrlInBrowser(url);
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
@ -33,31 +77,53 @@ public class ErrorDialog extends MageDialog {
private void initComponents() {
btnOK = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
lblMessage = new javax.swing.JTextArea();
jScrollPane2 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();
pnlError = new javax.swing.JScrollPane();
textError = new javax.swing.JTextArea();
pnlInfo = new javax.swing.JScrollPane();
textInfo = new javax.swing.JTextArea();
btnCopyToClipboard = new javax.swing.JButton();
btnOpenGithub = new javax.swing.JButton();
setResizable(true);
setTitle("Error");
btnOK.setText("OK");
btnOK.addActionListener(this::btnOKActionPerformed);
btnOK.setText("Close");
btnOK.setMaximumSize(new java.awt.Dimension(59, 33));
btnOK.setMinimumSize(new java.awt.Dimension(59, 33));
btnOK.setPreferredSize(new java.awt.Dimension(59, 33));
btnOK.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnOKActionPerformed(evt);
}
});
lblMessage.setColumns(20);
lblMessage.setEditable(false);
lblMessage.setFont(new java.awt.Font("Arial", 0, 10)); // NOI18N
lblMessage.setLineWrap(true);
lblMessage.setRows(5);
lblMessage.setWrapStyleWord(true);
jScrollPane1.setViewportView(lblMessage);
textError.setEditable(false);
textError.setColumns(20);
textError.setLineWrap(true);
textError.setRows(5);
textError.setWrapStyleWord(true);
pnlError.setViewportView(textError);
jTextArea1.setColumns(20);
jTextArea1.setEditable(false);
jTextArea1.setFont(new java.awt.Font("Arial", 0, 10)); // NOI18N
jTextArea1.setRows(2);
jTextArea1.setText("An error has occurred on the MAGE server. Your last action will be rollbacked.\nPlease post the following report here: https://github.com/magefree/mage/issues");
jScrollPane2.setViewportView(jTextArea1);
textInfo.setEditable(false);
textInfo.setLineWrap(true);
textInfo.setText("[bug report instructions]");
pnlInfo.setViewportView(textInfo);
btnCopyToClipboard.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/copy_24.png"))); // NOI18N
btnCopyToClipboard.setText("Copy error to clipboard");
btnCopyToClipboard.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCopyToClipboardActionPerformed(evt);
}
});
btnOpenGithub.setIcon(new javax.swing.ImageIcon(getClass().getResource("/buttons/search_24.png"))); // NOI18N
btnOpenGithub.setText("Open github and create bug report");
btnOpenGithub.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnOpenGithubActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
@ -66,25 +132,28 @@ public class ErrorDialog extends MageDialog {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 647, Short.MAX_VALUE)
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 647, Short.MAX_VALUE)
.addContainerGap())
.addComponent(pnlInfo)
.addComponent(pnlError)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(btnOK, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())))
.addComponent(btnCopyToClipboard, javax.swing.GroupLayout.PREFERRED_SIZE, 202, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnOpenGithub)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(btnOK, javax.swing.GroupLayout.PREFERRED_SIZE, 96, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(6, 6, 6)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 43, Short.MAX_VALUE)
.addGap(18, 18, 18)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE)
.addComponent(pnlInfo, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pnlError, javax.swing.GroupLayout.DEFAULT_SIZE, 225, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(btnOK)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnOK, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnCopyToClipboard)
.addComponent(btnOpenGithub))
.addGap(12, 12, 12))
);
@ -95,13 +164,23 @@ public class ErrorDialog extends MageDialog {
this.hideDialog();
}//GEN-LAST:event_btnOKActionPerformed
private void btnCopyToClipboardActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCopyToClipboardActionPerformed
AppUtil.setClipboardData(textError.getText());
}//GEN-LAST:event_btnCopyToClipboardActionPerformed
private void btnOpenGithubActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOpenGithubActionPerformed
openGithub();
}//GEN-LAST:event_btnOpenGithubActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnCopyToClipboard;
private javax.swing.JButton btnOK;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea jTextArea1;
private javax.swing.JTextArea lblMessage;
private javax.swing.JButton btnOpenGithub;
private javax.swing.JScrollPane pnlError;
private javax.swing.JScrollPane pnlInfo;
private javax.swing.JTextArea textError;
private javax.swing.JTextArea textInfo;
// End of variables declaration//GEN-END:variables
}

View file

@ -786,9 +786,9 @@ public class NewTableDialog extends MageDialog {
this.repaint();
}
private void handleError(Exception ex) {
logger.fatal("Error loading deck", ex);
MageFrame.getInstance().showErrorDialog("Error loading deck", ex.getMessage());
private void handleError(Exception e) {
logger.fatal("Can't join table due " + e, e);
MageFrame.getInstance().showErrorDialog("CLIENT - error on join table", e);
}
public void showDialog(UUID roomId) {

View file

@ -29,6 +29,8 @@ import java.awt.event.KeyEvent;
import java.util.*;
/**
* Client side implementation (process commands from a server)
*
* @author BetaSteward_at_googlemail.com, JayDi85
*/
public class CallbackClientImpl implements CallbackClient {
@ -266,7 +268,7 @@ public class CallbackClientImpl implements CallbackClient {
}
case GAME_ERROR: {
frame.showErrorDialog("Game Error", (String) callback.getData());
frame.showErrorDialog("SERVER", "game error", (String) callback.getData());
break;
}
@ -693,12 +695,8 @@ public class CallbackClientImpl implements CallbackClient {
});
}
private void handleException(Exception ex) {
logger.fatal("Client error\n", ex);
String errorMessage = ex.getMessage();
if (errorMessage == null || errorMessage.isEmpty() || errorMessage.equals("Null")) {
errorMessage = ex.getClass().getSimpleName() + " - look at server or client logs for more details";
}
frame.showError("Server's error: " + errorMessage);
private void handleException(Exception e) {
logger.fatal("General error\n", e);
frame.showErrorDialog("General error", e);
}
}

View file

@ -1,14 +1,24 @@
package mage.client.util;
import mage.client.MageFrame;
import org.apache.log4j.Logger;
import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.UUID;
/**
* Helper class for client side app
*
* @author JayDi85
*/
public class AppUtil {
private static final Logger logger = Logger.getLogger(AppUtil.class);
/**
* Application is active in operation system (got user focus)
*/
@ -25,4 +35,29 @@ public class AppUtil {
public static boolean isGameActive(UUID gameId) {
return MageFrame.getInstance().isGameFrameActive(gameId);
}
/**
* Save text to clipboard
*/
public static void setClipboardData(String text) {
try {
StringSelection data = new StringSelection(text);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(data, data);
} catch (HeadlessException ignore) {
}
}
public static void openUrlInBrowser(String url) {
Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
try {
URI uri = new URI(url);
desktop.browse(uri);
} catch (IOException | URISyntaxException e) {
logger.error("Can't open url in browser: " + url, e);
}
} else {
logger.error("Can't open url in browser: non supported desktop mode");
}
}
}

View file

@ -53,8 +53,7 @@ public class URLHandler {
try {
URI uri = new URI(url);
desktop.browse(uri);
} catch (IOException | URISyntaxException ex) {
// do nothing
} catch (IOException | URISyntaxException ignore) {
}
}
}

View file

@ -1648,12 +1648,12 @@ public class SessionImpl implements Session {
private void handleMageException(MageException ex) {
logger.fatal("Server error", ex);
client.showError(ex.getMessage());
client.showError("Server error: " + ex.getMessage());
}
private void handleGameException(GameException ex) {
logger.warn(ex.getMessage());
client.showError(ex.getMessage());
client.showError("Game error: " + ex.getMessage());
}
@Override