Added tabs to the ui

This commit is contained in:
Lenni0451 2023-01-06 21:43:56 +01:00
parent 0b0e498fc7
commit d036d37bd0
6 changed files with 491 additions and 206 deletions

View file

@ -6,4 +6,4 @@ org.gradle.configureondemand=true
# Project properties
maven_name=ViaProxy
maven_group=net.raphimc
maven_version=3.0.1
maven_version=3.0.2

View file

@ -0,0 +1,29 @@
package net.raphimc.viaproxy.ui;
import javax.swing.*;
public abstract class AUITab {
protected final ViaProxyUI frame;
private final String name;
private final JPanel contentPane;
public AUITab(final ViaProxyUI frame, final String name) {
this.frame = frame;
this.name = name;
this.contentPane = new JPanel();
this.contentPane.setLayout(null);
this.init(this.contentPane);
}
public void add(final JTabbedPane tabbedPane) {
tabbedPane.addTab(this.name, this.contentPane);
}
protected abstract void init(final JPanel contentPane);
public void setReady() {
}
}

View file

@ -1,54 +1,40 @@
package net.raphimc.viaproxy.ui;
import com.formdev.flatlaf.FlatDarkLaf;
import com.google.common.net.HostAndPort;
import net.raphimc.vialegacy.util.VersionEnum;
import net.lenni0451.reflect.stream.RStream;
import net.raphimc.viaproxy.ViaProxy;
import net.raphimc.viaproxy.cli.options.Options;
import net.raphimc.viaproxy.ui.impl.GeneralTab;
import net.raphimc.viaproxy.ui.impl.OnlineModeTab;
import net.raphimc.viaproxy.util.logging.Logger;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
public class ViaProxyUI extends JFrame {
private final JPanel contentPane = new JPanel();
private final JTabbedPane contentPane = new JTabbedPane();
private final List<AUITab> tabs = new ArrayList<>();
private final GeneralTab generalTab = new GeneralTab(this);
private final OnlineModeTab onlineModeTab = new OnlineModeTab(this);
private ImageIcon icon;
private JTextField serverAddress;
private JComboBox<VersionEnum> serverVersion;
private JSpinner bindPort;
private JComboBox<String> authMethod;
private JCheckBox betaCraftAuth;
private JCheckBox proxyOnlineMode;
private JLabel stateLabel;
private JButton stateButton;
public ViaProxyUI() {
this.applyDarkFlatLafTheme();
Thread.setDefaultUncaughtExceptionHandler((t, e) -> this.showException(e));
this.setLookAndFeel();
this.loadIcons();
this.initWindow();
this.initElements();
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
Logger.LOGGER.error("Caught exception in thread " + t.getName(), e);
final StringBuilder builder = new StringBuilder("An error occurred:\n");
builder.append("[").append(e.getClass().getSimpleName()).append("] ").append(e.getMessage()).append("\n");
for (StackTraceElement element : e.getStackTrace()) {
builder.append(element.toString()).append("\n");
}
this.showError(builder.toString());
});
this.initTabs();
SwingUtilities.updateComponentTreeUI(this);
this.setVisible(true);
}
private void applyDarkFlatLafTheme() {
private void setLookAndFeel() {
try {
UIManager.setLookAndFeel(new FlatDarkLaf());
} catch (Throwable t) {
@ -64,195 +50,44 @@ public class ViaProxyUI extends JFrame {
this.setTitle("ViaProxy v" + ViaProxy.VERSION);
this.setIconImage(this.icon.getImage());
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(500, 370);
this.setSize(500, 403);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.setContentPane(this.contentPane);
}
private void initElements() {
this.contentPane.setLayout(null);
{
JLabel titleLabel = new JLabel("ViaProxy");
titleLabel.setBounds(0, 0, 500, 50);
titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
titleLabel.setFont(titleLabel.getFont().deriveFont(30F));
this.contentPane.add(titleLabel);
}
{
JLabel copyrightLabel = new JLabel("© RK_01 & Lenni0451");
copyrightLabel.setBounds(360, 10, 500, 20);
this.contentPane.add(copyrightLabel);
}
{
JLabel discordLabel = new JLabel("Discord");
discordLabel.setBounds(10, 10, 45, 20);
discordLabel.setForeground(new Color(124, 171, 241));
discordLabel.addMouseListener(new MouseAdapter() {
private static final String LINK = "https://viaproxy.raphimc.net";
@Override
public void mouseReleased(MouseEvent e) {
try {
Desktop.getDesktop().browse(new URI(LINK));
} catch (Throwable t) {
showInfo("Couldn't open the link :(\nHere it is for you: " + LINK);
}
}
});
this.contentPane.add(discordLabel);
}
{
JLabel addressLabel = new JLabel("Server Address:");
addressLabel.setBounds(10, 50, 100, 20);
this.contentPane.add(addressLabel);
this.serverAddress = new JTextField();
this.serverAddress.setBounds(10, 70, 465, 20);
this.contentPane.add(this.serverAddress);
}
{
JLabel serverVersionLabel = new JLabel("Server Version:");
serverVersionLabel.setBounds(10, 100, 100, 20);
this.contentPane.add(serverVersionLabel);
this.serverVersion = new JComboBox<>(VersionEnum.RENDER_VERSIONS.toArray(new VersionEnum[0]));
this.serverVersion.setBounds(10, 120, 465, 20);
this.serverVersion.setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value instanceof VersionEnum) {
VersionEnum version = (VersionEnum) value;
value = version.getName();
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
});
this.contentPane.add(this.serverVersion);
}
{
JLabel bindPortLabel = new JLabel("Local Port:");
bindPortLabel.setBounds(10, 150, 100, 20);
this.contentPane.add(bindPortLabel);
this.bindPort = new JSpinner(new SpinnerNumberModel(25568, 1, 65535, 1));
this.bindPort.setBounds(10, 170, 465, 20);
this.bindPort.setEditor(new JSpinner.NumberEditor(this.bindPort, "#"));
((JSpinner.DefaultEditor) this.bindPort.getEditor()).getTextField().setHorizontalAlignment(SwingConstants.LEFT);
this.contentPane.add(this.bindPort);
}
{
JLabel authMethodLabel = new JLabel("Server Online Mode Auth Method:");
authMethodLabel.setBounds(10, 200, 250, 20);
this.contentPane.add(authMethodLabel);
this.authMethod = new JComboBox<>(new String[]{"OpenAuthMod"});
this.authMethod.setBounds(10, 220, 465, 20);
this.contentPane.add(this.authMethod);
}
{
this.betaCraftAuth = new JCheckBox("BetaCraft Auth (Classic)");
this.betaCraftAuth.setBounds(10, 250, 150, 20);
this.contentPane.add(this.betaCraftAuth);
}
{
this.proxyOnlineMode = new JCheckBox("Proxy Online Mode");
this.proxyOnlineMode.setBounds(350, 250, 465, 20);
this.contentPane.add(this.proxyOnlineMode);
}
{
this.stateLabel = new JLabel();
this.stateLabel.setBounds(14, 280, 465, 20);
this.stateLabel.setVisible(false);
this.contentPane.add(this.stateLabel);
}
{
this.stateButton = new JButton("Loading ViaProxy...");
this.stateButton.setBounds(10, 300, 465, 20);
this.stateButton.addActionListener(e -> {
if (this.stateButton.getText().equalsIgnoreCase("Start")) this.start();
else if (this.stateButton.getText().equalsIgnoreCase("Stop")) this.stop();
});
this.stateButton.setEnabled(false);
this.contentPane.add(this.stateButton);
}
}
private void setComponentsEnabled(final boolean state) {
this.serverAddress.setEnabled(state);
this.serverVersion.setEnabled(state);
this.bindPort.setEnabled(state);
this.authMethod.setEnabled(state);
this.betaCraftAuth.setEnabled(state);
this.proxyOnlineMode.setEnabled(state);
}
private void updateStateLabel() {
this.stateLabel.setText("ViaProxy is running! Connect with Minecraft 1.7+ to 127.0.0.1:" + this.bindPort.getValue());
this.stateLabel.setVisible(true);
}
private void start() {
this.setComponentsEnabled(false);
this.stateButton.setEnabled(false);
this.stateButton.setText("Starting...");
new Thread(() -> {
final String serverAddress = this.serverAddress.getText();
final VersionEnum serverVersion = (VersionEnum) this.serverVersion.getSelectedItem();
final int bindPort = (int) this.bindPort.getValue();
final String authMethod = (String) this.authMethod.getSelectedItem();
final boolean betaCraftAuth = this.betaCraftAuth.isSelected();
final boolean proxyOnlineMode = this.proxyOnlineMode.isSelected();
try {
final HostAndPort hostAndPort = HostAndPort.fromString(serverAddress);
Options.BIND_ADDRESS = "127.0.0.1";
Options.BIND_PORT = bindPort;
Options.ONLINE_MODE = proxyOnlineMode;
Options.CONNECT_ADDRESS = hostAndPort.getHost();
Options.CONNECT_PORT = hostAndPort.getPortOrDefault(25565);
Options.PROTOCOL_VERSION = serverVersion;
Options.OPENAUTHMOD_AUTH = true;
Options.BETACRAFT_AUTH = betaCraftAuth;
ViaProxy.startProxy();
SwingUtilities.invokeLater(() -> {
this.updateStateLabel();
this.stateButton.setEnabled(true);
this.stateButton.setText("Stop");
private void initTabs() {
RStream
.of(this)
.fields()
.filter(field -> AUITab.class.isAssignableFrom(field.type()))
.forEach(field -> {
AUITab tab = field.get();
this.tabs.add(field.get());
tab.add(this.contentPane);
});
} catch (Throwable e) {
SwingUtilities.invokeLater(() -> {
this.showError("Invalid server address!");
this.setComponentsEnabled(true);
this.stateButton.setEnabled(true);
this.stateButton.setText("Start");
this.stateLabel.setVisible(false);
});
}
}).start();
}
private void stop() {
ViaProxy.stopProxy();
this.stateLabel.setVisible(false);
this.stateButton.setText("Start");
this.setComponentsEnabled(true);
}
public void setReady() {
SwingUtilities.invokeLater(() -> {
this.stateButton.setText("Start");
this.stateButton.setEnabled(true);
});
for (AUITab tab : this.tabs) tab.setReady();
}
public void openURL(final String url) {
try {
Desktop.getDesktop().browse(new URI(url));
} catch (Throwable t) {
this.showInfo("Couldn't open the link :(\nHere it is for you: " + url);
}
}
public void showException(final Throwable t) {
Logger.LOGGER.error("Caught exception in thread " + Thread.currentThread().getName(), t);
StringBuilder builder = new StringBuilder("An error occurred:\n");
builder.append("[").append(t.getClass().getSimpleName()).append("] ").append(t.getMessage()).append("\n");
for (StackTraceElement element : t.getStackTrace()) builder.append(element.toString()).append("\n");
this.showError(builder.toString());
}
public void showInfo(final String message) {
this.showNotification(message, JOptionPane.INFORMATION_MESSAGE);

View file

@ -0,0 +1,204 @@
package net.raphimc.viaproxy.ui.impl;
import com.google.common.net.HostAndPort;
import net.raphimc.vialegacy.util.VersionEnum;
import net.raphimc.viaproxy.ViaProxy;
import net.raphimc.viaproxy.cli.options.Options;
import net.raphimc.viaproxy.ui.AUITab;
import net.raphimc.viaproxy.ui.ViaProxyUI;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class GeneralTab extends AUITab {
private JTextField serverAddress;
private JComboBox<VersionEnum> serverVersion;
private JSpinner bindPort;
private JComboBox<String> authMethod;
private JCheckBox betaCraftAuth;
private JCheckBox proxyOnlineMode;
private JLabel stateLabel;
private JButton stateButton;
public GeneralTab(final ViaProxyUI frame) {
super(frame, "General");
}
@Override
protected void init(JPanel contentPane) {
{
JLabel titleLabel = new JLabel("ViaProxy");
titleLabel.setBounds(0, 0, 500, 50);
titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
titleLabel.setFont(titleLabel.getFont().deriveFont(30F));
contentPane.add(titleLabel);
}
{
JLabel copyrightLabel = new JLabel("© RK_01 & Lenni0451");
copyrightLabel.setBounds(360, 10, 500, 20);
contentPane.add(copyrightLabel);
}
{
JLabel discordLabel = new JLabel("<html><a href=\"\">Discord</a></html>");
discordLabel.setBounds(10, 10, 45, 20);
discordLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
frame.openURL("https://viaproxy.raphimc.net");
}
});
contentPane.add(discordLabel);
}
{
JLabel addressLabel = new JLabel("Server Address:");
addressLabel.setBounds(10, 50, 100, 20);
contentPane.add(addressLabel);
this.serverAddress = new JTextField();
this.serverAddress.setBounds(10, 70, 465, 20);
contentPane.add(this.serverAddress);
}
{
JLabel serverVersionLabel = new JLabel("Server Version:");
serverVersionLabel.setBounds(10, 100, 100, 20);
contentPane.add(serverVersionLabel);
this.serverVersion = new JComboBox<>(VersionEnum.RENDER_VERSIONS.toArray(new VersionEnum[0]));
this.serverVersion.setBounds(10, 120, 465, 20);
this.serverVersion.setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value instanceof VersionEnum) {
VersionEnum version = (VersionEnum) value;
value = version.getName();
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
});
contentPane.add(this.serverVersion);
}
{
JLabel bindPortLabel = new JLabel("Local Port:");
bindPortLabel.setBounds(10, 150, 100, 20);
contentPane.add(bindPortLabel);
this.bindPort = new JSpinner(new SpinnerNumberModel(25568, 1, 65535, 1));
this.bindPort.setBounds(10, 170, 465, 20);
contentPane.add(this.bindPort);
}
{
JLabel authMethodLabel = new JLabel("Minecraft Account: (used when server is in online mode)");
authMethodLabel.setBounds(10, 200, 400, 20);
contentPane.add(authMethodLabel);
this.authMethod = new JComboBox<>(new String[]{"Use OpenAuthMod"});
this.authMethod.setBounds(10, 220, 465, 20);
contentPane.add(this.authMethod);
}
{
this.betaCraftAuth = new JCheckBox("BetaCraft Auth (Classic)");
this.betaCraftAuth.setBounds(10, 250, 150, 20);
contentPane.add(this.betaCraftAuth);
}
{
this.proxyOnlineMode = new JCheckBox("Proxy Online Mode");
this.proxyOnlineMode.setBounds(350, 250, 465, 20);
contentPane.add(this.proxyOnlineMode);
}
{
this.stateLabel = new JLabel();
this.stateLabel.setBounds(14, 280, 465, 20);
this.stateLabel.setVisible(false);
contentPane.add(this.stateLabel);
}
{
this.stateButton = new JButton("Loading ViaProxy...");
this.stateButton.setBounds(10, 300, 465, 20);
this.stateButton.addActionListener(e -> {
if (this.stateButton.getText().equalsIgnoreCase("Start")) this.start();
else if (this.stateButton.getText().equalsIgnoreCase("Stop")) this.stop();
});
this.stateButton.setEnabled(false);
contentPane.add(this.stateButton);
}
}
private void setComponentsEnabled(final boolean state) {
this.serverAddress.setEnabled(state);
this.serverVersion.setEnabled(state);
this.bindPort.setEnabled(state);
this.authMethod.setEnabled(state);
this.betaCraftAuth.setEnabled(state);
this.proxyOnlineMode.setEnabled(state);
}
private void updateStateLabel() {
this.stateLabel.setText("ViaProxy is running! Connect with Minecraft 1.7+ to 127.0.0.1:" + this.bindPort.getValue());
this.stateLabel.setVisible(true);
}
private void start() {
this.setComponentsEnabled(false);
this.stateButton.setEnabled(false);
this.stateButton.setText("Starting...");
new Thread(() -> {
final String serverAddress = this.serverAddress.getText();
final VersionEnum serverVersion = (VersionEnum) this.serverVersion.getSelectedItem();
final int bindPort = (int) this.bindPort.getValue();
final String authMethod = (String) this.authMethod.getSelectedItem();
final boolean betaCraftAuth = this.betaCraftAuth.isSelected();
final boolean proxyOnlineMode = this.proxyOnlineMode.isSelected();
try {
final HostAndPort hostAndPort = HostAndPort.fromString(serverAddress);
Options.BIND_ADDRESS = "127.0.0.1";
Options.BIND_PORT = bindPort;
Options.ONLINE_MODE = proxyOnlineMode;
Options.CONNECT_ADDRESS = hostAndPort.getHost();
Options.CONNECT_PORT = hostAndPort.getPortOrDefault(25565);
Options.PROTOCOL_VERSION = serverVersion;
Options.OPENAUTHMOD_AUTH = true;
Options.BETACRAFT_AUTH = betaCraftAuth;
ViaProxy.startProxy();
SwingUtilities.invokeLater(() -> {
this.updateStateLabel();
this.stateButton.setEnabled(true);
this.stateButton.setText("Stop");
});
} catch (Throwable e) {
SwingUtilities.invokeLater(() -> {
this.frame.showError("Invalid server address!");
this.setComponentsEnabled(true);
this.stateButton.setEnabled(true);
this.stateButton.setText("Start");
this.stateLabel.setVisible(false);
});
}
}).start();
}
private void stop() {
ViaProxy.stopProxy();
this.stateLabel.setVisible(false);
this.stateButton.setText("Start");
this.setComponentsEnabled(true);
}
@Override
public void setReady() {
SwingUtilities.invokeLater(() -> {
this.stateButton.setText("Start");
this.stateButton.setEnabled(true);
});
}
}

