fedilab-Android-App/app/src/main/java/app/fedilab/android/client/Entities/Notification.java

356 lines
17 KiB
Java
Raw Normal View History

2017-05-05 16:36:04 +02:00
/* Copyright 2017 Thomas Schneider
*
2019-05-18 11:10:30 +02:00
* This file is a part of Fedilab
2017-05-05 16:36:04 +02:00
*
* This program 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.
*
2019-05-18 11:10:30 +02:00
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
2017-05-05 16:36:04 +02:00
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
2019-05-18 11:10:30 +02:00
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
2017-05-05 16:36:04 +02:00
* see <http://www.gnu.org/licenses>. */
2019-05-18 11:10:30 +02:00
package app.fedilab.android.client.Entities;
2017-05-05 16:36:04 +02:00
2019-01-02 14:22:57 +01:00
import android.app.Activity;
import android.content.Context;
2019-07-26 15:58:54 +02:00
import android.content.SharedPreferences;
2019-01-02 14:22:57 +01:00
import android.graphics.Bitmap;
2019-07-26 15:58:54 +02:00
import android.graphics.drawable.BitmapDrawable;
2019-07-26 10:30:07 +02:00
import android.graphics.drawable.Drawable;
2017-08-28 15:01:45 +02:00
import android.os.Parcel;
import android.os.Parcelable;
2019-06-11 19:38:26 +02:00
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
2019-01-02 14:22:57 +01:00
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
2019-08-08 09:50:24 +02:00
2019-01-02 14:22:57 +01:00
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.github.penfeizhou.animation.apng.APNGDrawable;
2019-08-24 14:10:13 +02:00
import com.github.penfeizhou.animation.apng.decode.APNGParser;
import com.github.penfeizhou.animation.gif.GifDrawable;
2019-08-24 14:10:13 +02:00
import com.github.penfeizhou.animation.gif.decode.GifParser;
2017-08-28 15:01:45 +02:00
2019-08-02 18:35:49 +02:00
import java.io.File;
2017-05-05 16:36:04 +02:00
import java.util.Date;
2019-01-02 14:22:57 +01:00
import java.util.List;
2019-08-08 09:43:12 +02:00
import app.fedilab.android.R;
2019-05-18 11:10:30 +02:00
import app.fedilab.android.helper.Helper;
import app.fedilab.android.interfaces.OnRetrieveEmojiInterface;
2017-05-05 16:36:04 +02:00
2019-07-26 15:58:54 +02:00
import static app.fedilab.android.helper.Helper.drawableToBitmap;
2017-05-05 16:36:04 +02:00
/**
* Created by Thomas on 23/04/2017.
*/
2017-08-28 15:01:45 +02:00
public class Notification implements Parcelable {
2017-05-05 16:36:04 +02:00
private String id;
private String type;
private Date created_at;
private Account account;
private Status status;
2019-07-26 11:36:08 +02:00
private boolean notificationAnimated = false;
2019-08-02 18:35:49 +02:00
private boolean isEmojiFound = false;
2017-05-05 16:36:04 +02:00
2017-08-28 15:01:45 +02:00
protected Notification(Parcel in) {
id = in.readString();
type = in.readString();
account = in.readParcelable(Account.class.getClassLoader());
status = in.readParcelable(Status.class.getClassLoader());
}
public Notification(){};
2017-08-28 15:01:45 +02:00
public static final Creator<Notification> CREATOR = new Creator<Notification>() {
@Override
public Notification createFromParcel(Parcel in) {
return new Notification(in);
}
@Override
public Notification[] newArray(int size) {
return new Notification[size];
}
};
2017-05-05 16:36:04 +02:00
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Date getCreated_at() {
return created_at;
}
public void setCreated_at(Date created_at) {
this.created_at = created_at;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
2017-08-28 15:01:45 +02:00
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(type);
dest.writeParcelable(account, flags);
dest.writeParcelable(status, flags);
}
2018-01-09 18:56:23 +01:00
@Override
public boolean equals(Object otherNotifications) {
return otherNotifications != null && (otherNotifications == this || otherNotifications instanceof Notification && this.getId().equals(((Notification) otherNotifications).getId()));
}
2019-01-02 14:22:57 +01:00
public static void makeEmojis(final Context context, final OnRetrieveEmojiInterface listener, Notification notification){
if( ((Activity)context).isFinishing() )
return;
Status status = notification.getStatus();
2019-08-15 11:16:44 +02:00
java.util.List<Emojis> emojis = null;
if (status != null){
emojis = status.getEmojis();
}
List<Emojis> emojisAccounts = notification.getAccount().getEmojis();
2019-08-08 09:43:12 +02:00
String typeString = "";
switch (notification.getType()){
case "mention":
if( notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0)
typeString = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),context.getString(R.string.notif_mention));
else
typeString = String.format("@%s %s", notification.getAccount().getUsername(),context.getString(R.string.notif_mention));
break;
case "poll":
typeString = context.getString(R.string.notif_poll);;
break;
case "reblog":
if( notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0)
typeString = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),context.getString(R.string.notif_reblog));
else
typeString = String.format("@%s %s", notification.getAccount().getUsername(),context.getString(R.string.notif_reblog));
break;
case "favourite":
if( notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0)
typeString = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),context.getString(R.string.notif_favourite));
else
typeString = String.format("@%s %s", notification.getAccount().getUsername(),context.getString(R.string.notif_favourite));
break;
case "follow":
if( notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0)
typeString = String.format("%s %s", Helper.shortnameToUnicode(notification.getAccount().getDisplay_name(), true),context.getString(R.string.notif_follow));
else
typeString = String.format("@%s %s", notification.getAccount().getUsername(),context.getString(R.string.notif_follow));
break;
}
SpannableString displayNameSpan = new SpannableString(typeString);
2019-07-26 15:58:54 +02:00
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean disableAnimatedEmoji = sharedpreferences.getBoolean(Helper.SET_DISABLE_ANIMATED_EMOJI, false);
2019-08-08 09:43:12 +02:00
if( emojisAccounts != null && emojisAccounts.size() > 0 ) {
final int[] j = {0};
for (final Emojis emoji : emojisAccounts) {
Glide.with(context)
.asDrawable()
.load(emoji.getUrl())
.listener(new RequestListener<Drawable>() {
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
return false;
}
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
j[0]++;
if( j[0] == (emojisAccounts.size())) {
listener.onRetrieveEmoji(notification);
}
return false;
}
})
.into(new SimpleTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
final String targetedEmoji = ":" + emoji.getShortcode() + ":";
2019-08-08 18:44:41 +02:00
if (displayNameSpan.toString().contains(targetedEmoji)) {
2019-08-08 09:43:12 +02:00
//emojis can be used several times so we have to loop
for (int startPosition = -1; (startPosition = displayNameSpan.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + targetedEmoji.length();
if(endPosition <= displayNameSpan.toString().length() && endPosition >= startPosition) {
resource.setBounds(0,0,(int) Helper.convertDpToPixel(20, context),(int) Helper.convertDpToPixel(20, context));
resource.setVisible(true, true);
ImageSpan imageSpan = new ImageSpan(resource);
displayNameSpan.setSpan(
imageSpan, startPosition,
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
}
}
j[0]++;
if( j[0] == (emojisAccounts.size())) {
notification.getAccount().setdisplayNameSpan(displayNameSpan);
listener.onRetrieveEmoji(notification);
}
}
});
}
}
2019-08-15 11:16:44 +02:00
if( status != null && emojis != null && emojis.size() > 0 ) {
SpannableString contentSpan = status.getContentSpan();
SpannableString contentSpanCW = status.getContentSpanCW();
2019-01-02 14:22:57 +01:00
final int[] i = {0};
for (final Emojis emoji : emojis) {
2019-08-15 11:16:44 +02:00
List<Emojis> finalEmojis = emojis;
2019-01-02 14:22:57 +01:00
Glide.with(context)
2019-08-02 18:35:49 +02:00
.asFile()
2019-01-02 14:22:57 +01:00
.load(emoji.getUrl())
2019-08-02 18:35:49 +02:00
.listener(new RequestListener<File>() {
2019-01-02 14:22:57 +01:00
@Override
2019-08-02 18:35:49 +02:00
public boolean onResourceReady(File resource, Object model, Target<File> target, DataSource dataSource, boolean isFirstResource) {
2019-01-02 14:22:57 +01:00
return false;
}
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
i[0]++;
2019-08-15 11:16:44 +02:00
if( i[0] == (finalEmojis.size())) {
2019-01-02 14:22:57 +01:00
listener.onRetrieveEmoji(status,false);
}
return false;
}
})
2019-08-02 18:35:49 +02:00
.into(new SimpleTarget<File>() {
2019-01-02 14:22:57 +01:00
@Override
2019-08-02 18:35:49 +02:00
public void onResourceReady(@NonNull File resourceFile, @Nullable Transition<? super File> transition) {
Drawable resource;
2019-08-24 14:10:13 +02:00
if (GifParser.isGif(resourceFile.getAbsolutePath())) {
resource = GifDrawable.fromFile(resourceFile.getAbsolutePath());
2019-08-24 14:10:13 +02:00
} else if (APNGParser.isAPNG(resourceFile.getAbsolutePath())) {
resource = APNGDrawable.fromFile(resourceFile.getAbsolutePath());
2019-08-24 14:10:13 +02:00
} else {
resource = Drawable.createFromPath(resourceFile.getAbsolutePath());
}
if( resource == null){
return;
2019-08-02 18:35:49 +02:00
}
2019-01-02 14:22:57 +01:00
final String targetedEmoji = ":" + emoji.getShortcode() + ":";
if (contentSpan != null && contentSpan.toString().contains(targetedEmoji)) {
//emojis can be used several times so we have to loop
for (int startPosition = -1; (startPosition = contentSpan.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + targetedEmoji.length();
2019-07-26 10:30:07 +02:00
if( endPosition <= contentSpan.toString().length() && endPosition >= startPosition) {
2019-07-26 15:58:54 +02:00
ImageSpan imageSpan;
if( !disableAnimatedEmoji) {
resource.setBounds(0, 0, (int) Helper.convertDpToPixel(20, context), (int) Helper.convertDpToPixel(20, context));
resource.setVisible(true, true);
imageSpan = new ImageSpan(resource);
}else{
Bitmap bitmap = drawableToBitmap(resource);
imageSpan = new ImageSpan(context,
Bitmap.createScaledBitmap(bitmap, (int) Helper.convertDpToPixel(20, context),
(int) Helper.convertDpToPixel(20, context), false));
}
2019-01-02 14:22:57 +01:00
contentSpan.setSpan(
2019-07-26 10:30:07 +02:00
imageSpan, startPosition,
2019-01-02 14:22:57 +01:00
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
2019-07-26 10:30:07 +02:00
}
2019-01-02 14:22:57 +01:00
}
}
if (contentSpanCW != null && contentSpanCW.toString().contains(targetedEmoji)) {
//emojis can be used several times so we have to loop
for (int startPosition = -1; (startPosition = contentSpanCW.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + targetedEmoji.length();
2019-07-26 10:30:07 +02:00
if( endPosition <= contentSpanCW.toString().length() && endPosition >= startPosition) {
2019-07-26 15:58:54 +02:00
ImageSpan imageSpan;
if( !disableAnimatedEmoji) {
resource.setBounds(0, 0, (int) Helper.convertDpToPixel(20, context), (int) Helper.convertDpToPixel(20, context));
resource.setVisible(true, true);
imageSpan = new ImageSpan(resource);
}else {
resource.setVisible(true, true);
Bitmap bitmap = drawableToBitmap(resource);
imageSpan = new ImageSpan(context,
Bitmap.createScaledBitmap(bitmap, (int) Helper.convertDpToPixel(20, context),
(int) Helper.convertDpToPixel(20, context), false));
}
2019-01-02 14:22:57 +01:00
contentSpanCW.setSpan(
2019-07-26 10:30:07 +02:00
imageSpan, startPosition,
2019-01-02 14:22:57 +01:00
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
2019-07-26 10:30:07 +02:00
}
2019-01-02 14:22:57 +01:00
}
}
i[0]++;
2019-08-15 11:16:44 +02:00
if( i[0] == (finalEmojis.size())) {
2019-01-02 14:22:57 +01:00
status.setContentSpan(contentSpan);
status.setContentSpanCW(contentSpanCW);
status.setEmojiFound(true);
listener.onRetrieveEmoji(notification);
}
}
});
}
}
}
2019-07-26 11:36:08 +02:00
public boolean isNotificationAnimated() {
return notificationAnimated;
}
public void setNotificationAnimated(boolean notificationAnimated) {
this.notificationAnimated = notificationAnimated;
}
2019-08-02 18:35:49 +02:00
public boolean isEmojiFound() {
return isEmojiFound;
}
public void setEmojiFound(boolean emojiFound) {
isEmojiFound = emojiFound;
}
2017-05-05 16:36:04 +02:00
}