kopia lustrzana https://github.com/ryukoposting/Signal-Android
Enable lock screen fallback when biometric authentications may not work.
Fixes #9407 Fixes #10166fork-5.53.8
rodzic
be4b687e48
commit
3c4252a933
|
@ -312,6 +312,7 @@ dependencies {
|
||||||
implementation "androidx.camera:camera-view:1.0.0-alpha18"
|
implementation "androidx.camera:camera-view:1.0.0-alpha18"
|
||||||
implementation "androidx.concurrent:concurrent-futures:1.0.0"
|
implementation "androidx.concurrent:concurrent-futures:1.0.0"
|
||||||
implementation "androidx.autofill:autofill:1.0.0"
|
implementation "androidx.autofill:autofill:1.0.0"
|
||||||
|
implementation "androidx.biometric:biometric:1.1.0"
|
||||||
|
|
||||||
implementation ('com.google.firebase:firebase-messaging:20.2.0') {
|
implementation ('com.google.firebase:firebase-messaging:20.2.0') {
|
||||||
exclude group: 'com.google.firebase', module: 'firebase-core'
|
exclude group: 'com.google.firebase', module: 'firebase-core'
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.KeyguardManager;
|
import android.app.KeyguardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -46,9 +45,11 @@ import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.core.hardware.fingerprint.FingerprintManagerCompat;
|
import androidx.biometric.BiometricManager;
|
||||||
import androidx.core.os.CancellationSignal;
|
import androidx.biometric.BiometricManager.Authenticators;
|
||||||
|
import androidx.biometric.BiometricPrompt;
|
||||||
|
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||||
|
@ -70,7 +71,10 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
*/
|
*/
|
||||||
public class PassphrasePromptActivity extends PassphraseActivity {
|
public class PassphrasePromptActivity extends PassphraseActivity {
|
||||||
|
|
||||||
private static final String TAG = PassphrasePromptActivity.class.getSimpleName();
|
private static final String TAG = Log.tag(PassphrasePromptActivity.class);
|
||||||
|
private static final int BIOMETRIC_AUTHENTICATORS = Authenticators.BIOMETRIC_STRONG | Authenticators.BIOMETRIC_WEAK;
|
||||||
|
private static final int ALLOWED_AUTHENTICATORS = BIOMETRIC_AUTHENTICATORS | Authenticators.DEVICE_CREDENTIAL;
|
||||||
|
private static final short AUTHENTICATE_REQUEST_CODE = 1007;
|
||||||
|
|
||||||
private DynamicIntroTheme dynamicTheme = new DynamicIntroTheme();
|
private DynamicIntroTheme dynamicTheme = new DynamicIntroTheme();
|
||||||
private DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
private DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||||
|
@ -84,12 +88,12 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||||
private ImageButton hideButton;
|
private ImageButton hideButton;
|
||||||
private AnimatingToggle visibilityToggle;
|
private AnimatingToggle visibilityToggle;
|
||||||
|
|
||||||
private FingerprintManagerCompat fingerprintManager;
|
private BiometricManager biometricManager;
|
||||||
private CancellationSignal fingerprintCancellationSignal;
|
private BiometricPrompt biometricPrompt;
|
||||||
private FingerprintListener fingerprintListener;
|
private BiometricPrompt.PromptInfo biometricPromptInfo;
|
||||||
|
|
||||||
private boolean authenticated;
|
private boolean authenticated;
|
||||||
private boolean failure;
|
private boolean hadFailure;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -112,20 +116,11 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||||
|
|
||||||
setLockTypeVisibility();
|
setLockTypeVisibility();
|
||||||
|
|
||||||
if (TextSecurePreferences.isScreenLockEnabled(this) && !authenticated && !failure) {
|
if (TextSecurePreferences.isScreenLockEnabled(this) && !authenticated && !hadFailure) {
|
||||||
resumeScreenLock();
|
resumeScreenLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
failure = false;
|
hadFailure = false;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
|
|
||||||
if (TextSecurePreferences.isScreenLockEnabled(this)) {
|
|
||||||
pauseScreenLock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -160,15 +155,16 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressLint("MissingSuperCall") // no fragments to dispatch to
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
public void onActivityResult(int requestCode, int resultcode, Intent data) {
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
if (requestCode != 1) return;
|
|
||||||
|
|
||||||
if (resultcode == RESULT_OK) {
|
if (requestCode != AUTHENTICATE_REQUEST_CODE) return;
|
||||||
|
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
handleAuthenticated();
|
handleAuthenticated();
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Authentication failed");
|
Log.w(TAG, "Authentication failed");
|
||||||
failure = true;
|
hadFailure = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,16 +215,20 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||||
ImageButton okButton = findViewById(R.id.ok_button);
|
ImageButton okButton = findViewById(R.id.ok_button);
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
|
||||||
showButton = findViewById(R.id.passphrase_visibility);
|
showButton = findViewById(R.id.passphrase_visibility);
|
||||||
hideButton = findViewById(R.id.passphrase_visibility_off);
|
hideButton = findViewById(R.id.passphrase_visibility_off);
|
||||||
visibilityToggle = findViewById(R.id.button_toggle);
|
visibilityToggle = findViewById(R.id.button_toggle);
|
||||||
passphraseText = findViewById(R.id.passphrase_edit);
|
passphraseText = findViewById(R.id.passphrase_edit);
|
||||||
passphraseAuthContainer = findViewById(R.id.password_auth_container);
|
passphraseAuthContainer = findViewById(R.id.password_auth_container);
|
||||||
fingerprintPrompt = findViewById(R.id.fingerprint_auth_container);
|
fingerprintPrompt = findViewById(R.id.fingerprint_auth_container);
|
||||||
lockScreenButton = findViewById(R.id.lock_screen_auth_container);
|
lockScreenButton = findViewById(R.id.lock_screen_auth_container);
|
||||||
fingerprintManager = FingerprintManagerCompat.from(this);
|
biometricManager = BiometricManager.from(this);
|
||||||
fingerprintCancellationSignal = new CancellationSignal();
|
biometricPrompt = new BiometricPrompt(this, new BiometricAuthenticationListener());
|
||||||
fingerprintListener = new FingerprintListener();
|
biometricPromptInfo = new BiometricPrompt.PromptInfo
|
||||||
|
.Builder()
|
||||||
|
.setAllowedAuthenticators(ALLOWED_AUTHENTICATORS)
|
||||||
|
.setTitle(getString(R.string.PassphrasePromptActivity_unlock_signal))
|
||||||
|
.build();
|
||||||
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
getSupportActionBar().setTitle("");
|
getSupportActionBar().setTitle("");
|
||||||
|
@ -254,14 +254,9 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||||
private void setLockTypeVisibility() {
|
private void setLockTypeVisibility() {
|
||||||
if (TextSecurePreferences.isScreenLockEnabled(this)) {
|
if (TextSecurePreferences.isScreenLockEnabled(this)) {
|
||||||
passphraseAuthContainer.setVisibility(View.GONE);
|
passphraseAuthContainer.setVisibility(View.GONE);
|
||||||
|
fingerprintPrompt.setVisibility(biometricManager.canAuthenticate(BIOMETRIC_AUTHENTICATORS) == BiometricManager.BIOMETRIC_SUCCESS ? View.VISIBLE
|
||||||
if (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) {
|
: View.GONE);
|
||||||
fingerprintPrompt.setVisibility(View.VISIBLE);
|
lockScreenButton.setVisibility(View.VISIBLE);
|
||||||
lockScreenButton.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
fingerprintPrompt.setVisibility(View.GONE);
|
|
||||||
lockScreenButton.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
passphraseAuthContainer.setVisibility(View.VISIBLE);
|
passphraseAuthContainer.setVisibility(View.VISIBLE);
|
||||||
fingerprintPrompt.setVisibility(View.GONE);
|
fingerprintPrompt.setVisibility(View.GONE);
|
||||||
|
@ -280,26 +275,19 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) {
|
if (biometricManager.canAuthenticate(ALLOWED_AUTHENTICATORS) == BiometricManager.BIOMETRIC_SUCCESS) {
|
||||||
Log.i(TAG, "Listening for fingerprints...");
|
Log.i(TAG, "Listening for biometric authentication...");
|
||||||
fingerprintCancellationSignal = new CancellationSignal();
|
biometricPrompt.authenticate(biometricPromptInfo);
|
||||||
fingerprintManager.authenticate(null, 0, fingerprintCancellationSignal, fingerprintListener, null);
|
|
||||||
} else if (Build.VERSION.SDK_INT >= 21){
|
} else if (Build.VERSION.SDK_INT >= 21){
|
||||||
Log.i(TAG, "firing intent...");
|
Log.i(TAG, "firing intent...");
|
||||||
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(getString(R.string.PassphrasePromptActivity_unlock_signal), "");
|
Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(getString(R.string.PassphrasePromptActivity_unlock_signal), "");
|
||||||
startActivityForResult(intent, 1);
|
startActivityForResult(intent, AUTHENTICATE_REQUEST_CODE);
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "Not compatible...");
|
Log.w(TAG, "Not compatible...");
|
||||||
handleAuthenticated();
|
handleAuthenticated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void pauseScreenLock() {
|
|
||||||
if (fingerprintCancellationSignal != null) {
|
|
||||||
fingerprintCancellationSignal.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendEmailToSupport() {
|
private void sendEmailToSupport() {
|
||||||
String body = SupportEmailUtil.generateSupportEmailBody(this,
|
String body = SupportEmailUtil.generateSupportEmailBody(this,
|
||||||
R.string.PassphrasePromptActivity_signal_android_lock_screen,
|
R.string.PassphrasePromptActivity_signal_android_lock_screen,
|
||||||
|
@ -359,15 +347,19 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||||
System.gc();
|
System.gc();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FingerprintListener extends FingerprintManagerCompat.AuthenticationCallback {
|
private class BiometricAuthenticationListener extends BiometricPrompt.AuthenticationCallback {
|
||||||
@Override
|
@Override
|
||||||
public void onAuthenticationError(int errMsgId, CharSequence errString) {
|
public void onAuthenticationError(int errorCode, @NonNull CharSequence errorString) {
|
||||||
Log.w(TAG, "Authentication error: " + errMsgId + " " + errString);
|
Log.w(TAG, "Authentication error: " + errorCode);
|
||||||
onAuthenticationFailed();
|
hadFailure = true;
|
||||||
|
|
||||||
|
if (errorCode != BiometricPrompt.ERROR_CANCELED && errorCode != BiometricPrompt.ERROR_USER_CANCELED) {
|
||||||
|
onAuthenticationFailed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
|
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
|
||||||
Log.i(TAG, "onAuthenticationSucceeded");
|
Log.i(TAG, "onAuthenticationSucceeded");
|
||||||
fingerprintPrompt.setImageResource(R.drawable.ic_check_white_48dp);
|
fingerprintPrompt.setImageResource(R.drawable.ic_check_white_48dp);
|
||||||
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.green_500), PorterDuff.Mode.SRC_IN);
|
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.green_500), PorterDuff.Mode.SRC_IN);
|
||||||
|
@ -384,8 +376,7 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAuthenticationFailed() {
|
public void onAuthenticationFailed() {
|
||||||
Log.w(TAG, "onAuthenticatoinFailed()");
|
Log.w(TAG, "onAuthenticationFailed()");
|
||||||
FingerprintManagerCompat.AuthenticationCallback callback = this;
|
|
||||||
|
|
||||||
fingerprintPrompt.setImageResource(R.drawable.ic_close_white_48dp);
|
fingerprintPrompt.setImageResource(R.drawable.ic_close_white_48dp);
|
||||||
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.red_500), PorterDuff.Mode.SRC_IN);
|
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.red_500), PorterDuff.Mode.SRC_IN);
|
||||||
|
@ -409,6 +400,5 @@ public class PassphrasePromptActivity extends PassphraseActivity {
|
||||||
|
|
||||||
fingerprintPrompt.startAnimation(shake);
|
fingerprintPrompt.startAnimation(shake);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,6 +301,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActivity implement
|
||||||
byte[] localId;
|
byte[] localId;
|
||||||
byte[] remoteId;
|
byte[] remoteId;
|
||||||
|
|
||||||
|
//noinspection WrongThread
|
||||||
Recipient resolved = recipient.resolve();
|
Recipient resolved = recipient.resolve();
|
||||||
|
|
||||||
if (FeatureFlags.verifyV2() && resolved.getUuid().isPresent()) {
|
if (FeatureFlags.verifyV2() && resolved.getUuid().isPresent()) {
|
||||||
|
|
|
@ -260,16 +260,16 @@ public class ConversationFragment extends LoggingFragment {
|
||||||
this.messageCountsViewModel = ViewModelProviders.of(requireActivity()).get(MessageCountsViewModel.class);
|
this.messageCountsViewModel = ViewModelProviders.of(requireActivity()).get(MessageCountsViewModel.class);
|
||||||
this.conversationViewModel = ViewModelProviders.of(requireActivity(), new ConversationViewModel.Factory()).get(ConversationViewModel.class);
|
this.conversationViewModel = ViewModelProviders.of(requireActivity(), new ConversationViewModel.Factory()).get(ConversationViewModel.class);
|
||||||
|
|
||||||
conversationViewModel.getMessages().observe(this, messages -> {
|
conversationViewModel.getMessages().observe(getViewLifecycleOwner(), messages -> {
|
||||||
ConversationAdapter adapter = getListAdapter();
|
ConversationAdapter adapter = getListAdapter();
|
||||||
if (adapter != null) {
|
if (adapter != null) {
|
||||||
getListAdapter().submitList(messages);
|
getListAdapter().submitList(messages);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
conversationViewModel.getConversationMetadata().observe(this, this::presentConversationMetadata);
|
conversationViewModel.getConversationMetadata().observe(getViewLifecycleOwner(), this::presentConversationMetadata);
|
||||||
|
|
||||||
conversationViewModel.getShowMentionsButton().observe(this, shouldShow -> {
|
conversationViewModel.getShowMentionsButton().observe(getViewLifecycleOwner(), shouldShow -> {
|
||||||
if (shouldShow) {
|
if (shouldShow) {
|
||||||
ViewUtil.animateIn(scrollToMentionButton, mentionButtonInAnimation);
|
ViewUtil.animateIn(scrollToMentionButton, mentionButtonInAnimation);
|
||||||
} else {
|
} else {
|
||||||
|
@ -277,7 +277,7 @@ public class ConversationFragment extends LoggingFragment {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
conversationViewModel.getShowScrollToBottom().observe(this, shouldShow -> {
|
conversationViewModel.getShowScrollToBottom().observe(getViewLifecycleOwner(), shouldShow -> {
|
||||||
if (shouldShow) {
|
if (shouldShow) {
|
||||||
ViewUtil.animateIn(scrollToBottomButton, scrollButtonInAnimation);
|
ViewUtil.animateIn(scrollToBottomButton, scrollButtonInAnimation);
|
||||||
} else {
|
} else {
|
||||||
|
@ -367,7 +367,7 @@ public class ConversationFragment extends LoggingFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
ApplicationDependencies.getTypingStatusRepository().getTypists(threadId).removeObservers(this);
|
ApplicationDependencies.getTypingStatusRepository().getTypists(threadId).removeObservers(getViewLifecycleOwner());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -542,7 +542,7 @@ public class ConversationFragment extends LoggingFragment {
|
||||||
list.addOnScrollListener(new ShadowScrollListener());
|
list.addOnScrollListener(new ShadowScrollListener());
|
||||||
|
|
||||||
if (oldThreadId != threadId) {
|
if (oldThreadId != threadId) {
|
||||||
ApplicationDependencies.getTypingStatusRepository().getTypists(oldThreadId).removeObservers(this);
|
ApplicationDependencies.getTypingStatusRepository().getTypists(oldThreadId).removeObservers(getViewLifecycleOwner());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,8 +580,8 @@ public class ConversationFragment extends LoggingFragment {
|
||||||
|
|
||||||
LiveData<TypingStatusRepository.TypingState> typists = ApplicationDependencies.getTypingStatusRepository().getTypists(threadId);
|
LiveData<TypingStatusRepository.TypingState> typists = ApplicationDependencies.getTypingStatusRepository().getTypists(threadId);
|
||||||
|
|
||||||
typists.removeObservers(this);
|
typists.removeObservers(getViewLifecycleOwner());
|
||||||
typists.observe(this, typingState -> {
|
typists.observe(getViewLifecycleOwner(), typingState -> {
|
||||||
List<Recipient> recipients;
|
List<Recipient> recipients;
|
||||||
boolean replacedByIncomingMessage;
|
boolean replacedByIncomingMessage;
|
||||||
|
|
||||||
|
|
|
@ -532,7 +532,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeTypingObserver() {
|
private void initializeTypingObserver() {
|
||||||
ApplicationDependencies.getTypingStatusRepository().getTypingThreads().observe(this, threadIds -> {
|
ApplicationDependencies.getTypingStatusRepository().getTypingThreads().observe(getViewLifecycleOwner(), threadIds -> {
|
||||||
if (threadIds == null) {
|
if (threadIds == null) {
|
||||||
threadIds = Collections.emptySet();
|
threadIds = Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ public class HelpFragment extends LoggingFragment {
|
||||||
setSpinning(next);
|
setSpinning(next);
|
||||||
problem.setEnabled(false);
|
problem.setEnabled(false);
|
||||||
|
|
||||||
helpViewModel.onSubmitClicked(includeDebugLogs.isChecked()).observe(this, result -> {
|
helpViewModel.onSubmitClicked(includeDebugLogs.isChecked()).observe(getViewLifecycleOwner(), result -> {
|
||||||
if (result.getDebugLogUrl().isPresent()) {
|
if (result.getDebugLogUrl().isPresent()) {
|
||||||
submitFormWithDebugLog(result.getDebugLogUrl().get());
|
submitFormWithDebugLog(result.getDebugLogUrl().get());
|
||||||
} else if (result.isError()) {
|
} else if (result.isError()) {
|
||||||
|
|
|
@ -127,7 +127,7 @@ public final class InsightsDashboardDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
viewModel = ViewModelProviders.of(this, factory).get(InsightsDashboardViewModel.class);
|
viewModel = ViewModelProviders.of(this, factory).get(InsightsDashboardViewModel.class);
|
||||||
|
|
||||||
viewModel.getState().observe(this, state -> {
|
viewModel.getState().observe(getViewLifecycleOwner(), state -> {
|
||||||
updateInsecurePercent(state.getData());
|
updateInsecurePercent(state.getData());
|
||||||
updateInsecureRecipients(state.getInsecureRecipients());
|
updateInsecureRecipients(state.getInsecureRecipients());
|
||||||
updateUserAvatar(state.getUserAvatar());
|
updateUserAvatar(state.getUserAvatar());
|
||||||
|
|
|
@ -79,7 +79,7 @@ public final class InsightsModalDialogFragment extends DialogFragment {
|
||||||
final InsightsModalViewModel.Factory factory = new InsightsModalViewModel.Factory(repository);
|
final InsightsModalViewModel.Factory factory = new InsightsModalViewModel.Factory(repository);
|
||||||
final InsightsModalViewModel viewModel = ViewModelProviders.of(this, factory).get(InsightsModalViewModel.class);
|
final InsightsModalViewModel viewModel = ViewModelProviders.of(this, factory).get(InsightsModalViewModel.class);
|
||||||
|
|
||||||
viewModel.getState().observe(this, state -> {
|
viewModel.getState().observe(getViewLifecycleOwner(), state -> {
|
||||||
updateInsecurePercent(state.getData());
|
updateInsecurePercent(state.getData());
|
||||||
updateUserAvatar(state.getUserAvatar());
|
updateUserAvatar(state.getUserAvatar());
|
||||||
});
|
});
|
||||||
|
|
|
@ -128,7 +128,7 @@ public final class MediaOverviewPageFragment extends Fragment
|
||||||
MediaOverviewViewModel viewModel = MediaOverviewViewModel.getMediaOverviewViewModel(requireActivity());
|
MediaOverviewViewModel viewModel = MediaOverviewViewModel.getMediaOverviewViewModel(requireActivity());
|
||||||
|
|
||||||
viewModel.getSortOrder()
|
viewModel.getSortOrder()
|
||||||
.observe(this, sorting -> {
|
.observe(getViewLifecycleOwner(), sorting -> {
|
||||||
if (sorting != null) {
|
if (sorting != null) {
|
||||||
this.sorting = sorting;
|
this.sorting = sorting;
|
||||||
adapter.setShowFileSizes(sorting.isRelatedToFileSize());
|
adapter.setShowFileSizes(sorting.isRelatedToFileSize());
|
||||||
|
@ -139,7 +139,7 @@ public final class MediaOverviewPageFragment extends Fragment
|
||||||
|
|
||||||
if (gridMode == GridMode.FOLLOW_MODEL) {
|
if (gridMode == GridMode.FOLLOW_MODEL) {
|
||||||
viewModel.getDetailLayout()
|
viewModel.getDetailLayout()
|
||||||
.observe(this, this::setDetailView);
|
.observe(getViewLifecycleOwner(), this::setDetailView);
|
||||||
} else {
|
} else {
|
||||||
setDetailView(gridMode == GridMode.FIXED_DETAIL);
|
setDetailView(gridMode == GridMode.FIXED_DETAIL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,8 +111,8 @@ public class Camera1Fragment extends LoggingFragment implements CameraFragment,
|
||||||
GestureDetector gestureDetector = new GestureDetector(flipGestureListener);
|
GestureDetector gestureDetector = new GestureDetector(flipGestureListener);
|
||||||
cameraPreview.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event));
|
cameraPreview.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event));
|
||||||
|
|
||||||
viewModel.getMostRecentMediaItem().observe(this, this::presentRecentItemThumbnail);
|
viewModel.getMostRecentMediaItem().observe(getViewLifecycleOwner(), this::presentRecentItemThumbnail);
|
||||||
viewModel.getHudState().observe(this, this::presentHud);
|
viewModel.getHudState().observe(getViewLifecycleOwner(), this::presentHud);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -122,8 +122,8 @@ public class CameraXFragment extends LoggingFragment implements CameraFragment {
|
||||||
|
|
||||||
onOrientationChanged(getResources().getConfiguration().orientation);
|
onOrientationChanged(getResources().getConfiguration().orientation);
|
||||||
|
|
||||||
viewModel.getMostRecentMediaItem().observe(this, this::presentRecentItemThumbnail);
|
viewModel.getMostRecentMediaItem().observe(getViewLifecycleOwner(), this::presentRecentItemThumbnail);
|
||||||
viewModel.getHudState().observe(this, this::presentHud);
|
viewModel.getHudState().observe(getViewLifecycleOwner(), this::presentHud);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class MediaPickerFolderFragment extends Fragment implements MediaPickerFo
|
||||||
list.setLayoutManager(layoutManager);
|
list.setLayoutManager(layoutManager);
|
||||||
list.setAdapter(adapter);
|
list.setAdapter(adapter);
|
||||||
|
|
||||||
viewModel.getFolders(requireContext()).observe(this, adapter::setFolders);
|
viewModel.getFolders(requireContext()).observe(getViewLifecycleOwner(), adapter::setFolders);
|
||||||
|
|
||||||
initToolbar(view.findViewById(R.id.mediapicker_toolbar));
|
initToolbar(view.findViewById(R.id.mediapicker_toolbar));
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,8 +110,8 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem
|
||||||
initToolbar(view.findViewById(R.id.mediapicker_toolbar));
|
initToolbar(view.findViewById(R.id.mediapicker_toolbar));
|
||||||
onScreenWidthChanged(getScreenWidth());
|
onScreenWidthChanged(getScreenWidth());
|
||||||
|
|
||||||
viewModel.getSelectedMedia().observe(this, adapter::setSelected);
|
viewModel.getSelectedMedia().observe(getViewLifecycleOwner(), adapter::setSelected);
|
||||||
viewModel.getMediaInBucket(requireContext(), bucketId).observe(this, adapter::setMedia);
|
viewModel.getMediaInBucket(requireContext(), bucketId).observe(getViewLifecycleOwner(), adapter::setMedia);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -115,7 +115,7 @@ public class MediaSendFragment extends Fragment {
|
||||||
private void initViewModel() {
|
private void initViewModel() {
|
||||||
viewModel = ViewModelProviders.of(requireActivity(), new MediaSendViewModel.Factory(requireActivity().getApplication(), new MediaRepository())).get(MediaSendViewModel.class);
|
viewModel = ViewModelProviders.of(requireActivity(), new MediaSendViewModel.Factory(requireActivity().getApplication(), new MediaRepository())).get(MediaSendViewModel.class);
|
||||||
|
|
||||||
viewModel.getSelectedMedia().observe(this, media -> {
|
viewModel.getSelectedMedia().observe(getViewLifecycleOwner(), media -> {
|
||||||
if (Util.isEmpty(media)) {
|
if (Util.isEmpty(media)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ public class MediaSendFragment extends Fragment {
|
||||||
fragmentPagerAdapter.setMedia(media);
|
fragmentPagerAdapter.setMedia(media);
|
||||||
});
|
});
|
||||||
|
|
||||||
viewModel.getPosition().observe(this, position -> {
|
viewModel.getPosition().observe(getViewLifecycleOwner(), position -> {
|
||||||
if (position == null || position < 0) return;
|
if (position == null || position < 0) return;
|
||||||
|
|
||||||
fragmentPager.setCurrentItem(position, true);
|
fragmentPager.setCurrentItem(position, true);
|
||||||
|
|
|
@ -110,8 +110,8 @@ public class PinRestoreEntryFragment extends LoggingFragment {
|
||||||
private void initViewModel() {
|
private void initViewModel() {
|
||||||
viewModel = ViewModelProviders.of(this).get(PinRestoreViewModel.class);
|
viewModel = ViewModelProviders.of(this).get(PinRestoreViewModel.class);
|
||||||
|
|
||||||
viewModel.getTriesRemaining().observe(this, this::presentTriesRemaining);
|
viewModel.getTriesRemaining().observe(getViewLifecycleOwner(), this::presentTriesRemaining);
|
||||||
viewModel.getEvent().observe(this, this::presentEvent);
|
viewModel.getEvent().observe(getViewLifecycleOwner(), this::presentEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void presentTriesRemaining(PinRestoreViewModel.TriesRemaining triesRemaining) {
|
private void presentTriesRemaining(PinRestoreViewModel.TriesRemaining triesRemaining) {
|
||||||
|
|
|
@ -97,7 +97,7 @@ public final class EnterCodeFragment extends BaseRegistrationFragment
|
||||||
noCodeReceivedHelp.setOnClickListener(v -> sendEmailToSupport());
|
noCodeReceivedHelp.setOnClickListener(v -> sendEmailToSupport());
|
||||||
|
|
||||||
RegistrationViewModel model = getModel();
|
RegistrationViewModel model = getModel();
|
||||||
model.getSuccessfulCodeRequestAttempts().observe(this, (attempts) -> {
|
model.getSuccessfulCodeRequestAttempts().observe(getViewLifecycleOwner(), (attempts) -> {
|
||||||
if (attempts >= 3) {
|
if (attempts >= 3) {
|
||||||
noCodeReceivedHelp.setVisibility(View.VISIBLE);
|
noCodeReceivedHelp.setVisibility(View.VISIBLE);
|
||||||
scrollView.postDelayed(() -> scrollView.smoothScrollTo(0, noCodeReceivedHelp.getBottom()), 15000);
|
scrollView.postDelayed(() -> scrollView.smoothScrollTo(0, noCodeReceivedHelp.getBottom()), 15000);
|
||||||
|
@ -328,9 +328,9 @@ public final class EnterCodeFragment extends BaseRegistrationFragment
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
RegistrationViewModel model = getModel();
|
RegistrationViewModel model = getModel();
|
||||||
model.getLiveNumber().observe(this, (s) -> header.setText(requireContext().getString(R.string.RegistrationActivity_enter_the_code_we_sent_to_s, s.getFullFormattedNumber())));
|
model.getLiveNumber().observe(getViewLifecycleOwner(), (s) -> header.setText(requireContext().getString(R.string.RegistrationActivity_enter_the_code_we_sent_to_s, s.getFullFormattedNumber())));
|
||||||
|
|
||||||
model.getCanCallAtTime().observe(this, callAtTime -> callMeCountDown.startCountDownTo(callAtTime));
|
model.getCanCallAtTime().observe(getViewLifecycleOwner(), callAtTime -> callMeCountDown.startCountDownTo(callAtTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendEmailToSupport() {
|
private void sendEmailToSupport() {
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
|
|
||||||
['androidx.activity:activity:1.0.0',
|
['androidx.activity:activity:1.1.0',
|
||||||
'd1bc9842455c2e534415d88c44df4d52413b478db9093a1ba36324f705f44c3d'],
|
'4f2b35916768032f7d0c20e250e28b29037ed4ce9ebf3da4fcd51bcb0c6067ef'],
|
||||||
|
|
||||||
['androidx.annotation:annotation-experimental:1.0.0',
|
['androidx.annotation:annotation-experimental:1.0.0',
|
||||||
'b219d2b568e7e4ba534e09f8c2fd242343df6ccbdfbbe938846f5d740e6b0b11'],
|
'b219d2b568e7e4ba534e09f8c2fd242343df6ccbdfbbe938846f5d740e6b0b11'],
|
||||||
|
@ -30,6 +30,9 @@ dependencyVerification {
|
||||||
['androidx.autofill:autofill:1.0.0',
|
['androidx.autofill:autofill:1.0.0',
|
||||||
'c9468f56e05006ea151a426c54957cd0799b8b83a579d2846dd22061f33e5ecd'],
|
'c9468f56e05006ea151a426c54957cd0799b8b83a579d2846dd22061f33e5ecd'],
|
||||||
|
|
||||||
|
['androidx.biometric:biometric:1.1.0',
|
||||||
|
'270c7b7d99942d5ec1dd88594e4648feb33d8e31d8c3c2ab2321d49d9abdfc1f'],
|
||||||
|
|
||||||
['androidx.camera:camera-camera2:1.0.0-beta11',
|
['androidx.camera:camera-camera2:1.0.0-beta11',
|
||||||
'54d7c975ea7387f0d7c65faf531005fc543fe8e8d826eb696bb2c7f950041a9c'],
|
'54d7c975ea7387f0d7c65faf531005fc543fe8e8d826eb696bb2c7f950041a9c'],
|
||||||
|
|
||||||
|
@ -60,8 +63,8 @@ dependencyVerification {
|
||||||
['androidx.coordinatorlayout:coordinatorlayout:1.1.0',
|
['androidx.coordinatorlayout:coordinatorlayout:1.1.0',
|
||||||
'44a9e30abf56af1025c52a0af506fee9c4131aa55efda52f9fd9451211c5e8cb'],
|
'44a9e30abf56af1025c52a0af506fee9c4131aa55efda52f9fd9451211c5e8cb'],
|
||||||
|
|
||||||
['androidx.core:core:1.3.1',
|
['androidx.core:core:1.3.2',
|
||||||
'e92ea65a37d589943d405a6a54d1be9d12a225948f26c4e41e511dd55e81efb6'],
|
'94de196cd67950cff6ef3e1ac59015f8eaaf61840bdc238f2cf54ddef8dd0be9'],
|
||||||
|
|
||||||
['androidx.cursoradapter:cursoradapter:1.0.0',
|
['androidx.cursoradapter:cursoradapter:1.0.0',
|
||||||
'a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564'],
|
'a81c8fe78815fa47df5b749deb52727ad11f9397da58b16017f4eb2c11e28564'],
|
||||||
|
@ -78,8 +81,8 @@ dependencyVerification {
|
||||||
['androidx.exifinterface:exifinterface:1.0.0',
|
['androidx.exifinterface:exifinterface:1.0.0',
|
||||||
'ee48be10aab8f54efff4c14b77d11e10b9eeee4379d5ef6bf297a2923c55cc11'],
|
'ee48be10aab8f54efff4c14b77d11e10b9eeee4379d5ef6bf297a2923c55cc11'],
|
||||||
|
|
||||||
['androidx.fragment:fragment:1.1.0',
|
['androidx.fragment:fragment:1.2.5',
|
||||||
'a14c8b8f2153f128e800fbd266a6beab1c283982a29ec570d2cc05d307d81496'],
|
'd19e82d142def6c4e136da70bf92f194c0ecc61d14ab4e84567b2ced0920fa93'],
|
||||||
|
|
||||||
['androidx.gridlayout:gridlayout:1.0.0',
|
['androidx.gridlayout:gridlayout:1.0.0',
|
||||||
'a7e5dc6f39dbc3dc6ac6d57b02a9c6fd792e80f0e45ddb3bb08e8f03d23c8755'],
|
'a7e5dc6f39dbc3dc6ac6d57b02a9c6fd792e80f0e45ddb3bb08e8f03d23c8755'],
|
||||||
|
@ -105,14 +108,14 @@ dependencyVerification {
|
||||||
['androidx.lifecycle:lifecycle-common-java8:2.1.0',
|
['androidx.lifecycle:lifecycle-common-java8:2.1.0',
|
||||||
'a1ec63c1bb973443cb731d78ec336c5e20e7ee35c89cbb32d36f92c55bb02542'],
|
'a1ec63c1bb973443cb731d78ec336c5e20e7ee35c89cbb32d36f92c55bb02542'],
|
||||||
|
|
||||||
['androidx.lifecycle:lifecycle-common:2.2.0-alpha05',
|
['androidx.lifecycle:lifecycle-common:2.2.0',
|
||||||
'63898dabf7cfe5ec5d7ed8b8c2564c1427be876e1496ead95c2703cf59d3734b'],
|
'63898dabf7cfe5ec5d7ed8b8c2564c1427be876e1496ead95c2703cf59d3734b'],
|
||||||
|
|
||||||
['androidx.lifecycle:lifecycle-extensions:2.1.0',
|
['androidx.lifecycle:lifecycle-extensions:2.1.0',
|
||||||
'bd53c64b038585215b4959c1a388437a3ad525608a31c58e4283c3e371727d4d'],
|
'bd53c64b038585215b4959c1a388437a3ad525608a31c58e4283c3e371727d4d'],
|
||||||
|
|
||||||
['androidx.lifecycle:lifecycle-livedata-core:2.2.0-alpha05',
|
['androidx.lifecycle:lifecycle-livedata-core:2.2.0',
|
||||||
'6df2bcbf3be50a5fa29e9aa09d39437f2d61d17c2c46ef618d65bbac4a4a99fc'],
|
'556c1f3af90aa9d7d0d330565adbf6da71b2429148bac91e07c485f4f9abf614'],
|
||||||
|
|
||||||
['androidx.lifecycle:lifecycle-livedata:2.1.0',
|
['androidx.lifecycle:lifecycle-livedata:2.1.0',
|
||||||
'242e446bed3db36f0df0aab0cb7f91060bd2dab7adcad1117adf54e724cd1d26'],
|
'242e446bed3db36f0df0aab0cb7f91060bd2dab7adcad1117adf54e724cd1d26'],
|
||||||
|
@ -120,17 +123,17 @@ dependencyVerification {
|
||||||
['androidx.lifecycle:lifecycle-process:2.1.0',
|
['androidx.lifecycle:lifecycle-process:2.1.0',
|
||||||
'8cddd0c7f4927bbf71fb71fca000786df82cc597c99463d6916ccbe4a205a9ac'],
|
'8cddd0c7f4927bbf71fb71fca000786df82cc597c99463d6916ccbe4a205a9ac'],
|
||||||
|
|
||||||
['androidx.lifecycle:lifecycle-runtime:2.1.0',
|
['androidx.lifecycle:lifecycle-runtime:2.2.0',
|
||||||
'e5173897b965e870651e83d9d5af1742d3f532d58863223a390ce3a194c8312b'],
|
'2f866c07a1f33a8c9bb69a9545d4f20b4f0628cd0a155432386d7cb081e1e0bc'],
|
||||||
|
|
||||||
['androidx.lifecycle:lifecycle-service:2.1.0',
|
['androidx.lifecycle:lifecycle-service:2.1.0',
|
||||||
'23516745f34f16ff7850bb1eadd55cf193dd789cba428de4bca120433e3bfd69'],
|
'23516745f34f16ff7850bb1eadd55cf193dd789cba428de4bca120433e3bfd69'],
|
||||||
|
|
||||||
['androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-alpha05',
|
['androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0',
|
||||||
'f503b53f50c4e6c1f9a3d698c4733df6e7a44049fe477ad0b85cc2f460401fbc'],
|
'3ce866fb822b20fe2f188f974992869a0a6233fe40acbefcff090d6def5e7f33'],
|
||||||
|
|
||||||
['androidx.lifecycle:lifecycle-viewmodel:2.2.0-alpha05',
|
['androidx.lifecycle:lifecycle-viewmodel:2.2.0',
|
||||||
'7725715491963440ee483e46526cd4f83af1c758e072e97b3eab2115c6f4db35'],
|
'967efab24d6c49dd414a8c0ac4a1cd09b018f0b8bb43b739ad360c4158ebde27'],
|
||||||
|
|
||||||
['androidx.loader:loader:1.0.0',
|
['androidx.loader:loader:1.0.0',
|
||||||
'11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025'],
|
'11f735cb3b55c458d470bed9e25254375b518b4b1bad6926783a7026db0f5025'],
|
||||||
|
|
Ładowanie…
Reference in New Issue