View file

@ -0,0 +1,125 @@
package net.raphimc.viaproxy.ui.impl;
import net.raphimc.mcauth.MinecraftAuth;
import net.raphimc.mcauth.step.java.StepMCProfile;
import net.raphimc.viaproxy.ui.AUITab;
import net.raphimc.viaproxy.ui.ViaProxyUI;
import net.raphimc.viaproxy.ui.popups.AddAccountPopup;
import javax.swing.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.concurrent.TimeoutException;
public class OnlineModeTab extends AUITab {
private JList<String> accountsList;
private JButton addAccountButton;
private AddAccountPopup addAccountPopup;
private Thread addThread;
public OnlineModeTab(final ViaProxyUI frame) {
super(frame, "Online Mode");
}
@Override
protected void init(JPanel contentPane) {
{
JLabel infoLabel = new JLabel("To join online mode servers you have to add minecraft accounts for ViaProxy to use.");
infoLabel.setBounds(10, 10, 500, 20);
contentPane.add(infoLabel);
}
{
JLabel infoLabel = new JLabel("<html>If you change your account frequently, you might want to install <a href=\"\">OpenAuthMod</a> on your</html>");
infoLabel.setBounds(10, 40, 500, 20);
contentPane.add(infoLabel);
JLabel infoLabel2 = new JLabel("client. This allows ViaProxy to use the account you are logged in with on the client.");
infoLabel2.setBounds(10, 60, 500, 20);
contentPane.add(infoLabel2);
JLabel clickRect = new JLabel();
clickRect.setBounds(353, 40, 80, 20);
clickRect.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
frame.openURL("https://github.com/RaphiMC/OpenAuthMod/");
}
});
contentPane.add(clickRect);
}
{
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 85, 465, 205);
contentPane.add(scrollPane);
DefaultListModel<String> model = new DefaultListModel<>();
this.accountsList = new JList<>(model);
scrollPane.setViewportView(this.accountsList);
JPopupMenu contextMenu = new JPopupMenu();
JMenuItem removeItem = new JMenuItem("Remove");
removeItem.addActionListener(e -> {
int index = this.accountsList.getSelectedIndex();
if (index != -1) {
model.remove(index);
//TODO: Remove from save
}
if (index < model.getSize()) this.accountsList.setSelectedIndex(index);
else if (index > 0) this.accountsList.setSelectedIndex(index - 1);
});
contextMenu.add(removeItem);
this.accountsList.setComponentPopupMenu(contextMenu);
}
{
this.addAccountButton = new JButton("Add Account");
this.addAccountButton.setBounds(300, 300, 175, 20);
this.addAccountButton.addActionListener(event -> {
this.addAccountButton.setEnabled(false);
this.addThread = new Thread(() -> {
try {
StepMCProfile.MCProfile profile = MinecraftAuth.requestJavaLogin(msaDeviceCode -> {
SwingUtilities.invokeLater(() -> {
new AddAccountPopup(this.frame, msaDeviceCode, popup -> this.addAccountPopup = popup, () -> {
this.closePopup();
this.addThread.interrupt();
});
});
});
SwingUtilities.invokeLater(() -> {
this.closePopup();
DefaultListModel<String> model = (DefaultListModel<String>) this.accountsList.getModel();
model.addElement(profile.name());
this.frame.showInfo("The account " + profile.name() + " was added successfully.");
//TODO: Add to save
});
} catch (InterruptedException ignored) {
} catch (TimeoutException e) {
SwingUtilities.invokeLater(() -> {
this.closePopup();
this.frame.showError("The login request timed out.\nPlease login within 60 seconds.");
});
} catch (Throwable t) {
SwingUtilities.invokeLater(() -> {
this.closePopup();
this.frame.showException(t);
});
}
}, "Add Account Thread");
this.addThread.setDaemon(true);
this.addThread.start();
});
contentPane.add(this.addAccountButton);
}
}
private void closePopup() {
this.addAccountPopup.markExternalClose();
this.addAccountPopup.setVisible(false);
this.addAccountPopup.dispose();
this.addAccountPopup = null;
this.addAccountButton.setEnabled(true);
}
}

