Image resizing
This commit is contained in:
@@ -2,31 +2,22 @@ package org.joinmastodon.android.api;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.OpenableColumns;
|
||||
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSink;
|
||||
import okio.ForwardingSink;
|
||||
import okio.Okio;
|
||||
import okio.Sink;
|
||||
import okio.Source;
|
||||
|
||||
public class ContentUriRequestBody extends RequestBody{
|
||||
public class ContentUriRequestBody extends CountingRequestBody{
|
||||
private final Uri uri;
|
||||
private final long length;
|
||||
private ProgressListener progressListener;
|
||||
|
||||
public ContentUriRequestBody(Uri uri, ProgressListener progressListener){
|
||||
super(progressListener);
|
||||
this.uri=uri;
|
||||
this.progressListener=progressListener;
|
||||
try(Cursor cursor=MastodonApp.context.getContentResolver().query(uri, new String[]{OpenableColumns.SIZE}, null, null, null)){
|
||||
cursor.moveToFirst();
|
||||
length=cursor.getInt(0);
|
||||
@@ -39,40 +30,7 @@ public class ContentUriRequestBody extends RequestBody{
|
||||
}
|
||||
|
||||
@Override
|
||||
public long contentLength() throws IOException{
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(BufferedSink sink) throws IOException{
|
||||
if(progressListener!=null){
|
||||
try(Source source=Okio.source(MastodonApp.context.getContentResolver().openInputStream(uri))){
|
||||
BufferedSink wrappedSink=Okio.buffer(new CountingSink(sink));
|
||||
wrappedSink.writeAll(source);
|
||||
wrappedSink.flush();
|
||||
}
|
||||
}else{
|
||||
try(Source source=Okio.source(MastodonApp.context.getContentResolver().openInputStream(uri))){
|
||||
sink.writeAll(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class CountingSink extends ForwardingSink{
|
||||
private long bytesWritten=0;
|
||||
private long lastCallbackTime;
|
||||
public CountingSink(Sink delegate){
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Buffer source, long byteCount) throws IOException{
|
||||
super.write(source, byteCount);
|
||||
bytesWritten+=byteCount;
|
||||
if(SystemClock.uptimeMillis()-lastCallbackTime>=100L || bytesWritten==length){
|
||||
lastCallbackTime=SystemClock.uptimeMillis();
|
||||
UiUtils.runOnUiThread(()->progressListener.onProgress(bytesWritten, length));
|
||||
}
|
||||
}
|
||||
protected Source openSource() throws IOException{
|
||||
return Okio.source(MastodonApp.context.getContentResolver().openInputStream(uri));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.joinmastodon.android.api;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.RequestBody;
|
||||
import okio.BufferedSink;
|
||||
import okio.Okio;
|
||||
import okio.Source;
|
||||
|
||||
abstract class CountingRequestBody extends RequestBody{
|
||||
protected long length;
|
||||
protected ProgressListener progressListener;
|
||||
|
||||
CountingRequestBody(ProgressListener progressListener){
|
||||
this.progressListener=progressListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long contentLength() throws IOException{
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(BufferedSink sink) throws IOException{
|
||||
if(progressListener!=null){
|
||||
try(Source source=openSource()){
|
||||
BufferedSink wrappedSink=Okio.buffer(new CountingSink(length, progressListener, sink));
|
||||
wrappedSink.writeAll(source);
|
||||
wrappedSink.flush();
|
||||
}
|
||||
}else{
|
||||
try(Source source=openSource()){
|
||||
sink.writeAll(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Source openSource() throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.joinmastodon.android.api;
|
||||
|
||||
import android.os.SystemClock;
|
||||
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okio.Buffer;
|
||||
import okio.ForwardingSink;
|
||||
import okio.Sink;
|
||||
|
||||
class CountingSink extends ForwardingSink{
|
||||
private long bytesWritten=0;
|
||||
private long lastCallbackTime;
|
||||
private final long length;
|
||||
private final ProgressListener progressListener;
|
||||
|
||||
public CountingSink(long length, ProgressListener progressListener, Sink delegate){
|
||||
super(delegate);
|
||||
this.length=length;
|
||||
this.progressListener=progressListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Buffer source, long byteCount) throws IOException{
|
||||
super.write(source, byteCount);
|
||||
bytesWritten+=byteCount;
|
||||
if(SystemClock.uptimeMillis()-lastCallbackTime>=100L || bytesWritten==length){
|
||||
lastCallbackTime=SystemClock.uptimeMillis();
|
||||
UiUtils.runOnUiThread(()->progressListener.onProgress(bytesWritten, length));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
|
||||
return method;
|
||||
}
|
||||
|
||||
public RequestBody getRequestBody(){
|
||||
public RequestBody getRequestBody() throws IOException{
|
||||
return requestBody==null ? null : new JsonObjectRequestBody(requestBody);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package org.joinmastodon.android.api;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ImageDecoder;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.media.ExifInterface;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.OpenableColumns;
|
||||
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import okhttp3.MediaType;
|
||||
import okio.BufferedSink;
|
||||
import okio.Okio;
|
||||
import okio.Source;
|
||||
|
||||
public class ResizedImageRequestBody extends CountingRequestBody{
|
||||
private File tempFile;
|
||||
private Uri uri;
|
||||
private String contentType;
|
||||
|
||||
public ResizedImageRequestBody(Uri uri, int maxSize, ProgressListener progressListener) throws IOException{
|
||||
super(progressListener);
|
||||
this.uri=uri;
|
||||
contentType=MastodonApp.context.getContentResolver().getType(uri);
|
||||
BitmapFactory.Options opts=new BitmapFactory.Options();
|
||||
opts.inJustDecodeBounds=true;
|
||||
try(InputStream in=MastodonApp.context.getContentResolver().openInputStream(uri)){
|
||||
BitmapFactory.decodeStream(in, null, opts);
|
||||
}
|
||||
if(opts.outWidth*opts.outHeight>maxSize){
|
||||
Bitmap bitmap;
|
||||
if(Build.VERSION.SDK_INT>=29){
|
||||
bitmap=ImageDecoder.decodeBitmap(ImageDecoder.createSource(MastodonApp.context.getContentResolver(), uri), (decoder, info, source)->{
|
||||
int targetWidth=Math.round((float)Math.sqrt((float)maxSize*((float)info.getSize().getWidth()/info.getSize().getHeight())));
|
||||
int targetHeight=Math.round((float)Math.sqrt((float)maxSize*((float)info.getSize().getHeight()/info.getSize().getWidth())));
|
||||
decoder.setAllocator(ImageDecoder.ALLOCATOR_SOFTWARE);
|
||||
decoder.setTargetSize(targetWidth, targetHeight);
|
||||
});
|
||||
}else{
|
||||
int targetWidth=Math.round((float)Math.sqrt((float)maxSize*((float)opts.outWidth/opts.outHeight)));
|
||||
int targetHeight=Math.round((float)Math.sqrt((float)maxSize*((float)opts.outHeight/opts.outWidth)));
|
||||
float factor=opts.outWidth/(float)targetWidth;
|
||||
opts=new BitmapFactory.Options();
|
||||
opts.inSampleSize=(int)factor;
|
||||
try(InputStream in=MastodonApp.context.getContentResolver().openInputStream(uri)){
|
||||
bitmap=BitmapFactory.decodeStream(in, null, opts);
|
||||
}
|
||||
if(factor%1f!=0f){
|
||||
Bitmap scaled=Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
|
||||
new Canvas(scaled).drawBitmap(bitmap, null, new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()), new Paint(Paint.FILTER_BITMAP_FLAG));
|
||||
bitmap=scaled;
|
||||
}
|
||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
|
||||
int rotation;
|
||||
try(InputStream in=MastodonApp.context.getContentResolver().openInputStream(uri)){
|
||||
ExifInterface exif=new ExifInterface(in);
|
||||
int orientation=exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
|
||||
rotation=switch(orientation){
|
||||
case ExifInterface.ORIENTATION_ROTATE_90 -> 90;
|
||||
case ExifInterface.ORIENTATION_ROTATE_180 -> 180;
|
||||
case ExifInterface.ORIENTATION_ROTATE_270 -> 270;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
if(rotation!=0){
|
||||
Matrix matrix=new Matrix();
|
||||
matrix.setRotate(rotation);
|
||||
bitmap=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tempFile=new File(MastodonApp.context.getCacheDir(), "tmp_upload_image");
|
||||
try(FileOutputStream out=new FileOutputStream(tempFile)){
|
||||
if("image/png".equals(contentType)){
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 0, out);
|
||||
}else{
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 97, out);
|
||||
contentType="image/jpeg";
|
||||
}
|
||||
}
|
||||
length=tempFile.length();
|
||||
}else{
|
||||
try(Cursor cursor=MastodonApp.context.getContentResolver().query(uri, new String[]{OpenableColumns.SIZE}, null, null, null)){
|
||||
cursor.moveToFirst();
|
||||
length=cursor.getInt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Source openSource() throws IOException{
|
||||
if(tempFile==null){
|
||||
return Okio.source(MastodonApp.context.getContentResolver().openInputStream(uri));
|
||||
}else{
|
||||
return Okio.source(tempFile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaType contentType(){
|
||||
return MediaType.get(contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(BufferedSink sink) throws IOException{
|
||||
try{
|
||||
super.writeTo(sink);
|
||||
}finally{
|
||||
if(tempFile!=null){
|
||||
tempFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,31 +8,40 @@ import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.api.ContentUriRequestBody;
|
||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
import org.joinmastodon.android.api.ProgressListener;
|
||||
import org.joinmastodon.android.api.ResizedImageRequestBody;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.RequestBody;
|
||||
|
||||
public class UploadAttachment extends MastodonAPIRequest<Attachment>{
|
||||
private Uri uri;
|
||||
private ProgressListener progressListener;
|
||||
private int maxImageSize;
|
||||
|
||||
public UploadAttachment(Uri uri){
|
||||
super(HttpMethod.POST, "/media", Attachment.class);
|
||||
this.uri=uri;
|
||||
}
|
||||
|
||||
public UploadAttachment(Uri uri, int maxImageSize){
|
||||
this(uri);
|
||||
this.maxImageSize=maxImageSize;
|
||||
}
|
||||
|
||||
public UploadAttachment setProgressListener(ProgressListener progressListener){
|
||||
this.progressListener=progressListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestBody getRequestBody(){
|
||||
public RequestBody getRequestBody() throws IOException{
|
||||
return new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart("file", UiUtils.getFileName(uri), new ContentUriRequestBody(uri, progressListener))
|
||||
.addFormDataPart("file", UiUtils.getFileName(uri), maxImageSize>0 ? new ResizedImageRequestBody(uri, maxImageSize, progressListener) : new ContentUriRequestBody(uri, progressListener))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,25 +12,20 @@ public class AccountSession{
|
||||
public Token token;
|
||||
public Account self;
|
||||
public String domain;
|
||||
public int tootCharLimit;
|
||||
public Application app;
|
||||
public long infoLastUpdated;
|
||||
public long instanceLastUpdated;
|
||||
public Instance instance;
|
||||
public boolean activated=true;
|
||||
private transient MastodonAPIController apiController;
|
||||
private transient StatusInteractionController statusInteractionController;
|
||||
private transient CacheController cacheController;
|
||||
|
||||
AccountSession(Token token, Account self, Application app, String domain, int tootCharLimit, Instance instance, boolean activated){
|
||||
AccountSession(Token token, Account self, Application app, String domain, boolean activated){
|
||||
this.token=token;
|
||||
this.self=self;
|
||||
this.domain=domain;
|
||||
this.app=app;
|
||||
this.tootCharLimit=tootCharLimit;
|
||||
this.instance=instance;
|
||||
this.activated=activated;
|
||||
instanceLastUpdated=infoLastUpdated=System.currentTimeMillis();
|
||||
infoLastUpdated=System.currentTimeMillis();
|
||||
}
|
||||
|
||||
AccountSession(){}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.joinmastodon.android.api.session;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
@@ -37,12 +36,10 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
@@ -56,13 +53,14 @@ public class AccountSessionManager{
|
||||
|
||||
private HashMap<String, AccountSession> sessions=new HashMap<>();
|
||||
private HashMap<String, List<EmojiCategory>> customEmojis=new HashMap<>();
|
||||
private HashMap<String, Long> customEmojisLastUpdated=new HashMap<>();
|
||||
private HashMap<String, Long> instancesLastUpdated=new HashMap<>();
|
||||
private HashMap<String, Instance> instances=new HashMap<>();
|
||||
private MastodonAPIController unauthenticatedApiController=new MastodonAPIController(null);
|
||||
private Instance authenticatingInstance;
|
||||
private Application authenticatingApp;
|
||||
private String lastActiveAccountID;
|
||||
private SharedPreferences prefs;
|
||||
private boolean loadedCustomEmojis;
|
||||
private boolean loadedInstances;
|
||||
|
||||
public static AccountSessionManager getInstance(){
|
||||
return instance;
|
||||
@@ -84,14 +82,16 @@ public class AccountSessionManager{
|
||||
Log.e(TAG, "Error loading accounts", x);
|
||||
}
|
||||
lastActiveAccountID=prefs.getString("lastActiveAccount", null);
|
||||
MastodonAPIController.runInBackground(()->readCustomEmojis(domains));
|
||||
MastodonAPIController.runInBackground(()->readInstanceInfo(domains));
|
||||
}
|
||||
|
||||
public void addAccount(Instance instance, Token token, Account self, Application app, boolean active){
|
||||
AccountSession session=new AccountSession(token, self, app, instance.uri, instance.maxTootChars, instance, active);
|
||||
instances.put(instance.uri, instance);
|
||||
AccountSession session=new AccountSession(token, self, app, instance.uri, active);
|
||||
sessions.put(session.getID(), session);
|
||||
lastActiveAccountID=session.getID();
|
||||
writeAccountsFile();
|
||||
maybeUpdateLocalInfo();
|
||||
}
|
||||
|
||||
private void writeAccountsFile(){
|
||||
@@ -155,7 +155,7 @@ public class AccountSessionManager{
|
||||
writeAccountsFile();
|
||||
String domain=session.domain.toLowerCase();
|
||||
if(sessions.isEmpty() || !sessions.values().stream().map(s->s.domain.toLowerCase()).collect(Collectors.toSet()).contains(domain)){
|
||||
getCustomEmojisFile(domain).delete();
|
||||
getInstanceInfoFile(domain).delete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,11 +213,11 @@ public class AccountSessionManager{
|
||||
HashSet<String> domains=new HashSet<>();
|
||||
for(AccountSession session:sessions.values()){
|
||||
domains.add(session.domain.toLowerCase());
|
||||
if(now-session.infoLastUpdated>24L*3600_000L || now-session.instanceLastUpdated>24L*360_000L*3L){
|
||||
if(now-session.infoLastUpdated>24L*3600_000L){
|
||||
updateSessionLocalInfo(session);
|
||||
}
|
||||
}
|
||||
if(loadedCustomEmojis){
|
||||
if(loadedInstances){
|
||||
maybeUpdateCustomEmojis(domains);
|
||||
}
|
||||
}
|
||||
@@ -225,9 +225,9 @@ public class AccountSessionManager{
|
||||
private void maybeUpdateCustomEmojis(Set<String> domains){
|
||||
long now=System.currentTimeMillis();
|
||||
for(String domain:domains){
|
||||
Long lastUpdated=customEmojisLastUpdated.get(domain);
|
||||
Long lastUpdated=instancesLastUpdated.get(domain);
|
||||
if(lastUpdated==null || now-lastUpdated>24L*3600_000L){
|
||||
updateCustomEmojis(domain);
|
||||
updateInstanceInfo(domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,34 +248,33 @@ public class AccountSessionManager{
|
||||
}
|
||||
})
|
||||
.exec(session.getID());
|
||||
}
|
||||
|
||||
private void updateInstanceInfo(String domain){
|
||||
new GetInstance()
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Instance result){
|
||||
session.instance=result;
|
||||
session.instanceLastUpdated=System.currentTimeMillis();
|
||||
writeAccountsFile();
|
||||
}
|
||||
public void onSuccess(Instance instance){
|
||||
instances.put(domain, instance);
|
||||
new GetCustomEmojis()
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(List<Emoji> result){
|
||||
InstanceInfoStorageWrapper emojis=new InstanceInfoStorageWrapper();
|
||||
emojis.lastUpdated=System.currentTimeMillis();
|
||||
emojis.emojis=result;
|
||||
emojis.instance=instance;
|
||||
customEmojis.put(domain, groupCustomEmojis(emojis));
|
||||
instancesLastUpdated.put(domain, emojis.lastUpdated);
|
||||
MastodonAPIController.runInBackground(()->writeInstanceInfoFile(emojis, domain));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
|
||||
}
|
||||
})
|
||||
.exec(session.getID());
|
||||
}
|
||||
|
||||
private void updateCustomEmojis(String domain){
|
||||
new GetCustomEmojis()
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(List<Emoji> result){
|
||||
CustomEmojisStorageWrapper emojis=new CustomEmojisStorageWrapper();
|
||||
emojis.lastUpdated=System.currentTimeMillis();
|
||||
emojis.emojis=result;
|
||||
customEmojis.put(domain, groupCustomEmojis(emojis));
|
||||
customEmojisLastUpdated.put(domain, emojis.lastUpdated);
|
||||
MastodonAPIController.runInBackground(()->writeCustomEmojisFile(emojis, domain));
|
||||
}
|
||||
})
|
||||
.execNoAuth(domain);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -286,38 +285,39 @@ public class AccountSessionManager{
|
||||
.execNoAuth(domain);
|
||||
}
|
||||
|
||||
private File getCustomEmojisFile(String domain){
|
||||
return new File(MastodonApp.context.getFilesDir(), "emojis_"+domain.replace('.', '_')+".json");
|
||||
private File getInstanceInfoFile(String domain){
|
||||
return new File(MastodonApp.context.getFilesDir(), "instance_"+domain.replace('.', '_')+".json");
|
||||
}
|
||||
|
||||
private void writeCustomEmojisFile(CustomEmojisStorageWrapper emojis, String domain){
|
||||
try(FileOutputStream out=new FileOutputStream(getCustomEmojisFile(domain))){
|
||||
private void writeInstanceInfoFile(InstanceInfoStorageWrapper emojis, String domain){
|
||||
try(FileOutputStream out=new FileOutputStream(getInstanceInfoFile(domain))){
|
||||
OutputStreamWriter writer=new OutputStreamWriter(out, StandardCharsets.UTF_8);
|
||||
MastodonAPIController.gson.toJson(emojis, writer);
|
||||
writer.flush();
|
||||
}catch(IOException x){
|
||||
Log.w(TAG, "Error writing emojis file for "+domain, x);
|
||||
Log.w(TAG, "Error writing instance info file for "+domain, x);
|
||||
}
|
||||
}
|
||||
|
||||
private void readCustomEmojis(Set<String> domains){
|
||||
private void readInstanceInfo(Set<String> domains){
|
||||
for(String domain:domains){
|
||||
try(FileInputStream in=new FileInputStream(getCustomEmojisFile(domain))){
|
||||
try(FileInputStream in=new FileInputStream(getInstanceInfoFile(domain))){
|
||||
InputStreamReader reader=new InputStreamReader(in, StandardCharsets.UTF_8);
|
||||
CustomEmojisStorageWrapper emojis=MastodonAPIController.gson.fromJson(reader, CustomEmojisStorageWrapper.class);
|
||||
InstanceInfoStorageWrapper emojis=MastodonAPIController.gson.fromJson(reader, InstanceInfoStorageWrapper.class);
|
||||
customEmojis.put(domain, groupCustomEmojis(emojis));
|
||||
customEmojisLastUpdated.put(domain, emojis.lastUpdated);
|
||||
instances.put(domain, emojis.instance);
|
||||
instancesLastUpdated.put(domain, emojis.lastUpdated);
|
||||
}catch(IOException|JsonParseException x){
|
||||
Log.w(TAG, "Error reading emojis file for "+domain, x);
|
||||
Log.w(TAG, "Error reading instance info file for "+domain, x);
|
||||
}
|
||||
}
|
||||
if(!loadedCustomEmojis){
|
||||
loadedCustomEmojis=true;
|
||||
if(!loadedInstances){
|
||||
loadedInstances=true;
|
||||
maybeUpdateCustomEmojis(domains);
|
||||
}
|
||||
}
|
||||
|
||||
private List<EmojiCategory> groupCustomEmojis(CustomEmojisStorageWrapper emojis){
|
||||
private List<EmojiCategory> groupCustomEmojis(InstanceInfoStorageWrapper emojis){
|
||||
return emojis.emojis.stream()
|
||||
.filter(e->e.visibleInPicker)
|
||||
.collect(Collectors.groupingBy(e->e.category==null ? "" : e.category))
|
||||
@@ -333,6 +333,10 @@ public class AccountSessionManager{
|
||||
return r==null ? Collections.emptyList() : r;
|
||||
}
|
||||
|
||||
public Instance getInstanceInfo(String domain){
|
||||
return instances.get(domain);
|
||||
}
|
||||
|
||||
public void updateAccountInfo(String id, Account account){
|
||||
AccountSession session=getAccount(id);
|
||||
session.self=account;
|
||||
@@ -344,7 +348,8 @@ public class AccountSessionManager{
|
||||
public List<AccountSession> accounts;
|
||||
}
|
||||
|
||||
private static class CustomEmojisStorageWrapper{
|
||||
private static class InstanceInfoStorageWrapper{
|
||||
public Instance instance;
|
||||
public List<Emoji> emojis;
|
||||
public long lastUpdated;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user