diff --git a/gradle.properties b/gradle.properties index a380f94..c63afe2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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 diff --git a/src/main/java/net/raphimc/viaproxy/ui/AUITab.java b/src/main/java/net/raphimc/viaproxy/ui/AUITab.java new file mode 100644 index 0000000..3b9da05 --- /dev/null +++ b/src/main/java/net/raphimc/viaproxy/ui/AUITab.java @@ -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() { + } + +} diff --git a/src/main/java/net/raphimc/viaproxy/ui/ViaProxyUI.java b/src/main/java/net/raphimc/viaproxy/ui/ViaProxyUI.java index f31bb9b..5a74829 100644 --- a/src/main/java/net/raphimc/viaproxy/ui/ViaProxyUI.java +++ b/src/main/java/net/raphimc/viaproxy/ui/ViaProxyUI.java @@ -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 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 serverVersion; - private JSpinner bindPort; - private JComboBox 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); diff --git a/src/main/java/net/raphimc/viaproxy/ui/impl/GeneralTab.java b/src/main/java/net/raphimc/viaproxy/ui/impl/GeneralTab.java new file mode 100644 index 0000000..3da415c --- /dev/null +++ b/src/main/java/net/raphimc/viaproxy/ui/impl/GeneralTab.java @@ -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 serverVersion; + private JSpinner bindPort; + private JComboBox 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("Discord"); + 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); + }); + } + +} diff --git a/src/main/java/net/raphimc/viaproxy/ui/impl/OnlineModeTab.java b/src/main/java/net/raphimc/viaproxy/ui/impl/OnlineModeTab.java new file mode 100644 index 0000000..07deb9b --- /dev/null +++ b/src/main/java/net/raphimc/viaproxy/ui/impl/OnlineModeTab.java @@ -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 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("If you change your account frequently, you might want to install OpenAuthMod on your"); + 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 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 model = (DefaultListModel) 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); + } + +} diff --git a/src/main/java/net/raphimc/viaproxy/ui/popups/AddAccountPopup.java b/src/main/java/net/raphimc/viaproxy/ui/popups/AddAccountPopup.java new file mode 100644 index 0000000..5ccaf76 --- /dev/null +++ b/src/main/java/net/raphimc/viaproxy/ui/popups/AddAccountPopup.java @@ -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 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("" + this.deviceCode.verificationUri() + ""); + 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; + } + +}