View file

@ -0,0 +1,92 @@
package net.raphimc.viaproxy.ui.popups;
import net.raphimc.mcauth.step.msa.StepMsaDeviceCode;
import net.raphimc.viaproxy.ui.ViaProxyUI;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.function.Consumer;
public class AddAccountPopup extends JDialog {
private final ViaProxyUI parent;
private final StepMsaDeviceCode.MsaDeviceCode deviceCode;
private boolean externalClose;
public AddAccountPopup(final ViaProxyUI parent, final StepMsaDeviceCode.MsaDeviceCode deviceCode, final Consumer<AddAccountPopup> popupConsumer, final Runnable closeListener) {
super(parent, true);
this.parent = parent;
this.deviceCode = deviceCode;
popupConsumer.accept(this);
this.initWindow(closeListener);
this.initComponents();
this.setVisible(true);
}
private void initWindow(final Runnable closeListener) {
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
if (!externalClose) closeListener.run();
}
});
this.setTitle("Add Account");
this.setSize(400, 200);
this.setResizable(false);
this.setLocationRelativeTo(this.parent);
}
private void initComponents() {
JPanel contentPane = new JPanel();
contentPane.setLayout(null);
this.setContentPane(contentPane);
{
JLabel browserLabel = new JLabel("Please open the following URL in your browser:");
browserLabel.setBounds(10, 10, 380, 20);
contentPane.add(browserLabel);
JLabel urlLabel = new JLabel("<html><a href=\"\">" + this.deviceCode.verificationUri() + "</a></html>");
urlLabel.setBounds(10, 30, 380, 20);
urlLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
parent.openURL(deviceCode.verificationUri());
}
});
contentPane.add(urlLabel);
JLabel enterCodeLabel = new JLabel("Enter the following code:");
enterCodeLabel.setBounds(10, 50, 380, 20);
contentPane.add(enterCodeLabel);
JLabel codeLabel = new JLabel(this.deviceCode.userCode());
codeLabel.setBounds(10, 70, 380, 20);
contentPane.add(codeLabel);
JLabel closeInfo = new JLabel("The popup will close automatically after you have been logged in.");
closeInfo.setBounds(10, 100, 380, 20);
contentPane.add(closeInfo);
}
{
JButton copyCodeButton = new JButton("Copy Code");
copyCodeButton.setBounds(this.getWidth() / 2 - 130 / 2, 130, 100, 20);
copyCodeButton.addActionListener(e -> {
StringSelection selection = new StringSelection(this.deviceCode.userCode());
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection);
});
contentPane.add(copyCodeButton);
}
}
public void markExternalClose() {
this.externalClose = true;
}
}