biskuteri-cafe-JKomasto2/ProfileWindow.java
Snowyfox e6fea4c061 Fixed bug when redraft makes no changes
(Before this, JKomasto and sometimes the Mastodon web client would get '411 Record Not Found' when submitting the same text after deleting and redrafting. Presumably the Mastodon server caches both whether an idempotency key was fulfilled and which post it leads to, and for some reason it looks up the second and fails.)
2022-05-31 03:39:56 -04:00

428 lines
11 KiB
Java

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.Graphics;
import java.awt.Cursor;
import java.awt.Image;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Shape;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.geom.Ellipse2D;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
class
ProfileWindow extends JFrame {
private JKomasto
primaire;
private MastodonApi
api;
private Account
account;
// - -%- -
private ProfileComponent
display;
// ---%-@-%---
public void
use(Account account)
{
this.account = account;
account.resolveAvatar();
display.setAvatar(account.avatar);
display.setAccountID(account.id);
display.setDisplayName(account.name);
int n1 = account.followedCount;
int n2 = account.followerCount;
display.setFollowedAndFollowers(n1 + " & " + n2);
int n3 = account.postCount;
String hs;
if (n3 >= 1000) hs = "~" + (n3 / 1000) + "K";
else if (n3 >= 300) hs = "~" + (n3 / 100) + "00";
else hs = Integer.toString(n3);
hs += " posts since ";
switch (account.creationDate.getMonth())
{
case JANUARY: hs += "Jan"; break;
case FEBRUARY: hs += "Feb"; break;
case MARCH: hs += "Mar"; break;
case APRIL: hs += "Apr"; break;
case MAY: hs += "May"; break;
case JUNE: hs += "Jun"; break;
case JULY: hs += "Jul"; break;
case AUGUST: hs += "Aug"; break;
case SEPTEMBER: hs += "Sept"; break;
case OCTOBER: hs += "Oct"; break;
case NOVEMBER: hs += "Nov"; break;
case DECEMBER: hs += "Dec"; break;
/*
* (悪) We're hardcoding for English right now,
* but later we need to localise properly using
* Month#getDisplayName. Right now I'm just
* finishing this component ASAP for English.
*/
}
hs += " " + account.creationDate.getYear();
display.setHistory(hs);
for (int i = 1; i <= 4; ++i)
{
if (i > account.fields.length)
{
display.setField(i, "", "");
continue;
}
String[] field = account.fields[i - 1];
display.setField(i, field[0], field[1]);
}
display.setDescription(account.description);
setTitle(account.name + " - JKomasto");
}
// - -%- -
public void
seePosts()
{
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
TimelineWindow w = new TimelineWindow(primaire);
w.showAuthorPosts(account.numId);
w.showLatestPage();
w.setLocationRelativeTo(this);
w.setVisible(true);
display.setCursor(null);
}
// ---%-@-%---
ProfileWindow(JKomasto primaire)
{
super("Profile window - JKomasto");
this.primaire = primaire;
this.api = primaire.getMastodonApi();
this.display = new ProfileComponent(this);
add(display);
pack();
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
}
class
ProfileComponent extends JPanel
implements ActionListener {
private ProfileWindow
primaire;
// - -5- -
private Image
avatar;
private JLabel
accountIdLabel,
accountId,
displayNameLabel,
displayName,
followedLabel,
followed,
historyLabel,
history,
field1Label,
field1,
field2Label,
field2,
field3Label,
field3,
field4Label,
field4;
private JTextArea
description;
private JScrollPane
scroll;
private JButton
seePosts;
private int
dx1, dx2, dx3, dx4, dy1, dy2, dy3, dy4;
// ---%-@-%---
public void
setAvatar(Image avatar)
{
this.avatar = avatar;
}
public void
setAccountID(String id)
{
accountId.setText(id);
}
public void
setDisplayName(String name)
{
displayName.setText(name);
}
public void
setFollowedAndFollowers(String text)
{
followed.setText(text);
}
public void
setHistory(String text)
{
history.setText(text);
}
public void
setField(int index, String name, String value)
{
assert index >= 1 && index <= 4;
JLabel label = null, field = null;
switch (index)
{
case 1: label = field1Label; field = field1; break;
case 2: label = field2Label; field = field2; break;
case 3: label = field3Label; field = field3; break;
case 4: label = field4Label; field = field4; break;
}
label.setText(name);
field.setText(value);
}
public void
setDescription(String html)
{
description.setText(html);
}
// - -%- -
public void
actionPerformed(ActionEvent eA)
{
assert eA.getSource() == seePosts;
primaire.seePosts();
}
protected void
paintComponent(Graphics g)
{
g.clearRect(0, 0, getWidth(), getHeight());
int w = getWidth(), h = getHeight();
int aw = 256;
int ah = 256;
int ax = (w - aw) / 2;
int ay = 10;
int acx = ax + (aw / 2);
int acy = ay + (ah / 2);
Shape defaultClip = g.getClip();
g.setClip(new Ellipse2D.Float(ax, ay, aw, ah));
g.drawImage(avatar, ax, ay, aw, ah, this);
g.setClip(defaultClip);
g.setColor(new Color(0, 0, 0, 50));
g.fillRect(0, acy - dy1, acx - dx1, 2);
g.fillRect(0, acy - dy2, acx - dx2, 2);
g.fillRect(0, acy + dy3, acx - dx3, 2);
g.fillRect(0, acy + dy4, acx - dx4, 2);
g.fillRect(acx + dx1, acy - dy1, w - (acx + dx1), 2);
g.fillRect(acx + dx2, acy - dy2, w - (acx + dx2), 2);
g.fillRect(acx + dx3, acy + dy3, w - (acx + dx3), 2);
g.fillRect(acx + dx4, acy + dy4, w - (acx + dx4), 2);
((java.awt.Graphics2D)g).setRenderingHint(
java.awt.RenderingHints.KEY_ANTIALIASING,
java.awt.RenderingHints.VALUE_ANTIALIAS_ON
);
}
public void
doLayout()
{
final double TAU = 2 * Math.PI;
int w = getWidth(), h = getHeight();
int aw = 256;
int ah = 256;
int ax = (w - aw) / 2;
int ay = 10;
int acx = ax + (aw / 2);
int acy = ay + (ah / 2);
dx1 = (int)((aw * 11/20) * Math.cos(TAU * 45 / 360));
dx2 = (int)((aw * 11/20) * Math.cos(TAU * 15 / 360));
dx3 = dx2;
dx4 = dx1;
dy1 = (int)((ah / 2) * Math.sin(TAU * 45 / 360));
dy2 = (int)((ah / 2) * Math.sin(TAU * 15 / 360));
dy3 = dy2;
dy4 = dy1;
FontMetrics fm = getFontMetrics(field1.getFont());
int lh = fm.getAscent() * 9 / 8;
accountIdLabel.setLocation(10, acy - dy1 - lh - 1);
accountId.setLocation(10, acy - dy1 + 1);
accountIdLabel.setSize(acx - dx1 - 16, lh);
accountId.setSize(acx - dx1 - 24, lh);
displayNameLabel.setLocation(10, acy - dy2 - lh - 1);
displayName.setLocation(10, acy - dy2 + 1);
displayNameLabel.setSize(acx - dx2 - 16, lh);
displayName.setSize(acx - dx2 - 24, lh);
followedLabel.setLocation(10, acy + dy3 - lh - 1);
followed.setLocation(10, acy + dy3 + 1);
followedLabel.setSize(acx - dx3 - 24, lh);
followed.setSize(acx - dx3 - 16, lh);
historyLabel.setLocation(10, acy + dy4 - lh - 1);
history.setLocation(10, acy + dy4 + 1);
historyLabel.setSize(acx - dx4 - 24, lh);
history.setSize(acx - dx4 - 16, lh);
field1Label.setLocation(acx + dx1 + 16, acy - dy1 - lh - 1);
field1.setLocation(acx + dx1 + 24, acy - dy1 + 1);
field1Label.setSize(w - 10 - (acy + dx1 + 16), lh);
field1.setSize(w - 10 - (acy + dx1 + 24), lh);
field2Label.setLocation(acx + dx2 + 16, acy - dy2 - lh - 1);
field2.setLocation(acx + dx2 + 24, acy - dy2 + 1);
field2Label.setSize((w - 10) - (acy + dx2 + 16), lh);
field2.setSize((w - 10) - (acy + dx2 + 24), lh);
field3Label.setLocation(acx + dx3 + 24, acy + dy3 - lh - 1);
field3.setLocation(acx + dx3 + 16, acy + dy3 + 1);
field3Label.setSize((w - 10) - (acy + dx3 + 24), lh);
field3.setSize((w - 10) - (acy + dx3 + 16), lh);
field4Label.setLocation(acx + dx4 + 24, acy + dy4 - lh - 1);
field4.setLocation(acx + dx4 + 16, acy + dy4 + 1);
field4Label.setSize((w - 10) - (acy + dx4 + 24), lh);
field4.setSize((w - 10) - (acy + dx4 + 16), lh);
seePosts.setLocation(10, h - 10 - 24);
seePosts.setSize((w - 40) / 4, 24);
scroll.setLocation(10, (ay + ah) + 10);
scroll.setSize(w - 20, seePosts.getY() - 10 - scroll.getY());
}
// ---%-@-%---
ProfileComponent(ProfileWindow primaire)
{
this.primaire = primaire;
Font f1 = new Font("VL Gothic", Font.PLAIN, 16);
Font f2 = new Font("VL Gothic", Font.PLAIN, 14);
int a = JLabel.RIGHT;
accountIdLabel = new JLabel("Account ID", a);
accountId = new JLabel("", a);
displayNameLabel = new JLabel("Display name", a);
displayName = new JLabel("", a);
followedLabel = new JLabel("Followed & followers", a);
followed = new JLabel("", a);
historyLabel = new JLabel("History", a);
history = new JLabel("", a);
field1Label = new JLabel("");
field1 = new JLabel("");
field2Label = new JLabel("");
field2 = new JLabel("");
field3Label = new JLabel("");
field3 = new JLabel("");
field4Label = new JLabel("");
field4 = new JLabel("");
accountIdLabel.setFont(f1);
accountId.setFont(f1);
displayNameLabel.setFont(f1);
displayName.setFont(f1);
followedLabel.setFont(f1);
followed.setFont(f1);
historyLabel.setFont(f1);
history.setFont(f2);
field1Label.setFont(f1);
field1.setFont(f2);
field2Label.setFont(f1);
field2.setFont(f2);
field3Label.setFont(f1);
field3.setFont(f2);
field4Label.setFont(f1);
field4.setFont(f2);
description = new JTextArea();
description.setEditable(false);
description.setLineWrap(true);
description.setBackground(null);
description.setFont(f1);
scroll = new JScrollPane(
description,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
);
scroll.setBorder(null);
seePosts = new JButton("See posts");
seePosts.addActionListener(this);
setLayout(null);
add(accountIdLabel);
add(accountId);
add(displayNameLabel);
add(displayName);
add(followedLabel);
add(followed);
add(historyLabel);
add(history);
add(field1Label);
add(field1);
add(field2Label);
add(field2);
add(field3Label);
add(field3);
add(field4Label);
add(field4);
add(scroll);
add(seePosts);
setPreferredSize(new Dimension(640, 480));
}
}