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.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BlurMaskFilter;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
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.MenuItem;
|
||||
import android.view.SubMenu;
|
||||
@ -51,6 +57,9 @@ import org.nuclearfog.textviewtool.LinkAndScrollMovement;
|
||||
import org.nuclearfog.twidda.R;
|
||||
import org.nuclearfog.twidda.backend.api.ConnectionException;
|
||||
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.NotificationActionParam;
|
||||
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.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
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<TranslationResult> translationResult = this::onTranslationResult;
|
||||
private AsyncCallback<NotificationActionResult> notificationCallback = this::onNotificationResult;
|
||||
private AsyncCallback<EmojiResult> emojiResultCallback = this::onEmojiResult;
|
||||
|
||||
@Nullable
|
||||
private ClipboardManager clip;
|
||||
@ -197,6 +208,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
|
||||
private PollAction voteAsync;
|
||||
private NotificationAction notificationAsync;
|
||||
private TranslationLoader translationAsync;
|
||||
private EmojiLoader emojiAsync;
|
||||
private GlobalSettings settings;
|
||||
private Picasso picasso;
|
||||
private PreviewAdapter adapter;
|
||||
@ -257,6 +269,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
|
||||
voteAsync = new PollAction(this);
|
||||
notificationAsync = new NotificationAction(this);
|
||||
translationAsync = new TranslationLoader(this);
|
||||
emojiAsync = new EmojiLoader(this);
|
||||
|
||||
picasso = PicassoBuilder.get(this);
|
||||
settings = GlobalSettings.getInstance(this);
|
||||
@ -912,6 +925,10 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
|
||||
cardList.setVisibility(View.GONE);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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