mirror of https://github.com/tuskyapp/Tusky.git
21 changed files with 417 additions and 776 deletions
@ -1,133 +0,0 @@
|
||||
/* Copyright 2017 Andrew Dawson |
||||
* |
||||
* This file is part of Tusky. |
||||
* |
||||
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU |
||||
* General Public License as published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
||||
* Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License along with Tusky. If not, see |
||||
* <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package com.keylesspalace.tusky; |
||||
|
||||
import android.support.annotation.Nullable; |
||||
|
||||
import org.json.JSONArray; |
||||
import org.json.JSONException; |
||||
import org.json.JSONObject; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
class Notification { |
||||
enum Type { |
||||
MENTION, |
||||
REBLOG, |
||||
FAVOURITE, |
||||
FOLLOW, |
||||
} |
||||
private Type type; |
||||
private String id; |
||||
private String displayName; |
||||
private String username; |
||||
private String avatar; |
||||
private String accountId; |
||||
/** Which of the user's statuses has been mentioned, reblogged, or favourited. */ |
||||
private Status status; |
||||
|
||||
private Notification(Type type, String id, String displayName, String username, String avatar, |
||||
String accountId) { |
||||
this.type = type; |
||||
this.id = id; |
||||
this.displayName = displayName; |
||||
this.username = username; |
||||
this.avatar = avatar; |
||||
this.accountId = accountId; |
||||
} |
||||
|
||||
Type getType() { |
||||
return type; |
||||
} |
||||
|
||||
String getId() { |
||||
return id; |
||||
} |
||||
|
||||
String getDisplayName() { |
||||
return displayName; |
||||
} |
||||
|
||||
String getUsername() { |
||||
return username; |
||||
} |
||||
|
||||
String getAvatar() { |
||||
return avatar; |
||||
} |
||||
|
||||
String getAccountId() { |
||||
return accountId; |
||||
} |
||||
|
||||
@Nullable Status getStatus() { |
||||
return status; |
||||
} |
||||
|
||||
void setStatus(Status status) { |
||||
this.status = status; |
||||
} |
||||
|
||||
private boolean hasStatusType() { |
||||
return type == Type.MENTION |
||||
|| type == Type.FAVOURITE |
||||
|| type == Type.REBLOG; |
||||
} |
||||
|
||||
static List<Notification> parse(JSONArray array) throws JSONException { |
||||
List<Notification> notifications = new ArrayList<>(); |
||||
for (int i = 0; i < array.length(); i++) { |
||||
JSONObject object = array.getJSONObject(i); |
||||
String id = object.getString("id"); |
||||
Notification.Type type = Notification.Type.valueOf( |
||||
object.getString("type").toUpperCase()); |
||||
JSONObject account = object.getJSONObject("account"); |
||||
String displayName = account.getString("display_name"); |
||||
if (displayName.isEmpty()) { |
||||
displayName = account.getString("username"); |
||||
} |
||||
String username = account.getString("acct"); |
||||
String avatar = account.getString("avatar"); |
||||
String accountId = account.getString("id"); |
||||
Notification notification = new Notification(type, id, displayName, username, avatar, |
||||
accountId); |
||||
if (notification.hasStatusType()) { |
||||
JSONObject statusObject = object.getJSONObject("status"); |
||||
Status status = Status.parse(statusObject, false); |
||||
notification.setStatus(status); |
||||
} |
||||
notifications.add(notification); |
||||
} |
||||
return notifications; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return id.hashCode(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object other) { |
||||
if (this.id == null) { |
||||
return this == other; |
||||
} else if (!(other instanceof Notification)) { |
||||
return false; |
||||
} |
||||
Notification notification = (Notification) other; |
||||
return notification.getId().equals(this.id); |
||||
} |
||||
} |
||||
@ -1,357 +0,0 @@
|
||||
/* Copyright 2017 Andrew Dawson |
||||
* |
||||
* This file is part of Tusky. |
||||
* |
||||
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU |
||||
* General Public License as published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
||||
* Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License along with Tusky. If not, see |
||||
* <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package com.keylesspalace.tusky; |
||||
|
||||
import android.support.annotation.Nullable; |
||||
import android.text.Spanned; |
||||
|
||||
import com.emojione.Emojione; |
||||
|
||||
import org.json.JSONArray; |
||||
import org.json.JSONException; |
||||
import org.json.JSONObject; |
||||
|
||||
import java.text.ParseException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.List; |
||||
|
||||
public class Status { |
||||
enum Visibility { |
||||
PUBLIC, |
||||
UNLISTED, |
||||
PRIVATE, |
||||
} |
||||
|
||||
private String id; |
||||
private String accountId; |
||||
private String displayName; |
||||
/** the username with the remote domain appended, like @domain.name, if it's a remote account */ |
||||
private String username; |
||||
/** the main text of the status, marked up with style for links & mentions, etc */ |
||||
private Spanned content; |
||||
/** the fully-qualified url of the avatar image */ |
||||
private String avatar; |
||||
private String rebloggedByDisplayName; |
||||
/** when the status was initially created */ |
||||
private Date createdAt; |
||||
/** whether the authenticated user has reblogged this status */ |
||||
private boolean reblogged; |
||||
/** whether the authenticated user has favourited this status */ |
||||
private boolean favourited; |
||||
private boolean sensitive; |
||||
private String spoilerText; |
||||
private Visibility visibility; |
||||
private MediaAttachment[] attachments; |
||||
private Mention[] mentions; |
||||
|
||||
static final int MAX_MEDIA_ATTACHMENTS = 4; |
||||
|
||||
public Status(String id, String accountId, String displayName, String username, Spanned content, |
||||
String avatar, Date createdAt, boolean reblogged, boolean favourited, |
||||
String visibility) { |
||||
this.id = id; |
||||
this.accountId = accountId; |
||||
this.displayName = displayName; |
||||
this.username = username; |
||||
this.content = content; |
||||
this.avatar = avatar; |
||||
this.createdAt = createdAt; |
||||
this.reblogged = reblogged; |
||||
this.favourited = favourited; |
||||
this.spoilerText = ""; |
||||
this.visibility = Visibility.valueOf(visibility.toUpperCase()); |
||||
this.attachments = new MediaAttachment[0]; |
||||
this.mentions = new Mention[0]; |
||||
} |
||||
|
||||
String getId() { |
||||
return id; |
||||
} |
||||
|
||||
String getAccountId() { |
||||
return accountId; |
||||
} |
||||
|
||||
String getDisplayName() { |
||||
return displayName; |
||||
} |
||||
|
||||
String getUsername() { |
||||
return username; |
||||
} |
||||
|
||||
Spanned getContent() { |
||||
return content; |
||||
} |
||||
|
||||
String getAvatar() { |
||||
return avatar; |
||||
} |
||||
|
||||
Date getCreatedAt() { |
||||
return createdAt; |
||||
} |
||||
|
||||
String getRebloggedByDisplayName() { |
||||
return rebloggedByDisplayName; |
||||
} |
||||
|
||||
boolean getReblogged() { |
||||
return reblogged; |
||||
} |
||||
|
||||
boolean getFavourited() { |
||||
return favourited; |
||||
} |
||||
|
||||
boolean getSensitive() { |
||||
return sensitive; |
||||
} |
||||
|
||||
String getSpoilerText() { |
||||
return spoilerText; |
||||
} |
||||
|
||||
Visibility getVisibility() { |
||||
return visibility; |
||||
} |
||||
|
||||
MediaAttachment[] getAttachments() { |
||||
return attachments; |
||||
} |
||||
|
||||
Mention[] getMentions() { |
||||
return mentions; |
||||
} |
||||
|
||||
private void setRebloggedByDisplayName(String name) { |
||||
rebloggedByDisplayName = name; |
||||
} |
||||
|
||||
void setReblogged(boolean reblogged) { |
||||
this.reblogged = reblogged; |
||||
} |
||||
|
||||
void setFavourited(boolean favourited) { |
||||
this.favourited = favourited; |
||||
} |
||||
|
||||
private void setSpoilerText(String spoilerText) { |
||||
this.spoilerText = spoilerText; |
||||
} |
||||
|
||||
private void setMentions(Mention[] mentions) { |
||||
this.mentions = mentions; |
||||
} |
||||
|
||||
private void setAttachments(MediaAttachment[] attachments, boolean sensitive) { |
||||
this.attachments = attachments; |
||||
this.sensitive = sensitive; |
||||
} |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return id.hashCode(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object other) { |
||||
if (this.id == null) { |
||||
return this == other; |
||||
} else if (!(other instanceof Status)) { |
||||
return false; |
||||
} |
||||
Status status = (Status) other; |
||||
return status.id.equals(this.id); |
||||
} |
||||
|
||||
@SuppressWarnings("SimpleDateFormat") // UTC needs to not specify a Locale
|
||||
@Nullable |
||||
private static Date parseDate(String dateTime) { |
||||
Date date; |
||||
String s = dateTime.replace("Z", "+00:00"); |
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); |
||||
try { |
||||
date = format.parse(s); |
||||
} catch (ParseException e) { |
||||
e.printStackTrace(); |
||||
return null; |
||||
} |
||||
return date; |
||||
} |
||||
|
||||
private static MediaAttachment.Type parseMediaType(@Nullable String type) { |
||||
if (type == null) { |
||||
return MediaAttachment.Type.UNKNOWN; |
||||
} |
||||
switch (type.toUpperCase()) { |
||||
case "IMAGE": return MediaAttachment.Type.IMAGE; |
||||
case "GIFV": |
||||
case "VIDEO": return MediaAttachment.Type.VIDEO; |
||||
default: return MediaAttachment.Type.UNKNOWN; |
||||
} |
||||
} |
||||
|
||||
public static Status parse(JSONObject object, boolean isReblog) throws JSONException { |
||||
String id = object.getString("id"); |
||||
String content = object.getString("content"); |
||||
Date createdAt = parseDate(object.getString("created_at")); |
||||
boolean reblogged = object.optBoolean("reblogged"); |
||||
boolean favourited = object.optBoolean("favourited"); |
||||
String spoilerText = object.getString("spoiler_text"); |
||||
boolean sensitive = object.optBoolean("sensitive"); |
||||
String visibility = object.getString("visibility"); |
||||
|
||||
JSONObject account = object.getJSONObject("account"); |
||||
String accountId = account.getString("id"); |
||||
String displayName = account.getString("display_name"); |
||||
if (displayName.isEmpty()) { |
||||
displayName = account.getString("username"); |
||||
} |
||||
String username = account.getString("acct"); |
||||
String avatarUrl = account.getString("avatar"); |
||||
String avatar; |
||||
if (!avatarUrl.equals("/avatars/original/missing.png")) { |
||||
avatar = avatarUrl; |
||||
} else { |
||||
avatar = ""; |
||||
} |
||||
|
||||
JSONArray mentionsArray = object.getJSONArray("mentions"); |
||||
Mention[] mentions = null; |
||||
if (mentionsArray != null) { |
||||
int n = mentionsArray.length(); |
||||
mentions = new Mention[n]; |
||||
for (int i = 0; i < n; i++) { |
||||
JSONObject mention = mentionsArray.getJSONObject(i); |
||||
String url = mention.getString("url"); |
||||
String mentionedUsername = mention.getString("acct"); |
||||
String mentionedAccountId = mention.getString("id"); |
||||
mentions[i] = new Mention(url, mentionedUsername, mentionedAccountId); |
||||
} |
||||
} |
||||
|
||||
JSONArray mediaAttachments = object.getJSONArray("media_attachments"); |
||||
MediaAttachment[] attachments = null; |
||||
if (mediaAttachments != null) { |
||||
int n = mediaAttachments.length(); |
||||
attachments = new MediaAttachment[n]; |
||||
for (int i = 0; i < n; i++) { |
||||
JSONObject attachment = mediaAttachments.getJSONObject(i); |
||||
String url = attachment.getString("url"); |
||||
String previewUrl = attachment.getString("preview_url"); |
||||
String type = attachment.getString("type"); |
||||
attachments[i] = new MediaAttachment(url, previewUrl, parseMediaType(type)); |
||||
} |
||||
} |
||||
|
||||
Status reblog = null; |
||||
/* This case shouldn't be hit after the first recursion at all. But if this method is |
||||
* passed unusual data this check will prevent extra recursion */ |
||||
if (!isReblog) { |
||||
JSONObject reblogObject = object.optJSONObject("reblog"); |
||||
if (reblogObject != null) { |
||||
reblog = parse(reblogObject, true); |
||||
} |
||||
} |
||||
|
||||
Status status; |
||||
if (reblog != null) { |
||||
status = reblog; |
||||
status.setRebloggedByDisplayName(displayName); |
||||
} else { |
||||
Spanned contentPlus = HtmlUtils.fromHtml(Emojione.shortnameToUnicode(content, false)); |
||||
status = new Status( |
||||
id, accountId, displayName, username, contentPlus, avatar, createdAt, |
||||
reblogged, favourited, visibility); |
||||
if (mentions != null) { |
||||
status.setMentions(mentions); |
||||
} |
||||
if (attachments != null) { |
||||
status.setAttachments(attachments, sensitive); |
||||
} |
||||
if (!spoilerText.isEmpty()) { |
||||
status.setSpoilerText(spoilerText); |
||||
} |
||||
} |
||||
return status; |
||||
} |
||||
|
||||
public static List<Status> parse(JSONArray array) throws JSONException { |
||||
List<Status> statuses = new ArrayList<>(); |
||||
for (int i = 0; i < array.length(); i++) { |
||||
JSONObject object = array.getJSONObject(i); |
||||
statuses.add(parse(object, false)); |
||||
} |
||||
return statuses; |
||||
} |
||||
|
||||
static class MediaAttachment { |
||||
enum Type { |
||||
IMAGE, |
||||
VIDEO, |
||||
UNKNOWN, |
||||
} |
||||
|
||||
private String url; |
||||
private String previewUrl; |
||||
private Type type; |
||||
|
||||
MediaAttachment(String url, String previewUrl, Type type) { |
||||
this.url = url; |
||||
this.previewUrl = previewUrl; |
||||
this.type = type; |
||||
} |
||||
|
||||
String getUrl() { |
||||
return url; |
||||
} |
||||
|
||||
String getPreviewUrl() { |
||||
return previewUrl; |
||||
} |
||||
|
||||
Type getType() { |
||||
return type; |
||||
} |
||||
} |
||||
|
||||
static class Mention { |
||||
private String url; |
||||
private String username; |
||||
private String id; |
||||
|
||||
Mention(String url, String username, String id) { |
||||
this.url = url; |
||||
this.username = username; |
||||
this.id = id; |
||||
} |
||||
|
||||
String getUrl() { |
||||
return url; |
||||
} |
||||
|
||||
String getUsername() { |
||||
return username; |
||||
} |
||||
|
||||
String getId() { |
||||
return id; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,55 @@
|
||||
/* Copyright 2017 Andrew Dawson |
||||
* |
||||
* This file is part of Tusky. |
||||
* |
||||
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU |
||||
* General Public License as published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
||||
* Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License along with Tusky. If not, see |
||||
* <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package com.keylesspalace.tusky.entity; |
||||
|
||||
import com.google.gson.annotations.SerializedName; |
||||
|
||||
public class Notification { |
||||
public enum Type { |
||||
@SerializedName("mention") |
||||
MENTION, |
||||
@SerializedName("reblog") |
||||
REBLOG, |
||||
@SerializedName("favourite") |
||||
FAVOURITE, |
||||
@SerializedName("follow") |
||||
FOLLOW, |
||||
} |
||||
|
||||
public Type type; |
||||
|
||||
public String id; |
||||
|
||||
public Account account; |
||||
|
||||
public Status status; |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return id.hashCode(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object other) { |
||||
if (this.id == null) { |
||||
return this == other; |
||||
} else if (!(other instanceof Notification)) { |
||||
return false; |
||||
} |
||||
Notification notification = (Notification) other; |
||||
return notification.id.equals(this.id); |
||||
} |
||||
} |
||||
@ -0,0 +1,122 @@
|
||||
/* Copyright 2017 Andrew Dawson |
||||
* |
||||
* This file is part of Tusky. |
||||
* |
||||
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU |
||||
* General Public License as published by the Free Software Foundation, either version 3 of the |
||||
* License, or (at your option) any later version. |
||||
* |
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
||||
* Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License along with Tusky. If not, see |
||||
* <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package com.keylesspalace.tusky.entity; |
||||
|
||||
import android.text.Spanned; |
||||
|
||||
import com.google.gson.annotations.SerializedName; |
||||
|
||||
import java.util.Date; |
||||
|
||||
public class Status { |
||||
private Status actionableStatus; |
||||
|
||||
public String getActionableId() { |
||||
return reblog == null ? id : reblog.id; |
||||
} |
||||
|
||||
public Status getActionableStatus() { |
||||
return reblog == null ? this : reblog; |
||||
} |
||||
|
||||
public enum Visibility { |
||||
@SerializedName("public") |
||||
PUBLIC, |
||||
@SerializedName("unlisted") |
||||
UNLISTED, |
||||
@SerializedName("private") |
||||
PRIVATE, |
||||
} |
||||
|
||||
public String id; |
||||
|
||||
public Account account; |
||||
|
||||
public Spanned content; |
||||
|
||||
public Status reblog; |
||||
|
||||
@SerializedName("created_at") |
||||
public Date createdAt; |
||||
|
||||
public boolean reblogged; |
||||
|
||||
public boolean favourited; |
||||
|
||||
public boolean sensitive; |
||||
|
||||
@SerializedName("spoiler_text") |
||||
public String spoilerText; |
||||
|
||||
public Visibility visibility; |
||||
|
||||
@SerializedName("media_attachments") |
||||
public MediaAttachment[] attachments; |
||||
|
||||
public Mention[] mentions; |
||||
|
||||
public static final int MAX_MEDIA_ATTACHMENTS = 4; |
||||
|
||||
@Override |
||||
public int hashCode() { |
||||
return id.hashCode(); |
||||
} |
||||
|
||||
@Override |
||||
public boolean equals(Object other) { |
||||
if (this.id == null) { |
||||
return this == other; |
||||
} else if (!(other instanceof Status)) { |
||||
return false; |
||||
} |
||||
Status status = (Status) other; |
||||
return status.id.equals(this.id); |
||||
} |
||||
|
||||
public static class MediaAttachment { |
||||
public enum Type { |
||||
@SerializedName("image") |
||||
IMAGE, |
||||
@SerializedName("gifv") |
||||
GIFV, |
||||
@SerializedName("video") |
||||
VIDEO, |
||||
UNKNOWN, |
||||
} |
||||
|
||||
public String url; |
||||
|
||||
@SerializedName("preview_url") |
||||
public String previewUrl; |
||||
|
||||
@SerializedName("text_url") |
||||
public String textUrl; |
||||
|
||||
@SerializedName("remote_url") |
||||
public String remoteUrl; |
||||
|
||||
public Type type; |
||||
} |
||||
|
||||
public static class Mention { |
||||
public String id; |
||||
|
||||
public String url; |
||||
|
||||
@SerializedName("acct") |
||||
public String username; |
||||
} |
||||
} |
||||
Loading…
Reference in new issue