Some refactoring in TimelineWindow

This commit is contained in:
Snowyfox 2022-05-01 21:44:10 -04:00
parent 7673fe1419
commit db304ad2df
39 changed files with 231 additions and 192 deletions

0
ClipboardApi.java Executable file → Normal file
View File

0
ComposeWindow.java Executable file → Normal file
View File

0
ImageApi.java Executable file → Normal file
View File

0
ImageWindow.java Executable file → Normal file
View File

0
JKomasto.java Executable file → Normal file
View File

0
KDE_Dialog_Appear.wav Executable file → Normal file
View File

0
LoginWindow.java Executable file → Normal file
View File

0
MastodonApi.java Executable file → Normal file
View File

2
NotificationsWindow.java Executable file → Normal file
View File

@ -88,7 +88,7 @@ NotificationsWindow extends JFrame {
String pid, phtml, ptext;
pid = post.get("id").value;
phtml = post.get("content").value;
ptext = TimelineComponent.textApproximation(phtml);
ptext = TimelineWindow.textApproximation(phtml);
n.postId = pid;
n.postText = ptext;
}

4
PostWindow.java Executable file → Normal file
View File

@ -66,7 +66,7 @@ PostWindow extends JFrame {
// ---%-@-%---
public void
displayEntity(Tree<String> post)
readEntity(Tree<String> post)
{
this.post = post;
@ -122,7 +122,7 @@ PostWindow extends JFrame {
else display.setMediaPreview(null);
String html = post.get("content").value;
setTitle(TimelineComponent.textApproximation(html));
setTitle(TimelineWindow.textApproximation(html));
display.resetFocus();
repaint();

4
RepliesWindow.java Executable file → Normal file
View File

@ -53,7 +53,7 @@ RepliesWindow extends JFrame {
public void
postSelected(Tree<String> post)
{
postWindow.displayEntity(post);
postWindow.readEntity(post);
}
private Tree<String>
@ -259,7 +259,7 @@ implements TreeSelectionListener {
toString()
{
String html = post.get("content").value;
return TimelineComponent.textApproximation(html);
return TimelineWindow.textApproximation(html);
}
// -=%=-

0
RequestListener.java Executable file → Normal file
View File

0
RichTextPane.java Executable file → Normal file
View File

0
RudimentaryHTMLParser.java Executable file → Normal file
View File

363
TimelineWindow.java Executable file → Normal file
View File

@ -86,11 +86,70 @@ implements ActionListener {
// ---%-@-%---
public void
receive(Tree<String> pageEntity)
readEntity(Tree<String> postEntityArray)
{
page.posts = pageEntity;
display.displayEntities(page.posts);
boolean full = pageEntity.size() >= PREVIEW_COUNT;
page.posts = postEntityArray;
List<PostPreviewComponent> previews;
previews = display.getPostPreviews();
int available = postEntityArray.size();
int max = previews.size();
assert available <= max;
for (int o = 0; o < available; ++o)
{
PostPreviewComponent c = previews.get(o);
Tree<String> p = postEntityArray.get(o);
Tree<String> a = p.get("account");
String an = a.get("display_name").value;
if (an.isEmpty()) an = a.get("username").value;
c.setTopLeft(an);
Tree<String> boosted = p.get("reblog");
if (boosted.size() > 0) {
c.setTopLeft("boosted by " + an);
p = boosted;
a = p.get("account");
}
String f = "";
if (p.get("media_attachments").size() > 0) f += "a";
String t = "";
try {
String jv = p.get("created_at").value;
ZonedDateTime pv = ZonedDateTime.parse(jv);
ZoneId z = ZoneId.systemDefault();
pv = pv.withZoneSameInstant(z);
ZonedDateTime now = ZonedDateTime.now();
long d = ChronoUnit.SECONDS.between(pv, now);
long s = Math.abs(d);
if (s < 30) t = "now";
else if (s < 60) t = d + "s";
else if (s < 3600) t = (d / 60) + "m";
else if (s < 86400) t = (d / 3600) + "h";
else t = (d / 86400) + "d";
}
catch (DateTimeParseException eDt) {
assert false;
}
c.setTopRight(f + " " + t);
String html = p.get("content").value;
String cw = p.get("spoiler_text").value;
if (!cw.isEmpty())
c.setBottom("(" + cw + ")");
else
c.setBottom(textApproximation(html));
}
for (int o = available; o < max; ++o)
{
previews.get(o).reset();
}
boolean full = !(available < PREVIEW_COUNT);
display.setNextPageAvailable(full);
display.setPreviousPageAvailable(true);
display.resetFocus();
@ -99,36 +158,52 @@ implements ActionListener {
public void
refresh()
{
assert page.posts != null;
assert page.posts.size() != 0;
Tree<String> first = page.posts.get(0);
String firstId = first.get("id").value;
display.setCursor(new Cursor(Cursor.WAIT_CURSOR));
api.getTimelinePage(
page.type,
PREVIEW_COUNT, firstId, null,
page.accountNumId, page.listId,
new RequestListener() {
public void
connectionFailed(IOException eIo)
{
JOptionPane.showMessageDialog(
TimelineWindow.this,
"Failed to fetch page.."
+ "\n" + eIo.getMessage()
);
}
public void
setTimelineType(TimelineType type)
requestFailed(int httpCode, Tree<String> json)
{
page.type = type;
page.accountNumId = null;
String s1 = type.toString();
s1 = s1.charAt(0) + s1.substring(1).toLowerCase();
setTitle(s1 + " - JKomasto");
String s2 = type.toString().toLowerCase();
display.setBackgroundImage(ImageApi.local(s2));
JOptionPane.showMessageDialog(
TimelineWindow.this,
"Failed to fetch page.."
+ "\n" + json.get("error").value
+ "\n(HTTP code: " + httpCode + ")"
);
}
public TimelineType
getTimelineType() { return page.type; }
public void
showAuthorPosts(String authorNumId)
requestSucceeded(Tree<String> json)
{
assert authorNumId != null;
if (json.size() < PREVIEW_COUNT) {
showLatestPage();
return;
}
readEntity(json);
}
page.type = TimelineType.FEDERATED;
page.accountNumId = authorNumId;
setTitle(authorNumId + " - JKomasto");
display.setBackgroundImage(ImageApi.local("profile"));
}
);
display.setCursor(null);
}
public void
@ -165,7 +240,7 @@ implements ActionListener {
public void
requestSucceeded(Tree<String> json)
{
receive(json);
readEntity(json);
}
}
@ -174,7 +249,7 @@ implements ActionListener {
}
public void
nextPage()
showNextPage()
{
assert page.posts != null;
assert page.posts.size() != 0;
@ -218,12 +293,7 @@ implements ActionListener {
// quietly cancel.
return;
}
page.posts = json;
display.displayEntities(page.posts);
boolean full = json.size() >= PREVIEW_COUNT;
display.setNextPageAvailable(full);
display.setPreviousPageAvailable(true);
display.resetFocus();
readEntity(json);
}
}
@ -232,7 +302,7 @@ implements ActionListener {
}
public void
previousPage()
showPreviousPage()
{
assert page.posts != null;
assert page.posts.size() != 0;
@ -274,11 +344,7 @@ implements ActionListener {
showLatestPage();
return;
}
page.posts = json;
display.displayEntities(page.posts);
display.setNextPageAvailable(true);
display.setPreviousPageAvailable(true);
display.resetFocus();
readEntity(json);
}
}
@ -286,6 +352,36 @@ implements ActionListener {
display.setCursor(null);
}
public void
setTimelineType(TimelineType type)
{
page.type = type;
page.accountNumId = null;
String s1 = type.toString();
s1 = s1.charAt(0) + s1.substring(1).toLowerCase();
setTitle(s1 + " - JKomasto");
String s2 = type.toString().toLowerCase();
display.setBackgroundImage(ImageApi.local(s2));
}
public TimelineType
getTimelineType() { return page.type; }
public void
showAuthorPosts(String authorNumId)
{
assert authorNumId != null;
page.type = TimelineType.FEDERATED;
page.accountNumId = authorNumId;
setTitle(authorNumId + " - JKomasto");
display.setBackgroundImage(ImageApi.local("profile"));
}
public void
openOwnProfile()
{
@ -408,16 +504,20 @@ implements ActionListener {
// - -%- -
public void
postSelected(Tree<String> post)
previewSelected(int index)
{
primaire.getAutoViewWindow().displayEntity(post);
if (index > page.posts.size()) return;
Tree<String> post = page.posts.get(index - 1);
primaire.getAutoViewWindow().readEntity(post);
}
public void
postOpened(Tree<String> post)
previewOpened(int index)
{
if (index > page.posts.size()) return;
Tree<String> post = page.posts.get(index - 1);
PostWindow w = new PostWindow(primaire);
w.displayEntity(post);
w.readEntity(post);
w.setLocationRelativeTo(this);
w.setVisible(true);
}
@ -483,6 +583,36 @@ implements ActionListener {
}
}
// - -%- -
public static String
textApproximation(String html)
{
StringBuilder returnee = new StringBuilder();
Tree<String> nodes = RudimentaryHTMLParser.depthlessRead(html);
if (nodes.size() == 0) return "-";
Tree<String> first = nodes.get(0);
for (Tree<String> node: nodes)
{
if (node.key.equals("tag"))
{
if (node.get(0).key.equals("br"))
returnee.append("; ");
if (node.get(0).key.equals("p") && node != first)
returnee.append("; ");
}
if (node.key.equals("emoji"))
{
returnee.append(":" + node.value + ":");
}
if (node.key.equals("text"))
{
returnee.append(node.value);
}
}
return returnee.toString();
}
// - -%- -
private static String
@ -578,9 +708,6 @@ implements
private TimelineWindow
primaire;
private Tree<String>
posts;
// - -%- -
private JButton
@ -605,63 +732,10 @@ implements
// ---%-@-%---
public void
displayEntities(Tree<String> postArray)
public List<PostPreviewComponent>
getPostPreviews()
{
assert postArray.size() <= postPreviews.size();
this.posts = postArray;
for (int o = 0; o < postArray.size(); ++o)
{
PostPreviewComponent c = postPreviews.get(o);
Tree<String> p = postArray.get(o);
Tree<String> a = p.get("account");
String an = a.get("display_name").value;
if (an.isEmpty()) an = a.get("username").value;
c.setTopLeft(an);
Tree<String> boosted = p.get("reblog");
if (boosted.size() > 0) {
c.setTopLeft("boosted by " + an);
p = boosted;
a = p.get("account");
}
String f = "";
if (p.get("media_attachments").size() > 0) f += "a";
String t = "";
try {
String jv = p.get("created_at").value;
ZonedDateTime pv = ZonedDateTime.parse(jv);
ZoneId z = ZoneId.systemDefault();
pv = pv.withZoneSameInstant(z);
ZonedDateTime now = ZonedDateTime.now();
long d = ChronoUnit.SECONDS.between(pv, now);
long s = Math.abs(d);
if (s < 30) t = "now";
else if (s < 60) t = d + "s";
else if (s < 3600) t = (d / 60) + "m";
else if (s < 86400) t = (d / 3600) + "h";
else t = (d / 86400) + "d";
}
catch (DateTimeParseException eDt) {
assert false;
}
c.setTopRight(f + " " + t);
String html = p.get("content").value;
String cw = p.get("spoiler_text").value;
if (!cw.isEmpty())
c.setBottom("(" + cw + ")");
else
c.setBottom(textApproximation(html));
}
for (int o = posts.size(); o < postPreviews.size(); ++o)
{
postPreviews.get(o).reset();
}
return postPreviews;
}
public void
@ -691,16 +765,16 @@ implements
protected void
paintComponent(Graphics g)
{
((java.awt.Graphics2D)g).setRenderingHint(
java.awt.RenderingHints.KEY_ANTIALIASING,
java.awt.RenderingHints.VALUE_ANTIALIAS_ON
);
int w = getWidth(), h = getHeight();
g.clearRect(0, 0, w, h);
int h2 = h * 5 / 10, w2 = h2;
int x = w - w2, y = h - h2;
g.drawImage(backgroundImage, x, y, w2, h2, this);
((java.awt.Graphics2D)g).setRenderingHint(
java.awt.RenderingHints.KEY_ANTIALIASING,
java.awt.RenderingHints.VALUE_ANTIALIAS_ON
);
}
private void
@ -708,15 +782,18 @@ implements
{
assert c instanceof PostPreviewComponent;
for (int o = 0; o < postPreviews.size(); ++o)
for (PostPreviewComponent p: postPreviews)
{
PostPreviewComponent p = postPreviews.get(o);
if (c == p) {
primaire.postSelected(posts.get(o));
if (p == c) {
int index = 1 + postPreviews.indexOf(p);
primaire.previewSelected(index);
p.setSelected(true);
p.repaint();
}
else deselect(p);
else {
p.setSelected(false);
p.repaint();
}
}
}
@ -733,13 +810,9 @@ implements
private void
open(Object c)
{
assert c instanceof PostPreviewComponent;
PostPreviewComponent p = (PostPreviewComponent)c;
int o = postPreviews.indexOf(p);
int o = postPreviews.indexOf(c);
assert o != -1;
if (o >= posts.size()) return;
primaire.postOpened(posts.get(o));
primaire.previewOpened(1 + o);
}
public void
@ -778,7 +851,7 @@ implements
PostPreviewComponent selected = null;
for (PostPreviewComponent c: postPreviews)
if (c.getSelected()) selected = c;
if (c.isSelected()) selected = c;
if (selected == null) return;
open(selected);
@ -789,8 +862,8 @@ implements
{
Object src = eA.getSource();
if (src == next) primaire.nextPage();
else if (src == prev) primaire.previousPage();
if (src == next) primaire.showNextPage();
else if (src == prev) primaire.showPreviousPage();
/*
* I think the page previews will just forward to us.
* But I think they'll have to tell us where they are
@ -812,35 +885,6 @@ implements
public void
keyReleased(KeyEvent eK) { }
// - -%- -
public static String
textApproximation(String html)
{
StringBuilder returnee = new StringBuilder();
Tree<String> nodes = RudimentaryHTMLParser.depthlessRead(html);
if (nodes.size() == 0) return "-";
Tree<String> first = nodes.get(0);
for (Tree<String> node: nodes)
{
if (node.key.equals("tag"))
{
if (node.get(0).key.equals("br"))
returnee.append("; ");
if (node.get(0).key.equals("p") && node != first)
returnee.append("; ");
}
if (node.key.equals("emoji"))
{
returnee.append(":" + node.value + ":");
}
if (node.key.equals("text"))
{
returnee.append(node.value);
}
}
return returnee.toString();
}
// ---%-@-%---
TimelineComponent(TimelineWindow primaire)
@ -926,23 +970,19 @@ PostPreviewComponent extends JComponent {
}
public void
setSelected(boolean selected)
{
this.selected = selected;
if (!selected) setBackground(null);
else setBackground(new Color(0, 0, 0, 25));
}
setSelected(boolean selected) { this.selected = selected; }
public boolean
getSelected() { return selected; }
isSelected() { return selected; }
// - -%- -
protected void
paintComponent(Graphics g)
{
if (selected) {
g.setColor(getBackground());
if (selected)
{
g.setColor(new Color(0, 0, 0, 25));
g.fillRect(0, 0, getWidth(), getHeight());
}
}
@ -952,10 +992,9 @@ PostPreviewComponent extends JComponent {
public
PostPreviewComponent()
{
Font f = new JLabel().getFont();
Font f1 = f.deriveFont(Font.PLAIN, 12f);
Font f2 = f.deriveFont(Font.ITALIC, 12f);
Font f3 = f.deriveFont(Font.PLAIN, 14f);
Font f1 = new Font("Dialog", Font.PLAIN, 12);
Font f2 = new Font("Dialog", Font.ITALIC, 12);
Font f3 = new Font("Dialog", Font.PLAIN, 14);
topLeft = new JLabel();
topLeft.setFont(f1);

0
TimelineWindowUpdater.java Executable file → Normal file
View File

0
TwoToggleButton.java Executable file → Normal file
View File

0
graphics/Federated.xcf Executable file → Normal file
View File

0
graphics/Flags.xcf Executable file → Normal file
View File

0
graphics/Hourglass.xcf Executable file → Normal file
View File

0
graphics/boostToggled.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

0
graphics/boostUntoggled.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

0
graphics/button.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

0
graphics/disabledOverlay.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

0
graphics/favouriteToggled.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 353 B

After

Width:  |  Height:  |  Size: 353 B

0
graphics/favouriteUntoggled.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

0
graphics/federated.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

0
graphics/miscToggled.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

0
graphics/miscUntoggled.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

0
graphics/ref1.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

0
graphics/replyToggled.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

0
graphics/replyUntoggled.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

0
graphics/selectedOverlay.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 313 B

After

Width:  |  Height:  |  Size: 313 B

0
graphics/test1.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

0
graphics/test2.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

0
graphics/test3.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

0
graphics/test4.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

0
notifOptions.txt Executable file → Normal file
View File

0
notifOptions.txt~ Executable file → Normal file
View File