mirror of
https://gitlab.com/biskuteri-cafe/JKomasto2.git
synced 2025-01-08 20:34:44 +01:00
Added delete feature
This commit is contained in:
parent
26d4e8c97a
commit
0590cc6c19
@ -51,7 +51,7 @@ ComposeWindow extends JFrame {
|
|||||||
{
|
{
|
||||||
composition = new Composition();
|
composition = new Composition();
|
||||||
composition.text = "";
|
composition.text = "";
|
||||||
composition.visibility = PostVisibility.MENTIONED;
|
composition.visibility = PostVisibility.UNLISTED;
|
||||||
composition.replyToPostId = null;
|
composition.replyToPostId = null;
|
||||||
composition.contentWarning = null;
|
composition.contentWarning = null;
|
||||||
syncDisplayToComposition();
|
syncDisplayToComposition();
|
||||||
|
@ -351,6 +351,27 @@ MastodonApi {
|
|||||||
catch (IOException eIo) { handler.connectionFailed(eIo); }
|
catch (IOException eIo) { handler.connectionFailed(eIo); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void
|
||||||
|
deletePost(String postId, RequestListener handler)
|
||||||
|
{
|
||||||
|
String token = accessToken.get("access_token").value;
|
||||||
|
|
||||||
|
String url = instanceUrl + "/api/v1/statuses/" + postId;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
URL endpoint = new URL(url);
|
||||||
|
HttpURLConnection conn;
|
||||||
|
conn = (HttpURLConnection)endpoint.openConnection();
|
||||||
|
String s1 = "Bearer " + token;
|
||||||
|
conn.setRequestProperty("Authorization", s1);
|
||||||
|
conn.setRequestMethod("DELETE");
|
||||||
|
conn.connect();
|
||||||
|
|
||||||
|
doStandardJsonReturn(conn, handler);
|
||||||
|
}
|
||||||
|
catch (IOException eIo) { handler.connectionFailed(eIo); }
|
||||||
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
getAccounts(String query, RequestListener handler)
|
getAccounts(String query, RequestListener handler)
|
||||||
{
|
{
|
||||||
|
@ -132,13 +132,14 @@ NotificationsWindow extends JFrame {
|
|||||||
if (n.type != NotificationType.FOLLOW)
|
if (n.type != NotificationType.FOLLOW)
|
||||||
{
|
{
|
||||||
Tree<String> post = t.get("status");
|
Tree<String> post = t.get("status");
|
||||||
String pid = post.get("id").value;
|
String pid, phtml, ptext;
|
||||||
String ptext = post.get("content").value;
|
pid = post.get("id").value;
|
||||||
|
phtml = post.get("content").value;
|
||||||
|
ptext =
|
||||||
|
TimelineComponent
|
||||||
|
.textApproximation(phtml);
|
||||||
n.postId = pid;
|
n.postId = pid;
|
||||||
n.postText = ptext;
|
n.postText = ptext;
|
||||||
// Should we ask TimelineWindow for help here?
|
|
||||||
// Or should we break our text parsers into
|
|
||||||
// a separate class?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notifications.add(n);
|
notifications.add(n);
|
||||||
@ -162,7 +163,7 @@ NotificationsWindow extends JFrame {
|
|||||||
notifications = new ArrayList<>();
|
notifications = new ArrayList<>();
|
||||||
|
|
||||||
display = new NotificationsComponent(this);
|
display = new NotificationsComponent(this);
|
||||||
display.setPreferredSize(new Dimension(256, 400));
|
display.setPreferredSize(new Dimension(256, 260));
|
||||||
setContentPane(display);
|
setContentPane(display);
|
||||||
pack();
|
pack();
|
||||||
|
|
||||||
@ -190,7 +191,7 @@ implements ActionListener {
|
|||||||
// - -%- -
|
// - -%- -
|
||||||
|
|
||||||
static final int
|
static final int
|
||||||
ROW_COUNT = 16;
|
ROW_COUNT = 10;
|
||||||
|
|
||||||
// ---%-@-%---
|
// ---%-@-%---
|
||||||
|
|
||||||
@ -203,7 +204,16 @@ implements ActionListener {
|
|||||||
Notification n = notifications.get(o);
|
Notification n = notifications.get(o);
|
||||||
NotificationComponent c = rows.get(o);
|
NotificationComponent c = rows.get(o);
|
||||||
c.setName(n.actorName);
|
c.setName(n.actorName);
|
||||||
c.setType(n.type.toString());
|
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;
|
||||||
|
}
|
||||||
c.setText(n.postText);
|
c.setText(n.postText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,13 +289,13 @@ implements ComponentListener {
|
|||||||
componentResized(ComponentEvent eC)
|
componentResized(ComponentEvent eC)
|
||||||
{
|
{
|
||||||
int w = getWidth(), h = getHeight();
|
int w = getWidth(), h = getHeight();
|
||||||
name.setPreferredSize(new Dimension(w * 4 / 10, h));
|
name.setPreferredSize(new Dimension(w * 7 / 20, h));
|
||||||
type.setPreferredSize(new Dimension(w * 3 / 10, h));
|
type.setPreferredSize(new Dimension(w * 6 / 20, h));
|
||||||
text.setPreferredSize(new Dimension(w * 2 / 10, h));
|
text.setPreferredSize(new Dimension(w * 5 / 20, h));
|
||||||
|
|
||||||
name.setMaximumSize(new Dimension(w * 4 / 10, h));
|
name.setMaximumSize(new Dimension(w * 7 / 20, h));
|
||||||
type.setMaximumSize(new Dimension(w * 3 / 10, h));
|
type.setMaximumSize(new Dimension(w * 6 / 20, h));
|
||||||
text.setMaximumSize(new Dimension(w * 2 / 10, h));
|
text.setMaximumSize(new Dimension(w * 5 / 20, h));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
@ -301,9 +311,13 @@ implements ComponentListener {
|
|||||||
|
|
||||||
NotificationComponent()
|
NotificationComponent()
|
||||||
{
|
{
|
||||||
Font f1 = new Font("Dialog", Font.PLAIN, 12);
|
Font f = new Font("Dialog", Font.PLAIN, 12);
|
||||||
Font f2 = new Font("Dialog", Font.PLAIN, 10);
|
Font f1 = f.deriveFont(Font.PLAIN, 14);
|
||||||
Font f3 = new Font("Dialog", Font.ITALIC, 12);
|
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);
|
||||||
|
|
||||||
name = new JLabel();
|
name = new JLabel();
|
||||||
type = new JLabel();
|
type = new JLabel();
|
||||||
@ -314,17 +328,16 @@ implements ComponentListener {
|
|||||||
type.setHorizontalAlignment(JLabel.RIGHT);
|
type.setHorizontalAlignment(JLabel.RIGHT);
|
||||||
|
|
||||||
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
|
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
|
||||||
|
add(Box.createHorizontalStrut(4));
|
||||||
add(name);
|
add(name);
|
||||||
add(Box.createHorizontalStrut(4));
|
add(Box.createHorizontalStrut(8));
|
||||||
add(type);
|
add(type);
|
||||||
add(Box.createHorizontalStrut(4));
|
add(Box.createHorizontalStrut(8));
|
||||||
add(text);
|
add(text);
|
||||||
|
add(Box.createHorizontalStrut(4));
|
||||||
|
|
||||||
this.addComponentListener(this);
|
this.addComponentListener(this);
|
||||||
setBorder(
|
setBorder(b1);
|
||||||
BorderFactory.createMatteBorder
|
|
||||||
(1, 0, 0, 0, new Color(0, 0, 0, 25))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
160
PostWindow.java
160
PostWindow.java
@ -2,7 +2,7 @@
|
|||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JMenuBar;
|
import javax.swing.JMenuBar;
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
@ -86,6 +86,10 @@ implements ActionListener {
|
|||||||
postDisplay.setAuthorName(an);
|
postDisplay.setAuthorName(an);
|
||||||
postDisplay.setAuthorId(author.get("acct").value);
|
postDisplay.setAuthorId(author.get("acct").value);
|
||||||
|
|
||||||
|
String aid = author.get("id").value;
|
||||||
|
String oid = api.getAccountDetails().get("id").value;
|
||||||
|
postDisplay.setDeleteEnabled(aid.equals(oid));
|
||||||
|
|
||||||
String avurl = author.get("avatar").value;
|
String avurl = author.get("avatar").value;
|
||||||
postDisplay.setAuthorAvatar(ImageApi.remote(avurl));
|
postDisplay.setAuthorAvatar(ImageApi.remote(avurl));
|
||||||
|
|
||||||
@ -255,7 +259,7 @@ implements ActionListener {
|
|||||||
if (vs.equals("unlisted")) v = PostVisibility.UNLISTED;
|
if (vs.equals("unlisted")) v = PostVisibility.UNLISTED;
|
||||||
if (vs.equals("private")) v = PostVisibility.FOLLOWERS;
|
if (vs.equals("private")) v = PostVisibility.FOLLOWERS;
|
||||||
if (vs.equals("direct")) v = PostVisibility.MENTIONED;
|
if (vs.equals("direct")) v = PostVisibility.MENTIONED;
|
||||||
|
|
||||||
Composition c = new Composition();
|
Composition c = new Composition();
|
||||||
c.contentWarning = cw;
|
c.contentWarning = cw;
|
||||||
c.text = id1.equals(id2) ? "" : "@" + authorId + " ";
|
c.text = id1.equals(id2) ? "" : "@" + authorId + " ";
|
||||||
@ -300,6 +304,112 @@ implements ActionListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void
|
||||||
|
deletePost(boolean redraft)
|
||||||
|
{
|
||||||
|
postDisplay.setCursor(new Cursor(Cursor.WAIT_CURSOR));
|
||||||
|
postDisplay.setDeleteEnabled(false);
|
||||||
|
postDisplay.paintImmediately(postDisplay.getBounds());
|
||||||
|
|
||||||
|
if (redraft)
|
||||||
|
{
|
||||||
|
String html = post.get("content").value;
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
Tree<String> nodes;
|
||||||
|
nodes = RudimentaryHTMLParser.depthlessRead(html);
|
||||||
|
// We have to salvage whatever we can from the HTML.
|
||||||
|
for (Tree<String> node: nodes)
|
||||||
|
{
|
||||||
|
if (node.key.equals("text"))
|
||||||
|
{
|
||||||
|
b.append(node.value);
|
||||||
|
}
|
||||||
|
if (node.key.equals("emoji"))
|
||||||
|
{
|
||||||
|
b.append(":" + node.value + ":");
|
||||||
|
}
|
||||||
|
if (node.key.equals("tag"))
|
||||||
|
{
|
||||||
|
if (node.get(0).key.equals("/p"))
|
||||||
|
b.append("\n\n");
|
||||||
|
if (node.get(0).key.equals("br"))
|
||||||
|
b.append("\n");
|
||||||
|
if (node.get(0).key.equals("a")) {
|
||||||
|
b.append(node.get("href").value);
|
||||||
|
b.append(" ");
|
||||||
|
continue;
|
||||||
|
/*
|
||||||
|
* We don't omit the contents of the <a>
|
||||||
|
* which is an automatic label, but we'll
|
||||||
|
* need a non-depthless parser to omit that.
|
||||||
|
* For now prioritise not losing anything
|
||||||
|
* from our composition.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
// I think that's all. I hope.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String cw = post.get("spoiler_text").value;
|
||||||
|
|
||||||
|
String vs = post.get("visibility").value;
|
||||||
|
PostVisibility v = null;
|
||||||
|
if (vs.equals("public")) v = PostVisibility.PUBLIC;
|
||||||
|
if (vs.equals("unlisted")) v = PostVisibility.UNLISTED;
|
||||||
|
if (vs.equals("private")) v = PostVisibility.FOLLOWERS;
|
||||||
|
if (vs.equals("direct")) v = PostVisibility.MENTIONED;
|
||||||
|
|
||||||
|
String replyTo = post.get("in_reply_to_id").value;
|
||||||
|
|
||||||
|
Composition c = new Composition();
|
||||||
|
c.contentWarning = cw;
|
||||||
|
c.text = b.toString();
|
||||||
|
c.visibility = v;
|
||||||
|
c.replyToPostId = replyTo;
|
||||||
|
|
||||||
|
ComposeWindow w = primaire.getComposeWindow();
|
||||||
|
w.setLocation(getX(), getY() + 100);
|
||||||
|
w.setVisible(true);
|
||||||
|
w.setComposition(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
api.deletePost(post.get("id").value, new RequestListener() {
|
||||||
|
|
||||||
|
public void
|
||||||
|
connectionFailed(IOException eIo)
|
||||||
|
{
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
PostWindow.this,
|
||||||
|
"Failed to delete post.."
|
||||||
|
+ "\n" + eIo.getMessage()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void
|
||||||
|
requestFailed(int httpCode, Tree<String> json)
|
||||||
|
{
|
||||||
|
JOptionPane.showMessageDialog(
|
||||||
|
PostWindow.this,
|
||||||
|
"Failed to delete post.."
|
||||||
|
+ "\n" + json.get("error").value
|
||||||
|
+ "\n(HTTP code: " + httpCode + ")"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void
|
||||||
|
requestSucceeded(Tree<String> json)
|
||||||
|
{
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
postDisplay.setCursor(null);
|
||||||
|
postDisplay.setDeleteEnabled(true);
|
||||||
|
postDisplay.paintImmediately(postDisplay.getBounds());
|
||||||
|
if (!isVisible()) dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// - -%- -
|
// - -%- -
|
||||||
|
|
||||||
public void
|
public void
|
||||||
@ -379,6 +489,13 @@ implements ActionListener {
|
|||||||
profile,
|
profile,
|
||||||
media;
|
media;
|
||||||
|
|
||||||
|
private JPopupMenu
|
||||||
|
miscMenu;
|
||||||
|
|
||||||
|
private JMenuItem
|
||||||
|
deletePost,
|
||||||
|
redraftPost;
|
||||||
|
|
||||||
// ---%-@-%---
|
// ---%-@-%---
|
||||||
|
|
||||||
public void
|
public void
|
||||||
@ -475,6 +592,13 @@ implements ActionListener {
|
|||||||
favouriteBoost.setEnabled(a);
|
favouriteBoost.setEnabled(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void
|
||||||
|
setDeleteEnabled(boolean a)
|
||||||
|
{
|
||||||
|
deletePost.setEnabled(a);
|
||||||
|
redraftPost.setEnabled(a);
|
||||||
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
setMediaPreview(Image n) { media.setImage(n); }
|
setMediaPreview(Image n) { media.setImage(n); }
|
||||||
|
|
||||||
@ -510,7 +634,14 @@ implements ActionListener {
|
|||||||
|
|
||||||
if (src == replyMisc)
|
if (src == replyMisc)
|
||||||
{
|
{
|
||||||
if (command.startsWith("reply")) primaire.reply();
|
if (command.startsWith("reply"))
|
||||||
|
primaire.reply();
|
||||||
|
if (command.startsWith("misc"))
|
||||||
|
{
|
||||||
|
int rx = replyMisc.getWidth() / 2;
|
||||||
|
int ry = replyMisc.getHeight() - miscMenu.getHeight();
|
||||||
|
miscMenu.show(replyMisc, rx, ry);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,7 +662,20 @@ implements ActionListener {
|
|||||||
{
|
{
|
||||||
primaire.openMedia();
|
primaire.openMedia();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (src == deletePost)
|
||||||
|
{
|
||||||
|
primaire.deletePost(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src == redraftPost)
|
||||||
|
{
|
||||||
|
primaire.deletePost(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void
|
protected void
|
||||||
@ -584,6 +728,14 @@ implements ActionListener {
|
|||||||
nextPrev.addActionListener(this);
|
nextPrev.addActionListener(this);
|
||||||
media.addActionListener(this);
|
media.addActionListener(this);
|
||||||
|
|
||||||
|
deletePost = new JMenuItem("Delete post");
|
||||||
|
redraftPost = new JMenuItem("Delete and redraft post");
|
||||||
|
deletePost.addActionListener(this);
|
||||||
|
redraftPost.addActionListener(this);
|
||||||
|
miscMenu = new JPopupMenu();
|
||||||
|
miscMenu.add(deletePost);
|
||||||
|
miscMenu.add(redraftPost);
|
||||||
|
|
||||||
Box buttons = Box.createVerticalBox();
|
Box buttons = Box.createVerticalBox();
|
||||||
buttons.setOpaque(false);
|
buttons.setOpaque(false);
|
||||||
buttons.add(profile);
|
buttons.add(profile);
|
||||||
|
@ -26,26 +26,6 @@ RudimentaryHTMLParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String
|
|
||||||
stripTags(String html)
|
|
||||||
{
|
|
||||||
StringBuilder returnee = new StringBuilder();
|
|
||||||
for (Tree<String> node: depthlessRead(html))
|
|
||||||
{
|
|
||||||
if (node.key.equals("tag")) continue;
|
|
||||||
|
|
||||||
if (node.key.equals("emoji"))
|
|
||||||
{
|
|
||||||
returnee.append(":" + node.value + ":");
|
|
||||||
}
|
|
||||||
if (node.key.equals("text"))
|
|
||||||
{
|
|
||||||
returnee.append(node.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return returnee.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// - -%- -
|
// - -%- -
|
||||||
|
|
||||||
private static Tree<String>
|
private static Tree<String>
|
||||||
|
@ -450,7 +450,7 @@ implements ActionListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// - -%- -
|
// - -%- -
|
||||||
|
|
||||||
private static String
|
private static String
|
||||||
plainify(String html)
|
plainify(String html)
|
||||||
@ -620,12 +620,10 @@ implements
|
|||||||
|
|
||||||
String html = p.get("content").value;
|
String html = p.get("content").value;
|
||||||
String cw = p.get("spoiler_text").value;
|
String cw = p.get("spoiler_text").value;
|
||||||
if (!cw.isEmpty()) {
|
if (!cw.isEmpty())
|
||||||
c.setBottom("(" + cw + ")");
|
c.setBottom("(" + cw + ")");
|
||||||
}
|
else
|
||||||
else {
|
c.setBottom(textApproximation(html) + " ");
|
||||||
c.setBottom(RudimentaryHTMLParser.stripTags(html) + " ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (int o = posts.size(); o < postPreviews.size(); ++o)
|
for (int o = posts.size(); o < postPreviews.size(); ++o)
|
||||||
{
|
{
|
||||||
@ -781,6 +779,34 @@ implements
|
|||||||
public void
|
public void
|
||||||
keyReleased(KeyEvent eK) { }
|
keyReleased(KeyEvent eK) { }
|
||||||
|
|
||||||
|
// - -%- -
|
||||||
|
|
||||||
|
public static String
|
||||||
|
textApproximation(String html)
|
||||||
|
{
|
||||||
|
StringBuilder returnee = new StringBuilder();
|
||||||
|
Tree<String> nodes = RudimentaryHTMLParser.depthlessRead(html);
|
||||||
|
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)
|
TimelineComponent(TimelineWindow primaire)
|
||||||
|
Loading…
Reference in New Issue
Block a user