mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 02:39:05 +01:00
Merge branch '1482-startup-activity' into 'master'
Combine Password and OpenDatabase Activity into StartupActivity Closes #1482 See merge request briar/briar!1087
This commit is contained in:
@@ -73,13 +73,12 @@
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.briarproject.briar.android.login.PasswordActivity"
|
||||
android:label="@string/app_name"
|
||||
android:windowSoftInputMode="stateVisible">
|
||||
android:name="org.briarproject.briar.android.login.StartupActivity"
|
||||
android:label="@string/app_name">
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.briarproject.briar.android.login.SetupActivity"
|
||||
android:name="org.briarproject.briar.android.account.SetupActivity"
|
||||
android:label="@string/setup_title"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
</activity>
|
||||
@@ -94,11 +93,6 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".android.login.OpenDatabaseActivity"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop"/>
|
||||
|
||||
<activity
|
||||
android:name="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||
android:theme="@style/BriarTheme.NoActionBar"
|
||||
@@ -420,7 +414,7 @@
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".android.login.UnlockActivity"
|
||||
android:name=".android.account.UnlockActivity"
|
||||
android:label="@string/lock_unlock"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/BriarTheme.NoActionBar"/>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
@@ -11,6 +14,8 @@ import java.util.logging.LogRecord;
|
||||
*/
|
||||
public interface BriarApplication {
|
||||
|
||||
Class<? extends Activity> ENTRY_ACTIVITY = NavDrawerActivity.class;
|
||||
|
||||
Collection<LogRecord> getRecentLogRecords();
|
||||
|
||||
AndroidComponent getApplicationComponent();
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.logout.HideUiActivity;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.briar.api.android.LockManager;
|
||||
|
||||
@@ -48,6 +47,7 @@ import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING;
|
||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
|
||||
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_CHANNEL_ID;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_NOTIFICATION_ID;
|
||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_CHANNEL_ID;
|
||||
@@ -182,7 +182,7 @@ public class BriarService extends Service {
|
||||
NotificationManager nm = (NotificationManager) o;
|
||||
nm.notify(FAILURE_NOTIFICATION_ID, b.build());
|
||||
// Bring the dashboard to the front to clear the back stack
|
||||
i = new Intent(BriarService.this, NavDrawerActivity.class);
|
||||
i = new Intent(BriarService.this, ENTRY_ACTIVITY);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
|
||||
i.putExtra(EXTRA_STARTUP_FAILED, true);
|
||||
startActivity(i);
|
||||
|
||||
@@ -74,7 +74,7 @@ public class StartupFailureActivity extends BaseActivity implements
|
||||
|
||||
@Override
|
||||
public void runOnDbThread(@NonNull Runnable runnable) {
|
||||
throw new AssertionError("Deprecated and should not be used");
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.TextInputEditText;
|
||||
@@ -21,6 +21,7 @@ import static android.view.inputmethod.EditorInfo.IME_ACTION_NONE;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||
import static org.briarproject.briar.android.util.UiUtils.setError;
|
||||
import static org.briarproject.briar.android.util.UiUtils.showSoftKeyboard;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -63,6 +64,12 @@ public class AuthorNameFragment extends SetupFragment {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
showSoftKeyboard(authorNameInput);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getHelpText() {
|
||||
return getString(R.string.setup_name_explanation);
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
@@ -13,8 +13,8 @@ import android.widget.ProgressBar;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.account.PowerView.OnCheckedChangedListener;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.login.PowerView.OnCheckedChangedListener;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
@@ -0,0 +1,131 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.design.widget.TextInputEditText;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.login.StrengthMeter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static android.content.Context.INPUT_METHOD_SERVICE;
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
|
||||
import static org.briarproject.briar.android.util.UiUtils.setError;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class SetPasswordFragment extends SetupFragment {
|
||||
|
||||
private final static String TAG = SetPasswordFragment.class.getName();
|
||||
|
||||
private TextInputLayout passwordEntryWrapper;
|
||||
private TextInputLayout passwordConfirmationWrapper;
|
||||
private TextInputEditText passwordEntry;
|
||||
private TextInputEditText passwordConfirmation;
|
||||
private StrengthMeter strengthMeter;
|
||||
private Button nextButton;
|
||||
private ProgressBar progressBar;
|
||||
|
||||
public static SetPasswordFragment newInstance() {
|
||||
return new SetPasswordFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
requireNonNull(getActivity()).setTitle(getString(R.string.setup_password_intro));
|
||||
View v = inflater.inflate(R.layout.fragment_setup_password, container,
|
||||
false);
|
||||
|
||||
strengthMeter = v.findViewById(R.id.strength_meter);
|
||||
passwordEntryWrapper = v.findViewById(R.id.password_entry_wrapper);
|
||||
passwordEntry = v.findViewById(R.id.password_entry);
|
||||
passwordEntry.requestFocus();
|
||||
passwordConfirmationWrapper =
|
||||
v.findViewById(R.id.password_confirm_wrapper);
|
||||
passwordConfirmation = v.findViewById(R.id.password_confirm);
|
||||
nextButton = v.findViewById(R.id.next);
|
||||
progressBar = v.findViewById(R.id.progress);
|
||||
|
||||
passwordEntry.addTextChangedListener(this);
|
||||
passwordConfirmation.addTextChangedListener(this);
|
||||
nextButton.setOnClickListener(this);
|
||||
|
||||
if (!setupController.needToShowDozeFragment()) {
|
||||
nextButton.setText(R.string.create_account_button);
|
||||
passwordConfirmation.setImeOptions(IME_ACTION_DONE);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getHelpText() {
|
||||
return getString(R.string.setup_password_explanation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence authorName, int i, int i1, int i2) {
|
||||
String password1 = passwordEntry.getText().toString();
|
||||
String password2 = passwordConfirmation.getText().toString();
|
||||
boolean passwordsMatch = password1.equals(password2);
|
||||
|
||||
strengthMeter
|
||||
.setVisibility(password1.length() > 0 ? VISIBLE : INVISIBLE);
|
||||
float strength = setupController.estimatePasswordStrength(password1);
|
||||
strengthMeter.setStrength(strength);
|
||||
boolean strongEnough = strength >= QUITE_WEAK;
|
||||
|
||||
setError(passwordEntryWrapper, getString(R.string.password_too_weak),
|
||||
password1.length() > 0 && !strongEnough);
|
||||
setError(passwordConfirmationWrapper,
|
||||
getString(R.string.passwords_do_not_match),
|
||||
password2.length() > 0 && !passwordsMatch);
|
||||
|
||||
boolean enabled = passwordsMatch && strongEnough;
|
||||
nextButton.setEnabled(enabled);
|
||||
passwordConfirmation.setOnEditorActionListener(enabled ? this : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
IBinder token = passwordEntry.getWindowToken();
|
||||
Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
|
||||
((InputMethodManager) o).hideSoftInputFromWindow(token, 0);
|
||||
setupController.setPassword(passwordEntry.getText().toString());
|
||||
if (setupController.needToShowDozeFragment()) {
|
||||
setupController.showDozeFragment();
|
||||
} else {
|
||||
nextButton.setVisibility(INVISIBLE);
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
setupController.createAccount();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Intent;
|
||||
@@ -15,8 +15,11 @@ import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
|
||||
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -86,7 +89,7 @@ public class SetupActivity extends BaseActivity
|
||||
|
||||
void showPasswordFragment() {
|
||||
if (authorName == null) throw new IllegalStateException();
|
||||
showNextFragment(PasswordFragment.newInstance());
|
||||
showNextFragment(SetPasswordFragment.newInstance());
|
||||
}
|
||||
|
||||
@TargetApi(23)
|
||||
@@ -97,8 +100,9 @@ public class SetupActivity extends BaseActivity
|
||||
}
|
||||
|
||||
void showApp() {
|
||||
Intent i = new Intent(this, OpenDatabaseActivity.class);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME);
|
||||
Intent i = new Intent(this, ENTRY_ACTIVITY);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME |
|
||||
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(i);
|
||||
supportFinishAfterTransition();
|
||||
overridePendingTransition(R.anim.screen_new_in, R.anim.screen_old_out);
|
||||
@@ -1,9 +1,9 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface SetupController extends PasswordController {
|
||||
public interface SetupController {
|
||||
|
||||
void setSetupActivity(SetupActivity setupActivity);
|
||||
|
||||
@@ -11,6 +11,8 @@ public interface SetupController extends PasswordController {
|
||||
|
||||
void setAuthorName(String authorName);
|
||||
|
||||
float estimatePasswordStrength(String password);
|
||||
|
||||
void setPassword(String password);
|
||||
|
||||
/**
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
@@ -15,12 +15,15 @@ import java.util.logging.Logger;
|
||||
import javax.inject.Inject;
|
||||
|
||||
@NotNullByDefault
|
||||
public class SetupControllerImpl extends PasswordControllerImpl
|
||||
implements SetupController {
|
||||
public class SetupControllerImpl implements SetupController {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(SetupControllerImpl.class.getName());
|
||||
|
||||
private final AccountManager accountManager;
|
||||
private final PasswordStrengthEstimator strengthEstimator;
|
||||
@IoExecutor
|
||||
private final Executor ioExecutor;
|
||||
@Nullable
|
||||
private volatile SetupActivity setupActivity;
|
||||
|
||||
@@ -28,7 +31,9 @@ public class SetupControllerImpl extends PasswordControllerImpl
|
||||
SetupControllerImpl(AccountManager accountManager,
|
||||
@IoExecutor Executor ioExecutor,
|
||||
PasswordStrengthEstimator strengthEstimator) {
|
||||
super(accountManager, ioExecutor, strengthEstimator);
|
||||
this.accountManager = accountManager;
|
||||
this.strengthEstimator = strengthEstimator;
|
||||
this.ioExecutor = ioExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,6 +56,11 @@ public class SetupControllerImpl extends PasswordControllerImpl
|
||||
setupActivity.setAuthorName(authorName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float estimatePasswordStrength(String password) {
|
||||
return strengthEstimator.estimateStrength(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPassword(String password) {
|
||||
SetupActivity setupActivity = this.setupActivity;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.Editable;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Intent;
|
||||
@@ -4,6 +4,11 @@ import android.app.Activity;
|
||||
|
||||
import org.briarproject.briar.android.AndroidComponent;
|
||||
import org.briarproject.briar.android.StartupFailureActivity;
|
||||
import org.briarproject.briar.android.account.AuthorNameFragment;
|
||||
import org.briarproject.briar.android.account.DozeFragment;
|
||||
import org.briarproject.briar.android.account.SetPasswordFragment;
|
||||
import org.briarproject.briar.android.account.SetupActivity;
|
||||
import org.briarproject.briar.android.account.UnlockActivity;
|
||||
import org.briarproject.briar.android.blog.BlogActivity;
|
||||
import org.briarproject.briar.android.blog.BlogFragment;
|
||||
import org.briarproject.briar.android.blog.BlogModule;
|
||||
@@ -37,14 +42,10 @@ import org.briarproject.briar.android.keyagreement.ContactExchangeActivity;
|
||||
import org.briarproject.briar.android.keyagreement.ContactExchangeErrorFragment;
|
||||
import org.briarproject.briar.android.keyagreement.KeyAgreementActivity;
|
||||
import org.briarproject.briar.android.keyagreement.KeyAgreementFragment;
|
||||
import org.briarproject.briar.android.login.AuthorNameFragment;
|
||||
import org.briarproject.briar.android.login.ChangePasswordActivity;
|
||||
import org.briarproject.briar.android.login.DozeFragment;
|
||||
import org.briarproject.briar.android.login.OpenDatabaseActivity;
|
||||
import org.briarproject.briar.android.login.PasswordActivity;
|
||||
import org.briarproject.briar.android.login.OpenDatabaseFragment;
|
||||
import org.briarproject.briar.android.login.PasswordFragment;
|
||||
import org.briarproject.briar.android.login.SetupActivity;
|
||||
import org.briarproject.briar.android.login.UnlockActivity;
|
||||
import org.briarproject.briar.android.login.StartupActivity;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.android.panic.PanicPreferencesActivity;
|
||||
import org.briarproject.briar.android.panic.PanicResponderActivity;
|
||||
@@ -94,14 +95,12 @@ public interface ActivityComponent {
|
||||
|
||||
void inject(SplashScreenActivity activity);
|
||||
|
||||
void inject(StartupActivity activity);
|
||||
|
||||
void inject(SetupActivity activity);
|
||||
|
||||
void inject(OpenDatabaseActivity activity);
|
||||
|
||||
void inject(NavDrawerActivity activity);
|
||||
|
||||
void inject(PasswordActivity activity);
|
||||
|
||||
void inject(PanicResponderActivity activity);
|
||||
|
||||
void inject(PanicPreferencesActivity activity);
|
||||
@@ -177,12 +176,17 @@ public interface ActivityComponent {
|
||||
void inject(PendingContactListActivity activity);
|
||||
|
||||
// Fragments
|
||||
|
||||
void inject(AuthorNameFragment fragment);
|
||||
|
||||
void inject(PasswordFragment fragment);
|
||||
void inject(SetPasswordFragment fragment);
|
||||
|
||||
void inject(DozeFragment fragment);
|
||||
|
||||
void inject(PasswordFragment imageFragment);
|
||||
|
||||
void inject(OpenDatabaseFragment activity);
|
||||
|
||||
void inject(ContactListFragment fragment);
|
||||
|
||||
void inject(CreateGroupFragment fragment);
|
||||
|
||||
@@ -6,10 +6,10 @@ import org.briarproject.briar.android.controller.BriarController;
|
||||
import org.briarproject.briar.android.controller.BriarControllerImpl;
|
||||
import org.briarproject.briar.android.controller.DbController;
|
||||
import org.briarproject.briar.android.controller.DbControllerImpl;
|
||||
import org.briarproject.briar.android.login.PasswordController;
|
||||
import org.briarproject.briar.android.login.PasswordControllerImpl;
|
||||
import org.briarproject.briar.android.login.SetupController;
|
||||
import org.briarproject.briar.android.login.SetupControllerImpl;
|
||||
import org.briarproject.briar.android.login.ChangePasswordController;
|
||||
import org.briarproject.briar.android.login.ChangePasswordControllerImpl;
|
||||
import org.briarproject.briar.android.account.SetupController;
|
||||
import org.briarproject.briar.android.account.SetupControllerImpl;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerController;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerControllerImpl;
|
||||
|
||||
@@ -48,8 +48,8 @@ public class ActivityModule {
|
||||
|
||||
@ActivityScope
|
||||
@Provides
|
||||
PasswordController providePasswordController(
|
||||
PasswordControllerImpl passwordController) {
|
||||
ChangePasswordController providePasswordController(
|
||||
ChangePasswordControllerImpl passwordController) {
|
||||
return passwordController;
|
||||
}
|
||||
|
||||
|
||||
@@ -172,6 +172,12 @@ public abstract class BaseActivity extends AppCompatActivity
|
||||
.commit();
|
||||
}
|
||||
|
||||
protected boolean isFragmentAdded(String fragmentTag) {
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
Fragment f = fm.findFragmentByTag(fragmentTag);
|
||||
return f != null && f.isAdded();
|
||||
}
|
||||
|
||||
private boolean showScreenFilterWarning() {
|
||||
// If the dialog is already visible, filter the tap
|
||||
ScreenFilterDialogFragment f = findDialogFragment();
|
||||
|
||||
@@ -15,8 +15,8 @@ import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.controller.BriarController;
|
||||
import org.briarproject.briar.android.controller.DbController;
|
||||
import org.briarproject.briar.android.controller.handler.UiResultHandler;
|
||||
import org.briarproject.briar.android.login.PasswordActivity;
|
||||
import org.briarproject.briar.android.login.UnlockActivity;
|
||||
import org.briarproject.briar.android.login.StartupActivity;
|
||||
import org.briarproject.briar.android.account.UnlockActivity;
|
||||
import org.briarproject.briar.android.logout.ExitActivity;
|
||||
import org.briarproject.briar.api.android.LockManager;
|
||||
|
||||
@@ -86,8 +86,8 @@ public abstract class BriarActivity extends BaseActivity {
|
||||
if (!briarController.accountSignedIn() && !isFinishing()) {
|
||||
// Also check that the activity isn't finishing already.
|
||||
// This is possible if we finished in onActivityResult().
|
||||
// Launching another PasswordActivity would cause a loop.
|
||||
Intent i = new Intent(this, PasswordActivity.class);
|
||||
// Launching another StartupActivity would cause a loop.
|
||||
Intent i = new Intent(this, StartupActivity.class);
|
||||
startActivityForResult(i, REQUEST_PASSWORD);
|
||||
} else if (lockManager.isLocked() && !isFinishing()) {
|
||||
// Also check that the activity isn't finishing already.
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.support.annotation.CallSuper;
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.settings.Settings;
|
||||
import org.briarproject.bramble.api.settings.SettingsManager;
|
||||
import org.briarproject.briar.android.BriarService;
|
||||
@@ -21,6 +22,7 @@ import java.util.logging.Logger;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
@@ -34,6 +36,7 @@ public class BriarControllerImpl implements BriarController {
|
||||
|
||||
private final BriarServiceConnection serviceConnection;
|
||||
private final AccountManager accountManager;
|
||||
private final LifecycleManager lifecycleManager;
|
||||
private final Executor databaseExecutor;
|
||||
private final SettingsManager settingsManager;
|
||||
private final DozeWatchdog dozeWatchdog;
|
||||
@@ -44,11 +47,13 @@ public class BriarControllerImpl implements BriarController {
|
||||
@Inject
|
||||
BriarControllerImpl(BriarServiceConnection serviceConnection,
|
||||
AccountManager accountManager,
|
||||
LifecycleManager lifecycleManager,
|
||||
@DatabaseExecutor Executor databaseExecutor,
|
||||
SettingsManager settingsManager, DozeWatchdog dozeWatchdog,
|
||||
Activity activity) {
|
||||
this.serviceConnection = serviceConnection;
|
||||
this.accountManager = accountManager;
|
||||
this.lifecycleManager = lifecycleManager;
|
||||
this.databaseExecutor = databaseExecutor;
|
||||
this.settingsManager = settingsManager;
|
||||
this.dozeWatchdog = dozeWatchdog;
|
||||
@@ -84,7 +89,8 @@ public class BriarControllerImpl implements BriarController {
|
||||
|
||||
@Override
|
||||
public boolean accountSignedIn() {
|
||||
return accountManager.hasDatabaseKey();
|
||||
return accountManager.hasDatabaseKey() &&
|
||||
lifecycleManager.getLifecycleState().isAfter(STARTING_SERVICES);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -31,7 +31,7 @@ public class ChangePasswordActivity extends BriarActivity
|
||||
implements OnClickListener, OnEditorActionListener {
|
||||
|
||||
@Inject
|
||||
protected PasswordController passwordController;
|
||||
protected ChangePasswordController passwordController;
|
||||
|
||||
private TextInputLayout currentPasswordEntryWrapper;
|
||||
private TextInputLayout newPasswordEntryWrapper;
|
||||
|
||||
@@ -4,13 +4,10 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.android.controller.handler.ResultHandler;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface PasswordController {
|
||||
public interface ChangePasswordController {
|
||||
|
||||
float estimatePasswordStrength(String password);
|
||||
|
||||
void validatePassword(String password,
|
||||
ResultHandler<Boolean> resultHandler);
|
||||
|
||||
void changePassword(String oldPassword, String newPassword,
|
||||
ResultHandler<Boolean> resultHandler);
|
||||
|
||||
@@ -11,14 +11,14 @@ import java.util.concurrent.Executor;
|
||||
import javax.inject.Inject;
|
||||
|
||||
@NotNullByDefault
|
||||
public class PasswordControllerImpl implements PasswordController {
|
||||
public class ChangePasswordControllerImpl implements ChangePasswordController {
|
||||
|
||||
protected final AccountManager accountManager;
|
||||
protected final Executor ioExecutor;
|
||||
private final PasswordStrengthEstimator strengthEstimator;
|
||||
|
||||
@Inject
|
||||
PasswordControllerImpl(AccountManager accountManager,
|
||||
ChangePasswordControllerImpl(AccountManager accountManager,
|
||||
@IoExecutor Executor ioExecutor,
|
||||
PasswordStrengthEstimator strengthEstimator) {
|
||||
this.accountManager = accountManager;
|
||||
@@ -31,13 +31,6 @@ public class PasswordControllerImpl implements PasswordController {
|
||||
return strengthEstimator.estimateStrength(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validatePassword(String password,
|
||||
ResultHandler<Boolean> resultHandler) {
|
||||
ioExecutor.execute(() ->
|
||||
resultHandler.onResult(accountManager.signIn(password)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changePassword(String oldPassword, String newPassword,
|
||||
ResultHandler<Boolean> resultHandler) {
|
||||
@@ -1,101 +0,0 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState;
|
||||
import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BriarActivity;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE;
|
||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES;
|
||||
|
||||
@ParametersNotNullByDefault
|
||||
public class OpenDatabaseActivity extends BriarActivity
|
||||
implements EventListener {
|
||||
|
||||
@Inject
|
||||
LifecycleManager lifecycleManager;
|
||||
@Inject
|
||||
EventBus eventBus;
|
||||
|
||||
private TextView textView;
|
||||
private ImageView imageView;
|
||||
private boolean showingMigration = false, showingCompaction = false;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle state) {
|
||||
super.onCreate(state);
|
||||
setContentView(R.layout.activity_open_database);
|
||||
textView = findViewById(R.id.textView);
|
||||
imageView = findViewById(R.id.imageView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
LifecycleState state = lifecycleManager.getLifecycleState();
|
||||
if (state.isAfter(STARTING_SERVICES)) {
|
||||
finishAndStartApp();
|
||||
} else {
|
||||
if (state == MIGRATING_DATABASE) showMigration();
|
||||
else if (state == COMPACTING_DATABASE) showCompaction();
|
||||
eventBus.addListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
eventBus.removeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventOccurred(Event e) {
|
||||
if (e instanceof LifecycleEvent) {
|
||||
LifecycleState state = ((LifecycleEvent) e).getLifecycleState();
|
||||
if (state.isAfter(STARTING_SERVICES)) finishAndStartApp();
|
||||
else if (state == MIGRATING_DATABASE) showMigration();
|
||||
else if (state == COMPACTING_DATABASE) showCompaction();
|
||||
}
|
||||
}
|
||||
|
||||
private void showMigration() {
|
||||
if (showingMigration) return;
|
||||
textView.setText(R.string.startup_migrate_database);
|
||||
imageView.setImageResource(R.drawable.startup_migration);
|
||||
showingMigration = true;
|
||||
}
|
||||
|
||||
private void showCompaction() {
|
||||
if (showingCompaction) return;
|
||||
textView.setText(R.string.startup_compact_database);
|
||||
imageView.setImageResource(R.drawable.startup_migration);
|
||||
showingCompaction = true;
|
||||
}
|
||||
|
||||
private void finishAndStartApp() {
|
||||
startActivity(new Intent(this, NavDrawerActivity.class));
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.arch.lifecycle.ViewModelProvider;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.COMPACTING;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.MIGRATING;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class OpenDatabaseFragment extends BaseFragment {
|
||||
|
||||
final static String TAG = OpenDatabaseFragment.class.getName();
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
|
||||
private TextView textView;
|
||||
private ImageView imageView;
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_open_database, container,
|
||||
false);
|
||||
textView = v.findViewById(R.id.textView);
|
||||
imageView = v.findViewById(R.id.imageView);
|
||||
|
||||
StartupViewModel viewModel = ViewModelProviders.of(requireActivity(),
|
||||
viewModelFactory).get(StartupViewModel.class);
|
||||
viewModel.getState().observe(this, this::onStateChanged);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
private void onStateChanged(State state) {
|
||||
if (state == MIGRATING) showMigration();
|
||||
else if (state == COMPACTING) showCompaction();
|
||||
}
|
||||
|
||||
private void showMigration() {
|
||||
textView.setText(R.string.startup_migrate_database);
|
||||
imageView.setImageResource(R.drawable.startup_migration);
|
||||
}
|
||||
|
||||
private void showCompaction() {
|
||||
textView.setText(R.string.startup_compact_database);
|
||||
imageView.setImageResource(R.drawable.startup_migration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BaseActivity;
|
||||
import org.briarproject.briar.android.controller.BriarController;
|
||||
import org.briarproject.briar.android.controller.handler.UiResultHandler;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
|
||||
import static org.briarproject.briar.android.util.UiUtils.enterPressed;
|
||||
|
||||
public class PasswordActivity extends BaseActivity {
|
||||
|
||||
@Inject
|
||||
AccountManager accountManager;
|
||||
|
||||
@Inject
|
||||
AndroidNotificationManager notificationManager;
|
||||
|
||||
@Inject
|
||||
PasswordController passwordController;
|
||||
|
||||
@Inject
|
||||
BriarController briarController;
|
||||
|
||||
private Button signInButton;
|
||||
private ProgressBar progress;
|
||||
private TextInputLayout input;
|
||||
private EditText password;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
super.onCreate(state);
|
||||
// fade-in after splash screen instead of default animation
|
||||
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
|
||||
|
||||
if (!accountManager.accountExists()) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_password);
|
||||
signInButton = findViewById(R.id.btn_sign_in);
|
||||
progress = findViewById(R.id.progress_wheel);
|
||||
input = findViewById(R.id.password_layout);
|
||||
password = findViewById(R.id.edit_password);
|
||||
password.setOnEditorActionListener((v, actionId, event) -> {
|
||||
if (actionId == IME_ACTION_DONE || enterPressed(actionId, event)) {
|
||||
validatePassword();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
password.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) {
|
||||
if (count > 0) UiUtils.setError(input, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
// If the user has already signed in, clean up this instance
|
||||
if (briarController.accountSignedIn()) {
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
} else {
|
||||
notificationManager.blockSignInNotification();
|
||||
notificationManager.clearSignInNotification();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// Move task and activity to the background instead of showing another
|
||||
// password prompt. onActivityResult() won't be called in BriarActivity
|
||||
moveTaskToBack(true);
|
||||
}
|
||||
|
||||
private void deleteAccount() {
|
||||
accountManager.deleteAccount();
|
||||
startActivity(new Intent(this, SetupActivity.class));
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
}
|
||||
|
||||
public void onSignInClick(View v) {
|
||||
validatePassword();
|
||||
}
|
||||
|
||||
public void onForgottenPasswordClick(View v) {
|
||||
// TODO Encapsulate the dialog in a re-usable fragment
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this,
|
||||
R.style.BriarDialogTheme);
|
||||
builder.setTitle(R.string.dialog_title_lost_password);
|
||||
builder.setMessage(R.string.dialog_message_lost_password);
|
||||
builder.setPositiveButton(R.string.cancel, null);
|
||||
builder.setNegativeButton(R.string.delete,
|
||||
(dialog, which) -> deleteAccount());
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
private void validatePassword() {
|
||||
hideSoftKeyboard(password);
|
||||
signInButton.setVisibility(INVISIBLE);
|
||||
progress.setVisibility(VISIBLE);
|
||||
passwordController.validatePassword(password.getText().toString(),
|
||||
new UiResultHandler<Boolean>(this) {
|
||||
@Override
|
||||
public void onResultUi(@NonNull Boolean result) {
|
||||
if (result) {
|
||||
setResult(RESULT_OK);
|
||||
supportFinishAfterTransition();
|
||||
// don't show closing animation,
|
||||
// but one for opening NavDrawerActivity
|
||||
overridePendingTransition(R.anim.screen_new_in,
|
||||
R.anim.screen_old_out);
|
||||
} else {
|
||||
tryAgain();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void tryAgain() {
|
||||
UiUtils.setError(input, getString(R.string.try_again), true);
|
||||
signInButton.setVisibility(VISIBLE);
|
||||
progress.setVisibility(INVISIBLE);
|
||||
password.setText("");
|
||||
|
||||
// show the keyboard again
|
||||
showSoftKeyboard(password);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.arch.lifecycle.ViewModelProvider;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.design.widget.TextInputEditText;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
@@ -15,34 +18,33 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.content.Context.INPUT_METHOD_SERVICE;
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
|
||||
import static org.briarproject.briar.android.util.UiUtils.enterPressed;
|
||||
import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard;
|
||||
import static org.briarproject.briar.android.util.UiUtils.setError;
|
||||
import static org.briarproject.briar.android.util.UiUtils.showSoftKeyboard;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class PasswordFragment extends SetupFragment {
|
||||
public class PasswordFragment extends BaseFragment implements TextWatcher {
|
||||
|
||||
private final static String TAG = PasswordFragment.class.getName();
|
||||
final static String TAG = PasswordFragment.class.getName();
|
||||
|
||||
private TextInputLayout passwordEntryWrapper;
|
||||
private TextInputLayout passwordConfirmationWrapper;
|
||||
private TextInputEditText passwordEntry;
|
||||
private TextInputEditText passwordConfirmation;
|
||||
private StrengthMeter strengthMeter;
|
||||
private Button nextButton;
|
||||
private ProgressBar progressBar;
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
|
||||
public static PasswordFragment newInstance() {
|
||||
return new PasswordFragment();
|
||||
}
|
||||
private StartupViewModel viewModel;
|
||||
private Button signInButton;
|
||||
private ProgressBar progress;
|
||||
private TextInputLayout input;
|
||||
private TextInputEditText password;
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
@@ -53,78 +55,88 @@ public class PasswordFragment extends SetupFragment {
|
||||
public View onCreateView(LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
requireNonNull(getActivity()).setTitle(getString(R.string.setup_password_intro));
|
||||
View v = inflater.inflate(R.layout.fragment_setup_password, container,
|
||||
View v = inflater.inflate(R.layout.fragment_password, container,
|
||||
false);
|
||||
|
||||
strengthMeter = v.findViewById(R.id.strength_meter);
|
||||
passwordEntryWrapper = v.findViewById(R.id.password_entry_wrapper);
|
||||
passwordEntry = v.findViewById(R.id.password_entry);
|
||||
passwordConfirmationWrapper =
|
||||
v.findViewById(R.id.password_confirm_wrapper);
|
||||
passwordConfirmation = v.findViewById(R.id.password_confirm);
|
||||
nextButton = v.findViewById(R.id.next);
|
||||
progressBar = v.findViewById(R.id.progress);
|
||||
viewModel = ViewModelProviders.of(requireActivity(), viewModelFactory)
|
||||
.get(StartupViewModel.class);
|
||||
viewModel.getPasswordValidated().observeEvent(this, valid -> {
|
||||
if (!valid) onPasswordInvalid();
|
||||
});
|
||||
|
||||
passwordEntry.addTextChangedListener(this);
|
||||
passwordConfirmation.addTextChangedListener(this);
|
||||
nextButton.setOnClickListener(this);
|
||||
|
||||
if (!setupController.needToShowDozeFragment()) {
|
||||
nextButton.setText(R.string.create_account_button);
|
||||
passwordConfirmation.setImeOptions(IME_ACTION_DONE);
|
||||
}
|
||||
signInButton = v.findViewById(R.id.btn_sign_in);
|
||||
signInButton.setOnClickListener(view -> onSignInButtonClicked());
|
||||
progress = v.findViewById(R.id.progress_wheel);
|
||||
input = v.findViewById(R.id.password_layout);
|
||||
password = v.findViewById(R.id.edit_password);
|
||||
password.setOnEditorActionListener((view, actionId, event) -> {
|
||||
if (actionId == IME_ACTION_DONE || enterPressed(actionId, event)) {
|
||||
onSignInButtonClicked();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
password.addTextChangedListener(this);
|
||||
v.findViewById(R.id.btn_forgotten)
|
||||
.setOnClickListener(view -> onForgottenPasswordClick());
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
showSoftKeyboard(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count,
|
||||
int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before,
|
||||
int count) {
|
||||
if (count > 0) setError(input, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
|
||||
private void onSignInButtonClicked() {
|
||||
hideSoftKeyboard(password);
|
||||
signInButton.setVisibility(INVISIBLE);
|
||||
progress.setVisibility(VISIBLE);
|
||||
viewModel.validatePassword(password.getText().toString());
|
||||
}
|
||||
|
||||
private void onPasswordInvalid() {
|
||||
setError(input, getString(R.string.try_again), true);
|
||||
signInButton.setVisibility(VISIBLE);
|
||||
progress.setVisibility(INVISIBLE);
|
||||
password.setText(null);
|
||||
|
||||
// show the keyboard again
|
||||
showSoftKeyboard(password);
|
||||
}
|
||||
|
||||
public void onForgottenPasswordClick() {
|
||||
// TODO Encapsulate the dialog in a re-usable fragment
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
|
||||
R.style.BriarDialogTheme);
|
||||
builder.setTitle(R.string.dialog_title_lost_password);
|
||||
builder.setMessage(R.string.dialog_message_lost_password);
|
||||
builder.setPositiveButton(R.string.cancel, null);
|
||||
builder.setNegativeButton(R.string.delete,
|
||||
(dialog, which) -> viewModel.deleteAccount());
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getHelpText() {
|
||||
return getString(R.string.setup_password_explanation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence authorName, int i, int i1, int i2) {
|
||||
String password1 = passwordEntry.getText().toString();
|
||||
String password2 = passwordConfirmation.getText().toString();
|
||||
boolean passwordsMatch = password1.equals(password2);
|
||||
|
||||
strengthMeter
|
||||
.setVisibility(password1.length() > 0 ? VISIBLE : INVISIBLE);
|
||||
float strength = setupController.estimatePasswordStrength(password1);
|
||||
strengthMeter.setStrength(strength);
|
||||
boolean strongEnough = strength >= QUITE_WEAK;
|
||||
|
||||
UiUtils.setError(passwordEntryWrapper,
|
||||
getString(R.string.password_too_weak),
|
||||
password1.length() > 0 && !strongEnough);
|
||||
UiUtils.setError(passwordConfirmationWrapper,
|
||||
getString(R.string.passwords_do_not_match),
|
||||
password2.length() > 0 && !passwordsMatch);
|
||||
|
||||
boolean enabled = passwordsMatch && strongEnough;
|
||||
nextButton.setEnabled(enabled);
|
||||
passwordConfirmation.setOnEditorActionListener(enabled ? this : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
IBinder token = passwordEntry.getWindowToken();
|
||||
Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
|
||||
((InputMethodManager) o).hideSoftInputFromWindow(token, 0);
|
||||
setupController.setPassword(passwordEntry.getText().toString());
|
||||
if (setupController.needToShowDozeFragment()) {
|
||||
setupController.showDozeFragment();
|
||||
} else {
|
||||
nextButton.setVisibility(INVISIBLE);
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
setupController.createAccount();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.arch.lifecycle.ViewModelProvider;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.BriarService;
|
||||
import org.briarproject.briar.android.account.SetupActivity;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BaseActivity;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
|
||||
import org.briarproject.briar.android.login.StartupViewModel.State;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.SIGNED_IN;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.SIGNED_OUT;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.STARTED;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.STARTING;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class StartupActivity extends BaseActivity implements
|
||||
BaseFragmentListener {
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
|
||||
private StartupViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle state) {
|
||||
super.onCreate(state);
|
||||
// fade-in after splash screen instead of default animation
|
||||
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
|
||||
|
||||
setContentView(R.layout.activity_fragment_container);
|
||||
|
||||
viewModel = ViewModelProviders.of(this, viewModelFactory)
|
||||
.get(StartupViewModel.class);
|
||||
if (!viewModel.accountExists()) {
|
||||
// TODO ideally we would not have to delete the account again
|
||||
// The account needs to deleted again to remove the database folder,
|
||||
// because if it exists, we assume the database also exists
|
||||
// and when clearing app data, the folder does not get deleted.
|
||||
viewModel.deleteAccount();
|
||||
onAccountDeleted();
|
||||
return;
|
||||
}
|
||||
viewModel.getAccountDeleted().observeEvent(this, deleted -> {
|
||||
if (deleted) onAccountDeleted();
|
||||
});
|
||||
viewModel.getState().observe(this, this::onStateChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
viewModel.clearSignInNotification();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// Move task and activity to the background instead of showing another
|
||||
// password prompt.
|
||||
// onActivityResult() won't be called in BriarActivity
|
||||
moveTaskToBack(true);
|
||||
}
|
||||
|
||||
private void onStateChanged(State state) {
|
||||
if (state == SIGNED_OUT) {
|
||||
// Configuration changes such as screen rotation
|
||||
// can cause this to get called again.
|
||||
// Don't replace the fragment in that case to not lose view state.
|
||||
if (!isFragmentAdded(PasswordFragment.TAG)) {
|
||||
showInitialFragment(new PasswordFragment());
|
||||
}
|
||||
} else if (state == SIGNED_IN) {
|
||||
startService(new Intent(this, BriarService.class));
|
||||
} else if (state == STARTING) {
|
||||
// Only show OpenDatabaseFragment if not already visible.
|
||||
// This can happen because several LifecycleManager states are
|
||||
// mapped to STARTING, so this can get called several times
|
||||
// as the app's lifecycle advances.
|
||||
if (!isFragmentAdded(OpenDatabaseFragment.TAG)) {
|
||||
showNextFragment(new OpenDatabaseFragment());
|
||||
}
|
||||
} else if (state == STARTED) {
|
||||
setResult(RESULT_OK);
|
||||
supportFinishAfterTransition();
|
||||
overridePendingTransition(R.anim.screen_new_in,
|
||||
R.anim.screen_old_out);
|
||||
}
|
||||
}
|
||||
|
||||
private void onAccountDeleted() {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
Intent i = new Intent(this, SetupActivity.class);
|
||||
i.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP |
|
||||
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_TASK_ON_HOME);
|
||||
startActivity(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runOnDbThread(Runnable runnable) {
|
||||
// we don't need this and shouldn't be forced to implement it
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.app.Application;
|
||||
import android.arch.lifecycle.AndroidViewModel;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.arch.lifecycle.MutableLiveData;
|
||||
import android.support.annotation.UiThread;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState;
|
||||
import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.android.viewmodel.LiveEvent;
|
||||
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE;
|
||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.COMPACTING;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.MIGRATING;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.SIGNED_IN;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.SIGNED_OUT;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.STARTED;
|
||||
import static org.briarproject.briar.android.login.StartupViewModel.State.STARTING;
|
||||
|
||||
@NotNullByDefault
|
||||
public class StartupViewModel extends AndroidViewModel
|
||||
implements EventListener {
|
||||
|
||||
enum State {SIGNED_OUT, SIGNED_IN, STARTING, MIGRATING, COMPACTING, STARTED}
|
||||
|
||||
private final AccountManager accountManager;
|
||||
private final AndroidNotificationManager notificationManager;
|
||||
private final EventBus eventBus;
|
||||
@IoExecutor
|
||||
private final Executor ioExecutor;
|
||||
|
||||
private final MutableLiveEvent<Boolean> passwordValidated =
|
||||
new MutableLiveEvent<>();
|
||||
private final MutableLiveEvent<Boolean> accountDeleted =
|
||||
new MutableLiveEvent<>();
|
||||
private final MutableLiveData<State> state = new MutableLiveData<>();
|
||||
|
||||
@Inject
|
||||
StartupViewModel(Application app,
|
||||
AccountManager accountManager,
|
||||
LifecycleManager lifecycleManager,
|
||||
AndroidNotificationManager notificationManager,
|
||||
EventBus eventBus,
|
||||
@IoExecutor Executor ioExecutor) {
|
||||
super(app);
|
||||
this.accountManager = accountManager;
|
||||
this.notificationManager = notificationManager;
|
||||
this.eventBus = eventBus;
|
||||
this.ioExecutor = ioExecutor;
|
||||
|
||||
updateState(lifecycleManager.getLifecycleState());
|
||||
eventBus.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCleared() {
|
||||
eventBus.removeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventOccurred(Event e) {
|
||||
if (e instanceof LifecycleEvent) {
|
||||
LifecycleState s = ((LifecycleEvent) e).getLifecycleState();
|
||||
updateState(s);
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void updateState(LifecycleState s) {
|
||||
if (accountManager.hasDatabaseKey()) {
|
||||
if (s.isAfter(STARTING_SERVICES)) state.setValue(STARTED);
|
||||
else if (s == MIGRATING_DATABASE) state.setValue(MIGRATING);
|
||||
else if (s == COMPACTING_DATABASE) state.setValue(COMPACTING);
|
||||
else state.setValue(STARTING);
|
||||
} else {
|
||||
state.setValue(SIGNED_OUT);
|
||||
}
|
||||
}
|
||||
|
||||
boolean accountExists() {
|
||||
return accountManager.accountExists();
|
||||
}
|
||||
|
||||
void clearSignInNotification() {
|
||||
notificationManager.blockSignInNotification();
|
||||
notificationManager.clearSignInNotification();
|
||||
}
|
||||
|
||||
void validatePassword(String password) {
|
||||
ioExecutor.execute(() -> {
|
||||
boolean signedIn = accountManager.signIn(password);
|
||||
passwordValidated.postEvent(signedIn);
|
||||
if (signedIn) state.postValue(SIGNED_IN);
|
||||
});
|
||||
}
|
||||
|
||||
LiveEvent<Boolean> getPasswordValidated() {
|
||||
return passwordValidated;
|
||||
}
|
||||
|
||||
LiveEvent<Boolean> getAccountDeleted() {
|
||||
return accountDeleted;
|
||||
}
|
||||
|
||||
LiveData<State> getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
void deleteAccount() {
|
||||
accountManager.deleteAccount();
|
||||
accountDeleted.setEvent(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,7 +40,6 @@ import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.Localizer;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -53,6 +52,7 @@ import javax.inject.Inject;
|
||||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.media.RingtoneManager.ACTION_RINGTONE_PICKER;
|
||||
import static android.media.RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI;
|
||||
@@ -80,6 +80,7 @@ import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.bramble.util.LogUtils.now;
|
||||
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
||||
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_RINGTONE;
|
||||
import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_SIGN_OUT;
|
||||
import static org.briarproject.briar.android.util.UiUtils.hasScreenLock;
|
||||
@@ -192,7 +193,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
// bring up parent activity, so it can change its theme as well
|
||||
// upstream bug: https://issuetracker.google.com/issues/38352704
|
||||
Intent intent =
|
||||
new Intent(getActivity(), NavDrawerActivity.class);
|
||||
new Intent(getActivity(), ENTRY_ACTIVITY);
|
||||
intent.setFlags(
|
||||
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
@@ -575,9 +576,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
builder.setPositiveButton(R.string.sign_out_button,
|
||||
(dialogInterface, i) -> {
|
||||
language.setValue(newValue);
|
||||
Intent intent = new Intent(getContext(),
|
||||
NavDrawerActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Intent intent = new Intent(getContext(), ENTRY_ACTIVITY);
|
||||
intent.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
||||
intent.putExtra(INTENT_SIGN_OUT, true);
|
||||
requireActivity().startActivity(intent);
|
||||
requireActivity().finish();
|
||||
|
||||
@@ -2,10 +2,8 @@ package org.briarproject.briar.android.splash;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
import android.transition.Fade;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
@@ -15,10 +13,6 @@ import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BaseActivity;
|
||||
import org.briarproject.briar.android.login.OpenDatabaseActivity;
|
||||
import org.briarproject.briar.android.login.SetupActivity;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.api.android.LockManager;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -27,27 +21,35 @@ import javax.inject.Inject;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.support.v7.preference.PreferenceManager.setDefaultValues;
|
||||
import static java.lang.System.currentTimeMillis;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE;
|
||||
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class SplashScreenActivity extends BaseActivity {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(SplashScreenActivity.class.getName());
|
||||
getLogger(SplashScreenActivity.class.getName());
|
||||
|
||||
@Inject
|
||||
protected AccountManager accountManager;
|
||||
@Inject
|
||||
protected LockManager lockManager;
|
||||
@Inject
|
||||
protected AndroidExecutor androidExecutor;
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle state) {
|
||||
super.onCreate(state);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
if (SDK_INT >= 21) {
|
||||
getWindow().setExitTransition(new Fade());
|
||||
}
|
||||
|
||||
@@ -56,44 +58,21 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
setContentView(R.layout.splash);
|
||||
|
||||
if (accountManager.hasDatabaseKey()) {
|
||||
if (lockManager.isLocked()) {
|
||||
// The database needs to be opened for the app to be locked.
|
||||
// Start main activity right away. It will open UnlockActivity.
|
||||
// Otherwise, we would end up with two screen unlock inputs.
|
||||
startNextActivity(NavDrawerActivity.class);
|
||||
} else {
|
||||
startNextActivity(OpenDatabaseActivity.class);
|
||||
}
|
||||
startNextActivity(ENTRY_ACTIVITY);
|
||||
finish();
|
||||
} else {
|
||||
new Handler().postDelayed(() -> {
|
||||
startNextActivity();
|
||||
if (currentTimeMillis() >= EXPIRY_DATE) {
|
||||
LOG.info("Expired");
|
||||
startNextActivity(ExpiredActivity.class);
|
||||
} else {
|
||||
startNextActivity(ENTRY_ACTIVITY);
|
||||
}
|
||||
supportFinishAfterTransition();
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
private void startNextActivity() {
|
||||
if (System.currentTimeMillis() >= EXPIRY_DATE) {
|
||||
LOG.info("Expired");
|
||||
startNextActivity(ExpiredActivity.class);
|
||||
} else {
|
||||
if (accountManager.accountExists()) {
|
||||
LOG.info("Account exists");
|
||||
startNextActivity(OpenDatabaseActivity.class);
|
||||
} else {
|
||||
LOG.info("Account does not exist");
|
||||
accountManager.deleteAccount();
|
||||
startNextActivity(SetupActivity.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startNextActivity(Class<? extends Activity> activityClass) {
|
||||
Intent i = new Intent(this, activityClass);
|
||||
i.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
|
||||
@@ -101,8 +80,8 @@ public class SplashScreenActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
private void setPreferencesDefaults() {
|
||||
androidExecutor.runOnBackgroundThread(() ->
|
||||
PreferenceManager.setDefaultValues(SplashScreenActivity.this,
|
||||
androidExecutor.runOnBackgroundThread(
|
||||
() -> setDefaultValues(SplashScreenActivity.this,
|
||||
R.xml.panic_preferences, false));
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,12 @@ import android.widget.TextView;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.activity.BriarActivity;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.api.test.TestDataCreator;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
|
||||
|
||||
public class TestDataActivity extends BriarActivity {
|
||||
|
||||
@@ -154,7 +154,7 @@ public class TestDataActivity extends BriarActivity {
|
||||
testDataCreator.createTestData(contactsSeekBar.getProgress() + 1,
|
||||
messagesSeekBar.getProgress(), blogPostsSeekBar.getProgress(),
|
||||
forumsSeekBar.getProgress(), forumPostsSeekBar.getProgress());
|
||||
Intent intent = new Intent(this, NavDrawerActivity.class);
|
||||
Intent intent = new Intent(this, ENTRY_ACTIVITY);
|
||||
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.transition.Transition;
|
||||
import android.util.TypedValue;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.acra.ACRA;
|
||||
@@ -56,6 +57,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.os.Build.MANUFACTURER;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS;
|
||||
import static android.support.v4.content.ContextCompat.getSystemService;
|
||||
import static android.support.v4.view.ViewCompat.LAYOUT_DIRECTION_RTL;
|
||||
import static android.support.v7.app.AppCompatDelegate.MODE_NIGHT_AUTO;
|
||||
import static android.support.v7.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM;
|
||||
@@ -76,6 +78,8 @@ import static android.text.format.DateUtils.YEAR_IN_MILLIS;
|
||||
import static android.view.KeyEvent.ACTION_DOWN;
|
||||
import static android.view.KeyEvent.KEYCODE_ENTER;
|
||||
import static android.view.inputmethod.EditorInfo.IME_NULL;
|
||||
import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.briarproject.briar.BuildConfig.APPLICATION_ID;
|
||||
import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE;
|
||||
|
||||
@@ -87,6 +91,18 @@ public class UiUtils {
|
||||
public static final int TEASER_LENGTH = 320;
|
||||
public static final float GREY_OUT = 0.5f;
|
||||
|
||||
public static void showSoftKeyboard(View view) {
|
||||
InputMethodManager imm = requireNonNull(
|
||||
getSystemService(view.getContext(), InputMethodManager.class));
|
||||
imm.showSoftInput(view, SHOW_IMPLICIT);
|
||||
}
|
||||
|
||||
public static void hideSoftKeyboard(View view) {
|
||||
InputMethodManager imm = requireNonNull(
|
||||
getSystemService(view.getContext(), InputMethodManager.class));
|
||||
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
||||
}
|
||||
|
||||
public static String getContactDisplayName(Author author,
|
||||
@Nullable String alias) {
|
||||
String name = author.getName();
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.briarproject.briar.android.contact.add.remote.AddContactViewModel;
|
||||
import org.briarproject.briar.android.contact.add.remote.PendingContactListViewModel;
|
||||
import org.briarproject.briar.android.conversation.ConversationViewModel;
|
||||
import org.briarproject.briar.android.conversation.ImageViewModel;
|
||||
import org.briarproject.briar.android.login.StartupViewModel;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@@ -17,6 +18,11 @@ import dagger.multibindings.IntoMap;
|
||||
@Module
|
||||
public abstract class ViewModelModule {
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(StartupViewModel.class)
|
||||
abstract ViewModel bindStartupViewModel(StartupViewModel startupViewModel);
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(ConversationViewModel.class)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".android.login.UnlockActivity">
|
||||
tools:context=".android.account.UnlockActivity">
|
||||
|
||||
<android.support.v7.widget.AppCompatImageView
|
||||
android:id="@+id/image"
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".android.login.PasswordFragment">
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -21,7 +23,7 @@
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:passwordToggleEnabled="true">
|
||||
|
||||
<EditText
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/edit_password"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -37,7 +39,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_medium"
|
||||
android:onClick="onSignInClick"
|
||||
android:text="@string/sign_in_button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@@ -54,12 +55,12 @@
|
||||
app:layout_constraintTop_toTopOf="@id/btn_sign_in"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn_forgotten"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_large"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:onClick="onForgottenPasswordClick"
|
||||
android:text="@string/forgotten_password"
|
||||
android:textColor="?android:attr/textColorLink"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
@@ -12,7 +12,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/margin_activity_vertical">
|
||||
|
||||
<org.briarproject.briar.android.login.DozeView
|
||||
<org.briarproject.briar.android.account.DozeView
|
||||
android:id="@+id/dozeView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -20,7 +20,7 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<org.briarproject.briar.android.login.HuaweiView
|
||||
<org.briarproject.briar.android.account.HuaweiView
|
||||
android:id="@+id/huaweiView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.view.View;
|
||||
@@ -7,6 +7,10 @@ import android.widget.EditText;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.TestBriarApplication;
|
||||
import org.briarproject.briar.android.account.SetPasswordFragment;
|
||||
import org.briarproject.briar.android.account.SetupActivity;
|
||||
import org.briarproject.briar.android.account.SetupController;
|
||||
import org.briarproject.briar.android.login.StrengthMeter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -29,9 +33,9 @@ import static org.robolectric.shadows.support.v4.SupportFragmentTestUtil.startFr
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = 21, application = TestBriarApplication.class)
|
||||
public class PasswordFragmentTest {
|
||||
public class SetPasswordFragmentTest {
|
||||
|
||||
private PasswordFragment passwordFragment = new PasswordFragment();
|
||||
private SetPasswordFragment passwordFragment = new SetPasswordFragment();
|
||||
private EditText passwordEntry;
|
||||
private EditText passwordConfirmation;
|
||||
private TextInputLayout passwordConfirmationWrapper;
|
||||
@@ -1,10 +1,11 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.widget.EditText;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.TestBriarApplication;
|
||||
import org.briarproject.briar.android.account.SetupActivity;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
@@ -45,7 +45,7 @@ public class ChangePasswordActivityTest {
|
||||
private Button changePasswordButton;
|
||||
|
||||
@Mock
|
||||
private PasswordController passwordController;
|
||||
private ChangePasswordController passwordController;
|
||||
@Captor
|
||||
private ArgumentCaptor<ResultHandler<Boolean>> resultCaptor;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||
|
||||
public class PasswordControllerImplTest extends BrambleMockTestCase {
|
||||
public class ChangePasswordControllerImplTest extends BrambleMockTestCase {
|
||||
|
||||
private final AccountManager accountManager =
|
||||
context.mock(AccountManager.class);
|
||||
@@ -33,7 +33,7 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
|
||||
will(returnValue(true));
|
||||
}});
|
||||
|
||||
PasswordControllerImpl p = new PasswordControllerImpl(accountManager,
|
||||
ChangePasswordControllerImpl p = new ChangePasswordControllerImpl(accountManager,
|
||||
ioExecutor, estimator);
|
||||
|
||||
AtomicBoolean capturedResult = new AtomicBoolean(false);
|
||||
@@ -48,7 +48,7 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
|
||||
will(returnValue(false));
|
||||
}});
|
||||
|
||||
PasswordControllerImpl p = new PasswordControllerImpl(accountManager,
|
||||
ChangePasswordControllerImpl p = new ChangePasswordControllerImpl(accountManager,
|
||||
ioExecutor, estimator);
|
||||
|
||||
AtomicBoolean capturedResult = new AtomicBoolean(true);
|
||||
@@ -6,7 +6,8 @@ package org.briarproject.briar.android.login;
|
||||
*/
|
||||
public class TestChangePasswordActivity extends ChangePasswordActivity {
|
||||
|
||||
public void setPasswordController(PasswordController passwordController) {
|
||||
public void setPasswordController(
|
||||
ChangePasswordController passwordController) {
|
||||
this.passwordController = passwordController;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user