mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-08 22:37:40 +00:00
Show a banner in the event of a service outage.
We will now determine if there has been a service outage and render a banner at the top of the conversation list if we detect that there has been one.
This commit is contained in:
parent
0999359454
commit
2c17b54ef9
@ -270,6 +270,7 @@ android {
|
||||
buildConfigField "long", "BUILD_TIMESTAMP", getLastCommitTimestamp() + "L"
|
||||
buildConfigField "String", "SIGNAL_URL", "\"https://textsecure-service.whispersystems.org\""
|
||||
buildConfigField "String", "SIGNAL_CDN_URL", "\"https://cdn.signal.org\""
|
||||
buildConfigField "String", "SIGNAL_SERVICE_STATUS_URL", "\"uptime.signal.org\""
|
||||
buildConfigField "String", "GIPHY_PROXY_HOST", "\"giphy-proxy-production.whispersystems.org\""
|
||||
buildConfigField "int", "GIPHY_PROXY_PORT", "80"
|
||||
buildConfigField "String", "USER_AGENT", "\"OWA\""
|
||||
|
6
res/drawable/reminder_background_error.xml
Normal file
6
res/drawable/reminder_background_error.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true" android:drawable="@color/core_red_highlight" />
|
||||
<item android:state_focused="true" android:drawable="@color/core_red_highlight" />
|
||||
<item android:drawable="@color/core_red" />
|
||||
</selector>
|
@ -5,7 +5,7 @@
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/reminder_background"
|
||||
android:background="@drawable/reminder_background_normal"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
tools:visibility="visible">
|
||||
|
@ -5,7 +5,7 @@
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/reminder_background"
|
||||
android:background="@drawable/reminder_background_normal"
|
||||
android:focusable="true"
|
||||
android:nextFocusRight="@+id/cancel"
|
||||
android:orientation="horizontal"
|
||||
|
@ -5,7 +5,7 @@
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/reminder_background"
|
||||
android:background="@drawable/reminder_background_normal"
|
||||
android:focusable="true"
|
||||
android:nextFocusRight="@+id/cancel"
|
||||
android:orientation="horizontal"
|
||||
|
@ -58,4 +58,7 @@
|
||||
<color name="transparent">#00FFFFFF</color>
|
||||
|
||||
<color name="MediaOverview_Media_selected_overlay">#88000000</color>
|
||||
|
||||
<color name="core_red">#f44336</color>
|
||||
<color name="core_red_highlight">#ef5350</color>
|
||||
</resources>
|
||||
|
@ -1361,6 +1361,7 @@
|
||||
<string name="reminder_header_invite_text">Take your conversation with %1$s to the next level.</string>
|
||||
<string name="reminder_header_share_title">Invite your friends!</string>
|
||||
<string name="reminder_header_share_text">The more friends use Signal, the better it gets.</string>
|
||||
<string name="reminder_header_service_outage_text">Signal is experiencing technical difficulties. We are working hard to restore service as quickly as possible.</string>
|
||||
|
||||
<!-- media_preview -->
|
||||
<string name="media_preview__save_title">Save</string>
|
||||
|
@ -94,6 +94,7 @@ import org.thoughtcrime.securesms.components.location.SignalPlace;
|
||||
import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder;
|
||||
import org.thoughtcrime.securesms.components.reminder.InviteReminder;
|
||||
import org.thoughtcrime.securesms.components.reminder.ReminderView;
|
||||
import org.thoughtcrime.securesms.components.reminder.ServiceOutageReminder;
|
||||
import org.thoughtcrime.securesms.components.reminder.UnauthorizedReminder;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
@ -121,6 +122,7 @@ import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
|
||||
import org.thoughtcrime.securesms.giph.ui.GiphyActivity;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob;
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
|
||||
import org.thoughtcrime.securesms.jobs.ServiceOutageDetectionJob;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentManager;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentManager.MediaType;
|
||||
import org.thoughtcrime.securesms.mms.AudioSlide;
|
||||
@ -1115,12 +1117,15 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
protected void updateReminders(boolean seenInvite) {
|
||||
Log.w(TAG, "updateReminders(" + seenInvite+")");
|
||||
Log.w(TAG, "updateReminders(" + seenInvite + ")");
|
||||
|
||||
if (UnauthorizedReminder.isEligible(this)) {
|
||||
reminderView.get().showReminder(new UnauthorizedReminder(this));
|
||||
} else if (ExpiredBuildReminder.isEligible()) {
|
||||
reminderView.get().showReminder(new ExpiredBuildReminder(this));
|
||||
} else if (ServiceOutageReminder.isEligible(this)) {
|
||||
ApplicationContext.getInstance(this).getJobManager().add(new ServiceOutageDetectionJob(this));
|
||||
reminderView.get().showReminder(new ServiceOutageReminder(this));
|
||||
} else if (TextSecurePreferences.isPushRegistered(this) &&
|
||||
TextSecurePreferences.isShowInviteReminders(this) &&
|
||||
!isSecureText &&
|
||||
|
@ -66,14 +66,15 @@ import org.thoughtcrime.securesms.components.reminder.OutdatedBuildReminder;
|
||||
import org.thoughtcrime.securesms.components.reminder.PushRegistrationReminder;
|
||||
import org.thoughtcrime.securesms.components.reminder.Reminder;
|
||||
import org.thoughtcrime.securesms.components.reminder.ReminderView;
|
||||
import org.thoughtcrime.securesms.components.reminder.ServiceOutageReminder;
|
||||
import org.thoughtcrime.securesms.components.reminder.ShareReminder;
|
||||
import org.thoughtcrime.securesms.components.reminder.SystemSmsImportReminder;
|
||||
import org.thoughtcrime.securesms.components.reminder.UnauthorizedReminder;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.database.loaders.ConversationListLoader;
|
||||
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
|
||||
import org.thoughtcrime.securesms.jobs.ServiceOutageDetectionJob;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
@ -81,6 +82,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.task.SnackbarAsyncTask;
|
||||
import org.whispersystems.jobqueue.JobManager;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.util.HashSet;
|
||||
@ -190,6 +192,9 @@ public class ConversationListFragment extends Fragment
|
||||
return Optional.of(new UnauthorizedReminder(context));
|
||||
} else if (ExpiredBuildReminder.isEligible()) {
|
||||
return Optional.of(new ExpiredBuildReminder(context));
|
||||
} else if (ServiceOutageReminder.isEligible(context)) {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new ServiceOutageDetectionJob(context));
|
||||
return Optional.of(new ServiceOutageReminder(context));
|
||||
} else if (OutdatedBuildReminder.isEligible()) {
|
||||
return Optional.of(new OutdatedBuildReminder(context));
|
||||
} else if (DefaultSmsReminder.isEligible(context)) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.thoughtcrime.securesms.components.reminder;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.View.OnClickListener;
|
||||
|
||||
public abstract class Reminder {
|
||||
@ -10,14 +11,14 @@ public abstract class Reminder {
|
||||
private OnClickListener okListener;
|
||||
private OnClickListener dismissListener;
|
||||
|
||||
public Reminder(@NonNull CharSequence title,
|
||||
@NonNull CharSequence text)
|
||||
public Reminder(@Nullable CharSequence title,
|
||||
@NonNull CharSequence text)
|
||||
{
|
||||
this.title = title;
|
||||
this.text = text;
|
||||
this.title = title;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public CharSequence getTitle() {
|
||||
public @Nullable CharSequence getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
@ -44,4 +45,13 @@ public abstract class Reminder {
|
||||
public boolean isDismissable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public @NonNull Importance getImportance() {
|
||||
return Importance.NORMAL;
|
||||
}
|
||||
|
||||
|
||||
public enum Importance {
|
||||
NORMAL, ERROR
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.components.reminder;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -49,8 +50,16 @@ public class ReminderView extends LinearLayout {
|
||||
}
|
||||
|
||||
public void showReminder(final Reminder reminder) {
|
||||
title.setText(reminder.getTitle());
|
||||
if (!TextUtils.isEmpty(reminder.getTitle())) {
|
||||
title.setText(reminder.getTitle());
|
||||
title.setVisibility(VISIBLE);
|
||||
} else {
|
||||
title.setText("");
|
||||
title.setVisibility(GONE);
|
||||
}
|
||||
text.setText(reminder.getText());
|
||||
container.setBackgroundResource(reminder.getImportance() == Reminder.Importance.ERROR ? R.drawable.reminder_background_error
|
||||
: R.drawable.reminder_background_normal);
|
||||
|
||||
setOnClickListener(reminder.getOkListener());
|
||||
|
||||
|
@ -0,0 +1,30 @@
|
||||
package org.thoughtcrime.securesms.components.reminder;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
public class ServiceOutageReminder extends Reminder {
|
||||
|
||||
public ServiceOutageReminder(@NonNull Context context) {
|
||||
super(null,
|
||||
context.getString(R.string.reminder_header_service_outage_text));
|
||||
}
|
||||
|
||||
public static boolean isEligible(@NonNull Context context) {
|
||||
return TextSecurePreferences.getServiceOutage(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDismissable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Importance getImportance() {
|
||||
return Importance.ERROR;
|
||||
}
|
||||
}
|
@ -139,6 +139,8 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
super.onCanceled();
|
||||
|
||||
DatabaseFactory.getMmsDatabase(context).markAsSentFailed(messageId);
|
||||
}
|
||||
|
||||
|
@ -94,6 +94,8 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
super.onCanceled();
|
||||
|
||||
DatabaseFactory.getMmsDatabase(context).markAsSentFailed(messageId);
|
||||
notifyMediaMessageDeliveryFailed(context, messageId);
|
||||
}
|
||||
|
@ -71,6 +71,11 @@ public abstract class PushSendJob extends SendJob {
|
||||
onPushSend();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new ServiceOutageDetectionJob(context));
|
||||
}
|
||||
|
||||
protected Optional<byte[]> getProfileKey(@NonNull Recipient recipient) {
|
||||
if (!recipient.resolve().isSystemContact() && !recipient.resolve().isProfileSharing()) {
|
||||
return Optional.absent();
|
||||
|
@ -83,6 +83,8 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
super.onCanceled();
|
||||
|
||||
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId);
|
||||
|
||||
long threadId = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageId);
|
||||
|
@ -0,0 +1,78 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class ServiceOutageDetectionJob extends ContextJob {
|
||||
|
||||
private static final String TAG = ServiceOutageDetectionJob.class.getSimpleName();
|
||||
|
||||
private static final String IP_SUCCESS = "127.0.0.1";
|
||||
private static final String IP_FAILURE = "127.0.0.2";
|
||||
private static final long CHECK_TIME = 1000 * 60;
|
||||
|
||||
public ServiceOutageDetectionJob(Context context) {
|
||||
super(context, new JobParameters.Builder()
|
||||
.withGroupId(ServiceOutageDetectionJob.class.getSimpleName())
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.withRetryCount(5)
|
||||
.create());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdded() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRun() throws RetryLaterException {
|
||||
long timeSinceLastCheck = System.currentTimeMillis() - TextSecurePreferences.getLastOutageCheckTime(context);
|
||||
if (timeSinceLastCheck < CHECK_TIME) {
|
||||
Log.w(TAG, "Skipping service outage check. Too soon.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
InetAddress address = InetAddress.getByName(BuildConfig.SIGNAL_SERVICE_STATUS_URL);
|
||||
|
||||
if (IP_SUCCESS.equals(address.getHostAddress())) {
|
||||
Log.w(TAG, "Service is available.");
|
||||
TextSecurePreferences.setServiceOutage(context, false);
|
||||
} else if (IP_FAILURE.equals(address.getHostAddress())) {
|
||||
Log.w(TAG, "Service is down.");
|
||||
TextSecurePreferences.setServiceOutage(context, true);
|
||||
} else {
|
||||
Log.w(TAG, "Service status check returned an unrecognized IP address. Assuming outage.");
|
||||
TextSecurePreferences.setServiceOutage(context, true);
|
||||
}
|
||||
|
||||
TextSecurePreferences.setLastOutageCheckTime(context, System.currentTimeMillis());
|
||||
EventBus.getDefault().post(new ReminderUpdateEvent());
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RetryLaterException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onShouldRetry(Exception e) {
|
||||
return e instanceof RetryLaterException;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
Log.w(TAG, "Service status check could not complete. Assuming success to avoid false positives due to bad network.");
|
||||
TextSecurePreferences.setServiceOutage(context, false);
|
||||
TextSecurePreferences.setLastOutageCheckTime(context, System.currentTimeMillis());
|
||||
EventBus.getDefault().post(new ReminderUpdateEvent());
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ import android.util.Log;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.events.ReminderUpdateEvent;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.SqlCipherMigrationRequirementProvider;
|
||||
import org.thoughtcrime.securesms.lock.RegistrationLockReminders;
|
||||
import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference;
|
||||
@ -150,6 +151,9 @@ public class TextSecurePreferences {
|
||||
private static final String REGISTRATION_LOCK_LAST_REMINDER_TIME = "pref_registration_lock_last_reminder_time";
|
||||
private static final String REGISTRATION_LOCK_NEXT_REMINDER_INTERVAL = "pref_registration_lock_next_reminder_interval";
|
||||
|
||||
private static final String SERVICE_OUTAGE = "pref_service_outage";
|
||||
private static final String LAST_OUTAGE_CHECK_TIME = "pref_last_outage_check_time";
|
||||
|
||||
public static boolean isScreenLockEnabled(@NonNull Context context) {
|
||||
return getBooleanPreference(context, SCREEN_LOCK, false);
|
||||
}
|
||||
@ -903,6 +907,22 @@ public class TextSecurePreferences {
|
||||
new HashSet<>(Arrays.asList(context.getResources().getStringArray(defaultValuesRes))));
|
||||
}
|
||||
|
||||
public static void setLastOutageCheckTime(Context context, long timestamp) {
|
||||
setLongPreference(context, LAST_OUTAGE_CHECK_TIME, timestamp);
|
||||
}
|
||||
|
||||
public static long getLastOutageCheckTime(Context context) {
|
||||
return getLongPreference(context, LAST_OUTAGE_CHECK_TIME, 0);
|
||||
}
|
||||
|
||||
public static void setServiceOutage(Context context, boolean isOutage) {
|
||||
setBooleanPreference(context, SERVICE_OUTAGE, isOutage);
|
||||
}
|
||||
|
||||
public static boolean getServiceOutage(Context context) {
|
||||
return getBooleanPreference(context, SERVICE_OUTAGE, false);
|
||||
}
|
||||
|
||||
public static void setBooleanPreference(Context context, String key, boolean value) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(key, value).apply();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user