mirror of
https://gitlab.com/biskuteri-cafe/JKomasto2.git
synced 2024-11-20 05:04:51 +01:00
e4f13ad8c8
Somewhat works now, but I think we'll abandon it..
590 lines
14 KiB
Java
590 lines
14 KiB
Java
|
|
import javax.swing.JFrame;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JButton;
|
|
import javax.swing.JLabel;
|
|
import javax.swing.JTextField;
|
|
import javax.swing.JPasswordField;
|
|
import javax.swing.JTextArea;
|
|
import javax.swing.JCheckBox;
|
|
import javax.swing.JOptionPane;
|
|
import javax.swing.BorderFactory;
|
|
import javax.swing.border.Border;
|
|
import java.awt.BorderLayout;
|
|
import java.awt.FlowLayout;
|
|
import java.awt.Dimension;
|
|
import java.awt.Font;
|
|
import java.awt.Cursor;
|
|
import java.awt.Desktop;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.KeyEvent;
|
|
|
|
import cafe.biskuteri.hinoki.Tree;
|
|
import java.net.URI;
|
|
import java.io.IOException;
|
|
|
|
|
|
class
|
|
LoginWindow extends JFrame {
|
|
|
|
private JKomasto
|
|
primaire;
|
|
|
|
private MastodonApi
|
|
api;
|
|
|
|
// - -%- -
|
|
|
|
private LoginComponent
|
|
display;
|
|
|
|
private boolean
|
|
serverContacted = false,
|
|
haveAppCredentials = false,
|
|
haveAccessToken = false,
|
|
haveAccountDetails = false;
|
|
|
|
// ---%-@-%---
|
|
|
|
public void
|
|
updateStatusDisplay()
|
|
{
|
|
char prefix1 = serverContacted ? '✓' : '✕';
|
|
char prefix2 = haveAppCredentials ? '✓' : '✕';
|
|
char prefix3 = haveAccessToken ? '✓' : '✕';
|
|
char prefix4 = haveAccountDetails ? '✓' : '✕';
|
|
|
|
StringBuilder b = new StringBuilder();
|
|
b.append(prefix1 + " Have connection to server\n");
|
|
b.append(prefix2 + " Have app credentials\n");
|
|
b.append(prefix3 + " Have access token\n");
|
|
b.append(prefix4 + " Have account details\n");
|
|
display.setText(b.toString());
|
|
|
|
display.paintImmediately(display.getBounds(null));
|
|
}
|
|
|
|
public void
|
|
useCache()
|
|
{
|
|
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
|
try
|
|
{
|
|
api.loadCache();
|
|
haveAppCredentials = true;
|
|
haveAccessToken = true;
|
|
display.setInstanceUrl(api.getInstanceUrl());
|
|
updateStatusDisplay();
|
|
}
|
|
catch (IOException eIo)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
this,
|
|
"We couldn't get login details from the cache.."
|
|
+ "\n" + eIo.getClass() + ": " + eIo.getMessage()
|
|
);
|
|
display.setAutoLoginToggled(false);
|
|
}
|
|
display.setCursor(null);
|
|
if (!haveAccessToken) return;
|
|
|
|
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
|
api.getAccountDetails(new RequestListener() {
|
|
|
|
public void
|
|
connectionFailed(IOException eIo)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
"Tried to get account details, failed.."
|
|
+ "\n" + eIo.getMessage()
|
|
);
|
|
}
|
|
|
|
public void
|
|
requestFailed(int httpCode, Tree<String> json)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
"Tried to get account details, failed.."
|
|
+ "\n" + json.get("error").value
|
|
+ "\n(HTTP error code: " + httpCode + ")"
|
|
);
|
|
}
|
|
|
|
public void
|
|
requestSucceeded(Tree<String> json)
|
|
{
|
|
api.setAccountDetails(json);
|
|
serverContacted = true;
|
|
haveAccountDetails = true;
|
|
updateStatusDisplay();
|
|
}
|
|
|
|
});
|
|
display.setCursor(null);
|
|
if (!haveAccountDetails) return;
|
|
|
|
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
|
try
|
|
{
|
|
api.saveToCache();
|
|
}
|
|
catch (IOException eIo)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
this,
|
|
"We couldn't save login details into the cache.."
|
|
+ "\n" + eIo.getClass() + ": " + eIo.getMessage()
|
|
);
|
|
}
|
|
display.setCursor(null);
|
|
|
|
primaire.finishedLogin();
|
|
}
|
|
|
|
public void
|
|
useInstanceUrl()
|
|
{
|
|
if (display.isAutoLoginToggled()) { useCache(); return; }
|
|
|
|
String url = display.getInstanceUrl();
|
|
if (url.trim().isEmpty()) {
|
|
// Should we show an error dialog..?
|
|
display.setInstanceUrl("");
|
|
return;
|
|
}
|
|
if (!hasProtocol(url)) {
|
|
url = "https://" + url;
|
|
display.setInstanceUrl(url);
|
|
display.paintImmediately(display.getBounds(null));
|
|
}
|
|
serverContacted = false;
|
|
haveAppCredentials = false;
|
|
haveAccessToken = false;
|
|
haveAccountDetails = false;
|
|
|
|
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
|
api.testUrlConnection(url, new RequestListener() {
|
|
|
|
public void
|
|
connectionFailed(IOException eIo)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
"Tried to connect to URL, failed.."
|
|
+ "\n" + eIo.getClass() + ": " + eIo.getMessage()
|
|
);
|
|
}
|
|
|
|
public void
|
|
requestFailed(int httpCode, Tree<String> response)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
"Tried to connect to URL, failed.."
|
|
+ "\n" + response.get("body").value
|
|
);
|
|
}
|
|
|
|
public void
|
|
requestSucceeded(Tree<String> response)
|
|
{
|
|
serverContacted = true;
|
|
updateStatusDisplay();
|
|
}
|
|
|
|
});
|
|
display.setCursor(null);
|
|
if (!serverContacted) return;
|
|
|
|
api.setInstanceUrl(url);
|
|
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
|
api.getAppCredentials(new RequestListener() {
|
|
|
|
public void
|
|
connectionFailed(IOException eIo)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
"Tried to get app credentials, failed.."
|
|
+ "\n" + eIo.getMessage()
|
|
);
|
|
}
|
|
|
|
public void
|
|
requestFailed(int httpCode, Tree<String> json)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
"Tried to get app credentials, failed.."
|
|
+ "\n" + json.get("error").value
|
|
+ "\n(HTTP error code: " + httpCode + ")"
|
|
);
|
|
}
|
|
|
|
public void
|
|
requestSucceeded(Tree<String> json)
|
|
{
|
|
api.setAppCredentials(json);
|
|
haveAppCredentials = true;
|
|
updateStatusDisplay();
|
|
}
|
|
|
|
});
|
|
display.setCursor(null);
|
|
if (!haveAppCredentials) return;
|
|
|
|
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
|
|
|
URI uri = api.getAuthorisationURL();
|
|
|
|
final String MESSAGE1 =
|
|
"We will need you to login through a web browser,\n"
|
|
+ "and they will give you an authorisation code\n"
|
|
+ "that you will paste here. Sorry..!";
|
|
|
|
boolean supported =
|
|
Desktop.isDesktopSupported()
|
|
&& Desktop.getDesktop().isSupported(Desktop.Action.BROWSE);
|
|
if (supported)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
MESSAGE1,
|
|
"Authorisation code renewal",
|
|
JOptionPane.INFORMATION_MESSAGE
|
|
);
|
|
try { Desktop.getDesktop().browse(uri); }
|
|
catch (IOException eIo) { supported = false; }
|
|
}
|
|
if (!supported)
|
|
{
|
|
final String MESSAGE2 =
|
|
"\nWe cannot use Desktop.browse(URI) on your\n"
|
|
+ "computer.. You'll have to open your web\n"
|
|
+ "browser yourself, and copy this URL in.";
|
|
|
|
JTextField field = new JTextField();
|
|
field.setText(uri.toString());
|
|
field.setPreferredSize(new Dimension(120, 32));
|
|
field.selectAll();
|
|
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
new Object[] { MESSAGE1, MESSAGE2, field },
|
|
"Authorisation code renewal",
|
|
JOptionPane.INFORMATION_MESSAGE
|
|
);
|
|
}
|
|
display.receiveAuthorisationCode();
|
|
display.setCursor(null);
|
|
}
|
|
|
|
public void
|
|
useAuthorisationCode()
|
|
{
|
|
String code = display.getAuthorisationCode();
|
|
|
|
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
|
api.getAccessToken(code, new RequestListener() {
|
|
|
|
public void
|
|
connectionFailed(IOException eIo)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
"Tried to get app token, failed.."
|
|
+ "\n" + eIo.getMessage()
|
|
);
|
|
}
|
|
|
|
public void
|
|
requestFailed(int httpCode, Tree<String> json)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
"Tried to get app token, failed.."
|
|
+ "\n" + json.get("error").value
|
|
+ "\n(HTTP error code: " + httpCode + ")"
|
|
);
|
|
}
|
|
|
|
public void
|
|
requestSucceeded(Tree<String> json)
|
|
{
|
|
api.setAccessToken(json);
|
|
haveAccessToken = true;
|
|
updateStatusDisplay();
|
|
}
|
|
|
|
});
|
|
display.setCursor(null);
|
|
if (!haveAccessToken) return;
|
|
|
|
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
|
api.getAccountDetails(new RequestListener() {
|
|
|
|
public void
|
|
connectionFailed(IOException eIo)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
"Tried to get account details, failed.."
|
|
+ "\n" + eIo.getMessage()
|
|
);
|
|
}
|
|
|
|
public void
|
|
requestFailed(int httpCode, Tree<String> json)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
LoginWindow.this,
|
|
"Tried to get account details, failed.."
|
|
+ "\n" + json.get("error").value
|
|
+ "\n(HTTP error code: " + httpCode + ")"
|
|
);
|
|
}
|
|
|
|
public void
|
|
requestSucceeded(Tree<String> json)
|
|
{
|
|
api.setAccountDetails(json);
|
|
haveAccountDetails = true;
|
|
updateStatusDisplay();
|
|
}
|
|
|
|
});
|
|
display.setCursor(null);
|
|
if (!haveAccountDetails) return;
|
|
|
|
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
|
try
|
|
{
|
|
api.saveToCache();
|
|
}
|
|
catch (IOException eIo)
|
|
{
|
|
JOptionPane.showMessageDialog(
|
|
this,
|
|
"We couldn't save login details into the cache.."
|
|
+ "\n" + eIo.getClass() + ": " + eIo.getMessage()
|
|
);
|
|
}
|
|
display.setCursor(null);
|
|
|
|
primaire.finishedLogin();
|
|
}
|
|
|
|
// - -%- -
|
|
|
|
public static boolean
|
|
hasProtocol(String url) { return url.matches("^.+://.*"); }
|
|
|
|
// ---%-@-%---
|
|
|
|
LoginWindow(JKomasto primaire)
|
|
{
|
|
super("JKomasto - Login");
|
|
this.primaire = primaire;
|
|
this.api = primaire.getMastodonApi();
|
|
|
|
setLocationByPlatform(true);
|
|
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
|
|
|
display = new LoginComponent(this);
|
|
updateStatusDisplay();
|
|
|
|
display.setPreferredSize(new Dimension(320, 280));
|
|
setContentPane(display);
|
|
pack();
|
|
|
|
setIconImage(primaire.getProgramIcon());
|
|
}
|
|
|
|
}
|
|
|
|
class
|
|
LoginComponent extends JPanel
|
|
implements ActionListener {
|
|
|
|
private LoginWindow
|
|
primaire;
|
|
|
|
// - -%- -
|
|
|
|
private JTextArea
|
|
statusDisplay;
|
|
|
|
private JTextField
|
|
instanceUrlField,
|
|
authorisationCodeField;
|
|
|
|
private JLabel
|
|
instanceUrlLabel,
|
|
authorisationCodeLabel;
|
|
|
|
private JButton
|
|
instanceUrlButton,
|
|
authorisationCodeButton;
|
|
|
|
private JPanel
|
|
labelArea,
|
|
forField,
|
|
accountsPanel;
|
|
|
|
private JCheckBox
|
|
autoLoginToggle;
|
|
|
|
// ---%-@-%---
|
|
|
|
public String
|
|
getInstanceUrl()
|
|
{
|
|
return instanceUrlField.getText();
|
|
}
|
|
|
|
public void
|
|
setInstanceUrl(String url)
|
|
{
|
|
instanceUrlField.setText(url);
|
|
}
|
|
|
|
public String
|
|
getAuthorisationCode()
|
|
{
|
|
return authorisationCodeField.getText();
|
|
}
|
|
|
|
public void
|
|
setText(String status)
|
|
{
|
|
statusDisplay.setText(status);
|
|
}
|
|
|
|
public void
|
|
setAutoLoginToggled(boolean a) { autoLoginToggle.setSelected(a); }
|
|
|
|
public boolean
|
|
isAutoLoginToggled() { return autoLoginToggle.isSelected(); }
|
|
|
|
public void
|
|
actionPerformed(ActionEvent eA)
|
|
{
|
|
if (eA.getSource() == instanceUrlButton)
|
|
primaire.useInstanceUrl();
|
|
if (eA.getSource() == authorisationCodeButton)
|
|
primaire.useAuthorisationCode();
|
|
}
|
|
|
|
public void
|
|
receiveInstanceUrl()
|
|
{
|
|
labelArea.remove(authorisationCodeLabel);
|
|
forField.remove(authorisationCodeButton);
|
|
accountsPanel.remove(authorisationCodeField);
|
|
labelArea.add(instanceUrlLabel, BorderLayout.NORTH);
|
|
forField.add(instanceUrlButton, BorderLayout.EAST);
|
|
accountsPanel.add(instanceUrlField);
|
|
revalidate();
|
|
}
|
|
|
|
public void
|
|
receiveAuthorisationCode()
|
|
{
|
|
labelArea.remove(instanceUrlLabel);
|
|
forField.remove(instanceUrlButton);
|
|
accountsPanel.remove(instanceUrlField);
|
|
labelArea.add(authorisationCodeLabel, BorderLayout.NORTH);
|
|
forField.add(authorisationCodeButton, BorderLayout.EAST);
|
|
accountsPanel.add(authorisationCodeField);
|
|
revalidate();
|
|
}
|
|
|
|
// ---%-@-%---
|
|
|
|
LoginComponent(LoginWindow primaire)
|
|
{
|
|
this.primaire = primaire;
|
|
|
|
Border b1, b2, bi, bo, be;
|
|
b1 = BorderFactory.createEtchedBorder();
|
|
b2 = BorderFactory.createEmptyBorder(8, 8, 8, 8);
|
|
bi = BorderFactory.createCompoundBorder(b1, b2);
|
|
bo = BorderFactory.createEmptyBorder(8, 8, 8, 8);
|
|
be = BorderFactory.createEmptyBorder();
|
|
|
|
Font f1, f2;
|
|
f1 = new Font("Dialog", Font.PLAIN, 12);
|
|
f2 = new Font("Dialog", Font.PLAIN, 16);
|
|
|
|
// We can't use swing.Box for layout,
|
|
// it's malfunctioning for some reason.
|
|
|
|
instanceUrlField = new JTextField();
|
|
instanceUrlField.setFont(f1);
|
|
String s1 = "Enter an instance URL!";
|
|
instanceUrlLabel = new JLabel(s1);
|
|
instanceUrlLabel.setLabelFor(instanceUrlField);
|
|
instanceUrlLabel.setFont(f1);
|
|
instanceUrlButton = new JButton("Connect");
|
|
instanceUrlButton.setFont(f1);
|
|
instanceUrlButton.setMnemonic(KeyEvent.VK_C);
|
|
instanceUrlButton.addActionListener(this);
|
|
|
|
authorisationCodeField = new JPasswordField();
|
|
authorisationCodeField.setFont(f1);
|
|
String s2 = "Paste the authorisation code!";
|
|
authorisationCodeLabel = new JLabel(s2);
|
|
authorisationCodeLabel.setLabelFor(authorisationCodeField);
|
|
authorisationCodeLabel.setFont(f1);
|
|
authorisationCodeButton = new JButton("Login");
|
|
authorisationCodeButton.setFont(f1);
|
|
authorisationCodeButton.setMnemonic(KeyEvent.VK_L);
|
|
authorisationCodeButton.addActionListener(this);
|
|
|
|
labelArea = new JPanel();
|
|
labelArea.setLayout(new BorderLayout());
|
|
|
|
forField = new JPanel();
|
|
forField.setOpaque(false);
|
|
forField.setLayout(new BorderLayout());
|
|
forField.add(labelArea, BorderLayout.WEST);
|
|
|
|
String s3 = "Automatically login if possible";
|
|
autoLoginToggle = new JCheckBox(s3);
|
|
autoLoginToggle.setMnemonic(KeyEvent.VK_A);
|
|
autoLoginToggle.setBorder(be);
|
|
autoLoginToggle.setFont(f1);
|
|
|
|
JPanel optionsPanel = new JPanel();
|
|
optionsPanel.setOpaque(false);
|
|
optionsPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
|
|
optionsPanel.setBorder(bi);
|
|
optionsPanel.add(autoLoginToggle);
|
|
|
|
accountsPanel = new JPanel();
|
|
accountsPanel.setOpaque(false);
|
|
accountsPanel.setLayout(new BorderLayout(0, 4));
|
|
accountsPanel.add(instanceUrlField);
|
|
accountsPanel.add(forField, BorderLayout.SOUTH);
|
|
|
|
statusDisplay = new JTextArea();
|
|
statusDisplay.setEditable(false);
|
|
statusDisplay.setBackground(null);
|
|
statusDisplay.setBorder(bi);
|
|
statusDisplay.setFont(f2);
|
|
|
|
receiveInstanceUrl();
|
|
|
|
setLayout(new BorderLayout(0, 8));
|
|
add(accountsPanel, BorderLayout.NORTH);
|
|
add(optionsPanel, BorderLayout.CENTER);
|
|
add(statusDisplay, BorderLayout.SOUTH);
|
|
|
|
setBorder(bo);
|
|
}
|
|
|
|
}
|