Merge branch 'animated_emoji' into develop
This commit is contained in:
commit
0dff65192a
|
@ -4,7 +4,7 @@ android {
|
|||
compileSdkVersion 28
|
||||
buildToolsVersion "28.0.3"
|
||||
defaultConfig {
|
||||
minSdkVersion 18
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 28
|
||||
versionCode 295
|
||||
versionName "2.11.0"
|
||||
|
@ -52,6 +52,7 @@ allprojects {
|
|||
maven { url "https://jitpack.io" }
|
||||
maven { url "https://maven.google.com"}
|
||||
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
|
||||
maven { url "https://dl.bintray.com/osborn/Android" }
|
||||
}
|
||||
}
|
||||
ext.supportLibraryVersion = '28.0.0'
|
||||
|
@ -120,4 +121,6 @@ dependencies {
|
|||
implementation "ch.acra:acra-notification:$acraVersion"
|
||||
implementation 'com.github.stom79:Android-WYSIWYG-Editor:3.2.1'
|
||||
implementation 'com.github.duanhong169:colorpicker:1.1.6'
|
||||
|
||||
implementation 'com.github.pengfeizhou.android.animation:glide-plugin:0.2.16'
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
|
@ -18,6 +18,7 @@ package app.fedilab.android.client.Entities;
|
|||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -51,6 +52,7 @@ public class Notification implements Parcelable {
|
|||
private Date created_at;
|
||||
private Account account;
|
||||
private Status status;
|
||||
private boolean notificationAnimated = false;
|
||||
|
||||
protected Notification(Parcel in) {
|
||||
id = in.readString();
|
||||
|
@ -159,11 +161,11 @@ public class Notification implements Parcelable {
|
|||
final int[] i = {0};
|
||||
for (final Emojis emoji : emojis) {
|
||||
Glide.with(context)
|
||||
.asBitmap()
|
||||
.asDrawable()
|
||||
.load(emoji.getUrl())
|
||||
.listener(new RequestListener<Bitmap>() {
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -176,47 +178,53 @@ public class Notification implements Parcelable {
|
|||
return false;
|
||||
}
|
||||
})
|
||||
.into(new SimpleTarget<Bitmap>() {
|
||||
.into(new SimpleTarget<Drawable>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
|
||||
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
|
||||
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();
|
||||
if( endPosition <= contentSpan.toString().length() && endPosition >= startPosition)
|
||||
if( endPosition <= contentSpan.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);
|
||||
contentSpan.setSpan(
|
||||
new ImageSpan(context,
|
||||
Bitmap.createScaledBitmap(resource, (int) Helper.convertDpToPixel(20, context),
|
||||
(int) Helper.convertDpToPixel(20, context), false)), startPosition,
|
||||
imageSpan, startPosition,
|
||||
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if (displayNameSpan != null && displayNameSpan.toString().contains(targetedEmoji)) {
|
||||
//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)
|
||||
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(
|
||||
new ImageSpan(context,
|
||||
Bitmap.createScaledBitmap(resource, (int) Helper.convertDpToPixel(20, context),
|
||||
(int) Helper.convertDpToPixel(20, context), false)), startPosition,
|
||||
imageSpan, startPosition,
|
||||
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
status.setDisplayNameSpan(displayNameSpan);*/
|
||||
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();
|
||||
if( endPosition <= contentSpan.toString().length() && endPosition >= startPosition)
|
||||
if( endPosition <= contentSpanCW.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);
|
||||
contentSpanCW.setSpan(
|
||||
new ImageSpan(context,
|
||||
Bitmap.createScaledBitmap(resource, (int) Helper.convertDpToPixel(20, context),
|
||||
(int) Helper.convertDpToPixel(20, context), false)), startPosition,
|
||||
imageSpan, startPosition,
|
||||
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
i[0]++;
|
||||
if( i[0] == (emojis.size())) {
|
||||
status.setContentSpan(contentSpan);
|
||||
|
@ -231,4 +239,11 @@ public class Notification implements Parcelable {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isNotificationAnimated() {
|
||||
return notificationAnimated;
|
||||
}
|
||||
|
||||
public void setNotificationAnimated(boolean notificationAnimated) {
|
||||
this.notificationAnimated = notificationAnimated;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
@ -48,7 +49,6 @@ 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 java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -148,6 +148,7 @@ public class Status implements Parcelable{
|
|||
|
||||
private int warningFetched = -1;
|
||||
private List<String> imageURL;
|
||||
private boolean statusAnimated = false;
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
|
@ -1081,11 +1082,11 @@ public class Status implements Parcelable{
|
|||
final int[] i = {0};
|
||||
for (final Emojis emoji : emojis) {
|
||||
Glide.with(context)
|
||||
.asBitmap()
|
||||
.asDrawable()
|
||||
.load(emoji.getUrl())
|
||||
.listener(new RequestListener<Bitmap>() {
|
||||
.listener(new RequestListener<Drawable>() {
|
||||
@Override
|
||||
public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
|
||||
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1098,47 +1099,54 @@ public class Status implements Parcelable{
|
|||
return false;
|
||||
}
|
||||
})
|
||||
.into(new SimpleTarget<Bitmap>() {
|
||||
.into(new SimpleTarget<Drawable>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
|
||||
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
|
||||
|
||||
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();
|
||||
if( endPosition <= contentSpan.toString().length() && endPosition >= startPosition)
|
||||
if( endPosition <= contentSpan.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);
|
||||
contentSpan.setSpan(
|
||||
new ImageSpan(context,
|
||||
Bitmap.createScaledBitmap(resource, (int) Helper.convertDpToPixel(20, context),
|
||||
(int) Helper.convertDpToPixel(20, context), false)), startPosition,
|
||||
imageSpan, startPosition,
|
||||
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (displayNameSpan != null && displayNameSpan.toString().contains(targetedEmoji)) {
|
||||
//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)
|
||||
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(
|
||||
new ImageSpan(context,
|
||||
Bitmap.createScaledBitmap(resource, (int) Helper.convertDpToPixel(20, context),
|
||||
(int) Helper.convertDpToPixel(20, context), false)), startPosition,
|
||||
imageSpan, startPosition,
|
||||
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
status.setDisplayNameSpan(displayNameSpan);
|
||||
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();
|
||||
if( endPosition <= contentSpan.toString().length() && endPosition >= startPosition)
|
||||
if( endPosition <= contentSpanCW.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);
|
||||
contentSpanCW.setSpan(
|
||||
new ImageSpan(context,
|
||||
Bitmap.createScaledBitmap(resource, (int) Helper.convertDpToPixel(20, context),
|
||||
(int) Helper.convertDpToPixel(20, context), false)), startPosition,
|
||||
imageSpan, startPosition,
|
||||
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
i[0]++;
|
||||
if( i[0] == (emojis.size())) {
|
||||
status.setContentSpan(contentSpan);
|
||||
|
@ -1147,6 +1155,12 @@ public class Status implements Parcelable{
|
|||
listener.onRetrieveEmoji(status, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -1557,4 +1571,12 @@ public class Status implements Parcelable{
|
|||
public void setImageURL(List<String> imageURL) {
|
||||
this.imageURL = imageURL;
|
||||
}
|
||||
|
||||
public boolean isStatusAnimated() {
|
||||
return statusAnimated;
|
||||
}
|
||||
|
||||
public void setStatusAnimated(boolean statusAnimated) {
|
||||
this.statusAnimated = statusAnimated;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,10 @@ import java.io.FileOutputStream;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import app.fedilab.android.activities.AccountReportActivity;
|
||||
import app.fedilab.android.client.API;
|
||||
|
@ -372,7 +376,25 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On
|
|||
holder.status_document_container.setVisibility(View.GONE);
|
||||
else
|
||||
holder.status_document_container.setVisibility(View.VISIBLE);
|
||||
if( !notification.isNotificationAnimated() && status.getEmojis().size() > 0) {
|
||||
notification.setNotificationAnimated(true);
|
||||
try{
|
||||
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
holder.notification_status_content.invalidate();
|
||||
}
|
||||
}, 0, 130, TimeUnit.MILLISECONDS);
|
||||
}catch (Exception ignored){}
|
||||
|
||||
|
||||
/*new Timer().scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
holder.notification_status_content.invalidate();
|
||||
}
|
||||
}, 0, 500);*/
|
||||
}
|
||||
if( !status.isClickable())
|
||||
Status.transform(context, status);
|
||||
if( !status.isEmojiFound())
|
||||
|
|
|
@ -105,6 +105,10 @@ import java.util.Date;
|
|||
import java.util.GregorianCalendar;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -1171,7 +1175,18 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
|||
holder.status_toot_date.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12 * textSizePercent / 100);
|
||||
holder.status_content_translated.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14 * textSizePercent / 100);
|
||||
}
|
||||
if( !status.isStatusAnimated() && status.getEmojis().size() > 0 ) {
|
||||
status.setStatusAnimated(true);
|
||||
try{
|
||||
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
holder.status_content.invalidate();
|
||||
}
|
||||
}, 0, 130, TimeUnit.MILLISECONDS);
|
||||
}catch (Exception ignored){}
|
||||
|
||||
}
|
||||
holder.status_spoiler.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14 * textSizePercent / 100);
|
||||
|
||||
switch (translator) {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package app.fedilab.android.helper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.style.DynamicDrawableSpan;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import com.github.pengfeizhou.animation.apng.APNGDrawable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EmojiDrawableSpan extends DynamicDrawableSpan {
|
||||
|
||||
|
||||
private APNGDrawable mDrawable;
|
||||
private int size;
|
||||
public EmojiDrawableSpan(Context context, APNGDrawable apngDrawable) {
|
||||
mDrawable = apngDrawable;
|
||||
size = (int) Helper.convertDpToPixel(20, context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Drawable getDrawable() {
|
||||
return mDrawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NotNull Canvas canvas, CharSequence text,
|
||||
int start, int end, float x,
|
||||
int top, int y, int bottom, @NotNull Paint paint) {
|
||||
Drawable b = mDrawable;
|
||||
canvas.save();
|
||||
int transY = bottom - b.getBounds().bottom;
|
||||
canvas.translate(x, transY);
|
||||
|
||||
mDrawable.setBounds(0, 0, size, size);
|
||||
b.draw(canvas);
|
||||
canvas.restore();
|
||||
mDrawable.start();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue