Show megaphone to improve network reliability.

fork-5.53.8
Greyson Parrelli 2022-03-04 13:30:22 -05:00 zatwierdzone przez Alex Hart
rodzic 427e73f7fd
commit 852dcd9711
10 zmienionych plików z 217 dodań i 4 usunięć

Wyświetl plik

@ -47,6 +47,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencyProvider;
import org.thoughtcrime.securesms.emoji.EmojiSource;
import org.thoughtcrime.securesms.emoji.JumboEmoji;
import org.thoughtcrime.securesms.gcm.FcmJobService;
import org.thoughtcrime.securesms.jobs.CheckServiceReachabilityJob;
import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob;
import org.thoughtcrime.securesms.jobs.DownloadLatestEmojiDataJob;
import org.thoughtcrime.securesms.jobs.EmojiSearchIndexDownloadJob;
@ -199,6 +200,7 @@ public class ApplicationContext extends MultiDexApplication implements AppForegr
.addPostRender(RetrieveReleaseChannelJob::enqueue)
.addPostRender(() -> AndroidTelecomUtil.registerPhoneAccount())
.addPostRender(() -> ApplicationDependencies.getJobManager().add(new FontDownloaderJob()))
.addPostRender(CheckServiceReachabilityJob::enqueueIfNecessary)
.execute();
Log.d(TAG, "onCreate() took " + (System.currentTimeMillis() - startTime) + " ms");

Wyświetl plik

