Load custom emoji in statuses (#400)

This commit is contained in:
Ivan Kupalov 2017-10-19 17:25:04 +04:00 committed by Konrad Pozniak
parent 2859a5075c
commit 3adef27bbb
6 changed files with 199 additions and 82 deletions

View File

@ -49,6 +49,7 @@ dependencies {
compile "com.squareup.retrofit2:converter-gson:2.3.0" compile "com.squareup.retrofit2:converter-gson:2.3.0"
compile "com.squareup.picasso:picasso:2.5.2" compile "com.squareup.picasso:picasso:2.5.2"
compile "com.squareup.okhttp3:okhttp:3.9.0" compile "com.squareup.okhttp3:okhttp:3.9.0"
compile 'com.squareup.okhttp3:logging-interceptor:3.9.0'
compile "com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0" compile "com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0"
compile "com.pkmmte.view:circularimageview:1.1" compile "com.pkmmte.view:circularimageview:1.1"
compile "com.github.varunest:sparkbutton:1.0.5" compile "com.github.varunest:sparkbutton:1.0.5"

View File

@ -50,6 +50,7 @@ import okhttp3.Interceptor;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit; import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.gson.GsonConverterFactory;
@ -126,13 +127,12 @@ public class BaseActivity extends AppCompatActivity {
protected void createMastodonApi() { protected void createMastodonApi() {
mastodonApiDispatcher = new Dispatcher(); mastodonApiDispatcher = new Dispatcher();
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder().registerTypeAdapter(Spanned.class, new SpannedTypeAdapter())
.registerTypeAdapter(Spanned.class, new SpannedTypeAdapter())
.registerTypeAdapter(StringWithEmoji.class, new StringWithEmojiTypeAdapter()) .registerTypeAdapter(StringWithEmoji.class, new StringWithEmojiTypeAdapter())
.create(); .create();
OkHttpClient okHttpClient = OkHttpUtils.getCompatibleClientBuilder() OkHttpClient.Builder okBuilder =
.addInterceptor(new Interceptor() { OkHttpUtils.getCompatibleClientBuilder().addInterceptor(new Interceptor() {
@Override @Override
public Response intercept(Chain chain) throws IOException { public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request(); Request originalRequest = chain.request();
@ -140,20 +140,21 @@ public class BaseActivity extends AppCompatActivity {
Request.Builder builder = originalRequest.newBuilder(); Request.Builder builder = originalRequest.newBuilder();
String accessToken = getAccessToken(); String accessToken = getAccessToken();
if (accessToken != null) { if (accessToken != null) {
builder.header("Authorization", String.format("Bearer %s", builder.header("Authorization", String.format("Bearer %s", accessToken));
accessToken));
} }
Request newRequest = builder.build(); Request newRequest = builder.build();
return chain.proceed(newRequest); return chain.proceed(newRequest);
} }
}) }).dispatcher(mastodonApiDispatcher);
.dispatcher(mastodonApiDispatcher)
.build();
Retrofit retrofit = new Retrofit.Builder() if (BuildConfig.DEBUG) {
.baseUrl(getBaseUrl()) okBuilder.addInterceptor(
.client(okHttpClient) new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
}
Retrofit retrofit = new Retrofit.Builder().baseUrl(getBaseUrl())
.client(okBuilder.build())
.addConverterFactory(GsonConverterFactory.create(gson)) .addConverterFactory(GsonConverterFactory.create(gson))
.build(); .build();
@ -161,11 +162,11 @@ public class BaseActivity extends AppCompatActivity {
} }
protected void createTuskyApi() { protected void createTuskyApi() {
Retrofit retrofit = new Retrofit.Builder() Retrofit retrofit =
.baseUrl("https://" + getString(R.string.tusky_api_url)) new Retrofit.Builder().baseUrl("https://" + getString(R.string.tusky_api_url))
.client(OkHttpUtils.getCompatibleClient()) .client(OkHttpUtils.getCompatibleClient())
.addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create())
.build(); .build();
tuskyApi = retrofit.create(TuskyApi.class); tuskyApi = retrofit.create(TuskyApi.class);
} }
@ -208,27 +209,25 @@ public class BaseActivity extends AppCompatActivity {
long checkInterval = 1000 * 60 * minutes; long checkInterval = 1000 * 60 * minutes;
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, PullNotificationService.class); Intent intent = new Intent(this, PullNotificationService.class);
PendingIntent serviceAlarmIntent = PendingIntent.getService(this, SERVICE_REQUEST_CODE, PendingIntent serviceAlarmIntent = PendingIntent.getService(this, SERVICE_REQUEST_CODE, intent,
intent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(),
SystemClock.elapsedRealtime(), checkInterval, serviceAlarmIntent); checkInterval, serviceAlarmIntent);
} }
protected void disablePushNotifications() { protected void disablePushNotifications() {
// Cancel the repeating call for "pull" notifications. // Cancel the repeating call for "pull" notifications.
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, PullNotificationService.class); Intent intent = new Intent(this, PullNotificationService.class);
PendingIntent serviceAlarmIntent = PendingIntent.getService(this, SERVICE_REQUEST_CODE, PendingIntent serviceAlarmIntent = PendingIntent.getService(this, SERVICE_REQUEST_CODE, intent,
intent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(serviceAlarmIntent); alarmManager.cancel(serviceAlarmIntent);
} }
protected void clearNotifications() { protected void clearNotifications() {
SharedPreferences notificationPreferences = getApplicationContext() SharedPreferences notificationPreferences =
.getSharedPreferences("Notifications", MODE_PRIVATE); getApplicationContext().getSharedPreferences("Notifications", MODE_PRIVATE);
notificationPreferences.edit() notificationPreferences.edit().putString("current", "[]").apply();
.putString("current", "[]")
.apply();
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.cancel(PullNotificationService.NOTIFY_ID); manager.cancel(PullNotificationService.NOTIFY_ID);
@ -238,10 +237,10 @@ public class BaseActivity extends AppCompatActivity {
long checkInterval = 1000 * 60 * minutes; long checkInterval = 1000 * 60 * minutes;
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, PullNotificationService.class); Intent intent = new Intent(this, PullNotificationService.class);
PendingIntent serviceAlarmIntent = PendingIntent.getService(this, SERVICE_REQUEST_CODE, PendingIntent serviceAlarmIntent = PendingIntent.getService(this, SERVICE_REQUEST_CODE, intent,
intent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(serviceAlarmIntent); alarmManager.cancel(serviceAlarmIntent);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(),
SystemClock.elapsedRealtime(), checkInterval, serviceAlarmIntent); checkInterval, serviceAlarmIntent);
} }
} }

View File

@ -2,6 +2,11 @@ package com.keylesspalace.tusky.adapter;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
@ -9,7 +14,9 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.content.res.AppCompatResources; import android.support.v7.content.res.AppCompatResources;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.text.SpannableStringBuilder;
import android.text.Spanned; import android.text.Spanned;
import android.text.style.ReplacementSpan;
import android.view.View; import android.view.View;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.ImageButton; import android.widget.ImageButton;
@ -25,11 +32,17 @@ import com.keylesspalace.tusky.util.LinkHelper;
import com.keylesspalace.tusky.util.ThemeUtils; import com.keylesspalace.tusky.util.ThemeUtils;
import com.keylesspalace.tusky.view.RoundedTransformation; import com.keylesspalace.tusky.view.RoundedTransformation;
import com.keylesspalace.tusky.viewdata.StatusViewData; import com.keylesspalace.tusky.viewdata.StatusViewData;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;
import com.varunest.sparkbutton.SparkButton; import com.varunest.sparkbutton.SparkButton;
import com.varunest.sparkbutton.SparkEventListener; import com.varunest.sparkbutton.SparkEventListener;
import java.lang.ref.WeakReference;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class StatusBaseViewHolder extends RecyclerView.ViewHolder { class StatusBaseViewHolder extends RecyclerView.ViewHolder {
private View container; private View container;
@ -80,10 +93,8 @@ class StatusBaseViewHolder extends RecyclerView.ViewHolder {
videoIndicator = itemView.findViewById(R.id.status_video_indicator); videoIndicator = itemView.findViewById(R.id.status_video_indicator);
mediaLabel = itemView.findViewById(R.id.status_media_label); mediaLabel = itemView.findViewById(R.id.status_media_label);
contentWarningBar = itemView.findViewById(R.id.status_content_warning_bar); contentWarningBar = itemView.findViewById(R.id.status_content_warning_bar);
contentWarningDescription = contentWarningDescription = itemView.findViewById(R.id.status_content_warning_description);
itemView.findViewById(R.id.status_content_warning_description); contentWarningButton = itemView.findViewById(R.id.status_content_warning_button);
contentWarningButton =
itemView.findViewById(R.id.status_content_warning_button);
} }
private void setDisplayName(String name) { private void setDisplayName(String name) {
@ -97,14 +108,43 @@ class StatusBaseViewHolder extends RecyclerView.ViewHolder {
username.setText(usernameText); username.setText(usernameText);
} }
private void setContent(Spanned content, Status.Mention[] mentions, private Callback spanCallback = new Callback() {
@Override
public void onSuccess() {
content.invalidate();
}
@Override
public void onError() {
}
};
private void setContent(Spanned content, Status.Mention[] mentions, List<Status.Emoji> emojis,
StatusActionListener listener) { StatusActionListener listener) {
SpannableStringBuilder builder = new SpannableStringBuilder(content);
if (!emojis.isEmpty()) {
CharSequence text = builder.subSequence(0, builder.length());
for (Status.Emoji emoji : emojis) {
CharSequence pattern = new StringBuilder(":").append(emoji.getShortcode()).append(':');
Matcher matcher = Pattern.compile(pattern.toString()).matcher(text);
while (matcher.find()) {
EmojiSpan span = new EmojiSpan();
span.setCallback(spanCallback);
builder.setSpan(span, matcher.start(), matcher.end(), 0);
Picasso.with(container.getContext())
.load(emoji.getUrl())
.into(span);
}
}
}
/* Redirect URLSpan's in the status content to the listener for viewing tag pages and /* Redirect URLSpan's in the status content to the listener for viewing tag pages and
* account pages. */ * account pages. */
Context context = this.content.getContext(); Context context = this.content.getContext();
boolean useCustomTabs = PreferenceManager.getDefaultSharedPreferences(context) boolean useCustomTabs =
.getBoolean("customTabs", true); PreferenceManager.getDefaultSharedPreferences(context).getBoolean("customTabs", true);
LinkHelper.setClickableText(this.content, content, mentions, useCustomTabs, listener); LinkHelper.setClickableText(this.content, builder, mentions, useCustomTabs, listener);
} }
void setAvatar(String url, @Nullable String rebloggedUrl) { void setAvatar(String url, @Nullable String rebloggedUrl) {
@ -177,15 +217,13 @@ class StatusBaseViewHolder extends RecyclerView.ViewHolder {
private void setMediaPreviews(final Status.MediaAttachment[] attachments, boolean sensitive, private void setMediaPreviews(final Status.MediaAttachment[] attachments, boolean sensitive,
final StatusActionListener listener, boolean showingSensitive) { final StatusActionListener listener, boolean showingSensitive) {
final ImageView[] previews = { final ImageView[] previews = {
mediaPreview0, mediaPreview0, mediaPreview1, mediaPreview2, mediaPreview3
mediaPreview1,
mediaPreview2,
mediaPreview3
}; };
Context context = mediaPreview0.getContext(); Context context = mediaPreview0.getContext();
int mediaPreviewUnloadedId = ThemeUtils.getDrawableId(itemView.getContext(), int mediaPreviewUnloadedId =
R.attr.media_preview_unloaded_drawable, android.R.color.black); ThemeUtils.getDrawableId(itemView.getContext(), R.attr.media_preview_unloaded_drawable,
android.R.color.black);
final int n = Math.min(attachments.length, Status.MAX_MEDIA_ATTACHMENTS); final int n = Math.min(attachments.length, Status.MAX_MEDIA_ATTACHMENTS);
@ -200,9 +238,7 @@ class StatusBaseViewHolder extends RecyclerView.ViewHolder {
previews[i].setVisibility(View.VISIBLE); previews[i].setVisibility(View.VISIBLE);
if (previewUrl == null || previewUrl.isEmpty()) { if (previewUrl == null || previewUrl.isEmpty()) {
Picasso.with(context) Picasso.with(context).load(mediaPreviewUnloadedId).into(previews[i]);
.load(mediaPreviewUnloadedId)
.into(previews[i]);
} else { } else {
Picasso.with(context) Picasso.with(context)
.load(previewUrl) .load(previewUrl)
@ -211,8 +247,7 @@ class StatusBaseViewHolder extends RecyclerView.ViewHolder {
} }
final Status.MediaAttachment.Type type = attachments[i].type; final Status.MediaAttachment.Type type = attachments[i].type;
if (type == Status.MediaAttachment.Type.VIDEO if (type == Status.MediaAttachment.Type.VIDEO | type == Status.MediaAttachment.Type.GIFV) {
| type == Status.MediaAttachment.Type.GIFV) {
videoIndicator.setVisibility(View.VISIBLE); videoIndicator.setVisibility(View.VISIBLE);
} }
@ -233,7 +268,7 @@ class StatusBaseViewHolder extends RecyclerView.ViewHolder {
if (sensitive && (!isAlwayShowSensitive)) { if (sensitive && (!isAlwayShowSensitive)) {
sensitiveMediaWarning.setVisibility(showingSensitive ? View.GONE : View.VISIBLE); sensitiveMediaWarning.setVisibility(showingSensitive ? View.GONE : View.VISIBLE);
sensitiveMediaShow.setVisibility(showingSensitive ? View.VISIBLE : View.GONE); sensitiveMediaShow.setVisibility(showingSensitive ? View.VISIBLE : View.GONE);
sensitiveMediaShow.setOnClickListener(new View.OnClickListener(){ sensitiveMediaShow.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
v.setVisibility(View.GONE); v.setVisibility(View.GONE);
@ -330,20 +365,19 @@ class StatusBaseViewHolder extends RecyclerView.ViewHolder {
contentWarningDescription.setText(spoilerText); contentWarningDescription.setText(spoilerText);
contentWarningBar.setVisibility(View.VISIBLE); contentWarningBar.setVisibility(View.VISIBLE);
contentWarningButton.setChecked(expanded); contentWarningButton.setChecked(expanded);
contentWarningButton.setOnCheckedChangeListener( contentWarningButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
new CompoundButton.OnCheckedChangeListener() { @Override
@Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (getAdapterPosition() != RecyclerView.NO_POSITION) {
if (getAdapterPosition() != RecyclerView.NO_POSITION) { listener.onExpandedChange(isChecked, getAdapterPosition());
listener.onExpandedChange(isChecked, getAdapterPosition()); }
} if (isChecked) {
if (isChecked) { content.setVisibility(View.VISIBLE);
content.setVisibility(View.VISIBLE); } else {
} else { content.setVisibility(View.GONE);
content.setVisibility(View.GONE); }
} }
} });
});
if (expanded) { if (expanded) {
content.setVisibility(View.VISIBLE); content.setVisibility(View.VISIBLE);
} else { } else {
@ -441,7 +475,7 @@ class StatusBaseViewHolder extends RecyclerView.ViewHolder {
setDisplayName(status.getUserFullName()); setDisplayName(status.getUserFullName());
setUsername(status.getNickname()); setUsername(status.getNickname());
setCreatedAt(status.getCreatedAt()); setCreatedAt(status.getCreatedAt());
setContent(status.getContent(), status.getMentions(), listener); setContent(status.getContent(), status.getMentions(), status.getEmojis(), listener);
setAvatar(status.getAvatar(), status.getRebloggedAvatar()); setAvatar(status.getAvatar(), status.getRebloggedAvatar());
setReblogged(status.isReblogged()); setReblogged(status.isReblogged());
setFavourited(status.isFavourited()); setFavourited(status.isFavourited());
@ -478,4 +512,58 @@ class StatusBaseViewHolder extends RecyclerView.ViewHolder {
setSpoilerText(status.getSpoilerText(), status.isExpanded(), listener); setSpoilerText(status.getSpoilerText(), status.isExpanded(), listener);
} }
} }
static class EmojiSpan extends ReplacementSpan implements Target {
private @Nullable
Drawable imageDrawable;
private WeakReference<Callback> callbackWeakReference;
public void setImageDrawable(@Nullable Drawable imageDrawable) {
this.imageDrawable = imageDrawable;
}
public void setCallback(Callback callback) {
this.callbackWeakReference = new WeakReference<Callback>(callback);
}
@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end,
@Nullable Paint.FontMetricsInt fm) {
if (imageDrawable == null) return 0;
Rect sizeRect = imageDrawable.getBounds();
return sizeRect.right;
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x,
int top, int y, int bottom, @NonNull Paint paint) {
if (imageDrawable == null) return;
canvas.save();
int transY = bottom - imageDrawable.getBounds().bottom;
transY -= paint.getFontMetricsInt().descent;
canvas.translate(x, transY);
imageDrawable.draw(canvas);
canvas.restore();
}
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
imageDrawable = new BitmapDrawable(bitmap);
imageDrawable.setBounds(0, 0, imageDrawable.getIntrinsicWidth() + 10,
imageDrawable.getIntrinsicHeight() + 10);
if (callbackWeakReference != null) {
Callback cb = callbackWeakReference.get();
if (cb != null) cb.onSuccess();
}
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
}
} }

View File

@ -24,6 +24,7 @@ import com.google.gson.JsonParseException;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
import java.util.Date; import java.util.Date;
import java.util.List;
public class Status { public class Status {
private Status actionableStatus; private Status actionableStatus;
@ -79,6 +80,8 @@ public class Status {
public boolean sensitive; public boolean sensitive;
public List<Emoji> emojis;
@SerializedName("spoiler_text") @SerializedName("spoiler_text")
public String spoilerText; public String spoilerText;
@ -179,4 +182,17 @@ public class Status {
public String name; public String name;
public String website; public String website;
} }
public static class Emoji {
private String shortcode;
private String url;
public String getShortcode() {
return shortcode;
}
public String getUrl() {
return url;
}
}
} }

View File

@ -20,8 +20,7 @@ public final class ViewDataUtils {
public static StatusViewData statusToViewData(@Nullable Status status) { public static StatusViewData statusToViewData(@Nullable Status status) {
if (status == null) return null; if (status == null) return null;
Status visibleStatus = status.reblog == null ? status : status.reblog; Status visibleStatus = status.reblog == null ? status : status.reblog;
return new StatusViewData.Builder() return new StatusViewData.Builder().setId(status.id)
.setId(status.id)
.setAttachments(visibleStatus.attachments) .setAttachments(visibleStatus.attachments)
.setAvatar(visibleStatus.account.avatar) .setAvatar(visibleStatus.account.avatar)
.setContent(visibleStatus.content) .setContent(visibleStatus.content)
@ -44,6 +43,7 @@ public final class ViewDataUtils {
.setSenderId(visibleStatus.account.id) .setSenderId(visibleStatus.account.id)
.setRebloggingEnabled(visibleStatus.rebloggingAllowed()) .setRebloggingEnabled(visibleStatus.rebloggingAllowed())
.setApplication(visibleStatus.application) .setApplication(visibleStatus.application)
.setEmojis(visibleStatus.emojis)
.createStatusViewData(); .createStatusViewData();
} }
@ -64,8 +64,8 @@ public final class ViewDataUtils {
statusToViewData(notification.status)); statusToViewData(notification.status));
} }
public static List<NotificationViewData> public static List<NotificationViewData> notificationListToViewDataList(
notificationListToViewDataList(List<Notification> notifications) { List<Notification> notifications) {
List<NotificationViewData> viewDatas = new ArrayList<>(notifications.size()); List<NotificationViewData> viewDatas = new ArrayList<>(notifications.size());
for (Notification n : notifications) { for (Notification n : notifications) {
viewDatas.add(notificationToViewData(n)); viewDatas.add(notificationToViewData(n));

View File

@ -5,7 +5,9 @@ import android.text.Spanned;
import com.keylesspalace.tusky.entity.Status; import com.keylesspalace.tusky.entity.Status;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List;
/** /**
* Created by charlag on 11/07/2017. * Created by charlag on 11/07/2017.
@ -41,16 +43,15 @@ public final class StatusViewData {
private final String senderId; private final String senderId;
private final boolean rebloggingEnabled; private final boolean rebloggingEnabled;
private final Status.Application application; private final Status.Application application;
private final List<Status.Emoji> emojis;
public StatusViewData(String id, Spanned content, boolean reblogged, boolean favourited, public StatusViewData(String id, Spanned content, boolean reblogged, boolean favourited,
String spoilerText, Status.Visibility visibility, String spoilerText, Status.Visibility visibility, Status.MediaAttachment[] attachments,
Status.MediaAttachment[] attachments, String rebloggedByUsername, String rebloggedByUsername, String rebloggedAvatar, boolean sensitive, boolean isExpanded,
String rebloggedAvatar, boolean sensitive, boolean isExpanded, boolean isShowingSensitiveWarning, String userFullName, String nickname, String avatar,
boolean isShowingSensitiveWarning, String userFullName, String nickname, Date createdAt, String reblogsCount, String favouritesCount, String inReplyToId,
String avatar, Date createdAt, String reblogsCount, Status.Mention[] mentions, String senderId, boolean rebloggingEnabled,
String favouritesCount, String inReplyToId, Status.Mention[] mentions, Status.Application application, List<Status.Emoji> emojis) {
String senderId, boolean rebloggingEnabled,
Status.Application application) {
this.id = id; this.id = id;
this.content = content; this.content = content;
this.reblogged = reblogged; this.reblogged = reblogged;
@ -74,6 +75,7 @@ public final class StatusViewData {
this.senderId = senderId; this.senderId = senderId;
this.rebloggingEnabled = rebloggingEnabled; this.rebloggingEnabled = rebloggingEnabled;
this.application = application; this.application = application;
this.emojis = emojis;
} }
public String getId() { public String getId() {
@ -173,6 +175,10 @@ public final class StatusViewData {
return application; return application;
} }
public List<Status.Emoji> getEmojis() {
return emojis;
}
public static class Builder { public static class Builder {
private String id; private String id;
private Spanned content; private Spanned content;
@ -197,6 +203,7 @@ public final class StatusViewData {
private String senderId; private String senderId;
private boolean rebloggingEnabled; private boolean rebloggingEnabled;
private Status.Application application; private Status.Application application;
private List<Status.Emoji> emojis;
public Builder() { public Builder() {
} }
@ -225,6 +232,7 @@ public final class StatusViewData {
senderId = viewData.senderId; senderId = viewData.senderId;
rebloggingEnabled = viewData.rebloggingEnabled; rebloggingEnabled = viewData.rebloggingEnabled;
application = viewData.application; application = viewData.application;
emojis = viewData.getEmojis();
} }
public Builder setId(String id) { public Builder setId(String id) {
@ -342,12 +350,17 @@ public final class StatusViewData {
return this; return this;
} }
public Builder setEmojis(List<Status.Emoji> emojis) {
this.emojis = emojis;
return this;
}
public StatusViewData createStatusViewData() { public StatusViewData createStatusViewData() {
if (this.emojis == null) emojis = Collections.emptyList();
return new StatusViewData(id, content, reblogged, favourited, spoilerText, visibility, return new StatusViewData(id, content, reblogged, favourited, spoilerText, visibility,
attachments, rebloggedByUsername, rebloggedAvatar, isSensitive, isExpanded, attachments, rebloggedByUsername, rebloggedAvatar, isSensitive, isExpanded,
isShowingSensitiveContent, userFullName, nickname, avatar, createdAt, isShowingSensitiveContent, userFullName, nickname, avatar, createdAt, reblogsCount,
reblogsCount, favouritesCount, inReplyToId, mentions, senderId, favouritesCount, inReplyToId, mentions, senderId, rebloggingEnabled, application, emojis);
rebloggingEnabled, application);
} }
} }
} }