mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15:22 +00:00
Support for Registration Lock PINs
This commit is contained in:
parent
d28dc670ea
commit
110d33ddf8
12
build.gradle
12
build.gradle
@ -74,7 +74,7 @@ dependencies {
|
||||
compile('org.whispersystems:libpastelog:1.1.1') {
|
||||
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
|
||||
}
|
||||
compile 'org.whispersystems:signal-service-android:2.7.1'
|
||||
compile 'org.whispersystems:signal-service-android:2.7.2'
|
||||
compile 'org.whispersystems:webrtc-android:M64'
|
||||
|
||||
compile "me.leolin:ShortcutBadger:1.1.16"
|
||||
@ -93,9 +93,7 @@ dependencies {
|
||||
compile 'com.google.zxing:android-integration:3.1.0'
|
||||
compile 'com.squareup.dagger:dagger:1.2.2'
|
||||
annotationProcessor 'com.squareup.dagger:dagger-compiler:1.2.2'
|
||||
compile ("com.doomonafireball.betterpickers:library:1.5.3") {
|
||||
exclude group: 'com.android.support', module: 'support-v4'
|
||||
}
|
||||
compile 'com.code-troopers.betterpickers:library:3.1.0'
|
||||
provided 'com.squareup.dagger:dagger-compiler:1.2.2'
|
||||
compile 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
||||
compile 'com.google.zxing:core:3.2.1'
|
||||
@ -149,6 +147,7 @@ dependencyVerification {
|
||||
'com.android.support:preference-v7:d9f32ddc92f8d6a0bd86a18f4fcaff805fa021245e395b6e7dd382907443ee53',
|
||||
'com.pnikosis:materialish-progress:d71d80e00717a096784482aee21001a9d299fec3833e4ebd87739ed36cf77c54',
|
||||
'pl.tajchert:waitingdots:2835d49e0787dbcb606c5a60021ced66578503b1e9fddcd7a5ef0cd5f095ba2c',
|
||||
'com.code-troopers.betterpickers:library:ab5cb3f00bd9c575461300b38f31f5874d522524b10bbaf75f3f05a4b6dbf5fd',
|
||||
'com.codewaves.stickyheadergrid:stickyheadergrid:5b4aa6a52a957cfd55f60f4220c11c0c371385a3cb9786cae03c260dcdef5794',
|
||||
'com.android.support:appcompat-v7:b2825e8b47f665d3362d8481c8d147d1af9230d16f23a2b94f6ccbc53c68cec1',
|
||||
'com.melnykov:floatingactionbutton:15d58d4fac0f7a288d0e5301bbaf501a146f5b3f5921277811bf99bd3b397263',
|
||||
@ -163,7 +162,7 @@ dependencyVerification {
|
||||
'com.google.android.exoplayer:exoplayer:955085aa611a8f7cf6c61b88ae03d1a392f4ad94c9bfbc153f3dedb9ffb14718',
|
||||
'org.whispersystems:jobmanager:506f679fc2fcf7bb6d10f00f41d6f6ea0abf75c70dc95b913398661ad538a181',
|
||||
'org.whispersystems:libpastelog:9bdbc598c7d2c20aec8a2a480ecfd83f9d85f9f7fb5c3128810c6aae03969e33',
|
||||
'org.whispersystems:signal-service-android:e639df8c3ea76f27b3eb8784a0b0fb365fbf833fe7f196a1abc13d961ac642ca',
|
||||
'org.whispersystems:signal-service-android:a7dfcb2f88ec69e8a1d31215cc7b67f0db50a96cd9d3832bfe75f56e67188537',
|
||||
'org.whispersystems:webrtc-android:ed297e8b795dad9658cf306c2aa0f7d296c65f0997a2ac4353fd0157910acc12',
|
||||
'me.leolin:ShortcutBadger:e3cb3e7625892129b0c92dd5e4bc649faffdd526d5af26d9c45ee31ff8851774',
|
||||
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
|
||||
@ -176,7 +175,6 @@ dependencyVerification {
|
||||
'com.soundcloud.android:android-crop:ffd4b973cf6e97f7d64118a0dc088df50e9066fd5634fe6911dd0c0c5d346177',
|
||||
'com.google.zxing:android-integration:89e56aadf1164bd71e57949163c53abf90af368b51669c0d4a47a163335f95c4',
|
||||
'com.squareup.dagger:dagger:789aca24537022e49f91fc6444078d9de8f1dd99e1bfb090f18491b186967883',
|
||||
'com.doomonafireball.betterpickers:library:132ecd685c95a99e7377c4e27bfadbb2d7ed0bea995944060cd62d4369fdaf3d',
|
||||
'com.amulyakhare:com.amulyakhare.textdrawable:54c92b5fba38cfd316a07e5a30528068f45ce8515a6890f1297df4c401af5dcb',
|
||||
'com.google.zxing:core:b4d82452e7a6bf6ec2698904b332431717ed8f9a850224f295aec89de80f2259',
|
||||
'com.davemorrissey.labs:subsampling-scale-image-view:550c5baa07e0bb4ff0a18b705e96d34436d22619248bd8c08c08c730b1f55cfe',
|
||||
@ -203,7 +201,7 @@ dependencyVerification {
|
||||
'com.github.bumptech.glide:gifdecoder:59ccf3bb0cec11dab4b857382cbe0b171111b6fc62bf141adce4e1180889af15',
|
||||
'com.android.support:support-annotations:af05330d997eb92a066534dbe0a3ea24347d26d7001221092113ae02a8f233da',
|
||||
'org.whispersystems:signal-protocol-android:5b8acded7f2a40178eb90ab8e8cbfec89d170d91b3ff5e78487d1098df6185a1',
|
||||
'org.whispersystems:signal-service-java:49dbd3aeb84ed9640355791d78e0825d4ae88e6120d24cb626ec416360c6975d',
|
||||
'org.whispersystems:signal-service-java:f5ca4595eb09e25b9c9fd39c83bdcf1978a61d8a4b6f770bb548f3dd40ecc493',
|
||||
'com.github.bumptech.glide:disklrucache:c1b1b6f5bbd01e2fcdc9d7f60913c8d338bdb65ed4a93bfa02b56f19daaade4b',
|
||||
'com.github.bumptech.glide:annotations:bede99ef9f71517a4274bac18fd3e483e9f2b6108d7d6fe8f4949be4aa4d9512',
|
||||
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
|
||||
|
BIN
res/drawable-hdpi/ic_lock_white_48dp.png
Normal file
BIN
res/drawable-hdpi/ic_lock_white_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 540 B |
BIN
res/drawable-mdpi/ic_lock_white_48dp.png
Normal file
BIN
res/drawable-mdpi/ic_lock_white_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 372 B |
BIN
res/drawable-xhdpi/ic_lock_white_48dp.png
Normal file
BIN
res/drawable-xhdpi/ic_lock_white_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 702 B |
BIN
res/drawable-xxhdpi/ic_lock_white_48dp.png
Normal file
BIN
res/drawable-xxhdpi/ic_lock_white_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
res/drawable-xxxhdpi/ic_lock_white_48dp.png
Normal file
BIN
res/drawable-xxxhdpi/ic_lock_white_48dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -63,7 +63,7 @@
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:visibility="visible">
|
||||
tools:visibility="invisible">
|
||||
|
||||
<TextView android:id="@+id/backup_created_text"
|
||||
android:layout_width="wrap_content"
|
||||
@ -256,6 +256,89 @@
|
||||
android:layout_alignParentBottom="true"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
<LinearLayout android:id="@+id/pin_container"
|
||||
android:padding="16dp"
|
||||
android:paddingBottom="0dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:layout_below="@id/header"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:orientation="vertical"
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible">
|
||||
|
||||
<LinearLayout android:id="@+id/pin_clarification_container"
|
||||
android:visibility="gone"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginRight="20dp"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView android:id="@+id/clarification_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_marginTop="-2dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textColor="#73B7F0"
|
||||
android:text="@string/registration_activity__the_registration_lock_pin_is_not_the_same_as_the_sms_verification_code_you_just_received_please_enter_the_pin_you_previously_configured_in_the_application"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="100dp"
|
||||
android:paddingRight="100dp">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/pin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="numberPassword"
|
||||
android:imeOptions="actionDone"
|
||||
android:hint="@string/registration_activity__registration_lock_pin"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<com.dd.CircularProgressButton
|
||||
android:id="@+id/pinButton"
|
||||
app:cpb_textIdle="Continue"
|
||||
app:cpb_selectorIdle="@drawable/progress_button_state"
|
||||
app:cpb_colorIndicator="@color/white"
|
||||
app:cpb_colorProgress="@color/textsecure_primary"
|
||||
app:cpb_cornerRadius="50dp"
|
||||
android:background="@color/signal_primary"
|
||||
android:textColor="@color/white"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
|
||||
|
||||
<TextView android:id="@+id/forgot_button"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:padding="15dp"
|
||||
android:textColor="@color/blue_400"
|
||||
android:text="@string/registration_activity__forgot_pin"/>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
57
res/layout/registration_lock_dialog_view.xml
Normal file
57
res/layout/registration_lock_dialog_view.xml
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingLeft="23dp"
|
||||
android:paddingRight="23dp"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/registration_lock_dialog_view__the_pin_can_consist_of_four_or_more_digits_if_you_forget_your_pin_you_could_be_locked_out_of_your_account_for_up_to_seven_days"/>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/pin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="numberPassword"
|
||||
android:imeOptions="actionNext"
|
||||
android:hint="@string/registration_lock_dialog_view__enter_pin"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/repeat"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="numberPassword"
|
||||
android:imeOptions="actionDone"
|
||||
android:hint="@string/registration_lock_dialog_view__confirm_pin"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
|
||||
<ProgressBar android:id="@+id/progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</LinearLayout>
|
52
res/layout/registration_lock_reminder_view.xml
Normal file
52
res/layout/registration_lock_reminder_view.xml
Normal file
@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout android:id="@+id/header_container"
|
||||
android:background="@color/signal_primary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:padding="40dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="18sp"
|
||||
android:text="@string/registration_lock_reminder_view__enter_your_registration_lock_pin"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="40dp"
|
||||
android:paddingLeft="80dp"
|
||||
android:paddingRight="80dp">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/pin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="numberPassword"
|
||||
android:hint="@string/registration_lock_reminder_view__enter_pin"/>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<TextView android:id="@+id/reminder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="40dp"
|
||||
android:paddingBottom="40dp"
|
||||
android:paddingLeft="20dp"
|
||||
android:paddingRight="20dp"
|
||||
android:textSize="15sp"
|
||||
android:lineSpacingMultiplier="1.3"
|
||||
tools:text="Registration Lock is enabled for your phone number. I forgot my PIN."/>
|
||||
|
||||
</LinearLayout>
|
16
res/layout/registration_unlock_dialog_view.xml
Normal file
16
res/layout/registration_unlock_dialog_view.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:animateLayoutChanges="true">
|
||||
|
||||
<ProgressBar android:id="@+id/progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</LinearLayout>
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<android.inputmethodservice.KeyboardView
|
||||
android:id="@+id/keyboard_view"
|
||||
@ -38,6 +39,18 @@
|
||||
android:gravity="center_vertical"
|
||||
android:src="@drawable/ic_close_white_48dp"/>
|
||||
|
||||
<org.thoughtcrime.securesms.components.SquareImageView
|
||||
android:id="@+id/locked"
|
||||
android:layout_width="96dp"
|
||||
android:layout_height="96dp"
|
||||
android:padding="10dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/circle_tintable"
|
||||
android:backgroundTint="@color/green_400"
|
||||
android:gravity="center_vertical"
|
||||
android:src="@drawable/ic_lock_white_48dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
|
||||
</merge>
|
@ -39,7 +39,7 @@
|
||||
<string name="ApplicationPreferencesActivity_off">off</string>
|
||||
<string name="ApplicationPreferencesActivity_Off">Off</string>
|
||||
<string name="ApplicationPreferencesActivity_sms_mms_summary">SMS %1$s, MMS %2$s</string>
|
||||
<string name="ApplicationPreferencesActivity_privacy_summary">Screen lock %1$s, Screen security %2$s</string>
|
||||
<string name="ApplicationPreferencesActivity_privacy_summary">Screen lock %1$s, Registration lock %2$s</string>
|
||||
<string name="ApplicationPreferencesActivity_appearance_summary">Theme %1$s, Language %2$s</string>
|
||||
|
||||
<!-- AppProtectionPreferenceFragment -->
|
||||
@ -1365,8 +1365,37 @@
|
||||
<string name="preferences_app_protection__lock_signal_access_with_android_screen_lock_or_fingerprint">Lock Signal access with Android screen lock or fingerprint</string>
|
||||
<string name="preferences_app_protection__screen_lock_inactivity_timeout">Screen lock inactivity timeout</string>
|
||||
<string name="AppProtectionPreferenceFragment_none">None</string>
|
||||
|
||||
|
||||
<string name="registration_activity__the_registration_lock_pin_is_not_the_same_as_the_sms_verification_code_you_just_received_please_enter_the_pin_you_previously_configured_in_the_application">The Registration Lock PIN is not the same as the SMS verification code you just received. Please enter the PIN you previously configured in the application.</string>
|
||||
<string name="registration_activity__registration_lock_pin">Registration Lock PIN</string>
|
||||
<string name="registration_activity__forgot_pin">Forgot PIN?</string>
|
||||
<string name="registration_lock_dialog_view__the_pin_can_consist_of_four_or_more_digits_if_you_forget_your_pin_you_could_be_locked_out_of_your_account_for_up_to_seven_days">The PIN can consist of four or more digits. If you forget your PIN, you could be locked out of your account for up to seven days.</string>
|
||||
<string name="registration_lock_dialog_view__enter_pin">Enter PIN</string>
|
||||
<string name="registration_lock_dialog_view__confirm_pin">Confirm PIN</string>
|
||||
<string name="registration_lock_reminder_view__enter_your_registration_lock_pin">Enter your Registration Lock PIN</string>
|
||||
<string name="registration_lock_reminder_view__enter_pin">Enter PIN</string>
|
||||
<string name="preferences_app_protection__enable_a_registration_lock_pin_that_will_be_required">Enable a Registration Lock PIN that will be required to register this phone number with Signal again.</string>
|
||||
<string name="preferences_app_protection__registration_lock_pin">Registration Lock PIN</string>
|
||||
<string name="preferences_app_protection__registration_lock">Registration Lock</string>
|
||||
<string name="RegistrationActivity_you_must_enter_your_registration_lock_PIN">You must enter your Registration Lock PIN</string>
|
||||
<string name="RegistrationActivity_incorrect_registration_lock_pin">Incorrect Registration Lock PIN</string>
|
||||
<string name="RegistrationActivity_too_many_attempts">Too many attempts</string>
|
||||
<string name="RegistrationActivity_you_have_made_too_many_incorrect_registration_lock_pin_attempts_please_try_again_in_a_day">You\'ve made too many incorrect Registration Lock PIN attempts. Please try again in a day.</string>
|
||||
<string name="RegistrationActivity_error_connecting_to_service">Error connecting to service</string>
|
||||
<string name="RegistrationActivity_oh_no">Oh no!</string>
|
||||
<string name="RegistrationActivity_registration_of_this_phone_number_will_be_possible_without_your_registration_lock_pin_after_seven_days_have_passed">Registration of this phone number will be possible without your Registration Lock PIN after 7 days have passed since this phone number was last active on Signal. You have %d days remaining.</string>
|
||||
<string name="RegistrationActivity_registration_lock_pin">Registration lock PIN</string>
|
||||
<string name="RegistrationActivity_this_phone_number_has_registration_lock_enabled_please_enter_the_registration_lock_pin">This phone number has Registration Lock enabled. Please enter the Registration Lock PIN.</string>
|
||||
<string name="RegistrationLockDialog_registration_lock_is_enabled_for_your_phone_number">Registration Lock is enabled for your phone number.</string>
|
||||
<string name="RegistrationLockDialog_i_forgot_my_pin">I forgot my PIN.</string>
|
||||
<string name="RegistrationLockDialog_forgotten_pin">Forgotten PIN?</string>
|
||||
<string name="RegistrationLockDialog_registration_lock_helps_protect_your_phone_number_from_unauthorized_registration_attempts">Registration Lock helps protect your phone number from unauthorized registration attempts. This feature can be disabled at any time in your Signal privacy settings</string>
|
||||
<string name="RegistrationLockDialog_registration_lock">Registration Lock</string>
|
||||
<string name="RegistrationLockDialog_enable">Enable</string>
|
||||
<string name="RegistrationLockDialog_the_registration_lock_pin_must_be_at_least_four_digits">The Registration Lock PIN must be at least 4 digits.</string>
|
||||
<string name="RegistrationLockDialog_the_two_pins_you_entered_do_not_match">The two PINs you entered do not match.</string>
|
||||
<string name="RegistrationLockDialog_error_connecting_to_the_service">Error connecting to the service</string>
|
||||
<string name="RegistrationLockDialog_disable_registration_lock_pin">Disable Registration Lock PIN?</string>
|
||||
<string name="RegistrationLockDialog_disable">Disable</string>
|
||||
<!-- EOF -->
|
||||
|
||||
</resources>
|
||||
|
@ -67,4 +67,15 @@
|
||||
android:title="@string/preferences_app_protection__blocked_contacts" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:layout="@layout/preference_divider"/>
|
||||
|
||||
<PreferenceCategory android:title="@string/preferences_app_protection__registration_lock">
|
||||
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="pref_registration_lock"
|
||||
android:title="@string/preferences_app_protection__registration_lock_pin"
|
||||
android:summary="@string/preferences_app_protection__enable_a_registration_lock_pin_that_will_be_required"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
</PreferenceScreen>
|
||||
|
@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.components.RatingManager;
|
||||
import org.thoughtcrime.securesms.components.SearchToolbar;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.lock.RegistrationLockDialog;
|
||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
@ -80,6 +81,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
initializeSearchListener();
|
||||
|
||||
RatingManager.showRatingDialogIfNecessary(this);
|
||||
RegistrationLockDialog.showReminderIfNecessary(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -84,11 +84,14 @@ import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||
import org.whispersystems.libsignal.util.KeyHelper;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException;
|
||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||
import org.whispersystems.signalservice.internal.push.LockedException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* The register account activity. Prompts ths user for their registration information
|
||||
@ -127,6 +130,12 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif
|
||||
private TextView restoreBackupProgress;
|
||||
private CircularProgressButton restoreButton;
|
||||
|
||||
private View pinContainer;
|
||||
private EditText pin;
|
||||
private CircularProgressButton pinButton;
|
||||
private TextView pinForgotButton;
|
||||
private View pinClarificationContainer;
|
||||
|
||||
private CallMeCountDownView callMeCountDownView;
|
||||
private VerificationPinKeyboard keyboard;
|
||||
private VerificationCodeView verificationCodeView;
|
||||
@ -196,6 +205,12 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif
|
||||
this.restoreBackupProgress = findViewById(R.id.backup_progress_text);
|
||||
this.restoreButton = findViewById(R.id.restore_button);
|
||||
|
||||
this.pinContainer = findViewById(R.id.pin_container);
|
||||
this.pin = findViewById(R.id.pin);
|
||||
this.pinButton = findViewById(R.id.pinButton);
|
||||
this.pinForgotButton = findViewById(R.id.forgot_button);
|
||||
this.pinClarificationContainer = findViewById(R.id.pin_clarification_container);
|
||||
|
||||
this.registrationState = new RegistrationState(RegistrationState.State.INITIAL, null, null, null);
|
||||
|
||||
this.countryCode.addTextChangedListener(new CountryCodeChangedListener());
|
||||
@ -502,72 +517,36 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif
|
||||
callMeCountDownView.setVisibility(View.INVISIBLE);
|
||||
keyboard.displayProgress();
|
||||
|
||||
new AsyncTask<Void, Void, Boolean>() {
|
||||
new AsyncTask<Void, Void, Pair<Integer, Long>>() {
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
protected Pair<Integer, Long> doInBackground(Void... voids) {
|
||||
try {
|
||||
int registrationId = KeyHelper.generateRegistrationId(false);
|
||||
TextSecurePreferences.setLocalRegistrationId(RegistrationActivity.this, registrationId);
|
||||
SessionUtil.archiveAllSessions(RegistrationActivity.this);
|
||||
|
||||
String signalingKey = Util.getSecret(52);
|
||||
|
||||
accountManager.verifyAccountWithCode(code, signalingKey, registrationId, !registrationState.gcmToken.isPresent());
|
||||
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(RegistrationActivity.this);
|
||||
List<PreKeyRecord> records = PreKeyUtil.generatePreKeys(RegistrationActivity.this);
|
||||
SignedPreKeyRecord signedPreKey = PreKeyUtil.generateSignedPreKey(RegistrationActivity.this, identityKey, true);
|
||||
|
||||
accountManager.setPreKeys(identityKey.getPublicKey(), signedPreKey, records);
|
||||
|
||||
if (registrationState.gcmToken.isPresent()) {
|
||||
accountManager.setGcmId(registrationState.gcmToken);
|
||||
}
|
||||
|
||||
TextSecurePreferences.setGcmRegistrationId(RegistrationActivity.this, registrationState.gcmToken.orNull());
|
||||
TextSecurePreferences.setGcmDisabled(RegistrationActivity.this, !registrationState.gcmToken.isPresent());
|
||||
TextSecurePreferences.setWebsocketRegistered(RegistrationActivity.this, true);
|
||||
|
||||
DatabaseFactory.getIdentityDatabase(RegistrationActivity.this)
|
||||
.saveIdentity(Address.fromSerialized(registrationState.e164number),
|
||||
identityKey.getPublicKey(), IdentityDatabase.VerifiedStatus.VERIFIED,
|
||||
true, System.currentTimeMillis(), true);
|
||||
|
||||
TextSecurePreferences.setVerifying(RegistrationActivity.this, false);
|
||||
TextSecurePreferences.setPushRegistered(RegistrationActivity.this, true);
|
||||
TextSecurePreferences.setLocalNumber(RegistrationActivity.this, registrationState.e164number);
|
||||
TextSecurePreferences.setPushServerPassword(RegistrationActivity.this, registrationState.password);
|
||||
TextSecurePreferences.setSignalingKey(RegistrationActivity.this, signalingKey);
|
||||
TextSecurePreferences.setSignedPreKeyRegistered(RegistrationActivity.this, true);
|
||||
TextSecurePreferences.setPromptedPushRegistration(RegistrationActivity.this, true);
|
||||
TextSecurePreferences.setUnauthorizedReceived(RegistrationActivity.this, false);
|
||||
|
||||
return true;
|
||||
verifyAccount(code, null);
|
||||
return new Pair<>(1, -1L);
|
||||
} catch (LockedException e) {
|
||||
Log.w(TAG, e);
|
||||
return new Pair<>(2, e.getTimeRemaining());
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
return false;
|
||||
return new Pair<>(3, -1L);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
if (result) {
|
||||
protected void onPostExecute(Pair<Integer, Long> result) {
|
||||
if (result.first == 1) {
|
||||
keyboard.displaySuccess().addListener(new AssertedSuccessListener<Boolean>() {
|
||||
@Override
|
||||
public void onSuccess(Boolean result) {
|
||||
ApplicationContext.getInstance(RegistrationActivity.this).getJobManager().add(new DirectoryRefreshJob(RegistrationActivity.this, false));
|
||||
|
||||
DirectoryRefreshListener.schedule(RegistrationActivity.this);
|
||||
RotateSignedPreKeyListener.schedule(RegistrationActivity.this);
|
||||
|
||||
Intent nextIntent = getIntent().getParcelableExtra("next_intent");
|
||||
|
||||
if (nextIntent == null) {
|
||||
nextIntent = new Intent(RegistrationActivity.this, ConversationListActivity.class);
|
||||
}
|
||||
|
||||
startActivity(nextIntent);
|
||||
finish();
|
||||
handleSuccessfulRegistration();
|
||||
}
|
||||
});
|
||||
} else if (result.first == 2) {
|
||||
keyboard.displayLocked().addListener(new AssertedSuccessListener<Boolean>() {
|
||||
@Override
|
||||
public void onSuccess(Boolean r) {
|
||||
registrationState = new RegistrationState(RegistrationState.State.PIN, registrationState);
|
||||
displayPinView(code, result.second);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@ -585,6 +564,67 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif
|
||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private void handleVerifyWithPinClicked(@NonNull String code, @Nullable String pin) {
|
||||
if (TextUtils.isEmpty(pin) || TextUtils.isEmpty(pin.replace(" ", ""))) {
|
||||
Toast.makeText(this, R.string.RegistrationActivity_you_must_enter_your_registration_lock_PIN, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
pinButton.setIndeterminateProgressMode(true);
|
||||
pinButton.setProgress(50);
|
||||
|
||||
new AsyncTask<Void, Void, Integer>() {
|
||||
@Override
|
||||
protected Integer doInBackground(Void... voids) {
|
||||
try {
|
||||
verifyAccount(code, pin);
|
||||
return 1;
|
||||
} catch (LockedException e) {
|
||||
Log.w(TAG, e);
|
||||
return 2;
|
||||
} catch (RateLimitException e) {
|
||||
Log.w(TAG, e);
|
||||
return 3;
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Integer result) {
|
||||
pinButton.setIndeterminateProgressMode(false);
|
||||
pinButton.setProgress(0);
|
||||
|
||||
if (result == 1) {
|
||||
TextSecurePreferences.setRegistrationLockPin(RegistrationActivity.this, pin);
|
||||
TextSecurePreferences.setRegistrationtLockEnabled(RegistrationActivity.this, true);
|
||||
handleSuccessfulRegistration();
|
||||
} else if (result == 2) {
|
||||
RegistrationActivity.this.pin.setText("");
|
||||
Toast.makeText(RegistrationActivity.this, R.string.RegistrationActivity_incorrect_registration_lock_pin, Toast.LENGTH_LONG).show();
|
||||
} else if (result == 3) {
|
||||
new AlertDialog.Builder(RegistrationActivity.this)
|
||||
.setTitle(R.string.RegistrationActivity_too_many_attempts)
|
||||
.setMessage(R.string.RegistrationActivity_you_have_made_too_many_incorrect_registration_lock_pin_attempts_please_try_again_in_a_day)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
} else if (result == 4) {
|
||||
Toast.makeText(RegistrationActivity.this, R.string.RegistrationActivity_error_connecting_to_service, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private void handleForgottenPin(long timeRemaining) {
|
||||
new AlertDialog.Builder(RegistrationActivity.this)
|
||||
.setTitle(R.string.RegistrationActivity_oh_no)
|
||||
.setMessage(getString(R.string.RegistrationActivity_registration_of_this_phone_number_will_be_possible_without_your_registration_lock_pin_after_seven_days_have_passed, (TimeUnit.MILLISECONDS.toDays(timeRemaining) + 1)))
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private void handlePhoneCallRequest() {
|
||||
if (registrationState.state == RegistrationState.State.VERIFYING) {
|
||||
@ -605,6 +645,60 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyAccount(@NonNull String code, @Nullable String pin) throws IOException {
|
||||
int registrationId = KeyHelper.generateRegistrationId(false);
|
||||
TextSecurePreferences.setLocalRegistrationId(RegistrationActivity.this, registrationId);
|
||||
SessionUtil.archiveAllSessions(RegistrationActivity.this);
|
||||
|
||||
String signalingKey = Util.getSecret(52);
|
||||
|
||||
accountManager.verifyAccountWithCode(code, signalingKey, registrationId, !registrationState.gcmToken.isPresent(), pin);
|
||||
|
||||
IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(RegistrationActivity.this);
|
||||
List<PreKeyRecord> records = PreKeyUtil.generatePreKeys(RegistrationActivity.this);
|
||||
SignedPreKeyRecord signedPreKey = PreKeyUtil.generateSignedPreKey(RegistrationActivity.this, identityKey, true);
|
||||
|
||||
accountManager.setPreKeys(identityKey.getPublicKey(), signedPreKey, records);
|
||||
|
||||
if (registrationState.gcmToken.isPresent()) {
|
||||
accountManager.setGcmId(registrationState.gcmToken);
|
||||
}
|
||||
|
||||
TextSecurePreferences.setGcmRegistrationId(RegistrationActivity.this, registrationState.gcmToken.orNull());
|
||||
TextSecurePreferences.setGcmDisabled(RegistrationActivity.this, !registrationState.gcmToken.isPresent());
|
||||
TextSecurePreferences.setWebsocketRegistered(RegistrationActivity.this, true);
|
||||
|
||||
DatabaseFactory.getIdentityDatabase(RegistrationActivity.this)
|
||||
.saveIdentity(Address.fromSerialized(registrationState.e164number),
|
||||
identityKey.getPublicKey(), IdentityDatabase.VerifiedStatus.VERIFIED,
|
||||
true, System.currentTimeMillis(), true);
|
||||
|
||||
TextSecurePreferences.setVerifying(RegistrationActivity.this, false);
|
||||
TextSecurePreferences.setPushRegistered(RegistrationActivity.this, true);
|
||||
TextSecurePreferences.setLocalNumber(RegistrationActivity.this, registrationState.e164number);
|
||||
TextSecurePreferences.setPushServerPassword(RegistrationActivity.this, registrationState.password);
|
||||
TextSecurePreferences.setSignalingKey(RegistrationActivity.this, signalingKey);
|
||||
TextSecurePreferences.setSignedPreKeyRegistered(RegistrationActivity.this, true);
|
||||
TextSecurePreferences.setPromptedPushRegistration(RegistrationActivity.this, true);
|
||||
TextSecurePreferences.setUnauthorizedReceived(RegistrationActivity.this, false);
|
||||
}
|
||||
|
||||
private void handleSuccessfulRegistration() {
|
||||
ApplicationContext.getInstance(RegistrationActivity.this).getJobManager().add(new DirectoryRefreshJob(RegistrationActivity.this, false));
|
||||
|
||||
DirectoryRefreshListener.schedule(RegistrationActivity.this);
|
||||
RotateSignedPreKeyListener.schedule(RegistrationActivity.this);
|
||||
|
||||
Intent nextIntent = getIntent().getParcelableExtra("next_intent");
|
||||
|
||||
if (nextIntent == null) {
|
||||
nextIntent = new Intent(RegistrationActivity.this, ConversationListActivity.class);
|
||||
}
|
||||
|
||||
startActivity(nextIntent);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void displayRestoreView(@NonNull BackupUtil.BackupInfo backup) {
|
||||
title.animate().translationX(title.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() {
|
||||
@Override
|
||||
@ -782,6 +876,64 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif
|
||||
this.callMeCountDownView.startCountDown(callCountdown);
|
||||
}
|
||||
|
||||
private void displayPinView(String code, long lockedUntil) {
|
||||
title.animate().translationX(-1 * title.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
title.setText(R.string.RegistrationActivity_registration_lock_pin);
|
||||
title.clearAnimation();
|
||||
title.setTranslationX(title.getWidth());
|
||||
title.animate().translationX(0).setListener(null).setInterpolator(new OvershootInterpolator()).setDuration(SCENE_TRANSITION_DURATION).start();
|
||||
}
|
||||
}).start();
|
||||
|
||||
subtitle.animate().translationX(-1 * subtitle.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
subtitle.setText(R.string.RegistrationActivity_this_phone_number_has_registration_lock_enabled_please_enter_the_registration_lock_pin);
|
||||
subtitle.clearAnimation();
|
||||
subtitle.setTranslationX(subtitle.getWidth());
|
||||
subtitle.animate().translationX(0).setListener(null).setInterpolator(new OvershootInterpolator()).setDuration(SCENE_TRANSITION_DURATION).start();
|
||||
}
|
||||
}).start();
|
||||
|
||||
verificationContainer.animate().translationX(-1 * verificationContainer.getWidth()).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
verificationContainer.clearAnimation();
|
||||
verificationContainer.setVisibility(View.INVISIBLE);
|
||||
verificationContainer.setTranslationX(0);
|
||||
|
||||
pinContainer.setTranslationX(pinContainer.getWidth());
|
||||
pinContainer.setVisibility(View.VISIBLE);
|
||||
pinContainer.animate().translationX(0).setListener(null).setInterpolator(new OvershootInterpolator()).setDuration(SCENE_TRANSITION_DURATION).start();
|
||||
}
|
||||
}).start();
|
||||
|
||||
fab.animate().rotationBy(-360f).setDuration(SCENE_TRANSITION_DURATION).setListener(new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
fab.clearAnimation();
|
||||
fab.setImageResource(R.drawable.ic_lock_white_24dp);
|
||||
fab.animate().rotationBy(-360f).setDuration(SCENE_TRANSITION_DURATION).setListener(null).start();
|
||||
}
|
||||
}).start();
|
||||
|
||||
pinButton.setOnClickListener(v -> handleVerifyWithPinClicked(code, pin.getText().toString()));
|
||||
pinForgotButton.setOnClickListener(v -> handleForgottenPin(lockedUntil));
|
||||
pin.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (s != null && code.equals(s.toString())) pinClarificationContainer.setVisibility(View.VISIBLE);
|
||||
else if (pinClarificationContainer.getVisibility() == View.VISIBLE) pinClarificationContainer.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handleCancel() {
|
||||
TextSecurePreferences.setPromptedPushRegistration(RegistrationActivity.this, true);
|
||||
Intent nextIntent = getIntent().getParcelableExtra("next_intent");
|
||||
@ -916,7 +1068,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements Verif
|
||||
|
||||
private static class RegistrationState {
|
||||
private enum State {
|
||||
INITIAL, VERIFYING, CHECKING
|
||||
INITIAL, VERIFYING, CHECKING, PIN
|
||||
}
|
||||
|
||||
private final State state;
|
||||
|
@ -30,6 +30,7 @@ public class VerificationPinKeyboard extends FrameLayout {
|
||||
private ProgressBar progressBar;
|
||||
private ImageView successView;
|
||||
private ImageView failureView;
|
||||
private ImageView lockedView;
|
||||
|
||||
private OnKeyPressListener listener;
|
||||
|
||||
@ -60,7 +61,8 @@ public class VerificationPinKeyboard extends FrameLayout {
|
||||
this.keyboardView = findViewById(R.id.keyboard_view);
|
||||
this.progressBar = findViewById(R.id.progress);
|
||||
this.successView = findViewById(R.id.success);
|
||||
this.failureView = findViewById(R.id.failure); ;
|
||||
this.failureView = findViewById(R.id.failure);
|
||||
this.lockedView = findViewById(R.id.locked);
|
||||
|
||||
keyboardView.setPreviewEnabled(false);
|
||||
keyboardView.setKeyboard(new Keyboard(getContext(), R.xml.pin_keyboard));
|
||||
@ -97,6 +99,7 @@ public class VerificationPinKeyboard extends FrameLayout {
|
||||
this.progressBar.setVisibility(View.GONE);
|
||||
this.successView.setVisibility(View.GONE);
|
||||
this.failureView.setVisibility(View.GONE);
|
||||
this.lockedView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void displayProgress() {
|
||||
@ -104,6 +107,7 @@ public class VerificationPinKeyboard extends FrameLayout {
|
||||
this.progressBar.setVisibility(View.VISIBLE);
|
||||
this.successView.setVisibility(View.GONE);
|
||||
this.failureView.setVisibility(View.GONE);
|
||||
this.lockedView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public ListenableFuture<Boolean> displaySuccess() {
|
||||
@ -112,6 +116,7 @@ public class VerificationPinKeyboard extends FrameLayout {
|
||||
this.keyboardView.setVisibility(View.INVISIBLE);
|
||||
this.progressBar.setVisibility(View.GONE);
|
||||
this.failureView.setVisibility(View.GONE);
|
||||
this.lockedView.setVisibility(View.GONE);
|
||||
|
||||
this.successView.getBackground().setColorFilter(getResources().getColor(R.color.green_500), PorterDuff.Mode.SRC_IN);
|
||||
|
||||
@ -143,6 +148,7 @@ public class VerificationPinKeyboard extends FrameLayout {
|
||||
this.keyboardView.setVisibility(View.INVISIBLE);
|
||||
this.progressBar.setVisibility(View.GONE);
|
||||
this.failureView.setVisibility(View.GONE);
|
||||
this.lockedView.setVisibility(View.GONE);
|
||||
|
||||
this.failureView.getBackground().setColorFilter(getResources().getColor(R.color.red_500), PorterDuff.Mode.SRC_IN);
|
||||
this.failureView.setVisibility(View.VISIBLE);
|
||||
@ -168,6 +174,38 @@ public class VerificationPinKeyboard extends FrameLayout {
|
||||
return result;
|
||||
}
|
||||
|
||||
public ListenableFuture<Boolean> displayLocked() {
|
||||
SettableFuture<Boolean> result = new SettableFuture<>();
|
||||
|
||||
this.keyboardView.setVisibility(View.INVISIBLE);
|
||||
this.progressBar.setVisibility(View.GONE);
|
||||
this.failureView.setVisibility(View.GONE);
|
||||
this.lockedView.setVisibility(View.GONE);
|
||||
|
||||
this.lockedView.getBackground().setColorFilter(getResources().getColor(R.color.green_500), PorterDuff.Mode.SRC_IN);
|
||||
|
||||
ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1,
|
||||
ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
|
||||
ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
|
||||
scaleAnimation.setInterpolator(new OvershootInterpolator());
|
||||
scaleAnimation.setDuration(800);
|
||||
scaleAnimation.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
result.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {}
|
||||
});
|
||||
|
||||
ViewUtil.animateIn(this.lockedView, scaleAnimation);
|
||||
return result;
|
||||
}
|
||||
|
||||
public interface OnKeyPressListener {
|
||||
void onKeyPress(int keyCode);
|
||||
}
|
||||
|
@ -33,6 +33,8 @@ import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob;
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
|
||||
import org.thoughtcrime.securesms.jobs.RotateSignedPreKeyJob;
|
||||
import org.thoughtcrime.securesms.jobs.SendReadReceiptJob;
|
||||
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
|
||||
import org.thoughtcrime.securesms.preferences.SmsMmsPreferenceFragment;
|
||||
import org.thoughtcrime.securesms.push.SecurityEventListener;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||
import org.thoughtcrime.securesms.service.MessageRetrievalService;
|
||||
@ -75,7 +77,8 @@ import dagger.Provides;
|
||||
RetrieveProfileAvatarJob.class,
|
||||
MultiDeviceProfileKeyUpdateJob.class,
|
||||
SendReadReceiptJob.class,
|
||||
MultiDeviceReadReceiptUpdateJob.class})
|
||||
MultiDeviceReadReceiptUpdateJob.class,
|
||||
AppProtectionPreferenceFragment.class})
|
||||
public class SignalCommunicationModule {
|
||||
|
||||
private static final String TAG = SignalCommunicationModule.class.getSimpleName();
|
||||
|
@ -37,11 +37,12 @@ public class RefreshAttributesJob extends ContextJob implements InjectableType {
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException {
|
||||
String signalingKey = TextSecurePreferences.getSignalingKey(context);
|
||||
int registrationId = TextSecurePreferences.getLocalRegistrationId(context);
|
||||
boolean fetchesMessages = TextSecurePreferences.isGcmDisabled(context);
|
||||
String signalingKey = TextSecurePreferences.getSignalingKey(context);
|
||||
int registrationId = TextSecurePreferences.getLocalRegistrationId(context);
|
||||
boolean fetchesMessages = TextSecurePreferences.isGcmDisabled(context);
|
||||
String pin = TextSecurePreferences.getRegistrationLockPin(context);
|
||||
|
||||
signalAccountManager.setAccountAttributes(signalingKey, registrationId, fetchesMessages);
|
||||
signalAccountManager.setAccountAttributes(signalingKey, registrationId, fetchesMessages, pin);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
231
src/org/thoughtcrime/securesms/lock/RegistrationLockDialog.java
Normal file
231
src/org/thoughtcrime/securesms/lock/RegistrationLockDialog.java
Normal file
@ -0,0 +1,231 @@
|
||||
package org.thoughtcrime.securesms.lock;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class RegistrationLockDialog {
|
||||
|
||||
private static final String TAG = RegistrationLockDialog.class.getSimpleName();
|
||||
|
||||
public static void showReminderIfNecessary(@NonNull Context context) {
|
||||
if (!RegistrationLockReminders.needsReminder(context)) return;
|
||||
|
||||
AlertDialog dialog = new AlertDialog.Builder(context, R.style.RationaleDialog)
|
||||
.setView(R.layout.registration_lock_reminder_view)
|
||||
.setCancelable(true)
|
||||
.setOnCancelListener(d -> RegistrationLockReminders.scheduleReminder(context, false))
|
||||
.create();
|
||||
|
||||
WindowManager windowManager = ServiceUtil.getWindowManager(context);
|
||||
Display display = windowManager.getDefaultDisplay();
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
display.getMetrics(metrics);
|
||||
|
||||
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
||||
dialog.getWindow().setLayout((int)(metrics.widthPixels * .75), ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
dialog.show();
|
||||
|
||||
EditText pinEditText = dialog.findViewById(R.id.pin);
|
||||
TextView reminder = dialog.findViewById(R.id.reminder);
|
||||
|
||||
assert pinEditText != null;
|
||||
assert reminder != null;
|
||||
|
||||
SpannableString reminderText = new SpannableString(context.getString(R.string.RegistrationLockDialog_registration_lock_is_enabled_for_your_phone_number));
|
||||
SpannableString forgotText = new SpannableString(context.getString(R.string.RegistrationLockDialog_i_forgot_my_pin));
|
||||
|
||||
ClickableSpan clickableSpan = new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
dialog.dismiss();
|
||||
new AlertDialog.Builder(context).setTitle(R.string.RegistrationLockDialog_forgotten_pin)
|
||||
.setMessage(R.string.RegistrationLockDialog_registration_lock_helps_protect_your_phone_number_from_unauthorized_registration_attempts)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
};
|
||||
|
||||
forgotText.setSpan(clickableSpan, 0, forgotText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
reminder.setText(new SpannableStringBuilder(reminderText).append(" ").append(forgotText));
|
||||
reminder.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
pinEditText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (s != null && s.toString().replace(" ", "").equals(TextSecurePreferences.getRegistrationLockPin(context))) {
|
||||
dialog.dismiss();
|
||||
RegistrationLockReminders.scheduleReminder(context, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public static void showRegistrationLockPrompt(@NonNull Context context, @NonNull SwitchPreferenceCompat preference, @NonNull SignalServiceAccountManager accountManager) {
|
||||
AlertDialog dialog = new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.RegistrationLockDialog_registration_lock)
|
||||
.setView(R.layout.registration_lock_dialog_view)
|
||||
.setPositiveButton(R.string.RegistrationLockDialog_enable, null)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create();
|
||||
|
||||
dialog.setOnShowListener(created -> {
|
||||
Button button = ((AlertDialog) created).getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
button.setOnClickListener(v -> {
|
||||
EditText pin = dialog.findViewById(R.id.pin);
|
||||
EditText repeat = dialog.findViewById(R.id.repeat);
|
||||
ProgressBar progressBar = dialog.findViewById(R.id.progress);
|
||||
|
||||
assert pin != null;
|
||||
assert repeat != null;
|
||||
assert progressBar != null;
|
||||
|
||||
String pinValue = pin.getText().toString().replace(" ", "");
|
||||
String repeatValue = repeat.getText().toString().replace(" ", "");
|
||||
|
||||
if (pinValue.length() < 4) {
|
||||
Toast.makeText(context, R.string.RegistrationLockDialog_the_registration_lock_pin_must_be_at_least_four_digits, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pinValue.equals(repeatValue)) {
|
||||
Toast.makeText(context, R.string.RegistrationLockDialog_the_two_pins_you_entered_do_not_match, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
new AsyncTask<Void, Void, Boolean>() {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
progressBar.setIndeterminate(true);
|
||||
button.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
try {
|
||||
accountManager.setPin(Optional.of(pinValue));
|
||||
TextSecurePreferences.setRegistrationLockPin(context, pinValue);
|
||||
TextSecurePreferences.setRegistrationLockLastReminderTime(context, System.currentTimeMillis());
|
||||
TextSecurePreferences.setRegistrationLockNextReminderInterval(context, RegistrationLockReminders.INITIAL_INTERVAL);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(@NonNull Boolean result) {
|
||||
button.setEnabled(true);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
if (result) {
|
||||
preference.setChecked(true);
|
||||
created.dismiss();
|
||||
} else {
|
||||
Toast.makeText(context, R.string.RegistrationLockDialog_error_connecting_to_the_service, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
});
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public static void showRegistrationUnlockPrompt(@NonNull Context context, @NonNull SwitchPreferenceCompat preference, @NonNull SignalServiceAccountManager accountManager) {
|
||||
AlertDialog dialog = new AlertDialog.Builder(context)
|
||||
.setTitle(R.string.RegistrationLockDialog_disable_registration_lock_pin)
|
||||
.setView(R.layout.registration_unlock_dialog_view)
|
||||
.setPositiveButton(R.string.RegistrationLockDialog_disable, null)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create();
|
||||
|
||||
dialog.setOnShowListener(created -> {
|
||||
Button button = ((AlertDialog) created).getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
button.setOnClickListener(v -> {
|
||||
ProgressBar progressBar = dialog.findViewById(R.id.progress);
|
||||
assert progressBar != null;
|
||||
|
||||
new AsyncTask<Void, Void, Boolean>() {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
progressBar.setIndeterminate(true);
|
||||
button.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
try {
|
||||
accountManager.setPin(Optional.absent());
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
button.setEnabled(true);
|
||||
|
||||
if (result) {
|
||||
preference.setChecked(false);
|
||||
created.dismiss();
|
||||
} else {
|
||||
Toast.makeText(context, R.string.RegistrationLockDialog_error_connecting_to_the_service, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
});
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package org.thoughtcrime.securesms.lock;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class RegistrationLockReminders {
|
||||
|
||||
public static final long INITIAL_INTERVAL = TimeUnit.HOURS.toMillis(6);
|
||||
|
||||
private static Map<Long, Long> INTERVAL_PROGRESSION = new HashMap<Long, Long>() {{
|
||||
put(TimeUnit.HOURS.toMillis(6), TimeUnit.HOURS.toMillis(12));
|
||||
put(TimeUnit.HOURS.toMillis(12), TimeUnit.DAYS.toMillis(1));
|
||||
put(TimeUnit.DAYS.toMillis(1), TimeUnit.DAYS.toMillis(3));
|
||||
put(TimeUnit.DAYS.toMillis(3), TimeUnit.DAYS.toMillis(7));
|
||||
put(TimeUnit.DAYS.toMillis(7), TimeUnit.DAYS.toMillis(7));
|
||||
}};
|
||||
|
||||
|
||||
private static Map<Long, Long> INTERVAL_REGRESSION = new HashMap<Long, Long>() {{
|
||||
put(TimeUnit.HOURS.toMillis(12), TimeUnit.HOURS.toMillis(6));
|
||||
put(TimeUnit.DAYS.toMillis(1), TimeUnit.HOURS.toMillis(12));
|
||||
put(TimeUnit.DAYS.toMillis(3), TimeUnit.DAYS.toMillis(1));
|
||||
put(TimeUnit.DAYS.toMillis(7), TimeUnit.DAYS.toMillis(3));
|
||||
}};
|
||||
|
||||
|
||||
public static boolean needsReminder(@NonNull Context context) {
|
||||
if (!TextSecurePreferences.isRegistrationtLockEnabled(context)) return false;
|
||||
|
||||
long lastReminderTime = TextSecurePreferences.getRegistrationLockLastReminderTime(context);
|
||||
long nextIntervalTime = TextSecurePreferences.getRegistrationLockNextReminderInterval(context);
|
||||
|
||||
return System.currentTimeMillis() > lastReminderTime + nextIntervalTime;
|
||||
}
|
||||
|
||||
public static void scheduleReminder(@NonNull Context context, boolean success) {
|
||||
long lastReminderInterval = TextSecurePreferences.getRegistrationLockNextReminderInterval(context);
|
||||
long nextReminderInterval;
|
||||
|
||||
if (success) nextReminderInterval = INTERVAL_PROGRESSION.get(lastReminderInterval);
|
||||
else nextReminderInterval = INTERVAL_REGRESSION.get(lastReminderInterval);
|
||||
|
||||
TextSecurePreferences.setRegistrationLockLastReminderTime(context, System.currentTimeMillis());
|
||||
TextSecurePreferences.setRegistrationLockNextReminderInterval(context, nextReminderInterval);
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package org.thoughtcrime.securesms.preferences;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
@ -12,8 +13,8 @@ import android.support.v7.preference.CheckBoxPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.doomonafireball.betterpickers.hmspicker.HmsPickerBuilder;
|
||||
import com.doomonafireball.betterpickers.hmspicker.HmsPickerDialogFragment;
|
||||
import com.codetroopers.betterpickers.hmspicker.HmsPickerBuilder;
|
||||
import com.codetroopers.betterpickers.hmspicker.HmsPickerDialogFragment;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
||||
@ -22,24 +23,39 @@ import org.thoughtcrime.securesms.PassphraseChangeActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceReadReceiptUpdateJob;
|
||||
import org.thoughtcrime.securesms.lock.RegistrationLockDialog;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment {
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment implements InjectableType {
|
||||
|
||||
private static final String PREFERENCE_CATEGORY_BLOCKED = "preference_category_blocked";
|
||||
|
||||
private CheckBoxPreference disablePassphrase;
|
||||
|
||||
@Inject
|
||||
SignalServiceAccountManager accountManager;
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
ApplicationContext.getInstance(activity).injectDependencies(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle paramBundle) {
|
||||
super.onCreate(paramBundle);
|
||||
|
||||
disablePassphrase = (CheckBoxPreference) this.findPreference("pref_enable_passphrase_temporary");
|
||||
|
||||
this.findPreference(TextSecurePreferences.REGISTRATION_LOCK_PREF).setOnPreferenceClickListener(new AccountLockClickListener());
|
||||
this.findPreference(TextSecurePreferences.SCREEN_LOCK).setOnPreferenceChangeListener(new ScreenLockListener());
|
||||
this.findPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT).setOnPreferenceClickListener(new ScreenLockTimeoutListener());
|
||||
|
||||
@ -116,7 +132,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
||||
}
|
||||
}
|
||||
|
||||
private class ScreenLockTimeoutListener implements Preference.OnPreferenceClickListener, HmsPickerDialogFragment.HmsPickerDialogHandler {
|
||||
private class ScreenLockTimeoutListener implements Preference.OnPreferenceClickListener, HmsPickerDialogFragment.HmsPickerDialogHandlerV2 {
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
@ -132,18 +148,31 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDialogHmsSet(int reference, int hours, int minutes, int seconds) {
|
||||
public void onDialogHmsSet(int reference, boolean isNegative, int hours, int minutes, int seconds) {
|
||||
long timeoutSeconds = Math.max(TimeUnit.HOURS.toSeconds(hours) +
|
||||
TimeUnit.MINUTES.toSeconds(minutes) +
|
||||
TimeUnit.SECONDS.toSeconds(seconds), 60);
|
||||
TimeUnit.MINUTES.toSeconds(minutes) +
|
||||
TimeUnit.SECONDS.toSeconds(seconds), 60);
|
||||
|
||||
TextSecurePreferences.setScreenLockTimeout(getContext(), timeoutSeconds);
|
||||
initializeScreenLockTimeoutSummary();
|
||||
}
|
||||
}
|
||||
|
||||
private class AccountLockClickListener implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
if (((SwitchPreferenceCompat)preference).isChecked()) {
|
||||
RegistrationLockDialog.showRegistrationUnlockPrompt(getContext(), (SwitchPreferenceCompat)preference, accountManager);
|
||||
} else {
|
||||
RegistrationLockDialog.showRegistrationLockPrompt(getContext(), (SwitchPreferenceCompat)preference, accountManager);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockedContactsClickListener implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
@ -153,6 +182,40 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
||||
}
|
||||
}
|
||||
|
||||
private class ReadReceiptToggleListener implements Preference.OnPreferenceChangeListener {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
boolean enabled = (boolean)newValue;
|
||||
ApplicationContext.getInstance(getContext())
|
||||
.getJobManager()
|
||||
.add(new MultiDeviceReadReceiptUpdateJob(getContext(), enabled));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static CharSequence getSummary(Context context) {
|
||||
final int privacySummaryResId = R.string.ApplicationPreferencesActivity_privacy_summary;
|
||||
final String onRes = context.getString(R.string.ApplicationPreferencesActivity_on);
|
||||
final String offRes = context.getString(R.string.ApplicationPreferencesActivity_off);
|
||||
|
||||
if (TextSecurePreferences.isPasswordDisabled(context) && !TextSecurePreferences.isScreenLockEnabled(context)) {
|
||||
if (TextSecurePreferences.isRegistrationtLockEnabled(context)) {
|
||||
return context.getString(privacySummaryResId, offRes, onRes);
|
||||
} else {
|
||||
return context.getString(privacySummaryResId, offRes, offRes);
|
||||
}
|
||||
} else {
|
||||
if (TextSecurePreferences.isRegistrationtLockEnabled(context)) {
|
||||
return context.getString(privacySummaryResId, onRes, onRes);
|
||||
} else {
|
||||
return context.getString(privacySummaryResId, onRes, offRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Derecated
|
||||
|
||||
private class ChangePassphraseClickListener implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
@ -160,15 +223,15 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
||||
startActivity(new Intent(getActivity(), PassphraseChangeActivity.class));
|
||||
} else {
|
||||
Toast.makeText(getActivity(),
|
||||
R.string.ApplicationPreferenceActivity_you_havent_set_a_passphrase_yet,
|
||||
Toast.LENGTH_LONG).show();
|
||||
R.string.ApplicationPreferenceActivity_you_havent_set_a_passphrase_yet,
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class PassphraseIntervalClickListener implements Preference.OnPreferenceClickListener, HmsPickerDialogFragment.HmsPickerDialogHandler {
|
||||
private class PassphraseIntervalClickListener implements Preference.OnPreferenceClickListener, HmsPickerDialogFragment.HmsPickerDialogHandlerV2 {
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
@ -186,12 +249,13 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDialogHmsSet(int reference, int hours, int minutes, int seconds) {
|
||||
public void onDialogHmsSet(int reference, boolean isNegative, int hours, int minutes, int seconds) {
|
||||
int timeoutMinutes = Math.max((int)TimeUnit.HOURS.toMinutes(hours) +
|
||||
minutes +
|
||||
(int)TimeUnit.SECONDS.toMinutes(seconds), 1);
|
||||
minutes +
|
||||
(int)TimeUnit.SECONDS.toMinutes(seconds), 1);
|
||||
|
||||
TextSecurePreferences.setPassphraseTimeoutInterval(getActivity(), timeoutMinutes);
|
||||
|
||||
initializePassphraseTimeoutSummary();
|
||||
}
|
||||
}
|
||||
@ -230,35 +294,4 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
|
||||
}
|
||||
}
|
||||
|
||||
private class ReadReceiptToggleListener implements Preference.OnPreferenceChangeListener {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
boolean enabled = (boolean)newValue;
|
||||
ApplicationContext.getInstance(getContext())
|
||||
.getJobManager()
|
||||
.add(new MultiDeviceReadReceiptUpdateJob(getContext(), enabled));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static CharSequence getSummary(Context context) {
|
||||
final int privacySummaryResId = R.string.ApplicationPreferencesActivity_privacy_summary;
|
||||
final String onRes = context.getString(R.string.ApplicationPreferencesActivity_on);
|
||||
final String offRes = context.getString(R.string.ApplicationPreferencesActivity_off);
|
||||
|
||||
if (TextSecurePreferences.isPasswordDisabled(context) && !TextSecurePreferences.isScreenLockEnabled(context)) {
|
||||
if (TextSecurePreferences.isScreenSecurityEnabled(context)) {
|
||||
return context.getString(privacySummaryResId, offRes, onRes);
|
||||
} else {
|
||||
return context.getString(privacySummaryResId, offRes, offRes);
|
||||
}
|
||||
} else {
|
||||
if (TextSecurePreferences.isScreenSecurityEnabled(context)) {
|
||||
return context.getString(privacySummaryResId, onRes, onRes);
|
||||
} else {
|
||||
return context.getString(privacySummaryResId, onRes, offRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,11 +12,11 @@ import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.SqlCipherMigrationRequirementProvider;
|
||||
import org.thoughtcrime.securesms.lock.RegistrationLockReminders;
|
||||
import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference;
|
||||
import org.whispersystems.libsignal.util.Medium;
|
||||
|
||||
@ -145,6 +145,11 @@ public class TextSecurePreferences {
|
||||
public static final String SCREEN_LOCK = "pref_android_screen_lock";
|
||||
public static final String SCREEN_LOCK_TIMEOUT = "pref_android_screen_lock_timeout";
|
||||
|
||||
public static final String REGISTRATION_LOCK_PREF = "pref_registration_lock";
|
||||
private static final String REGISTRATION_LOCK_PIN_PREF = "pref_registration_lock_pin";
|
||||
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";
|
||||
|
||||
public static boolean isScreenLockEnabled(@NonNull Context context) {
|
||||
return getBooleanPreference(context, SCREEN_LOCK, false);
|
||||
}
|
||||
@ -161,6 +166,38 @@ public class TextSecurePreferences {
|
||||
setLongPreference(context, SCREEN_LOCK_TIMEOUT, value);
|
||||
}
|
||||
|
||||
public static boolean isRegistrationtLockEnabled(@NonNull Context context) {
|
||||
return getBooleanPreference(context, REGISTRATION_LOCK_PREF, false);
|
||||
}
|
||||
|
||||
public static void setRegistrationtLockEnabled(@NonNull Context context, boolean value) {
|
||||
setBooleanPreference(context, REGISTRATION_LOCK_PREF, value);
|
||||
}
|
||||
|
||||
public static @Nullable String getRegistrationLockPin(@NonNull Context context) {
|
||||
return getStringPreference(context, REGISTRATION_LOCK_PIN_PREF, null);
|
||||
}
|
||||
|
||||
public static void setRegistrationLockPin(@NonNull Context context, String pin) {
|
||||
setStringPreference(context, REGISTRATION_LOCK_PIN_PREF, pin);
|
||||
}
|
||||
|
||||
public static long getRegistrationLockLastReminderTime(@NonNull Context context) {
|
||||
return getLongPreference(context, REGISTRATION_LOCK_LAST_REMINDER_TIME, 0);
|
||||
}
|
||||
|
||||
public static void setRegistrationLockLastReminderTime(@NonNull Context context, long time) {
|
||||
setLongPreference(context, REGISTRATION_LOCK_LAST_REMINDER_TIME, time);
|
||||
}
|
||||
|
||||
public static long getRegistrationLockNextReminderInterval(@NonNull Context context) {
|
||||
return getLongPreference(context, REGISTRATION_LOCK_NEXT_REMINDER_INTERVAL, RegistrationLockReminders.INITIAL_INTERVAL);
|
||||
}
|
||||
|
||||
public static void setRegistrationLockNextReminderInterval(@NonNull Context context, long value) {
|
||||
setLongPreference(context, REGISTRATION_LOCK_NEXT_REMINDER_INTERVAL, value);
|
||||
}
|
||||
|
||||
public static void setBackupPassphrase(@NonNull Context context, @Nullable String passphrase) {
|
||||
setStringPreference(context, BACKUP_PASSPHRASE, passphrase);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user