mirror of
https://github.com/nuclearfog/Shitter.git
synced 2025-01-31 11:25:03 +01:00
added emoji loader, added status emoji support
This commit is contained in:
parent
f0170c4e19
commit
2519b1732b
@ -0,0 +1,118 @@
|
|||||||
|
package org.nuclearfog.twidda.backend.async;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.nuclearfog.twidda.backend.api.Connection;
|
||||||
|
import org.nuclearfog.twidda.backend.api.ConnectionException;
|
||||||
|
import org.nuclearfog.twidda.backend.api.ConnectionManager;
|
||||||
|
import org.nuclearfog.twidda.backend.helper.MediaStatus;
|
||||||
|
import org.nuclearfog.twidda.model.Emoji;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emoji image loader class
|
||||||
|
*
|
||||||
|
* @author nuclearfog
|
||||||
|
*/
|
||||||
|
public class EmojiLoader extends AsyncExecutor<EmojiLoader.EmojiParam, EmojiLoader.EmojiResult> {
|
||||||
|
|
||||||
|
private static final String FOLDER = "emojis";
|
||||||
|
|
||||||
|
private File imageFolder;
|
||||||
|
private Connection connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public EmojiLoader(Context context) {
|
||||||
|
connection = ConnectionManager.getDefaultConnection(context);
|
||||||
|
imageFolder = new File(context.getExternalCacheDir(), FOLDER);
|
||||||
|
imageFolder.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
protected EmojiResult doInBackground(@NonNull EmojiParam param) {
|
||||||
|
try {
|
||||||
|
Map<String, File> files = new TreeMap<>();
|
||||||
|
Map<String, Bitmap> result = new TreeMap<>();
|
||||||
|
// cache all local image files first
|
||||||
|
File[] imageFiles = imageFolder.listFiles();
|
||||||
|
if (imageFiles != null) {
|
||||||
|
for (File file : imageFiles) {
|
||||||
|
files.put(file.getName(), file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Emoji emoji : param.emojis) {
|
||||||
|
File file = files.get(emoji.getCode());
|
||||||
|
if (file == null) {
|
||||||
|
// download image to cache
|
||||||
|
MediaStatus media = connection.downloadImage(emoji.getUrl());
|
||||||
|
InputStream input = media.getStream();
|
||||||
|
file = new File(imageFolder, emoji.getCode());
|
||||||
|
file.createNewFile();
|
||||||
|
FileOutputStream output = new FileOutputStream(file);
|
||||||
|
Bitmap icon = BitmapFactory.decodeStream(input);
|
||||||
|
icon.compress(Bitmap.CompressFormat.PNG, 1, output);
|
||||||
|
// resize image
|
||||||
|
icon = Bitmap.createScaledBitmap(icon, icon.getWidth() / icon.getHeight() * param.size, param.size, false);
|
||||||
|
result.put(emoji.getCode(), icon);
|
||||||
|
} else {
|
||||||
|
// load image from cache
|
||||||
|
FileInputStream inputStream = new FileInputStream(file);
|
||||||
|
Bitmap icon = BitmapFactory.decodeStream(inputStream);
|
||||||
|
// resize image
|
||||||
|
icon = Bitmap.createScaledBitmap(icon, icon.getWidth() / icon.getHeight() * param.size, param.size, false);
|
||||||
|
result.put(emoji.getCode(), icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new EmojiResult(result, null);
|
||||||
|
} catch (ConnectionException exception) {
|
||||||
|
return new EmojiResult(null, exception);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
return new EmojiResult(null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static class EmojiParam {
|
||||||
|
Emoji[] emojis;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
public EmojiParam(Emoji[] emojis, int size) {
|
||||||
|
this.emojis = emojis;
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static class EmojiResult {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Map<String, Bitmap> images;
|
||||||
|
@Nullable
|
||||||
|
public ConnectionException exception;
|
||||||
|
|
||||||
|
EmojiResult(@Nullable Map<String, Bitmap> images, @Nullable ConnectionException exception) {
|
||||||
|
this.exception = exception;
|
||||||
|
this.images = images;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,10 +17,16 @@ import android.content.ClipData;
|
|||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BlurMaskFilter;
|
import android.graphics.BlurMaskFilter;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
|
import android.text.SpannableString;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.text.style.ImageSpan;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.SubMenu;
|
import android.view.SubMenu;
|
||||||
@ -51,6 +57,9 @@ import org.nuclearfog.textviewtool.LinkAndScrollMovement;
|
|||||||
import org.nuclearfog.twidda.R;
|
import org.nuclearfog.twidda.R;
|
||||||
import org.nuclearfog.twidda.backend.api.ConnectionException;
|
import org.nuclearfog.twidda.backend.api.ConnectionException;
|
||||||
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
|
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
|
||||||
|
import org.nuclearfog.twidda.backend.async.EmojiLoader;
|
||||||
|
import org.nuclearfog.twidda.backend.async.EmojiLoader.EmojiParam;
|
||||||
|
import org.nuclearfog.twidda.backend.async.EmojiLoader.EmojiResult;
|
||||||
import org.nuclearfog.twidda.backend.async.NotificationAction;
|
import org.nuclearfog.twidda.backend.async.NotificationAction;
|
||||||
import org.nuclearfog.twidda.backend.async.NotificationAction.NotificationActionParam;
|
import org.nuclearfog.twidda.backend.async.NotificationAction.NotificationActionParam;
|
||||||
import org.nuclearfog.twidda.backend.async.NotificationAction.NotificationActionResult;
|
import org.nuclearfog.twidda.backend.async.NotificationAction.NotificationActionResult;
|
||||||
@ -87,6 +96,7 @@ import org.nuclearfog.twidda.ui.fragments.StatusFragment;
|
|||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation;
|
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation;
|
||||||
@ -190,6 +200,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
|
|||||||
private AsyncCallback<PollActionResult> pollResult = this::onPollResult;
|
private AsyncCallback<PollActionResult> pollResult = this::onPollResult;
|
||||||
private AsyncCallback<TranslationResult> translationResult = this::onTranslationResult;
|
private AsyncCallback<TranslationResult> translationResult = this::onTranslationResult;
|
||||||
private AsyncCallback<NotificationActionResult> notificationCallback = this::onNotificationResult;
|
private AsyncCallback<NotificationActionResult> notificationCallback = this::onNotificationResult;
|
||||||
|
private AsyncCallback<EmojiResult> emojiResultCallback = this::onEmojiResult;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private ClipboardManager clip;
|
private ClipboardManager clip;
|
||||||
@ -197,6 +208,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
|
|||||||
private PollAction voteAsync;
|
private PollAction voteAsync;
|
||||||
private NotificationAction notificationAsync;
|
private NotificationAction notificationAsync;
|
||||||
private TranslationLoader translationAsync;
|
private TranslationLoader translationAsync;
|
||||||
|
private EmojiLoader emojiAsync;
|
||||||
private GlobalSettings settings;
|
private GlobalSettings settings;
|
||||||
private Picasso picasso;
|
private Picasso picasso;
|
||||||
private PreviewAdapter adapter;
|
private PreviewAdapter adapter;
|
||||||
@ -257,6 +269,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
|
|||||||
voteAsync = new PollAction(this);
|
voteAsync = new PollAction(this);
|
||||||
notificationAsync = new NotificationAction(this);
|
notificationAsync = new NotificationAction(this);
|
||||||
translationAsync = new TranslationLoader(this);
|
translationAsync = new TranslationLoader(this);
|
||||||
|
emojiAsync = new EmojiLoader(this);
|
||||||
|
|
||||||
picasso = PicassoBuilder.get(this);
|
picasso = PicassoBuilder.get(this);
|
||||||
settings = GlobalSettings.getInstance(this);
|
settings = GlobalSettings.getInstance(this);
|
||||||
@ -912,6 +925,10 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
|
|||||||
cardList.setVisibility(View.GONE);
|
cardList.setVisibility(View.GONE);
|
||||||
statusText.setMaxLines(10);
|
statusText.setMaxLines(10);
|
||||||
}
|
}
|
||||||
|
if (status.getEmojis().length > 0 && emojiAsync.isIdle()) {
|
||||||
|
EmojiParam param = new EmojiParam(status.getEmojis(), statusText.getLineHeight());
|
||||||
|
emojiAsync.execute(param, emojiResultCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1119,4 +1136,21 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
|
|||||||
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set cached status emojis
|
||||||
|
*/
|
||||||
|
private void onEmojiResult(EmojiResult result) {
|
||||||
|
if (result.images != null && statusText.getText() instanceof SpannableString) {
|
||||||
|
SpannableStringBuilder builder = new SpannableStringBuilder((SpannableString) statusText.getText());
|
||||||
|
for (Map.Entry<String, Bitmap> item : result.images.entrySet()) {
|
||||||
|
int idx = TextUtils.indexOf(builder, ':' + item.getKey() + ':');
|
||||||
|
if (idx >= 0) {
|
||||||
|
ImageSpan imgSpan = new ImageSpan(getApplicationContext(), item.getValue());
|
||||||
|
builder.setSpan(imgSpan, idx, idx + item.getKey().length() + 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statusText.setText(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user