Implement multi device removal sheet

This commit is contained in:
nielsandriesse 2020-07-30 16:53:34 +10:00
parent 5e9dd8d286
commit f56e3be1d4
9 changed files with 165 additions and 13 deletions

View file

@ -57,6 +57,7 @@
android:layout_height="@dimen/onboarding_button_bottom_offset"
android:layout_marginLeft="@dimen/massive_spacing"
android:layout_marginRight="@dimen/massive_spacing"
android:visibility="invisible"
android:gravity="center"
android:background="@color/transparent"
android:textAllCaps="false"

View file

@ -57,6 +57,7 @@
android:layout_height="@dimen/onboarding_button_bottom_offset"
android:layout_marginLeft="@dimen/massive_spacing"
android:layout_marginRight="@dimen/massive_spacing"
android:visibility="invisible"
android:gravity="center"
android:background="@color/transparent"
android:textAllCaps="false"

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:paddingLeft="@dimen/very_large_spacing"
android:paddingTop="@dimen/large_spacing"
android:paddingRight="@dimen/very_large_spacing"
android:paddingBottom="@dimen/very_large_spacing"
app:behavior_hideable="true"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
android:background="@drawable/default_bottom_sheet_background_inset">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Changes to Multi-Device"
android:textColor="@color/text"
android:textStyle="bold"
android:textSize="@dimen/large_font_size" />
<TextView
android:id="@+id/explanationTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/large_spacing"
android:text="Youre seeing this because you have a secondary device linked to your Session ID. To improve reliability and stability, weve decided to temporarily disable Sessions multi-device functionality. Device linking has been disabled, and existing secondary clients will be erased on %s.\n\nTo read more about this change, visit the Session FAQ at getsession.org/faq"
android:textColor="@color/text"
android:textSize="@dimen/small_font_size" />
<Button
style="@style/MediumProminentOutlineButton"
android:id="@+id/okButton"
android:layout_width="240dp"
android:layout_height="@dimen/medium_button_height"
android:layout_marginTop="@dimen/large_spacing"
android:text="@string/ok" />
</LinearLayout>

View file

