Settings and other things
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package org.joinmastodon.android.api;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
@@ -14,8 +13,6 @@ import org.joinmastodon.android.BuildConfig;
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.api.requests.notifications.GetNotifications;
|
||||
import org.joinmastodon.android.api.requests.timelines.GetHomeTimeline;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Hashtag;
|
||||
import org.joinmastodon.android.model.Notification;
|
||||
import org.joinmastodon.android.model.SearchResult;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
@@ -26,7 +23,6 @@ import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
import me.grishka.appkit.utils.WorkerThread;
|
||||
@@ -87,7 +83,7 @@ public class CacheController{
|
||||
.exec(accountID);
|
||||
}catch(SQLiteException x){
|
||||
Log.w(TAG, x);
|
||||
uiHandler.post(()->callback.onError(new MastodonErrorResponse(x.getLocalizedMessage())));
|
||||
uiHandler.post(()->callback.onError(new MastodonErrorResponse(x.getLocalizedMessage(), 500)));
|
||||
}finally{
|
||||
closeDelayed();
|
||||
}
|
||||
@@ -145,7 +141,7 @@ public class CacheController{
|
||||
.exec(accountID);
|
||||
}catch(SQLiteException x){
|
||||
Log.w(TAG, x);
|
||||
uiHandler.post(()->callback.onError(new MastodonErrorResponse(x.getLocalizedMessage())));
|
||||
uiHandler.post(()->callback.onError(new MastodonErrorResponse(x.getLocalizedMessage(), 500)));
|
||||
}finally{
|
||||
closeDelayed();
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ public class MastodonAPIController{
|
||||
synchronized(req){
|
||||
req.okhttpCall=null;
|
||||
}
|
||||
req.onError(e.getLocalizedMessage());
|
||||
req.onError(e.getLocalizedMessage(), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -136,7 +136,7 @@ public class MastodonAPIController{
|
||||
}catch(JsonIOException|JsonSyntaxException x){
|
||||
if(BuildConfig.DEBUG)
|
||||
Log.w(TAG, "["+(session==null ? "no-auth" : session.getID())+"] "+response+" error parsing or reading body", x);
|
||||
req.onError(x.getLocalizedMessage());
|
||||
req.onError(x.getLocalizedMessage(), response.code());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ public class MastodonAPIController{
|
||||
}catch(IOException x){
|
||||
if(BuildConfig.DEBUG)
|
||||
Log.w(TAG, "["+(session==null ? "no-auth" : session.getID())+"] "+response+" error post-processing or validating response", x);
|
||||
req.onError(x.getLocalizedMessage());
|
||||
req.onError(x.getLocalizedMessage(), response.code());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -157,11 +157,11 @@ public class MastodonAPIController{
|
||||
try{
|
||||
JsonObject error=JsonParser.parseReader(reader).getAsJsonObject();
|
||||
Log.w(TAG, "["+(session==null ? "no-auth" : session.getID())+"] "+response+" received error: "+error);
|
||||
req.onError(error.get("error").getAsString());
|
||||
req.onError(error.get("error").getAsString(), response.code());
|
||||
}catch(JsonIOException|JsonSyntaxException x){
|
||||
req.onError(response.code()+" "+response.message());
|
||||
req.onError(response.code()+" "+response.message(), response.code());
|
||||
}catch(IllegalStateException x){
|
||||
req.onError("Error parsing an API error");
|
||||
req.onError("Error parsing an API error", response.code());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,7 +170,7 @@ public class MastodonAPIController{
|
||||
}catch(Exception x){
|
||||
if(BuildConfig.DEBUG)
|
||||
Log.w(TAG, "["+(session==null ? "no-auth" : session.getID())+"] error creating and sending http request", x);
|
||||
req.onError(x.getLocalizedMessage());
|
||||
req.onError(x.getLocalizedMessage(), 0);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@ package org.joinmastodon.android.api;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import org.joinmastodon.android.BuildConfig;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.BaseModel;
|
||||
@@ -60,6 +60,8 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
|
||||
|
||||
@Override
|
||||
public synchronized void cancel(){
|
||||
if(BuildConfig.DEBUG)
|
||||
Log.d(TAG, "canceling request "+this);
|
||||
canceled=true;
|
||||
if(okhttpCall!=null){
|
||||
okhttpCall.cancel();
|
||||
@@ -181,8 +183,8 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
|
||||
}
|
||||
}
|
||||
|
||||
void onError(String msg){
|
||||
invokeErrorCallback(new MastodonErrorResponse(msg));
|
||||
void onError(String msg, int httpStatus){
|
||||
invokeErrorCallback(new MastodonErrorResponse(msg, httpStatus));
|
||||
}
|
||||
|
||||
void onSuccess(T resp){
|
||||
|
||||
@@ -11,9 +11,11 @@ import me.grishka.appkit.api.ErrorResponse;
|
||||
|
||||
public class MastodonErrorResponse extends ErrorResponse{
|
||||
public final String error;
|
||||
public final int httpStatus;
|
||||
|
||||
public MastodonErrorResponse(String error){
|
||||
public MastodonErrorResponse(String error, int httpStatus){
|
||||
this.error=error;
|
||||
this.httpStatus=httpStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.util.Log;
|
||||
import org.joinmastodon.android.BuildConfig;
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.api.requests.notifications.RegisterForPushNotifications;
|
||||
import org.joinmastodon.android.api.requests.notifications.UpdatePushSettings;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.PushNotification;
|
||||
@@ -119,6 +120,10 @@ public class PushSubscriptionManager{
|
||||
}
|
||||
|
||||
public void registerAccountForPush(){
|
||||
registerAccountForPush(null);
|
||||
}
|
||||
|
||||
public void registerAccountForPush(PushSubscription subscription){
|
||||
if(TextUtils.isEmpty(deviceToken))
|
||||
throw new IllegalStateException("No device push token available");
|
||||
MastodonAPIController.runInBackground(()->{
|
||||
@@ -143,19 +148,22 @@ public class PushSubscriptionManager{
|
||||
Log.e(TAG, "registerAccountForPush: error generating encryption key", e);
|
||||
return;
|
||||
}
|
||||
new RegisterForPushNotifications(deviceToken, encodedPublicKey, encodedAuthKey, PushSubscription.Alerts.ofAll(), accountID)
|
||||
new RegisterForPushNotifications(deviceToken,
|
||||
encodedPublicKey,
|
||||
encodedAuthKey,
|
||||
subscription==null ? PushSubscription.Alerts.ofAll() : subscription.alerts,
|
||||
subscription==null ? PushSubscription.Policy.ALL : subscription.policy,
|
||||
accountID)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(PushSubscription result){
|
||||
MastodonAPIController.runInBackground(()->{
|
||||
serverKey=deserializeRawPublicKey(Base64.decode(result.serverKey, Base64.URL_SAFE));
|
||||
|
||||
if(serverKey!=null){
|
||||
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
|
||||
session.pushServerKey=Base64.encodeToString(serverKey.getEncoded(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
|
||||
AccountSessionManager.getInstance().writeAccountsFile();
|
||||
Log.d(TAG, "Successfully registered "+accountID+" for push notifications");
|
||||
}
|
||||
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
|
||||
session.pushSubscription=result;
|
||||
AccountSessionManager.getInstance().writeAccountsFile();
|
||||
Log.d(TAG, "Successfully registered "+accountID+" for push notifications");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -168,6 +176,34 @@ public class PushSubscriptionManager{
|
||||
});
|
||||
}
|
||||
|
||||
public void updatePushSettings(PushSubscription subscription){
|
||||
new UpdatePushSettings(subscription.alerts, subscription.policy)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(PushSubscription result){
|
||||
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
|
||||
if(result.policy!=subscription.policy)
|
||||
result.policy=subscription.policy;
|
||||
session.pushSubscription=result;
|
||||
session.needUpdatePushSettings=false;
|
||||
AccountSessionManager.getInstance().writeAccountsFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
if(((MastodonErrorResponse)error).httpStatus==404){ // Not registered for push, register now
|
||||
registerAccountForPush(subscription);
|
||||
}else{
|
||||
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
|
||||
session.needUpdatePushSettings=true;
|
||||
session.pushSubscription=subscription;
|
||||
AccountSessionManager.getInstance().writeAccountsFile();
|
||||
}
|
||||
}
|
||||
})
|
||||
.exec(accountID);
|
||||
}
|
||||
|
||||
private PublicKey deserializeRawPublicKey(byte[] rawBytes){
|
||||
if(rawBytes.length!=65 && rawBytes.length!=64)
|
||||
return null;
|
||||
@@ -320,8 +356,10 @@ public class PushSubscriptionManager{
|
||||
|
||||
private static void registerAllAccountsForPush(){
|
||||
for(AccountSession session:AccountSessionManager.getInstance().getLoggedInAccounts()){
|
||||
if(TextUtils.isEmpty(session.pushServerKey))
|
||||
if(session.pushSubscription==null)
|
||||
session.getPushSubscriptionManager().registerAccountForPush();
|
||||
else if(session.needUpdatePushSettings)
|
||||
session.getPushSubscriptionManager().updatePushSettings(session.pushSubscription);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,12 @@ import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
import org.joinmastodon.android.model.PushSubscription;
|
||||
|
||||
public class RegisterForPushNotifications extends MastodonAPIRequest<PushSubscription>{
|
||||
public RegisterForPushNotifications(String deviceToken, String encryptionKey, String authKey, PushSubscription.Alerts alerts, String accountID){
|
||||
public RegisterForPushNotifications(String deviceToken, String encryptionKey, String authKey, PushSubscription.Alerts alerts, PushSubscription.Policy policy, String accountID){
|
||||
super(HttpMethod.POST, "/push/subscription", PushSubscription.class);
|
||||
Request r=new Request();
|
||||
r.subscription.endpoint="https://app.joinmastodon.org/relay-to/fcm/"+deviceToken+"/"+accountID;
|
||||
r.data.alerts=alerts;
|
||||
r.data.policy=policy;
|
||||
r.subscription.keys.p256dh=encryptionKey;
|
||||
r.subscription.keys.auth=authKey;
|
||||
setRequestBody(r);
|
||||
@@ -30,6 +31,7 @@ public class RegisterForPushNotifications extends MastodonAPIRequest<PushSubscri
|
||||
|
||||
private static class Data{
|
||||
public PushSubscription.Alerts alerts;
|
||||
public PushSubscription.Policy policy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.joinmastodon.android.api.requests.notifications;
|
||||
|
||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
import org.joinmastodon.android.model.PushSubscription;
|
||||
|
||||
public class UpdatePushSettings extends MastodonAPIRequest<PushSubscription>{
|
||||
public UpdatePushSettings(PushSubscription.Alerts alerts, PushSubscription.Policy policy){
|
||||
super(HttpMethod.PUT, "/push/subscription", PushSubscription.class);
|
||||
setRequestBody(new Request(alerts, policy));
|
||||
}
|
||||
|
||||
private static class Request{
|
||||
public Data data=new Data();
|
||||
|
||||
public Request(PushSubscription.Alerts alerts, PushSubscription.Policy policy){
|
||||
this.data.alerts=alerts;
|
||||
this.data.policy=policy;
|
||||
}
|
||||
|
||||
private static class Data{
|
||||
public PushSubscription.Alerts alerts;
|
||||
public PushSubscription.Policy policy;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import org.joinmastodon.android.api.PushSubscriptionManager;
|
||||
import org.joinmastodon.android.api.StatusInteractionController;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Application;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.PushSubscription;
|
||||
import org.joinmastodon.android.model.Token;
|
||||
|
||||
public class AccountSession{
|
||||
@@ -19,7 +19,8 @@ public class AccountSession{
|
||||
public String pushPrivateKey;
|
||||
public String pushPublicKey;
|
||||
public String pushAuthKey;
|
||||
public String pushServerKey;
|
||||
public PushSubscription pushSubscription;
|
||||
public boolean needUpdatePushSettings;
|
||||
private transient MastodonAPIController apiController;
|
||||
private transient StatusInteractionController statusInteractionController;
|
||||
private transient CacheController cacheController;
|
||||
|
||||
Reference in New Issue
Block a user