@ -77,6 +77,7 @@ class AdvancedPrivacySettingsViewModel(
fun setCensorshipCircumventionEnabled(enabled: Boolean) {
SignalStore.settings().setCensorshipCircumventionEnabled(enabled)
SignalStore.misc().isServiceReachableWithoutCircumvention = false
ApplicationDependencies.resetNetworkConnectionsAfterProxyChange()
refresh()
}

Wyświetl plik

@ -0,0 +1,119 @@
package org.thoughtcrime.securesms.jobs
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.BuildConfig
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.jobmanager.Data
import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.whispersystems.libsignal.util.guava.Optional
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState
import org.whispersystems.signalservice.internal.util.StaticCredentialsProvider
import org.whispersystems.signalservice.internal.websocket.WebSocketConnection
import java.util.concurrent.TimeUnit
/**
* Checks to see if a censored user can establish a websocket connection with an uncensored network configuration.
*/
class CheckServiceReachabilityJob private constructor(params: Parameters) : BaseJob(params) {
constructor() : this(
Parameters.Builder()
.addConstraint(NetworkConstraint.KEY)
.setLifespan(TimeUnit.HOURS.toMillis(12))
.setMaxAttempts(1)
.build()
)
companion object {
private val TAG = Log.tag(CheckServiceReachabilityJob::class.java)
const val KEY = "CheckServiceReachabilityJob"
@JvmStatic
fun enqueueIfNecessary() {
val isCensored = ApplicationDependencies.getSignalServiceNetworkAccess().isCensored()
val timeSinceLastCheck = System.currentTimeMillis() - SignalStore.misc().lastCensorshipServiceReachabilityCheckTime
if (SignalStore.account().isRegistered && isCensored && timeSinceLastCheck > TimeUnit.DAYS.toMillis(1)) {
ApplicationDependencies.getJobManager().add(CheckServiceReachabilityJob())
}
}
}
override fun serialize(): Data {
return Data.EMPTY
}
override fun getFactoryKey(): String {
return KEY
}
override fun onRun() {
if (!SignalStore.account().isRegistered) {
Log.w(TAG, "Not registered, skipping.")
SignalStore.misc().lastCensorshipServiceReachabilityCheckTime = System.currentTimeMillis()
return
}
if (!ApplicationDependencies.getSignalServiceNetworkAccess().isCensored()) {
Log.w(TAG, "Not currently censored, skipping.")
SignalStore.misc().lastCensorshipServiceReachabilityCheckTime = System.currentTimeMillis()
return
}
SignalStore.misc().lastCensorshipServiceReachabilityCheckTime = System.currentTimeMillis()
val uncensoredWebsocket = WebSocketConnection(
"uncensored-test",
ApplicationDependencies.getSignalServiceNetworkAccess().uncensoredConfiguration,
Optional.of(
StaticCredentialsProvider(
SignalStore.account().aci,
SignalStore.account().pni,
SignalStore.account().e164,
SignalStore.account().deviceId,
SignalStore.account().servicePassword
)
),
BuildConfig.SIGNAL_AGENT,
null,
""
)
try {
val startTime = System.currentTimeMillis()
val state: WebSocketConnectionState = uncensoredWebsocket.connect()
.filter { it == WebSocketConnectionState.CONNECTED || it == WebSocketConnectionState.FAILED }
.timeout(30, TimeUnit.SECONDS)
.blockingFirst(WebSocketConnectionState.FAILED)
if (state == WebSocketConnectionState.CONNECTED) {
Log.i(TAG, "Established connection in ${System.currentTimeMillis() - startTime} ms! Service is reachable!")
SignalStore.misc().isServiceReachableWithoutCircumvention = true
} else {
Log.w(TAG, "Failed to establish a connection in ${System.currentTimeMillis() - startTime} ms.")
SignalStore.misc().isServiceReachableWithoutCircumvention = false
}
} catch (exception: Exception) {
Log.w(TAG, "Failed to connect to the websocket.", exception)
SignalStore.misc().isServiceReachableWithoutCircumvention = false
} finally {
uncensoredWebsocket.disconnect()
}
}
override fun onShouldRetry(e: Exception): Boolean {
return false
}
override fun onFailure() {
}
class Factory : Job.Factory<CheckServiceReachabilityJob> {
override fun create(parameters: Parameters, data: Data): CheckServiceReachabilityJob {
return CheckServiceReachabilityJob(parameters)
}
}
}

Wyświetl plik

@ -82,6 +82,7 @@ public final class JobManagerFactories {
put(AvatarGroupsV1DownloadJob.KEY, new AvatarGroupsV1DownloadJob.Factory());
put(AvatarGroupsV2DownloadJob.KEY, new AvatarGroupsV2DownloadJob.Factory());
put(BoostReceiptRequestResponseJob.KEY, new BoostReceiptRequestResponseJob.Factory());
put(CheckServiceReachabilityJob.KEY, new CheckServiceReachabilityJob.Factory());
put(CleanPreKeysJob.KEY, new CleanPreKeysJob.Factory());
put(ClearFallbackKbsEnclaveJob.KEY, new ClearFallbackKbsEnclaveJob.Factory());
put(ConversationShortcutUpdateJob.KEY, new ConversationShortcutUpdateJob.Factory());

Wyświetl plik

@ -16,6 +16,8 @@ public final class MiscellaneousValues extends SignalStoreValues {
private static final String OLD_DEVICE_TRANSFER_LOCKED = "misc.old_device.transfer.locked";
private static final String HAS_EVER_HAD_AN_AVATAR = "misc.has.ever.had.an.avatar";
private static final String CHANGE_NUMBER_LOCK = "misc.change_number.lock";
private static final String CENSORSHIP_LAST_CHECK_TIME = "misc.censorship.last_check_time";
private static final String CENSORSHIP_SERVICE_REACHABLE = "misc.censorship.service_reachable";
MiscellaneousValues(@NonNull KeyValueStore store) {
super(store);
@ -110,4 +112,20 @@ public final class MiscellaneousValues extends SignalStoreValues {
public void unlockChangeNumber() {
putBoolean(CHANGE_NUMBER_LOCK, false);
}
public long getLastCensorshipServiceReachabilityCheckTime() {
return getLong(CENSORSHIP_LAST_CHECK_TIME, 0);
}
public void setLastCensorshipServiceReachabilityCheckTime(long value) {
putLong(CENSORSHIP_LAST_CHECK_TIME, value);
}
public boolean isServiceReachableWithoutCircumvention() {
return getBoolean(CENSORSHIP_SERVICE_REACHABLE, false);
}
public void setServiceReachableWithoutCircumvention(boolean value) {
putBoolean(CENSORSHIP_SERVICE_REACHABLE, value);
}
}

Wyświetl plik

@ -106,6 +106,7 @@ public final class Megaphones {
put(Event.CLIENT_DEPRECATED, SignalStore.misc().isClientDeprecated() ? ALWAYS : NEVER);
put(Event.NOTIFICATIONS, shouldShowNotificationsMegaphone(context) ? RecurringSchedule.every(TimeUnit.DAYS.toMillis(30)) : NEVER);
put(Event.ONBOARDING, shouldShowOnboardingMegaphone(context) ? ALWAYS : NEVER);
put(Event.TURN_OFF_CENSORSHIP_CIRCUMVENTION, shouldShowTurnOffCircumventionMegaphone() ? RecurringSchedule.every(TimeUnit.DAYS.toMillis(7)) : NEVER);
put(Event.BECOME_A_SUSTAINER, shouldShowDonateMegaphone(context, records) ? ShowForDurationSchedule.showForDays(7) : NEVER);
put(Event.PIN_REMINDER, new SignalPinReminderSchedule());
@ -136,6 +137,8 @@ public final class Megaphones {
return buildBecomeASustainerMegaphone(context);
case NOTIFICATION_PROFILES:
return buildNotificationProfilesMegaphone(context);
case TURN_OFF_CENSORSHIP_CIRCUMVENTION:
return buildTurnOffCircumventionMegaphone(context);
default:
throw new IllegalArgumentException("Event not handled!");
}
@ -295,6 +298,21 @@ public final class Megaphones {
.build();
}
private static @NonNull Megaphone buildTurnOffCircumventionMegaphone(@NonNull Context context) {
return new Megaphone.Builder(Event.TURN_OFF_CENSORSHIP_CIRCUMVENTION, Megaphone.Style.BASIC)
.setTitle(R.string.CensorshipCircumventionMegaphone_turn_off_censorship_circumvention)
.setImage(R.drawable.ic_censorship_megaphone_64)
.setBody(R.string.CensorshipCircumventionMegaphone_you_can_now_connect_to_the_signal_service)
.setActionButton(R.string.CensorshipCircumventionMegaphone_turn_off, (megaphone, listener) -> {
SignalStore.settings().setCensorshipCircumventionEnabled(false);
listener.onMegaphoneSnooze(Event.TURN_OFF_CENSORSHIP_CIRCUMVENTION);
})
.setSecondaryButton(R.string.CensorshipCircumventionMegaphone_no_thanks, (megaphone, listener) -> {
listener.onMegaphoneSnooze(Event.TURN_OFF_CENSORSHIP_CIRCUMVENTION);
})
.build();
}
private static boolean shouldShowDonateMegaphone(@NonNull Context context, @NonNull Map<Event, MegaphoneRecord> records) {
long timeSinceLastDonatePrompt = timeSinceLastDonatePrompt(records);
@ -313,6 +331,11 @@ public final class Megaphones {
return SignalStore.onboarding().hasOnboarding(context);
}
private static boolean shouldShowTurnOffCircumventionMegaphone() {
return ApplicationDependencies.getSignalServiceNetworkAccess().isCensored() &&
SignalStore.misc().isServiceReachableWithoutCircumvention();
}
private static boolean shouldShowNotificationsMegaphone(@NonNull Context context) {
boolean shouldShow = !SignalStore.settings().isMessageNotificationsEnabled() ||
!NotificationChannels.isMessageChannelEnabled(context) ||
@ -374,7 +397,8 @@ public final class Megaphones {
ADD_A_PROFILE_PHOTO("add_a_profile_photo"),
BECOME_A_SUSTAINER("become_a_sustainer"),
VALENTINES_DONATIONS_2022("valentines_donations_2022"),
NOTIFICATION_PROFILES("notification_profiles");
NOTIFICATION_PROFILES("notification_profiles"),
TURN_OFF_CENSORSHIP_CIRCUMVENTION("turn_off_censorship_circumvention");
private final String key;

Wyświetl plik

@ -1,8 +1,6 @@
package org.thoughtcrime.securesms.megaphone;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
final class SignalPinReminderSchedule implements MegaphoneSchedule {

Wyświetl plik

@ -211,7 +211,7 @@ class SignalServiceNetworkAccess(context: Context) {
COUNTRY_CODE_UZBEKISTAN,
)
private val uncensoredConfiguration: SignalServiceConfiguration = SignalServiceConfiguration(
val uncensoredConfiguration: SignalServiceConfiguration = SignalServiceConfiguration(
arrayOf(SignalServiceUrl(BuildConfig.SIGNAL_URL, serviceTrustStore)),
mapOf(
0 to arrayOf(SignalCdnUrl(BuildConfig.SIGNAL_CDN_URL, serviceTrustStore)),

Wyświetl plik

@ -0,0 +1,41 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp"
android:height="64dp"
android:viewportWidth="64"
android:viewportHeight="64">
<path
android:pathData="M32,0C40.4869,0 48.6263,3.3714 54.6274,9.3726C60.6286,15.3737 64,23.5131 64,32C64,40.4869 60.6286,48.6263 54.6274,54.6274C48.6263,60.6286 40.4869,64 32,64V64C23.5131,64 15.3737,60.6286 9.3726,54.6274C3.3714,48.6263 0,40.4869 0,32V32C0,23.5131 3.3714,15.3737 9.3726,9.3726C15.3737,3.3714 23.5131,0 32,0V0Z"
android:fillColor="#DCE1F9"
android:fillAlpha="0.4"/>
<path
android:pathData="M31.5,47C39.5081,47 46,40.5081 46,32.5C46,24.4919 39.5081,18 31.5,18C23.4919,18 17,24.4919 17,32.5C17,40.5081 23.4919,47 31.5,47Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M30.417,45.367V41.5C30.0012,41.5001 29.5893,41.4183 29.2051,41.2593C28.8209,41.1002 28.4718,40.8671 28.1777,40.573C27.8836,40.279 27.6503,39.93 27.4911,39.5458C27.3319,39.1616 27.25,38.7498 27.25,38.334V36.75L24.875,34.375L22.5,32L20.917,30.417L19.333,28.834L19,28.5C18.4999,30.3658 18.4069,32.3174 18.7272,34.2224C19.0476,36.1273 19.7737,37.9411 20.8565,39.5408C21.9393,41.1405 23.3535,42.4887 25.003,43.4939C26.6525,44.4991 28.4989,45.1379 30.417,45.367V45.367ZM21.117,24.084H24.085V21.115C22.9469,21.9445 21.9449,22.9462 21.115,24.084H21.117ZM36.75,19.4C38.8576,20.1949 40.7319,21.506 42.2015,23.2131C43.671,24.9201 44.6887,26.9687 45.1614,29.171C45.634,31.3734 45.5465,33.6591 44.9068,35.8188C44.2672,37.9786 43.0958,39.9433 41.5,41.533V41.5C41.5,41.0841 41.4181,40.6724 41.2589,40.2882C41.0997,39.904 40.8664,39.5549 40.5723,39.2609C40.2782,38.9669 39.9291,38.7338 39.5449,38.5747C39.1607,38.4157 38.7488,38.3339 38.333,38.334H36.75V33.584C36.75,33.1641 36.5833,32.7613 36.2864,32.4643C35.9896,32.1673 35.5869,32.0003 35.167,32H25.667V28.834H28.833C29.2531,28.834 29.656,28.6671 29.9531,28.3701C30.2501,28.073 30.417,27.6701 30.417,27.25V24.084H33.583C34.4229,24.084 35.2285,23.7503 35.8224,23.1564C36.4163,22.5625 36.75,21.7569 36.75,20.917V19.4ZM47.833,32C47.833,35.1315 46.9044,38.1926 45.1647,40.7963C43.4249,43.4001 40.9521,45.4294 38.059,46.6278C35.1659,47.8261 31.9824,48.1397 28.9111,47.5288C25.8398,46.9178 23.0187,45.4099 20.8044,43.1956C18.5901,40.9813 17.0821,38.1602 16.4712,35.0889C15.8603,32.0176 16.1739,28.8341 17.3722,25.941C18.5706,23.0479 20.5999,20.5751 23.2037,18.8353C25.8074,17.0956 28.8685,16.167 32,16.167C36.1991,16.1673 40.2261,17.8355 43.1953,20.8047C46.1645,23.7739 47.8327,27.8009 47.833,32Z"
android:fillColor="#2C6BED"
android:fillType="evenOdd"/>
<path
android:pathData="M51.526,42.2379L53.621,43.3569C54.394,41.913 55.0233,40.3967 55.5,38.8299L53.227,38.1399L53.193,38.1299C52.7613,39.5458 52.1919,40.916 51.493,42.2209L51.526,42.2379Z"
android:fillColor="#B6C5FA"/>
<path
android:pathData="M54.052,29.3581C54.1253,30.0915 54.1617,30.8298 54.161,31.5731C54.1603,32.3165 54.124,33.0545 54.052,33.7871H54.089L56.452,34.0201C56.532,33.2088 56.5723,32.3921 56.573,31.5701C56.5737,30.7481 56.5333,29.9311 56.452,29.1191L54.089,29.3521L54.052,29.3581Z"
android:fillColor="#B6C5FA"/>
<path
android:pathData="M45.9,49.0338L45.923,49.0618L47.432,50.8998C48.062,50.3825 48.668,49.8332 49.25,49.2518C49.832,48.6705 50.382,48.0638 50.9,47.4318L49.064,45.9258L49.036,45.9028C48.5693,46.4722 48.073,47.0195 47.547,47.5448C47.021,48.0702 46.472,48.5665 45.9,49.0338Z"
android:fillColor="#B6C5FA"/>
<path
android:pathData="M51.494,20.9241C52.1929,22.229 52.7623,23.5992 53.194,25.0151L53.228,25.0051L55.501,24.3151C55.0256,22.7484 54.3976,21.2321 53.626,19.7881L51.531,20.9071L51.494,20.9241Z"
android:fillColor="#B6C5FA"/>
<path
android:pathData="M38.13,9.9559C39.5459,10.3876 40.9161,10.957 42.221,11.6559L42.238,11.6239L43.357,9.5239C41.913,8.7524 40.3967,8.1243 38.83,7.6489L38.14,9.9219L38.13,9.9559Z"
android:fillColor="#B6C5FA"/>
<path
android:pathData="M45.9,14.1111C46.4693,14.5777 47.0167,15.0741 47.542,15.6001C48.0673,16.1261 48.5637,16.6734 49.031,17.2421L49.059,17.2191L50.9,15.7131C50.3827,15.0831 49.8333,14.4771 49.252,13.8951C48.6707,13.3131 48.0647,12.7637 47.434,12.2471L45.928,14.0831L45.9,14.1111Z"
android:fillColor="#B6C5FA"/>
<path
android:pathData="M38.361,50.3149L36.061,55.1249L40.87,57.4249L41.65,55.7999L39.871,55.0579C41.3818,54.5437 42.8436,53.8955 44.239,53.1209L42.839,51.1019C41.6381,51.8173 40.3982,52.4649 39.125,53.0419L39.996,51.1009L38.361,50.3149Z"
android:fillColor="#B6C5FA"/>
<path
android:pathData="M31.573,54.1612C28.594,54.181 25.6405,53.6113 22.8825,52.485C20.1246,51.3588 17.6166,49.698 15.5031,47.5985C13.3896,45.499 11.7122,43.0022 10.5676,40.2518C9.423,37.5014 8.8337,34.5517 8.8337,31.5727C8.8337,28.5936 9.423,25.6439 10.5676,22.8935C11.7122,20.1431 13.3896,17.6463 15.5031,15.5468C17.6166,13.4473 20.1246,11.7866 22.8825,10.6603C25.6405,9.534 28.594,8.9643 31.573,8.9842C31.996,8.9842 32.415,9.0222 32.836,9.0462V6.6062H32.76C32.3653,6.5868 31.9697,6.5775 31.573,6.5782C24.9426,6.5782 18.5837,9.2121 13.8953,13.9005C9.2069,18.5889 6.573,24.9477 6.573,31.5782C6.573,38.2086 9.2069,44.5674 13.8953,49.2558C18.5837,53.9442 24.9426,56.5782 31.573,56.5782C31.969,56.5782 32.3647,56.5685 32.76,56.5492H32.836V54.1002C32.415,54.1232 32,54.1612 31.573,54.1612Z"
android:fillColor="#B6C5FA"/>
</vector>

Wyświetl plik

@ -4600,6 +4600,15 @@
<!-- Displayed in the viewer when network is available but content could not be downloaded -->
<string name="StorySlateView__couldnt_load_content">Couldn\'t Load Content</string>
<!-- Title for a notification at the bottom of the chat list suggesting that the user disable censorship circumvention because the service has become reachable -->
<string name="TurnOffCircumventionMegaphone_turn_off_censorship_circumvention">Turn off censorship circumvention?</string>
<!-- Body for a notification at the bottom of the chat list suggesting that the user disable censorship circumvention because the service has become reachable -->
<string name="TurnOffCircumventionMegaphone_you_can_now_connect_to_the_signal_service_directly">You can now connect to the Signal service directly for a better experience.</string>
<!-- Label for a button to dismiss a notification at the bottom of the chat list suggesting that the user disable censorship circumvention because the service has become reachable -->
<string name="TurnOffCircumventionMegaphone_no_thanks">No thanks</string>
<!-- Label for a button in a notification at the bottom of the chat list to turn off censorship circumvention -->
<string name="TurnOffCircumventionMegaphone_turn_off">Turn off</string>
<!-- endregion -->
<!-- Content description for expand contacts chevron -->
<string name="ExpandModel__view_more">View more</string>