@ -7,6 +7,7 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.database.Cursor
import android.net.Uri
import android.os.AsyncTask
import android.os.Bundle
import android.os.Handler
@ -30,7 +31,9 @@ import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase
import org.thoughtcrime.securesms.loki.dialogs.ConversationOptionsBottomSheet
import org.thoughtcrime.securesms.loki.dialogs.MultiDeviceRemovalBottomSheet
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
import org.thoughtcrime.securesms.loki.utilities.*
@ -189,6 +192,25 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
if (hasViewedSeed || !isMasterDevice) {
seedReminderView.visibility = View.GONE
}
val hasSeenMultiDeviceRemovalSheet = TextSecurePreferences.getHasSeenMultiDeviceRemovalSheet(this)
if (!hasSeenMultiDeviceRemovalSheet) {
TextSecurePreferences.setHasSeenMultiDeviceRemovalSheet(this)
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
val deviceLinks = DatabaseFactory.getLokiAPIDatabase(this).getDeviceLinks(userPublicKey)
if (deviceLinks.isNotEmpty()) {
val bottomSheet = MultiDeviceRemovalBottomSheet()
bottomSheet.onOKTapped = {
bottomSheet.dismiss()
}
bottomSheet.onLinkTapped = {
bottomSheet.dismiss()
val url = "https://getsession.org/faq"
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(intent)
}
bottomSheet.show(supportFragmentManager, bottomSheet.tag)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

View file

@ -44,7 +44,7 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
fakeChatView.startAnimating()
registerButton.setOnClickListener { register() }
restoreButton.setOnClickListener { restore() }
linkButton.setOnClickListener { linkDevice() }
// linkButton.setOnClickListener { linkDevice() }
if (TextSecurePreferences.getWasUnlinked(this)) {
Toast.makeText(this, R.string.activity_landing_device_unlinked_dialog_title, Toast.LENGTH_LONG).show()
}

View file

@ -115,7 +115,7 @@ class PNModeActivity : BaseActionBarActivity() {
TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
TextSecurePreferences.setPromptedPushRegistration(this, true)
TextSecurePreferences.setIsUsingFCM(this, (selectedOptionView == fcmOptionView))
TextSecurePreferences.setHasSeenPNModeSheet(this, true) // Shouldn't be shown to users who've done the new onboarding
TextSecurePreferences.setHasSeenMultiDeviceRemovalSheet(this)
val application = ApplicationContext.getInstance(this)
application.setUpStorageAPIIfNeeded()
application.setUpP2PAPIIfNeeded()

View file

@ -83,16 +83,16 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
copyButton.setOnClickListener { copyPublicKey() }
shareButton.setOnClickListener { sharePublicKey() }
val isMasterDevice = (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == null)
linkedDevicesButtonTopSeparator.visibility = View.GONE
linkedDevicesButton.visibility = View.GONE
if (!isMasterDevice) {
linkedDevicesButtonTopSeparator.visibility = View.GONE
linkedDevicesButton.visibility = View.GONE
seedButtonTopSeparator.visibility = View.GONE
seedButton.visibility = View.GONE
}
privacyButton.setOnClickListener { showPrivacySettings() }
notificationsButton.setOnClickListener { showNotificationSettings() }
chatsButton.setOnClickListener { showChatSettings() }
linkedDevicesButton.setOnClickListener { showLinkedDevices() }
// linkedDevicesButton.setOnClickListener { showLinkedDevices() }
seedButton.setOnClickListener { showSeed() }
clearAllDataButton.setOnClickListener { clearAllData() }
versionTextView.text = String.format(getString(R.string.version_s), BuildConfig.VERSION_NAME)

View file

@ -0,0 +1,86 @@
package org.thoughtcrime.securesms.loki.dialogs
import android.graphics.Typeface
import android.os.Bundle
import android.support.design.widget.BottomSheetDialogFragment
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import kotlinx.android.synthetic.main.fragment_multi_device_removal_bottom_sheet.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
import org.thoughtcrime.securesms.util.TextSecurePreferences
import java.text.SimpleDateFormat
import java.util.*
class MultiDeviceRemovalBottomSheet : BottomSheetDialogFragment() {
var onOKTapped: (() -> Unit)? = null
var onLinkTapped: (() -> Unit)? = null
private val removalDate by lazy {
val timeZone = TimeZone.getTimeZone("Australia/Melbourne")
val calendar = GregorianCalendar.getInstance(timeZone)
calendar.set(2020, 8 - 1, 6, 17, 0, 0)
calendar.time
}
private val removalDateDescription by lazy {
val formatter = SimpleDateFormat("MMMM d", Locale.getDefault())
formatter.format(removalDate)
}
private val explanation by lazy {
if (TextSecurePreferences.getMasterHexEncodedPublicKey(context!!) != null) {
"Youre seeing this because this is a secondary device in a multi-device setup. To improve reliability and stability, weve decided to temporarily disable Sessions multi-device functionality. Device linking has been disabled, and existing secondary clients will be erased on $removalDateDescription.\n\nTo read more about this change, visit the Session FAQ at getsession.org/faq."
} else {
"Youre seeing this because you have a secondary device linked to your Session ID. To improve reliability and stability, weve decided to temporarily disable Sessions multi-device functionality. Device linking has been disabled, and existing secondary clients will be erased on $removalDateDescription.\n\nTo read more about this change, visit the Session FAQ at getsession.org/faq"
}
}
private val decoratedExplanation by lazy {
val result = SpannableStringBuilder(explanation)
val removalDateStartIndex = explanation.indexOf(removalDateDescription)
val removalDateEndIndex = removalDateStartIndex + removalDateDescription.count()
result.setSpan(StyleSpan(Typeface.BOLD), removalDateStartIndex, removalDateEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
result.setSpan(ForegroundColorSpan(resources.getColorWithID(R.color.accent, context!!.theme)), removalDateStartIndex, removalDateEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
val link = "getsession.org/faq"
val linkStartIndex = explanation.indexOf(link)
val linkEndIndex = linkStartIndex + link.count()
result.setSpan(object : ClickableSpan() {
override fun onClick(widget: View) {
try {
onLinkTapped?.invoke()
} catch (e: Exception) {
Toast.makeText(context!!, R.string.invalid_url, Toast.LENGTH_SHORT).show()
}
}
}, linkStartIndex, linkEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
result.setSpan(StyleSpan(Typeface.BOLD), linkStartIndex, linkEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
result.setSpan(ForegroundColorSpan(resources.getColorWithID(R.color.accent, context!!.theme)), linkStartIndex, linkEndIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
result
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL, R.style.SessionBottomSheetDialogTheme)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_multi_device_removal_bottom_sheet, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
explanationTextView.movementMethod = LinkMovementMethod.getInstance()
explanationTextView.text = decoratedExplanation
okButton.setOnClickListener { onOKTapped?.invoke() }
}
}

View file

@ -214,14 +214,6 @@ public class TextSecurePreferences {
public static void setLastFCMUploadTime(Context context, long value) {
setLongPreference(context, LAST_FCM_TOKEN_UPLOAD_TIME, value);
}
public static boolean hasSeenPNModeSheet(Context context) {
return getBooleanPreference(context, HAS_SEEN_PN_MODE_SHEET, false);
}
public static void setHasSeenPNModeSheet(Context context, boolean value) {
setBooleanPreference(context, HAS_SEEN_PN_MODE_SHEET, value);
}
// endregion
public static boolean isScreenLockEnabled(@NonNull Context context) {
@ -1316,5 +1308,13 @@ public class TextSecurePreferences {
public static void clearAll(Context context) {
PreferenceManager.getDefaultSharedPreferences(context).edit().clear().commit();
}
public static boolean getHasSeenMultiDeviceRemovalSheet(Context context) {
return getBooleanPreference(context, "has_seen_multi_device_removal_sheet", false);
}
public static void setHasSeenMultiDeviceRemovalSheet(Context context) {
setBooleanPreference(context, "has_seen_multi_device_removal_sheet", true);
}
// endregion
}