2022-04-16 16:54:17 +02:00
|
|
|
|
|
|
|
import javax.swing.JFrame;
|
|
|
|
import javax.swing.JPanel;
|
|
|
|
import javax.swing.JComponent;
|
|
|
|
import javax.swing.JLabel;
|
|
|
|
import javax.swing.Box;
|
|
|
|
import javax.swing.BoxLayout;
|
|
|
|
import javax.swing.JButton;
|
|
|
|
import javax.swing.BorderFactory;
|
|
|
|
import javax.swing.border.Border;
|
|
|
|
import java.awt.Font;
|
|
|
|
import java.awt.Color;
|
|
|
|
import java.awt.Dimension;
|
|
|
|
import java.awt.GridLayout;
|
|
|
|
import java.awt.BorderLayout;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.awt.event.ActionListener;
|
|
|
|
import java.awt.event.ActionEvent;
|
|
|
|
import java.awt.Cursor;
|
|
|
|
import cafe.biskuteri.hinoki.Tree;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.awt.event.ComponentListener;
|
|
|
|
import java.awt.event.ComponentEvent;
|
|
|
|
|
|
|
|
class
|
|
|
|
NotificationsWindow extends JFrame {
|
|
|
|
|
|
|
|
private JKomasto
|
|
|
|
primaire;
|
|
|
|
|
|
|
|
private List<Notification>
|
|
|
|
notifications;
|
|
|
|
|
|
|
|
private MastodonApi
|
|
|
|
api;
|
|
|
|
|
|
|
|
// - -%- -
|
|
|
|
|
|
|
|
private NotificationsComponent
|
|
|
|
display;
|
|
|
|
|
2022-05-02 05:05:36 +02:00
|
|
|
private boolean
|
|
|
|
showingLatest;
|
|
|
|
|
2022-04-16 16:54:17 +02:00
|
|
|
// - -%- -
|
|
|
|
|
|
|
|
private static int
|
|
|
|
ROW_COUNT = NotificationsComponent.ROW_COUNT;
|
|
|
|
|
|
|
|
// ---%-@-%---
|
|
|
|
|
2022-05-01 14:33:17 +02:00
|
|
|
public void
|
2022-05-02 05:05:36 +02:00
|
|
|
readEntity(Tree<String> entity)
|
2022-05-01 14:33:17 +02:00
|
|
|
{
|
|
|
|
notifications = new ArrayList<>();
|
|
|
|
for (Tree<String> t: entity)
|
|
|
|
{
|
|
|
|
Notification n = new Notification();
|
|
|
|
|
|
|
|
n.id = t.get("id").value;
|
|
|
|
|
|
|
|
String type = t.get("type").value;
|
|
|
|
if (type.equals("favourite"))
|
|
|
|
n.type = NotificationType.FAVOURITE;
|
|
|
|
else if (type.equals("reblog"))
|
|
|
|
n.type = NotificationType.BOOST;
|
|
|
|
else if (type.equals("mention"))
|
|
|
|
n.type = NotificationType.MENTION;
|
|
|
|
else if (type.equals("follow"))
|
|
|
|
n.type = NotificationType.FOLLOW;
|
|
|
|
else if (type.equals("follow_request"))
|
|
|
|
n.type = NotificationType.FOLLOWREQ;
|
|
|
|
else if (type.equals("poll"))
|
|
|
|
n.type = NotificationType.POLL;
|
|
|
|
else if (type.equals("status"))
|
|
|
|
n.type = NotificationType.ALERT;
|
|
|
|
|
|
|
|
Tree<String> actor = t.get("account");
|
|
|
|
String aid, aname, adisp;
|
|
|
|
aid = actor.get("id").value;
|
|
|
|
aname = actor.get("username").value;
|
|
|
|
adisp = actor.get("display_name").value;
|
|
|
|
if (!adisp.isEmpty()) n.actorName = adisp;
|
|
|
|
else n.actorName = aname;
|
|
|
|
n.actorNumId = aid;
|
2022-05-02 03:44:10 +02:00
|
|
|
|
2022-05-01 14:33:17 +02:00
|
|
|
if (n.type != NotificationType.FOLLOW)
|
|
|
|
{
|
2022-05-06 09:05:01 +02:00
|
|
|
Post post = new Post(t.get("status"));
|
|
|
|
post.resolveApproximateText();
|
|
|
|
n.postId = post.id;
|
|
|
|
n.postText = post.approximateText;
|
2022-05-01 14:33:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
notifications.add(n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-02 05:05:36 +02:00
|
|
|
public void
|
|
|
|
refresh()
|
|
|
|
{
|
|
|
|
String firstId = null;
|
|
|
|
if (!showingLatest)
|
|
|
|
{
|
|
|
|
assert !notifications.isEmpty();
|
|
|
|
firstId = notifications.get(0).id;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fetchPage(firstId, null))
|
|
|
|
{
|
|
|
|
if (notifications.size() < ROW_COUNT) showLatestPage();
|
|
|
|
display.showNotifications(notifications);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-16 16:54:17 +02:00
|
|
|
public void
|
|
|
|
showLatestPage()
|
|
|
|
{
|
2022-05-02 05:05:36 +02:00
|
|
|
if (fetchPage(null, null))
|
|
|
|
{
|
|
|
|
display.showNotifications(notifications);
|
|
|
|
showingLatest = true;
|
|
|
|
primaire.getWindowUpdater().add(this);
|
|
|
|
}
|
2022-04-16 16:54:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void
|
|
|
|
showPrevPage()
|
|
|
|
{
|
|
|
|
assert !notifications.isEmpty();
|
2022-05-02 05:05:36 +02:00
|
|
|
if (fetchPage(null, notifications.get(0).id))
|
|
|
|
{
|
|
|
|
if (notifications.size() < ROW_COUNT) showLatestPage();
|
|
|
|
display.showNotifications(notifications);
|
|
|
|
showingLatest = false;
|
|
|
|
primaire.getWindowUpdater().remove(this);
|
|
|
|
}
|
2022-04-16 16:54:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void
|
|
|
|
showNextPage()
|
|
|
|
{
|
|
|
|
assert !notifications.isEmpty();
|
|
|
|
int last = notifications.size() - 1;
|
2022-05-02 05:05:36 +02:00
|
|
|
if (fetchPage(notifications.get(last).id, null))
|
|
|
|
{
|
|
|
|
display.showNotifications(notifications);
|
|
|
|
showingLatest = false;
|
|
|
|
primaire.getWindowUpdater().remove(this);
|
|
|
|
}
|
2022-04-16 16:54:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// - -%- -
|
|
|
|
|
2022-05-02 05:05:36 +02:00
|
|
|
private boolean
|
2022-04-16 16:54:17 +02:00
|
|
|
fetchPage(String maxId, String minId)
|
|
|
|
{
|
|
|
|
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
2022-05-02 05:05:36 +02:00
|
|
|
class Handler implements RequestListener {
|
|
|
|
|
|
|
|
boolean
|
|
|
|
succeeded = false;
|
|
|
|
|
|
|
|
// -=%=-
|
|
|
|
|
|
|
|
public void
|
|
|
|
connectionFailed(IOException eIo)
|
|
|
|
{
|
|
|
|
eIo.printStackTrace();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void
|
|
|
|
requestFailed(int httpCode, Tree<String> json)
|
|
|
|
{
|
|
|
|
System.err.println(httpCode + json.get("error").value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void
|
|
|
|
requestSucceeded(Tree<String> json)
|
|
|
|
{
|
|
|
|
readEntity(json);
|
|
|
|
succeeded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Handler handler = new Handler();
|
|
|
|
api.getNotifications(ROW_COUNT, maxId, minId, handler);
|
2022-04-16 16:54:17 +02:00
|
|
|
display.setCursor(null);
|
|
|
|
repaint();
|
2022-05-02 05:05:36 +02:00
|
|
|
return handler.succeeded;
|
2022-04-16 16:54:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---%-@-%---
|
|
|
|
|
|
|
|
NotificationsWindow(JKomasto primaire)
|
|
|
|
{
|
|
|
|
super("Notifications");
|
|
|
|
this.primaire = primaire;
|
|
|
|
this.api = primaire.getMastodonApi();
|
|
|
|
|
|
|
|
notifications = new ArrayList<>();
|
|
|
|
|
|
|
|
display = new NotificationsComponent(this);
|
2022-04-28 03:56:25 +02:00
|
|
|
display.setPreferredSize(new Dimension(256, 260));
|
2022-04-16 16:54:17 +02:00
|
|
|
setContentPane(display);
|
|
|
|
pack();
|
|
|
|
|
2022-05-06 15:57:17 +02:00
|
|
|
setIconImage(primaire.getProgramIcon());
|
2022-04-16 16:54:17 +02:00
|
|
|
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
|
|
|
setVisible(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class
|
|
|
|
NotificationsComponent extends JPanel
|
|
|
|
implements ActionListener {
|
|
|
|
|
|
|
|
private NotificationsWindow
|
|
|
|
primaire;
|
|
|
|
|
|
|
|
private JButton
|
|
|
|
prev, next;
|
|
|
|
|
|
|
|
// - -%- -
|
|
|
|
|
|
|
|
private List<NotificationComponent>
|
|
|
|
rows;
|
|
|
|
|
|
|
|
// - -%- -
|
|
|
|
|
|
|
|
static final int
|
2022-04-28 03:56:25 +02:00
|
|
|
ROW_COUNT = 10;
|
2022-04-16 16:54:17 +02:00
|
|
|
|
|
|
|
// ---%-@-%---
|
|
|
|
|
|
|
|
public void
|
|
|
|
showNotifications(List<Notification> notifications)
|
|
|
|
{
|
|
|
|
assert notifications.size() == rows.size();
|
|
|
|
for (int o = 0; o < rows.size(); ++o)
|
|
|
|
{
|
|
|
|
Notification n = notifications.get(o);
|
|
|
|
NotificationComponent c = rows.get(o);
|
|
|
|
c.setName(n.actorName);
|
2022-04-28 03:56:25 +02:00
|
|
|
switch (n.type)
|
|
|
|
{
|
|
|
|
case MENTION: c.setType("mentioned"); break;
|
|
|
|
case BOOST: c.setType("boosted"); break;
|
|
|
|
case FAVOURITE: c.setType("favourited"); break;
|
|
|
|
case FOLLOW: c.setType("followed"); break;
|
|
|
|
case FOLLOWREQ: c.setType("req. follow"); break;
|
|
|
|
case POLL: c.setType("poll ended"); break;
|
|
|
|
case ALERT: c.setType("posted"); break;
|
|
|
|
}
|
2022-04-16 16:54:17 +02:00
|
|
|
c.setText(n.postText);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// - -%- -
|
|
|
|
|
|
|
|
public void
|
|
|
|
actionPerformed(ActionEvent eA)
|
|
|
|
{
|
|
|
|
if (eA.getSource() == prev) primaire.showPrevPage();
|
|
|
|
if (eA.getSource() == next) primaire.showNextPage();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---%-@-%---
|
|
|
|
|
|
|
|
NotificationsComponent(NotificationsWindow primaire)
|
|
|
|
{
|
|
|
|
this.primaire = primaire;
|
|
|
|
|
|
|
|
Border b = BorderFactory.createEmptyBorder(8, 8, 8, 8);
|
|
|
|
|
|
|
|
rows = new ArrayList<>();
|
|
|
|
for (int n = ROW_COUNT; n > 0; --n)
|
|
|
|
rows.add(new NotificationComponent());
|
|
|
|
|
|
|
|
prev = new JButton("<");
|
|
|
|
next = new JButton(">");
|
|
|
|
prev.addActionListener(this);
|
|
|
|
next.addActionListener(this);
|
|
|
|
|
|
|
|
JPanel centre = new JPanel();
|
|
|
|
centre.setLayout(new GridLayout(ROW_COUNT, 1));
|
|
|
|
for (NotificationComponent c: rows) centre.add(c);
|
|
|
|
|
|
|
|
Box bottom = Box.createHorizontalBox();
|
|
|
|
bottom.add(Box.createGlue());
|
|
|
|
bottom.add(prev);
|
|
|
|
bottom.add(Box.createHorizontalStrut(8));
|
|
|
|
bottom.add(next);
|
|
|
|
bottom.setBorder(b);
|
|
|
|
|
|
|
|
setLayout(new BorderLayout());
|
|
|
|
add(centre);
|
|
|
|
add(bottom, BorderLayout.SOUTH);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class
|
|
|
|
NotificationComponent extends JComponent
|
|
|
|
implements ComponentListener {
|
|
|
|
|
|
|
|
private JLabel
|
|
|
|
type;
|
|
|
|
|
|
|
|
private JLabel
|
|
|
|
name, text;
|
|
|
|
|
|
|
|
// ---%-@-%---
|
|
|
|
|
|
|
|
public void
|
|
|
|
setType(String n) { type.setText(n); }
|
|
|
|
|
|
|
|
public void
|
|
|
|
setName(String n) { name.setText(n); }
|
|
|
|
|
|
|
|
public void
|
|
|
|
setText(String n) { text.setText(n); }
|
|
|
|
|
|
|
|
// - -%- -
|
|
|
|
|
|
|
|
public void
|
|
|
|
componentResized(ComponentEvent eC)
|
|
|
|
{
|
|
|
|
int w = getWidth(), h = getHeight();
|
2022-04-28 03:56:25 +02:00
|
|
|
name.setPreferredSize(new Dimension(w * 7 / 20, h));
|
|
|
|
type.setPreferredSize(new Dimension(w * 6 / 20, h));
|
|
|
|
text.setPreferredSize(new Dimension(w * 5 / 20, h));
|
2022-04-16 16:54:17 +02:00
|
|
|
|
2022-04-28 03:56:25 +02:00
|
|
|
name.setMaximumSize(new Dimension(w * 7 / 20, h));
|
|
|
|
type.setMaximumSize(new Dimension(w * 6 / 20, h));
|
|
|
|
text.setMaximumSize(new Dimension(w * 5 / 20, h));
|
2022-04-16 16:54:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void
|
|
|
|
componentShown(ComponentEvent eC) { }
|
|
|
|
|
|
|
|
public void
|
|
|
|
componentHidden(ComponentEvent eC) { }
|
2022-05-02 03:44:10 +02:00
|
|
|
|
2022-04-16 16:54:17 +02:00
|
|
|
public void
|
|
|
|
componentMoved(ComponentEvent eC) { }
|
|
|
|
|
|
|
|
// ---%-@-%---
|
|
|
|
|
|
|
|
NotificationComponent()
|
|
|
|
{
|
2022-04-28 03:56:25 +02:00
|
|
|
Font f = new Font("Dialog", Font.PLAIN, 12);
|
|
|
|
Font f1 = f.deriveFont(Font.PLAIN, 14);
|
|
|
|
Font f2 = f.deriveFont(Font.PLAIN, 11);
|
|
|
|
Font f3 = f.deriveFont(Font.ITALIC, 14);
|
|
|
|
|
|
|
|
Color c = new Color(0, 0, 0, 25);
|
|
|
|
Border b1 = BorderFactory.createMatteBorder(0, 0, 1, 0, c);
|
2022-04-16 16:54:17 +02:00
|
|
|
|
|
|
|
name = new JLabel();
|
|
|
|
type = new JLabel();
|
|
|
|
text = new JLabel();
|
|
|
|
name.setFont(f1);
|
|
|
|
type.setFont(f2);
|
|
|
|
text.setFont(f3);
|
|
|
|
type.setHorizontalAlignment(JLabel.RIGHT);
|
|
|
|
|
|
|
|
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
|
|
|
|
add(Box.createHorizontalStrut(4));
|
2022-04-28 03:56:25 +02:00
|
|
|
add(name);
|
|
|
|
add(Box.createHorizontalStrut(8));
|
2022-04-16 16:54:17 +02:00
|
|
|
add(type);
|
2022-04-28 03:56:25 +02:00
|
|
|
add(Box.createHorizontalStrut(8));
|
2022-04-16 16:54:17 +02:00
|
|
|
add(text);
|
2022-04-28 03:56:25 +02:00
|
|
|
add(Box.createHorizontalStrut(4));
|
2022-04-16 16:54:17 +02:00
|
|
|
|
|
|
|
this.addComponentListener(this);
|
2022-04-28 03:56:25 +02:00
|
|
|
setBorder(b1);
|
2022-04-16 16:54:17 +02:00
|
|
|
}
|
|
|
|
|
2022-05-02 03:44:10 +02:00
|
|
|
}
|