mirror of
https://github.com/nuclearfog/Shitter.git
synced 2025-02-05 21:43:27 +01:00
added initial web push implementation, bug fix
This commit is contained in:
parent
9eb1943e5d
commit
81c4c64167
@ -61,4 +61,5 @@ dependencies {
|
||||
implementation 'com.github.nuclearfog:Tagger:2.4'
|
||||
implementation 'com.github.nuclearfog:LinkAndScrollMovement:1.4.1'
|
||||
implementation 'com.github.kyleduo:SwitchButton:2.0.3-SNAPSHOT'
|
||||
implementation 'com.github.UnifiedPush:android-connector:2.1.1'
|
||||
}
|
@ -10,14 +10,11 @@
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="29"
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" tools:ignore="ScopedStorage" />
|
||||
|
||||
<application
|
||||
android:name=".ClientApplication"
|
||||
@ -128,6 +125,19 @@
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme" />
|
||||
|
||||
<receiver
|
||||
android:name=".receiver.PushNotificationReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="org.unifiedpush.android.connector.MESSAGE"/>
|
||||
<action android:name="org.unifiedpush.android.connector.UNREGISTERED"/>
|
||||
<action android:name="org.unifiedpush.android.connector.NEW_ENDPOINT"/>
|
||||
<action android:name="org.unifiedpush.android.connector.REGISTRATION_FAILED"/>
|
||||
<action android:name="org.unifiedpush.android.connector.REGISTRATION_REFUSED"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -4,12 +4,33 @@ import android.app.Application;
|
||||
|
||||
import org.nuclearfog.twidda.backend.image.ImageCache;
|
||||
import org.nuclearfog.twidda.backend.image.PicassoBuilder;
|
||||
import org.unifiedpush.android.connector.ConstantsKt;
|
||||
import org.unifiedpush.android.connector.UnifiedPush;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class ClientApplication extends Application {
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
ArrayList<String> features = new ArrayList<>(1);
|
||||
features.add(UnifiedPush.FEATURE_BYTES_MESSAGE);
|
||||
UnifiedPush.registerApp(this, ConstantsKt.INSTANCE_DEFAULT, features, "");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
UnifiedPush.unregisterApp(this, ConstantsKt.INSTANCE_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
ImageCache.clear();
|
||||
|
@ -2,6 +2,7 @@ package org.nuclearfog.twidda.backend.api;
|
||||
|
||||
import org.nuclearfog.twidda.backend.helper.ConnectionConfig;
|
||||
import org.nuclearfog.twidda.backend.helper.MediaStatus;
|
||||
import org.nuclearfog.twidda.backend.helper.update.PushUpdate;
|
||||
import org.nuclearfog.twidda.lists.Domains;
|
||||
import org.nuclearfog.twidda.lists.Messages;
|
||||
import org.nuclearfog.twidda.backend.helper.update.ProfileUpdate;
|
||||
@ -24,6 +25,7 @@ import org.nuclearfog.twidda.model.Translation;
|
||||
import org.nuclearfog.twidda.model.Trend;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
import org.nuclearfog.twidda.model.UserList;
|
||||
import org.nuclearfog.twidda.model.WebPush;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -447,15 +449,6 @@ public interface Connection {
|
||||
*/
|
||||
void deleteStatus(long id) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* upload status with additional attachment
|
||||
*
|
||||
* @param update status update information
|
||||
* @param mediaIds IDs of the uploaded media files if any
|
||||
* @return uploaded status
|
||||
*/
|
||||
Status uploadStatus(StatusUpdate update, List<Long> mediaIds) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* return a list of domain names the current user has blocked
|
||||
*
|
||||
@ -478,6 +471,15 @@ public interface Connection {
|
||||
*/
|
||||
void unblockDomain(String domain) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* upload status with additional attachment
|
||||
*
|
||||
* @param update status update information
|
||||
* @param mediaIds IDs of the uploaded media files if any
|
||||
* @return uploaded status
|
||||
*/
|
||||
Status updateStatus(StatusUpdate update, List<Long> mediaIds) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* create userlist
|
||||
*
|
||||
@ -494,6 +496,30 @@ public interface Connection {
|
||||
*/
|
||||
UserList updateUserlist(UserListUpdate update) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* updates current user's profile
|
||||
*
|
||||
* @param update profile update information
|
||||
* @return updated user information
|
||||
*/
|
||||
User updateProfile(ProfileUpdate update) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* upload media file and generate a media ID
|
||||
*
|
||||
* @param mediaUpdate inputstream with MIME type of the media
|
||||
* @return media ID
|
||||
*/
|
||||
long updateMedia(MediaStatus mediaUpdate) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* create Web push subscription
|
||||
*
|
||||
* @param pushUpdate web push update
|
||||
* @return created web push subscription
|
||||
*/
|
||||
WebPush updatePush(PushUpdate pushUpdate) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* return userlist information
|
||||
*
|
||||
@ -622,22 +648,6 @@ public interface Connection {
|
||||
*/
|
||||
MediaStatus downloadImage(String link) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* updates current user's profile
|
||||
*
|
||||
* @param update profile update information
|
||||
* @return updated user information
|
||||
*/
|
||||
User updateProfile(ProfileUpdate update) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* upload media file and generate a media ID
|
||||
*
|
||||
* @param mediaUpdate inputstream with MIME type of the media
|
||||
* @return media ID
|
||||
*/
|
||||
long uploadMedia(MediaStatus mediaUpdate) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* get notification of the current user
|
||||
*
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.nuclearfog.twidda.backend.api.mastodon;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Base64;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -17,6 +18,7 @@ import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonInstance;
|
||||
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonList;
|
||||
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonNotification;
|
||||
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonPoll;
|
||||
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonPush;
|
||||
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonRelation;
|
||||
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonStatus;
|
||||
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonTranslation;
|
||||
@ -24,6 +26,7 @@ import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonTrend;
|
||||
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonUser;
|
||||
import org.nuclearfog.twidda.backend.helper.ConnectionConfig;
|
||||
import org.nuclearfog.twidda.backend.helper.MediaStatus;
|
||||
import org.nuclearfog.twidda.backend.helper.update.PushUpdate;
|
||||
import org.nuclearfog.twidda.lists.Domains;
|
||||
import org.nuclearfog.twidda.lists.Messages;
|
||||
import org.nuclearfog.twidda.backend.helper.update.PollUpdate;
|
||||
@ -50,10 +53,19 @@ import org.nuclearfog.twidda.model.Translation;
|
||||
import org.nuclearfog.twidda.model.Trend;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
import org.nuclearfog.twidda.model.UserList;
|
||||
import org.nuclearfog.twidda.model.WebPush;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.interfaces.ECPublicKey;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
import java.security.spec.ECPoint;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -85,7 +97,7 @@ public class Mastodon implements Connection {
|
||||
/**
|
||||
* scopes used by this app
|
||||
*/
|
||||
private static final String AUTH_SCOPES = "read%20write%20follow";
|
||||
private static final String AUTH_SCOPES = "read%20write%20follow%20push";
|
||||
|
||||
/**
|
||||
* oauth no redirect (oob)
|
||||
@ -126,6 +138,7 @@ public class Mastodon implements Connection {
|
||||
private static final String ENDPOINT_CUSTOM_EMOJIS = "/api/v1/custom_emojis";
|
||||
private static final String ENDPOINT_POLL = "/api/v1/polls/";
|
||||
private static final String ENDPOINT_DOMAIN_BLOCK = "/api/v1/domain_blocks";
|
||||
private static final String ENDPOINT_PUSH_UPDATE = "/api/v1/push/subscription";
|
||||
|
||||
private static final MediaType TYPE_TEXT = MediaType.parse("text/plain");
|
||||
private static final MediaType TYPE_STREAM = MediaType.parse("application/octet-stream");
|
||||
@ -166,7 +179,7 @@ public class Mastodon implements Connection {
|
||||
String client_id = json.getString("client_id");
|
||||
String client_secret = json.getString("client_secret");
|
||||
connection.setOauthTokens(client_id, client_secret);
|
||||
return hostname + ENDPOINT_AUTHORIZE_APP + "?scope=read%20write%20follow&response_type=code&redirect_uri=" + REDIRECT_URI + "&client_id=" + client_id;
|
||||
return hostname + ENDPOINT_AUTHORIZE_APP + "?scope=" + AUTH_SCOPES + "&response_type=code&redirect_uri=" + REDIRECT_URI + "&client_id=" + client_id;
|
||||
}
|
||||
throw new MastodonException(response);
|
||||
} catch (IOException | JSONException e) {
|
||||
@ -625,7 +638,7 @@ public class Mastodon implements Connection {
|
||||
|
||||
|
||||
@Override
|
||||
public Status uploadStatus(StatusUpdate update, List<Long> mediaIds) throws MastodonException {
|
||||
public Status updateStatus(StatusUpdate update, List<Long> mediaIds) throws MastodonException {
|
||||
List<String> params = new ArrayList<>();
|
||||
// add identifier to prevent duplicate posts
|
||||
params.add("Idempotency-Key=" + System.currentTimeMillis() / 5000);
|
||||
@ -972,7 +985,7 @@ public class Mastodon implements Connection {
|
||||
|
||||
|
||||
@Override
|
||||
public long uploadMedia(MediaStatus mediaUpdate) throws MastodonException {
|
||||
public long updateMedia(MediaStatus mediaUpdate) throws MastodonException {
|
||||
try {
|
||||
List<String> params = new ArrayList<>();
|
||||
if (!mediaUpdate.getDescription().isEmpty())
|
||||
@ -1004,6 +1017,65 @@ public class Mastodon implements Connection {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WebPush updatePush(PushUpdate pushUpdate) throws ConnectionException {
|
||||
try {
|
||||
KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
|
||||
ECGenParameterSpec spec = new ECGenParameterSpec("prime256v1");
|
||||
generator.initialize(spec);
|
||||
KeyPair keyPair = generator.generateKeyPair();
|
||||
byte[] privKeyData = keyPair.getPrivate().getEncoded();
|
||||
byte[] pubKeyData = keyPair.getPublic().getEncoded();
|
||||
byte[] serializedPubKey = serializeRawPublicKey((ECPublicKey) keyPair.getPublic());
|
||||
String encodedPublicKey = Base64.encodeToString(serializedPubKey, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
|
||||
String pushPrivateKey = Base64.encodeToString(privKeyData, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
|
||||
String pushPublicKey = Base64.encodeToString(pubKeyData, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
|
||||
String randomString = StringUtils.getRandomString();
|
||||
|
||||
List<String> params = new ArrayList<>();
|
||||
params.add("subscription[endpoint]=" + pushUpdate.getEndpoint());
|
||||
params.add("subscription[keys][p256dh]=" + encodedPublicKey);
|
||||
params.add("subscription[keys][auth]=" + randomString);
|
||||
if (pushUpdate.enableMentions())
|
||||
params.add("data[alerts][mention]=true");
|
||||
if (pushUpdate.enableFavorite())
|
||||
params.add("data[alerts][favourite]=true");
|
||||
if (pushUpdate.enableRepost())
|
||||
params.add("data[alerts][reblog]=true");
|
||||
if (pushUpdate.enableFollow())
|
||||
params.add("data[alerts][follow]=true");
|
||||
if (pushUpdate.enableFollowRequest())
|
||||
params.add("data[alerts][follow_request]=true");
|
||||
if (pushUpdate.enablePoll())
|
||||
params.add("data[alerts][poll]=true");
|
||||
if (pushUpdate.enableStatus())
|
||||
params.add("data[alerts][status]=true");
|
||||
if (pushUpdate.enableStatusEdit())
|
||||
params.add("data[alerts][update]=true");
|
||||
if (pushUpdate.getPolicy() == PushUpdate.POLICY_ALL)
|
||||
params.add("data[policy]=all");
|
||||
else if (pushUpdate.getPolicy() == PushUpdate.POLICY_FOLLOWER)
|
||||
params.add("data[policy]=follower");
|
||||
else if (pushUpdate.getPolicy() == PushUpdate.POLICY_FOLLOWING)
|
||||
params.add("data[policy]=followed");
|
||||
else if (pushUpdate.getPolicy() == PushUpdate.POLICY_NONE)
|
||||
params.add("data[policy]=none");
|
||||
Response response = post(ENDPOINT_PUSH_UPDATE, params);
|
||||
ResponseBody body = response.body();
|
||||
if (response.code() == 200 && body != null) {
|
||||
JSONObject json = new JSONObject(body.string());
|
||||
MastodonPush result = new MastodonPush(json);
|
||||
result.setKeys(pushPublicKey, pushPrivateKey);
|
||||
result.setAuthSecret(randomString);
|
||||
return result;
|
||||
}
|
||||
throw new MastodonException(response);
|
||||
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | JSONException | IOException e) {
|
||||
throw new MastodonException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Notifications getNotifications(long minId, long maxId) throws ConnectionException {
|
||||
List<String> params = new ArrayList<>();
|
||||
@ -1624,4 +1696,22 @@ public class Mastodon implements Connection {
|
||||
}
|
||||
return hostname + endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private byte[] serializeRawPublicKey(ECPublicKey key) {
|
||||
ECPoint point = key.getW();
|
||||
byte[] x = point.getAffineX().toByteArray();
|
||||
byte[] y = point.getAffineY().toByteArray();
|
||||
if(x.length>32)
|
||||
x = Arrays.copyOfRange(x, x.length-32, x.length);
|
||||
if(y.length>32)
|
||||
y = Arrays.copyOfRange(y, y.length-32, y.length);
|
||||
byte[] result = new byte[65];
|
||||
result[0] = 4;
|
||||
System.arraycopy(x, 0, result, 1+(32-x.length), x.length);
|
||||
System.arraycopy(y, 0, result, result.length-y.length, y.length);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
package org.nuclearfog.twidda.backend.api.mastodon.impl;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.nuclearfog.twidda.model.WebPush;
|
||||
|
||||
/**
|
||||
* Mastodon push implementation
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class MastodonPush implements WebPush {
|
||||
|
||||
private static final long serialVersionUID = 565081495547561476L;
|
||||
|
||||
private long id;
|
||||
private String endpoint;
|
||||
private String serverKey, publicKey, privateKey, authSec;
|
||||
|
||||
/**
|
||||
* @param json web push json object
|
||||
*/
|
||||
public MastodonPush(JSONObject json) throws JSONException {
|
||||
String id = json.getString("id");
|
||||
endpoint = json.getString("endpoint");
|
||||
serverKey = json.getString("server_key");
|
||||
try {
|
||||
this.id = Long.parseLong(id);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new JSONException("bad ID: " + id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getServerKey() {
|
||||
return serverKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getAuthSecret() {
|
||||
return authSec;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertMentionEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertStatusEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertRepostEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertFollowingEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertFollowRequestEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertFavoriteEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertPollEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertStatusChangeEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "id=" + getId() + " url=\"" + getEndpoint() + "\"";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (!(obj instanceof WebPush))
|
||||
return false;
|
||||
WebPush push = (WebPush) obj;
|
||||
return getId() == push.getId() && getEndpoint().equals(push.getEndpoint());
|
||||
}
|
||||
|
||||
/**
|
||||
* set encryption keys
|
||||
*/
|
||||
public void setKeys(String publicKey, String privateKey) {
|
||||
this.publicKey = publicKey;
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* set auth key
|
||||
*/
|
||||
public void setAuthSecret(String authSec) {
|
||||
this.authSec = authSec;
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import org.nuclearfog.twidda.backend.api.twitter.v1.impl.UserListV1;
|
||||
import org.nuclearfog.twidda.backend.api.twitter.v1.impl.UserV1;
|
||||
import org.nuclearfog.twidda.backend.helper.ConnectionConfig;
|
||||
import org.nuclearfog.twidda.backend.helper.MediaStatus;
|
||||
import org.nuclearfog.twidda.backend.helper.update.PushUpdate;
|
||||
import org.nuclearfog.twidda.lists.Domains;
|
||||
import org.nuclearfog.twidda.lists.Messages;
|
||||
import org.nuclearfog.twidda.backend.helper.update.ProfileUpdate;
|
||||
@ -49,6 +50,7 @@ import org.nuclearfog.twidda.model.Translation;
|
||||
import org.nuclearfog.twidda.model.Trend;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
import org.nuclearfog.twidda.model.UserList;
|
||||
import org.nuclearfog.twidda.model.WebPush;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -746,7 +748,7 @@ public class TwitterV1 implements Connection {
|
||||
|
||||
|
||||
@Override
|
||||
public Status uploadStatus(StatusUpdate update, List<Long> mediaIds) throws TwitterException {
|
||||
public Status updateStatus(StatusUpdate update, List<Long> mediaIds) throws TwitterException {
|
||||
List<String> params = new ArrayList<>();
|
||||
if (update.getText() != null)
|
||||
params.add("status=" + StringUtils.encode(update.getText()));
|
||||
@ -1012,7 +1014,7 @@ public class TwitterV1 implements Connection {
|
||||
|
||||
|
||||
@Override
|
||||
public long uploadMedia(MediaStatus mediaUpdate) throws TwitterException {
|
||||
public long updateMedia(MediaStatus mediaUpdate) throws TwitterException {
|
||||
List<String> params = new ArrayList<>();
|
||||
boolean enableChunk;
|
||||
final long mediaId;
|
||||
@ -1096,6 +1098,12 @@ public class TwitterV1 implements Connection {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WebPush updatePush(PushUpdate pushUpdate) throws TwitterException {
|
||||
throw new TwitterException("not implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MediaStatus downloadImage(String link) throws TwitterException {
|
||||
try {
|
||||
|
@ -37,7 +37,7 @@ public class MessageUpdater extends AsyncExecutor<MessageUpdate, MessageUpdater.
|
||||
// upload media if any
|
||||
long mediaId = 0L;
|
||||
if (update.getMediaUpdate() != null) {
|
||||
mediaId = connection.uploadMedia(update.getMediaUpdate());
|
||||
mediaId = connection.updateMedia(update.getMediaUpdate());
|
||||
}
|
||||
// upload message and media ID
|
||||
connection.sendDirectmessage(id, update.getMessage(), mediaId);
|
||||
|
@ -0,0 +1,42 @@
|
||||
package org.nuclearfog.twidda.backend.async;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.nuclearfog.twidda.backend.api.Connection;
|
||||
import org.nuclearfog.twidda.backend.api.ConnectionManager;
|
||||
import org.nuclearfog.twidda.backend.helper.update.PushUpdate;
|
||||
import org.nuclearfog.twidda.config.GlobalSettings;
|
||||
import org.nuclearfog.twidda.model.WebPush;
|
||||
|
||||
/**
|
||||
* Async class used to update push information
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class PushUpdater extends AsyncExecutor <PushUpdate, Void> {
|
||||
|
||||
private Connection connection;
|
||||
private GlobalSettings settings;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public PushUpdater(Context context) {
|
||||
connection = ConnectionManager.getDefaultConnection(context);
|
||||
settings = GlobalSettings.getInstance(context);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(@NonNull PushUpdate param) {
|
||||
try {
|
||||
WebPush webpush = connection.updatePush(param);
|
||||
settings.setWebPush(webpush);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -41,12 +41,12 @@ public class StatusUpdater extends AsyncExecutor<StatusUpdate, StatusUpdater.Sta
|
||||
List<Long> mediaIds = new LinkedList<>();
|
||||
for (MediaStatus mediaStatus : update.getMediaStatuses()) {
|
||||
if (mediaStatus.isLocal()) {
|
||||
long mediaId = connection.uploadMedia(mediaStatus);
|
||||
long mediaId = connection.updateMedia(mediaStatus);
|
||||
mediaIds.add(mediaId);
|
||||
}
|
||||
}
|
||||
// upload status
|
||||
Status status = connection.uploadStatus(update, mediaIds);
|
||||
Status status = connection.updateStatus(update, mediaIds);
|
||||
return new StatusUpdateResult(status, null);
|
||||
} catch (ConnectionException exception) {
|
||||
return new StatusUpdateResult(null, exception);
|
||||
|
@ -6,6 +6,7 @@ import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
@ -15,7 +16,7 @@ import java.io.Serializable;
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class MediaStatus implements Serializable {
|
||||
public class MediaStatus implements Serializable, Closeable {
|
||||
|
||||
private static final long serialVersionUID = 6824278073662885637L;
|
||||
|
||||
@ -50,6 +51,20 @@ public class MediaStatus implements Serializable {
|
||||
local = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* close stream
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create a stream to upload media file
|
||||
*
|
||||
@ -113,20 +128,6 @@ public class MediaStatus implements Serializable {
|
||||
return local;
|
||||
}
|
||||
|
||||
/**
|
||||
* close stream
|
||||
*/
|
||||
public void close() {
|
||||
try {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
|
@ -11,6 +11,7 @@ import androidx.documentfile.provider.DocumentFile;
|
||||
import org.nuclearfog.twidda.backend.helper.MediaStatus;
|
||||
import org.nuclearfog.twidda.model.Instance;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.TreeSet;
|
||||
@ -20,7 +21,7 @@ import java.util.TreeSet;
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class MessageUpdate implements Serializable {
|
||||
public class MessageUpdate implements Serializable, Closeable {
|
||||
|
||||
private static final long serialVersionUID = 991295406939128220L;
|
||||
|
||||
@ -36,6 +37,16 @@ public class MessageUpdate implements Serializable {
|
||||
|
||||
private TreeSet<String> supportedFormats = new TreeSet<>();
|
||||
|
||||
/**
|
||||
* close inputstream of media file
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
if (mediaUpdate != null) {
|
||||
mediaUpdate.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name screen name of the user
|
||||
*/
|
||||
@ -135,14 +146,6 @@ public class MessageUpdate implements Serializable {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* close inputstream of media file
|
||||
*/
|
||||
public void close() {
|
||||
if (mediaUpdate != null) {
|
||||
mediaUpdate.close();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
|
@ -9,6 +9,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@ -17,7 +18,7 @@ import java.io.InputStream;
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class ProfileUpdate {
|
||||
public class ProfileUpdate implements Closeable {
|
||||
|
||||
private Uri[] imageUrls = new Uri[2];
|
||||
private InputStream[] imageStreams = new InputStream[2];
|
||||
@ -27,6 +28,23 @@ public class ProfileUpdate {
|
||||
private String description = "";
|
||||
private String location = "";
|
||||
|
||||
|
||||
/**
|
||||
* close all image streams
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
for (InputStream imageStream : imageStreams) {
|
||||
if (imageStream != null) {
|
||||
imageStream.close();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* setup profile information
|
||||
*
|
||||
@ -151,21 +169,6 @@ public class ProfileUpdate {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* close all image streams
|
||||
*/
|
||||
public void close() {
|
||||
try {
|
||||
for (InputStream imageStream : imageStreams) {
|
||||
if (imageStream != null) {
|
||||
imageStream.close();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
|
@ -0,0 +1,101 @@
|
||||
package org.nuclearfog.twidda.backend.helper.update;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Webpush updater class used to create a webpush subscription
|
||||
* @see org.nuclearfog.twidda.backend.api.Connection
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class PushUpdate implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -34599486422177957L;
|
||||
|
||||
/**
|
||||
* show all notifications
|
||||
*/
|
||||
public static final int POLICY_ALL = 1;
|
||||
|
||||
/**
|
||||
* show only notifications of followed users
|
||||
*/
|
||||
public static final int POLICY_FOLLOWING = 2;
|
||||
|
||||
/**
|
||||
* show only notifications of followers
|
||||
*/
|
||||
public static final int POLICY_FOLLOWER = 3;
|
||||
|
||||
/**
|
||||
* disable push notification
|
||||
*/
|
||||
public static final int POLICY_NONE = 4;
|
||||
|
||||
private String endpoint;
|
||||
private boolean notifyMention, notifyStatus, notifyFollow, notifyFollowRequest;
|
||||
private boolean notifyFavorite, notifyRepost, notifyPoll, notifyEdit;
|
||||
private int policy;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public PushUpdate(String endpoint) {
|
||||
int idx = endpoint.indexOf('?');
|
||||
if (idx > 0) {
|
||||
this.endpoint = endpoint.substring(0, idx);
|
||||
} else {
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
|
||||
public boolean enableMentions() {
|
||||
return notifyMention;
|
||||
}
|
||||
|
||||
|
||||
public boolean enableStatus() {
|
||||
return notifyStatus;
|
||||
}
|
||||
|
||||
|
||||
public boolean enableStatusEdit() {
|
||||
return notifyEdit;
|
||||
}
|
||||
|
||||
|
||||
public boolean enableRepost() {
|
||||
return notifyRepost;
|
||||
}
|
||||
|
||||
|
||||
public boolean enableFavorite() {
|
||||
return notifyFavorite;
|
||||
}
|
||||
|
||||
|
||||
public boolean enablePoll() {
|
||||
return notifyPoll;
|
||||
}
|
||||
|
||||
|
||||
public boolean enableFollow() {
|
||||
return notifyFollow;
|
||||
}
|
||||
|
||||
|
||||
public boolean enableFollowRequest() {
|
||||
return notifyFollowRequest;
|
||||
}
|
||||
|
||||
|
||||
public int getPolicy() {
|
||||
return policy;
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ import org.nuclearfog.twidda.model.Instance;
|
||||
import org.nuclearfog.twidda.model.Media;
|
||||
import org.nuclearfog.twidda.model.Status;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -25,7 +26,7 @@ import java.util.TreeSet;
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class StatusUpdate implements Serializable {
|
||||
public class StatusUpdate implements Serializable, Closeable {
|
||||
|
||||
private static final long serialVersionUID = -5300983806882462557L;
|
||||
|
||||
@ -93,6 +94,18 @@ public class StatusUpdate implements Serializable {
|
||||
private boolean attachmentLimitReached = false;
|
||||
private int attachment = EMPTY;
|
||||
|
||||
/**
|
||||
* close all open streams
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
for (MediaStatus mediaUpdate : mediaStatuses) {
|
||||
if (mediaUpdate != null) {
|
||||
mediaUpdate.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set informations of an existing status to edit these
|
||||
*
|
||||
@ -465,17 +478,6 @@ public class StatusUpdate implements Serializable {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* close all open streams
|
||||
*/
|
||||
public void close() {
|
||||
for (MediaStatus mediaUpdate : mediaStatuses) {
|
||||
if (mediaUpdate != null) {
|
||||
mediaUpdate.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
|
@ -12,8 +12,10 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import org.nuclearfog.twidda.config.impl.ConfigAccount;
|
||||
import org.nuclearfog.twidda.config.impl.ConfigLocation;
|
||||
import org.nuclearfog.twidda.config.impl.ConfigPush;
|
||||
import org.nuclearfog.twidda.model.Account;
|
||||
import org.nuclearfog.twidda.model.Location;
|
||||
import org.nuclearfog.twidda.model.WebPush;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -85,6 +87,12 @@ public class GlobalSettings {
|
||||
private static final String PROXY_PASS = "proxy_pass";
|
||||
private static final String TREND_LOC = "location";
|
||||
private static final String TREND_ID = "world_id_long";
|
||||
private static final String PUSH_ID = "push_id";
|
||||
private static final String PUSH_SERVER_HOST = "push_server_host";
|
||||
private static final String PUSH_SERVER_KEY = "push_server_key";
|
||||
private static final String PUSH_PUBLIC_KEY = "push_public_key";
|
||||
private static final String PUSH_PRIVATE_KEY = "push_private_key";
|
||||
private static final String PUSH_AUTH_KEY = "push_auth_key";
|
||||
private static final String ENABLE_LIKE = "like_enable";
|
||||
private static final String ENABLE_TWITTER_ALT = "twitter_alt_set";
|
||||
private static final String FILTER_RESULTS = "filter_results";
|
||||
@ -125,6 +133,7 @@ public class GlobalSettings {
|
||||
private SharedPreferences settings;
|
||||
|
||||
private Location location;
|
||||
private ConfigPush webPush;
|
||||
private ConfigAccount login;
|
||||
private String proxyHost, proxyPort;
|
||||
private String proxyUser, proxyPass;
|
||||
@ -547,6 +556,31 @@ public class GlobalSettings {
|
||||
edit.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* get used web push instance
|
||||
*/
|
||||
public WebPush getWebPush() {
|
||||
return webPush;
|
||||
}
|
||||
|
||||
/**
|
||||
* save web push configuration
|
||||
*
|
||||
* @param webPush web push information
|
||||
*/
|
||||
public void setWebPush(WebPush webPush) {
|
||||
this.webPush = new ConfigPush(webPush);
|
||||
|
||||
Editor edit = settings.edit();
|
||||
edit.putLong(PUSH_ID, webPush.getId());
|
||||
edit.putString(PUSH_SERVER_KEY, webPush.getServerKey());
|
||||
edit.putString(PUSH_SERVER_HOST, webPush.getEndpoint());
|
||||
edit.putString(PUSH_PUBLIC_KEY, webPush.getPublicKey());
|
||||
edit.putString(PUSH_PRIVATE_KEY, webPush.getPrivateKey());
|
||||
edit.putString(PUSH_AUTH_KEY, webPush.getAuthSecret());
|
||||
edit.apply();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get loading limit of tweets/users
|
||||
@ -967,7 +1001,14 @@ public class GlobalSettings {
|
||||
proxyPass = settings.getString(PROXY_PASS, "");
|
||||
String place = settings.getString(TREND_LOC, DEFAULT_LOCATION_NAME);
|
||||
long woeId = settings.getLong(TREND_ID, DEFAULT_LOCATION_ID);
|
||||
long pushID = settings.getLong(PUSH_ID, 0L);
|
||||
String pushServerKey = settings.getString(PUSH_SERVER_KEY, "");
|
||||
String pushServerHost = settings.getString(PUSH_SERVER_HOST, "");
|
||||
String pushPublicKey = settings.getString(PUSH_PUBLIC_KEY, "");
|
||||
String pushPrivateKey = settings.getString(PUSH_PRIVATE_KEY, "");
|
||||
String pushAuthKey = settings.getString(PUSH_AUTH_KEY, "");
|
||||
location = new ConfigLocation(woeId, place);
|
||||
webPush = new ConfigPush(pushID, pushServerHost, pushServerKey, pushPublicKey, pushPrivateKey, pushAuthKey);
|
||||
// login informations
|
||||
initLogin();
|
||||
}
|
||||
|
@ -0,0 +1,142 @@
|
||||
package org.nuclearfog.twidda.config.impl;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.nuclearfog.twidda.model.WebPush;
|
||||
|
||||
/**
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class ConfigPush implements WebPush {
|
||||
|
||||
private static final long serialVersionUID = -6942479639448210795L;
|
||||
|
||||
private long id;
|
||||
private String endpoint;
|
||||
private String serverKey, publicKey, privateKey, authKey;
|
||||
|
||||
/**
|
||||
* @param webPush web push instance to copy information
|
||||
*/
|
||||
public ConfigPush(WebPush webPush) {
|
||||
id = webPush.getId();
|
||||
endpoint = webPush.getEndpoint();
|
||||
serverKey = webPush.getServerKey();
|
||||
publicKey = webPush.getPublicKey();
|
||||
privateKey = webPush.getPrivateKey();
|
||||
authKey = webPush.getAuthSecret();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public ConfigPush(long id, String endpoint, String serverKey, String publicKey, String privateKey, String authKey) {
|
||||
this.id = id;
|
||||
this.endpoint = endpoint;
|
||||
this.serverKey = serverKey;
|
||||
this.privateKey = privateKey;
|
||||
this.publicKey = publicKey;
|
||||
this.authKey = authKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getServerKey() {
|
||||
return serverKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getAuthSecret() {
|
||||
return authKey;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertMentionEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertStatusEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertRepostEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertFollowingEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertFollowRequestEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertFavoriteEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertPollEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alertStatusChangeEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "id=" + getId() + " url=\"" + getEndpoint() + "\"";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (!(obj instanceof WebPush))
|
||||
return false;
|
||||
WebPush push = (WebPush) obj;
|
||||
return getId() == push.getId() && getEndpoint().equals(push.getEndpoint());
|
||||
}
|
||||
}
|
81
app/src/main/java/org/nuclearfog/twidda/model/WebPush.java
Normal file
81
app/src/main/java/org/nuclearfog/twidda/model/WebPush.java
Normal file
@ -0,0 +1,81 @@
|
||||
package org.nuclearfog.twidda.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Represents a web push subscription.
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public interface WebPush extends Serializable {
|
||||
|
||||
/**
|
||||
* @return ID of the subscription
|
||||
*/
|
||||
long getId();
|
||||
|
||||
/**
|
||||
* @return webpush host url
|
||||
*/
|
||||
String getEndpoint();
|
||||
|
||||
/**
|
||||
* @return unique server key set from {@link org.nuclearfog.twidda.backend.api.Connection}
|
||||
*/
|
||||
String getServerKey();
|
||||
|
||||
/**
|
||||
* @return encryption public key
|
||||
*/
|
||||
String getPublicKey();
|
||||
|
||||
/**
|
||||
* @return encryption public key
|
||||
*/
|
||||
String getPrivateKey();
|
||||
|
||||
/**
|
||||
* @return auth secret
|
||||
*/
|
||||
String getAuthSecret();
|
||||
|
||||
/**
|
||||
* @return true if notification for mentions is enabled
|
||||
*/
|
||||
boolean alertMentionEnabled();
|
||||
|
||||
/**
|
||||
* @return true if status notification (profile subscription) is enabled
|
||||
*/
|
||||
boolean alertStatusEnabled();
|
||||
|
||||
/**
|
||||
* @return true if 'status reposted' notification is enabled
|
||||
*/
|
||||
boolean alertRepostEnabled();
|
||||
|
||||
/**
|
||||
* @return true if 'new follower' notification is enabled
|
||||
*/
|
||||
boolean alertFollowingEnabled();
|
||||
|
||||
/**
|
||||
* @return true if 'follow request' notification is enabled
|
||||
*/
|
||||
boolean alertFollowRequestEnabled();
|
||||
|
||||
/**
|
||||
* @return true if 'status favorited' notification is enabled
|
||||
*/
|
||||
boolean alertFavoriteEnabled();
|
||||
|
||||
/**
|
||||
* @return true if 'poll finished' notification is enabled
|
||||
*/
|
||||
boolean alertPollEnabled();
|
||||
|
||||
/**
|
||||
* @return true if 'status changed' notification is enabled
|
||||
*/
|
||||
boolean alertStatusChangeEnabled();
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package org.nuclearfog.twidda.receiver;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.nuclearfog.twidda.backend.async.PushUpdater;
|
||||
import org.nuclearfog.twidda.backend.helper.update.PushUpdate;
|
||||
import org.unifiedpush.android.connector.MessagingReceiver;
|
||||
|
||||
/**
|
||||
* Push notification receiver used to trigger synchronization.
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class PushNotificationReceiver extends MessagingReceiver {
|
||||
|
||||
|
||||
@Override
|
||||
public void onMessage(@NonNull Context context, @NonNull byte[] message, @NonNull String instance) {
|
||||
super.onMessage(context, message, instance);
|
||||
// todo add manual synchonization
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onNewEndpoint(@NonNull Context context, @NonNull String endpoint, @NonNull String instance) {
|
||||
super.onNewEndpoint(context, endpoint, instance);
|
||||
PushUpdater pushUpdater = new PushUpdater(context);
|
||||
PushUpdate update = new PushUpdate(endpoint);
|
||||
pushUpdater.execute(update, null);
|
||||
}
|
||||
}
|
@ -76,7 +76,7 @@ public class UserlistActivity extends AppCompatActivity implements ActivityResul
|
||||
* regex pattern to validate username
|
||||
* e.g. username, @username or @username@instance.social
|
||||
*/
|
||||
private static final Pattern USERNAME_PATTERN = Pattern.compile("@?[\\w\\d]{1,20}(@[\\w\\d.]{1,50})?");
|
||||
private static final Pattern USERNAME_PATTERN = Pattern.compile("@?\\w{1,20}(@[\\w.]{1,50})?");
|
||||
|
||||
private ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this);
|
||||
|
||||
|
@ -48,6 +48,7 @@ public class AnimatedImageView extends AppCompatImageView {
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setImageURI(@Nullable Uri uri) {
|
||||
ContentResolver resolver = getContext().getContentResolver();
|
||||
String mime = resolver.getType(uri);
|
||||
@ -66,6 +67,7 @@ public class AnimatedImageView extends AppCompatImageView {
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (movie != null) {
|
||||
// calculate scale and offsets
|
||||
|
Loading…
x
Reference in New Issue
Block a user