mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Setup Wizard that asks for Doze Mode exception
Keep checking if we are whitelisted and request it if not
This commit is contained in:
@@ -27,8 +27,11 @@ import org.briarproject.briar.android.introduction.IntroductionMessageFragment;
|
||||
import org.briarproject.briar.android.keyagreement.IntroFragment;
|
||||
import org.briarproject.briar.android.keyagreement.KeyAgreementActivity;
|
||||
import org.briarproject.briar.android.keyagreement.ShowQrCodeFragment;
|
||||
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.PasswordActivity;
|
||||
import org.briarproject.briar.android.login.PasswordFragment;
|
||||
import org.briarproject.briar.android.login.SetupActivity;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.android.panic.PanicPreferencesActivity;
|
||||
@@ -148,6 +151,10 @@ public interface ActivityComponent {
|
||||
void inject(RssFeedManageActivity activity);
|
||||
|
||||
// Fragments
|
||||
void inject(AuthorNameFragment fragment);
|
||||
void inject(PasswordFragment fragment);
|
||||
void inject(DozeFragment fragment);
|
||||
|
||||
void inject(ContactListFragment fragment);
|
||||
|
||||
void inject(CreateGroupFragment fragment);
|
||||
|
||||
@@ -12,11 +12,13 @@ import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.AndroidComponent;
|
||||
import org.briarproject.briar.android.BriarApplication;
|
||||
import org.briarproject.briar.android.DestroyableContext;
|
||||
import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
||||
import org.briarproject.briar.android.forum.ForumModule;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
import org.briarproject.briar.android.fragment.ScreenFilterDialogFragment;
|
||||
import org.briarproject.briar.android.widget.TapSafeFrameLayout;
|
||||
import org.briarproject.briar.android.widget.TapSafeFrameLayout.OnTapFilteredListener;
|
||||
@@ -113,6 +115,22 @@ public abstract class BaseActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
protected void showInitialFragment(BaseFragment f) {
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
|
||||
.commit();
|
||||
}
|
||||
|
||||
public void showNextFragment(BaseFragment f) {
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.setCustomAnimations(R.anim.step_next_in,
|
||||
R.anim.step_previous_out, R.anim.step_previous_in,
|
||||
R.anim.step_next_out)
|
||||
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
|
||||
.addToBackStack(f.getUniqueTag())
|
||||
.commit();
|
||||
}
|
||||
|
||||
private void showScreenFilterWarning() {
|
||||
if (dialogFrag != null && dialogFrag.isVisible()) return;
|
||||
Set<String> apps = screenFilterMonitor.getApps();
|
||||
|
||||
@@ -14,7 +14,6 @@ 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.ResultHandler;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
import org.briarproject.briar.android.login.PasswordActivity;
|
||||
import org.briarproject.briar.android.panic.ExitActivity;
|
||||
|
||||
@@ -64,22 +63,6 @@ public abstract class BriarActivity extends BaseActivity {
|
||||
}
|
||||
}
|
||||
|
||||
protected void showInitialFragment(BaseFragment f) {
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
|
||||
.commit();
|
||||
}
|
||||
|
||||
public void showNextFragment(BaseFragment f) {
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.setCustomAnimations(R.anim.step_next_in,
|
||||
R.anim.step_previous_out, R.anim.step_previous_in,
|
||||
R.anim.step_next_out)
|
||||
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
|
||||
.addToBackStack(f.getUniqueTag())
|
||||
.commit();
|
||||
}
|
||||
|
||||
public void setSceneTransitionAnimation() {
|
||||
if (Build.VERSION.SDK_INT < 21) return;
|
||||
Transition slide = new Slide(Gravity.RIGHT);
|
||||
|
||||
@@ -3,13 +3,13 @@ package org.briarproject.briar.android.activity;
|
||||
public interface RequestCodes {
|
||||
|
||||
int REQUEST_PASSWORD = 1;
|
||||
int REQUEST_BLUETOOTH = 2;
|
||||
int REQUEST_INTRODUCTION = 3;
|
||||
int REQUEST_GROUP_INVITE = 4;
|
||||
int REQUEST_SHARE_FORUM = 5;
|
||||
int REQUEST_WRITE_BLOG_POST = 6;
|
||||
int REQUEST_SHARE_BLOG = 7;
|
||||
int REQUEST_RINGTONE = 8;
|
||||
int REQUEST_PERMISSION_CAMERA = 9;
|
||||
int REQUEST_INTRODUCTION = 2;
|
||||
int REQUEST_GROUP_INVITE = 3;
|
||||
int REQUEST_SHARE_FORUM = 4;
|
||||
int REQUEST_WRITE_BLOG_POST = 5;
|
||||
int REQUEST_SHARE_BLOG = 6;
|
||||
int REQUEST_RINGTONE = 7;
|
||||
int REQUEST_PERMISSION_CAMERA = 8;
|
||||
int REQUEST_DOZE_WHITELISTING = 9;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.os.Bundle;
|
||||
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.widget.Button;
|
||||
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
|
||||
import static android.view.inputmethod.EditorInfo.IME_ACTION_NEXT;
|
||||
import static android.view.inputmethod.EditorInfo.IME_ACTION_NONE;
|
||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||
import static org.briarproject.briar.android.util.UiUtils.setError;
|
||||
|
||||
public class AuthorNameFragment extends SetupFragment {
|
||||
|
||||
private final static String TAG = AuthorNameFragment.class.getName();
|
||||
|
||||
private TextInputLayout authorNameWrapper;
|
||||
private TextInputEditText authorNameInput;
|
||||
private Button nextButton;
|
||||
|
||||
public static AuthorNameFragment newInstance() {
|
||||
return new AuthorNameFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
getActivity().setTitle(getString(R.string.setup_title));
|
||||
View v =
|
||||
inflater.inflate(R.layout.fragment_setup_author_name, container,
|
||||
false);
|
||||
authorNameWrapper =
|
||||
(TextInputLayout) v.findViewById(R.id.nickname_entry_wrapper);
|
||||
authorNameInput =
|
||||
(TextInputEditText) v.findViewById(R.id.nickname_entry);
|
||||
nextButton = (Button) v.findViewById(R.id.next);
|
||||
|
||||
authorNameInput.addTextChangedListener(this);
|
||||
|
||||
nextButton.setOnClickListener(this);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getHelpText() {
|
||||
return getString(R.string.setup_name_explanation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence authorName, int i, int i1, int i2) {
|
||||
int authorNameLength = StringUtils.toUtf8(authorName.toString()).length;
|
||||
boolean error = authorNameLength > MAX_AUTHOR_NAME_LENGTH;
|
||||
setError(authorNameWrapper, getString(R.string.name_too_long), error);
|
||||
boolean enabled = authorNameLength > 0 && !error;
|
||||
authorNameInput
|
||||
.setImeOptions(enabled ? IME_ACTION_NEXT : IME_ACTION_NONE);
|
||||
authorNameInput.setOnEditorActionListener(enabled ? this : null);
|
||||
nextButton.setEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
setupController.setAuthorName(authorNameInput.getText().toString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,8 +32,6 @@ public class ChangePasswordActivity extends BaseActivity
|
||||
|
||||
@Inject
|
||||
protected PasswordController passwordController;
|
||||
@Inject
|
||||
protected SetupController setupController;
|
||||
|
||||
private TextInputLayout currentPasswordEntryWrapper;
|
||||
private TextInputLayout newPasswordEntryWrapper;
|
||||
@@ -105,7 +103,7 @@ public class ChangePasswordActivity extends BaseActivity
|
||||
String secondPassword = newPasswordConfirmation.getText().toString();
|
||||
boolean passwordsMatch = firstPassword.equals(secondPassword);
|
||||
float strength =
|
||||
setupController.estimatePasswordStrength(firstPassword);
|
||||
passwordController.estimatePasswordStrength(firstPassword);
|
||||
strengthMeter.setStrength(strength);
|
||||
UiUtils.setError(newPasswordEntryWrapper,
|
||||
getString(R.string.password_too_weak),
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
|
||||
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
|
||||
|
||||
@TargetApi(23)
|
||||
public class DozeFragment extends SetupFragment {
|
||||
|
||||
private final static String TAG = DozeFragment.class.getName();
|
||||
|
||||
private Button dozeButton;
|
||||
private ProgressBar progressBar;
|
||||
|
||||
public static DozeFragment newInstance() {
|
||||
return new DozeFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
getActivity().setTitle(getString(R.string.setup_doze_title));
|
||||
View v =
|
||||
inflater.inflate(R.layout.fragment_setup_doze, container,
|
||||
false);
|
||||
dozeButton = (Button) v.findViewById(R.id.dozeButton);
|
||||
progressBar = (ProgressBar) v.findViewById(R.id.progress);
|
||||
|
||||
dozeButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
askForDozeWhitelisting();
|
||||
}
|
||||
});
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getHelpText() {
|
||||
return getString(R.string.setup_doze_explanation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int request, int result, Intent data) {
|
||||
super.onActivityResult(request, result, data);
|
||||
if (request == REQUEST_DOZE_WHITELISTING) {
|
||||
if (!setupController.needsDozeWhitelisting()) {
|
||||
dozeButton.setEnabled(false);
|
||||
onClick(dozeButton);
|
||||
} else {
|
||||
showOnboardingDialog(getContext(), getHelpText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("BatteryLife")
|
||||
private void askForDozeWhitelisting() {
|
||||
Intent i = UiUtils.getDozeWhitelistingIntent(getContext());
|
||||
startActivityForResult(i, REQUEST_DOZE_WHITELISTING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
dozeButton.setVisibility(INVISIBLE);
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
setupController.createAccount();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,9 +7,12 @@ import org.briarproject.briar.android.controller.handler.ResultHandler;
|
||||
@NotNullByDefault
|
||||
public interface PasswordController extends ConfigController {
|
||||
|
||||
float estimatePasswordStrength(String password);
|
||||
|
||||
void validatePassword(String password,
|
||||
ResultHandler<Boolean> resultHandler);
|
||||
|
||||
void changePassword(String password, String newPassword,
|
||||
ResultHandler<Boolean> resultHandler);
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.SharedPreferences;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
@@ -27,14 +28,22 @@ public class PasswordControllerImpl extends ConfigControllerImpl
|
||||
|
||||
protected final Executor cryptoExecutor;
|
||||
protected final CryptoComponent crypto;
|
||||
private final PasswordStrengthEstimator strengthEstimator;
|
||||
|
||||
@Inject
|
||||
PasswordControllerImpl(SharedPreferences briarPrefs,
|
||||
DatabaseConfig databaseConfig,
|
||||
@CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto) {
|
||||
@CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto,
|
||||
PasswordStrengthEstimator strengthEstimator) {
|
||||
super(briarPrefs, databaseConfig);
|
||||
this.cryptoExecutor = cryptoExecutor;
|
||||
this.crypto = crypto;
|
||||
this.strengthEstimator = strengthEstimator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float estimatePasswordStrength(String password) {
|
||||
return strengthEstimator.estimateStrength(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.os.Bundle;
|
||||
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.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
|
||||
|
||||
public class PasswordFragment extends SetupFragment {
|
||||
|
||||
private 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;
|
||||
|
||||
public static PasswordFragment newInstance() {
|
||||
return new PasswordFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
getActivity().setTitle(getString(R.string.setup_password_intro));
|
||||
View v =
|
||||
inflater.inflate(R.layout.fragment_setup_password, container,
|
||||
false);
|
||||
|
||||
strengthMeter = (StrengthMeter) v.findViewById(R.id.strength_meter);
|
||||
passwordEntryWrapper =
|
||||
(TextInputLayout) v.findViewById(R.id.password_entry_wrapper);
|
||||
passwordEntry = (TextInputEditText) v.findViewById(R.id.password_entry);
|
||||
passwordConfirmationWrapper =
|
||||
(TextInputLayout) v.findViewById(R.id.password_confirm_wrapper);
|
||||
passwordConfirmation =
|
||||
(TextInputEditText) v.findViewById(R.id.password_confirm);
|
||||
nextButton = (Button) v.findViewById(R.id.next);
|
||||
progressBar = (ProgressBar) v.findViewById(R.id.progress);
|
||||
|
||||
passwordEntry.addTextChangedListener(this);
|
||||
passwordConfirmation.addTextChangedListener(this);
|
||||
nextButton.setOnClickListener(this);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
|
||||
// the controller is not yet available in onCreateView()
|
||||
if (!setupController.needsDozeWhitelisting()) {
|
||||
nextButton.setText(R.string.create_account_button);
|
||||
}
|
||||
}
|
||||
|
||||
@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) {
|
||||
if (!setupController.needsDozeWhitelisting()) {
|
||||
nextButton.setVisibility(INVISIBLE);
|
||||
progressBar.setVisibility(VISIBLE);
|
||||
}
|
||||
String password = passwordEntry.getText().toString();
|
||||
setupController.setPassword(password);
|
||||
setupController.showDozeOrCreateAccount();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,157 +1,64 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
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.handler.UiResultHandler;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
|
||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||
|
||||
public class SetupActivity extends BaseActivity implements OnClickListener,
|
||||
OnEditorActionListener {
|
||||
public class SetupActivity extends BaseActivity
|
||||
implements BaseFragmentListener {
|
||||
|
||||
@Inject
|
||||
SetupController setupController;
|
||||
|
||||
private TextInputLayout nicknameEntryWrapper;
|
||||
private TextInputLayout passwordEntryWrapper;
|
||||
private TextInputLayout passwordConfirmationWrapper;
|
||||
private EditText nicknameEntry;
|
||||
private EditText passwordEntry;
|
||||
private EditText passwordConfirmation;
|
||||
private StrengthMeter strengthMeter;
|
||||
private Button createAccountButton;
|
||||
private ProgressBar progress;
|
||||
|
||||
@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);
|
||||
setContentView(R.layout.activity_setup);
|
||||
setContentView(R.layout.activity_fragment_container);
|
||||
|
||||
nicknameEntryWrapper =
|
||||
(TextInputLayout) findViewById(R.id.nickname_entry_wrapper);
|
||||
passwordEntryWrapper =
|
||||
(TextInputLayout) findViewById(R.id.password_entry_wrapper);
|
||||
passwordConfirmationWrapper =
|
||||
(TextInputLayout) findViewById(R.id.password_confirm_wrapper);
|
||||
nicknameEntry = (EditText) findViewById(R.id.nickname_entry);
|
||||
passwordEntry = (EditText) findViewById(R.id.password_entry);
|
||||
passwordConfirmation = (EditText) findViewById(R.id.password_confirm);
|
||||
strengthMeter = (StrengthMeter) findViewById(R.id.strength_meter);
|
||||
createAccountButton = (Button) findViewById(R.id.create_account);
|
||||
progress = (ProgressBar) findViewById(R.id.progress_wheel);
|
||||
|
||||
TextWatcher tw = 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) {
|
||||
enableOrDisableContinueButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
};
|
||||
|
||||
nicknameEntry.addTextChangedListener(tw);
|
||||
passwordEntry.addTextChangedListener(tw);
|
||||
passwordConfirmation.addTextChangedListener(tw);
|
||||
passwordConfirmation.setOnEditorActionListener(this);
|
||||
createAccountButton.setOnClickListener(this);
|
||||
if (state == null) {
|
||||
showInitialFragment(AuthorNameFragment.newInstance());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
setupController.setSetupActivity(this);
|
||||
}
|
||||
|
||||
private void enableOrDisableContinueButton() {
|
||||
if (progress == null) return; // Not created yet
|
||||
if (passwordEntry.getText().length() > 0 && passwordEntry.hasFocus())
|
||||
strengthMeter.setVisibility(VISIBLE);
|
||||
else strengthMeter.setVisibility(GONE);
|
||||
String nickname = nicknameEntry.getText().toString();
|
||||
int nicknameLength = StringUtils.toUtf8(nickname).length;
|
||||
String firstPassword = passwordEntry.getText().toString();
|
||||
String secondPassword = passwordConfirmation.getText().toString();
|
||||
boolean passwordsMatch = firstPassword.equals(secondPassword);
|
||||
float strength =
|
||||
setupController.estimatePasswordStrength(firstPassword);
|
||||
strengthMeter.setStrength(strength);
|
||||
UiUtils.setError(nicknameEntryWrapper,
|
||||
getString(R.string.name_too_long),
|
||||
nicknameLength > MAX_AUTHOR_NAME_LENGTH);
|
||||
UiUtils.setError(passwordEntryWrapper,
|
||||
getString(R.string.password_too_weak),
|
||||
firstPassword.length() > 0 && strength < QUITE_WEAK);
|
||||
UiUtils.setError(passwordConfirmationWrapper,
|
||||
getString(R.string.passwords_do_not_match),
|
||||
secondPassword.length() > 0 && !passwordsMatch);
|
||||
createAccountButton.setEnabled(nicknameLength > 0
|
||||
&& nicknameLength <= MAX_AUTHOR_NAME_LENGTH
|
||||
&& passwordsMatch && strength >= QUITE_WEAK);
|
||||
public void showPasswordFragment() {
|
||||
showNextFragment(PasswordFragment.newInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
hideSoftKeyboard(v);
|
||||
return true;
|
||||
@TargetApi(23)
|
||||
public void showDozeFragment() {
|
||||
showNextFragment(DozeFragment.newInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
// Replace the button with a progress bar
|
||||
createAccountButton.setVisibility(INVISIBLE);
|
||||
progress.setVisibility(VISIBLE);
|
||||
String nickname = nicknameEntry.getText().toString();
|
||||
String password = passwordEntry.getText().toString();
|
||||
|
||||
setupController.storeAuthorInfo(nickname, password,
|
||||
new UiResultHandler<Void>(this) {
|
||||
@Override
|
||||
public void onResultUi(Void result) {
|
||||
showMain();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showMain() {
|
||||
public void showApp() {
|
||||
Intent i = new Intent(this, NavDrawerActivity.class);
|
||||
i.setFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(i);
|
||||
supportFinishAfterTransition();
|
||||
overridePendingTransition(R.anim.screen_new_in, R.anim.screen_old_out);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void runOnDbThread(Runnable runnable) {
|
||||
throw new RuntimeException("Don't use this deprecated method here.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,9 +6,25 @@ import org.briarproject.briar.android.controller.handler.ResultHandler;
|
||||
@NotNullByDefault
|
||||
public interface SetupController {
|
||||
|
||||
void setSetupActivity(SetupActivity setupActivity);
|
||||
|
||||
boolean needsDozeWhitelisting();
|
||||
|
||||
void setAuthorName(String authorName);
|
||||
|
||||
void setPassword(String password);
|
||||
|
||||
float estimatePasswordStrength(String password);
|
||||
|
||||
void storeAuthorInfo(String nickname, String password,
|
||||
ResultHandler<Void> resultHandler);
|
||||
/**
|
||||
* This should be called after the author name and the password have been
|
||||
* set. It decides whether to ask for doze exception or create the account
|
||||
* right away.
|
||||
*/
|
||||
void showDozeOrCreateAccount();
|
||||
|
||||
void createAccount();
|
||||
|
||||
void createAccount(final ResultHandler<Void> resultHandler);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||
@@ -9,6 +10,8 @@ import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.android.controller.handler.ResultHandler;
|
||||
import org.briarproject.briar.android.controller.handler.UiResultHandler;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@@ -18,29 +21,75 @@ import javax.inject.Inject;
|
||||
public class SetupControllerImpl extends PasswordControllerImpl
|
||||
implements SetupController {
|
||||
|
||||
private final PasswordStrengthEstimator strengthEstimator;
|
||||
@Nullable
|
||||
private String authorName, password;
|
||||
@Nullable
|
||||
private SetupActivity setupActivity;
|
||||
|
||||
@Inject
|
||||
SetupControllerImpl(SharedPreferences briarPrefs,
|
||||
DatabaseConfig databaseConfig,
|
||||
@CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto,
|
||||
PasswordStrengthEstimator strengthEstimator) {
|
||||
super(briarPrefs, databaseConfig, cryptoExecutor, crypto);
|
||||
this.strengthEstimator = strengthEstimator;
|
||||
super(briarPrefs, databaseConfig, cryptoExecutor, crypto,
|
||||
strengthEstimator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float estimatePasswordStrength(String password) {
|
||||
return strengthEstimator.estimateStrength(password);
|
||||
public void setSetupActivity(SetupActivity setupActivity) {
|
||||
this.setupActivity = setupActivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeAuthorInfo(final String nickname, final String password,
|
||||
final ResultHandler<Void> resultHandler) {
|
||||
public boolean needsDozeWhitelisting() {
|
||||
if (setupActivity == null) throw new IllegalStateException();
|
||||
return UiUtils.needsDozeWhitelisting(setupActivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthorName(String authorName) {
|
||||
this.authorName = authorName;
|
||||
if (setupActivity == null) throw new IllegalStateException();
|
||||
setupActivity.showPasswordFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDozeOrCreateAccount() {
|
||||
if (setupActivity == null) throw new IllegalStateException();
|
||||
if (needsDozeWhitelisting()) {
|
||||
setupActivity.showDozeFragment();
|
||||
} else {
|
||||
createAccount();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAccount() {
|
||||
final UiResultHandler<Void> resultHandler =
|
||||
new UiResultHandler<Void>(setupActivity) {
|
||||
@Override
|
||||
public void onResultUi(Void result) {
|
||||
if (setupActivity == null)
|
||||
throw new IllegalStateException();
|
||||
setupActivity.showApp();
|
||||
}
|
||||
};
|
||||
createAccount(resultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAccount(final ResultHandler<Void> resultHandler) {
|
||||
if (authorName == null || password == null)
|
||||
throw new IllegalStateException();
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
databaseConfig.setLocalAuthorName(nickname);
|
||||
databaseConfig.setLocalAuthorName(authorName);
|
||||
SecretKey key = crypto.generateSecretKey();
|
||||
databaseConfig.setEncryptionKey(key);
|
||||
String hex = encryptDatabaseKey(key, password);
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
|
||||
|
||||
abstract class SetupFragment extends BaseFragment implements TextWatcher,
|
||||
OnEditorActionListener, OnClickListener {
|
||||
|
||||
@Inject
|
||||
SetupController setupController;
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.help_action, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_help) {
|
||||
showOnboardingDialog(getContext(), getHelpText());
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String getHelpText();
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1,
|
||||
int i2) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence authorName, int i, int i1, int i2) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
|
||||
onClick(textView);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
// noop
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +1,19 @@
|
||||
package org.briarproject.briar.android.navdrawer;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.NavigationView;
|
||||
import android.support.design.widget.NavigationView.OnNavigationItemSelectedListener;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBarDrawerToggle;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
@@ -49,9 +54,12 @@ import static android.support.v4.view.GravityCompat.START;
|
||||
import static android.support.v4.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
|
||||
import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.NO;
|
||||
import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.UPDATE;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getDaysUntilExpiry;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getDozeWhitelistingIntent;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
|
||||
public class NavDrawerActivity extends BriarActivity implements
|
||||
BaseFragmentListener, TransportStateListener,
|
||||
@@ -134,6 +142,7 @@ public class NavDrawerActivity extends BriarActivity implements
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressLint("NewApi")
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
updateTransports();
|
||||
@@ -143,6 +152,7 @@ public class NavDrawerActivity extends BriarActivity implements
|
||||
if (expiry != NO) showExpiryWarning(expiry);
|
||||
}
|
||||
});
|
||||
if (needsDozeWhitelisting(this)) requestDozeWhitelisting();
|
||||
}
|
||||
|
||||
private void exitIfStartupFailed(Intent intent) {
|
||||
@@ -178,7 +188,7 @@ public class NavDrawerActivity extends BriarActivity implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(MenuItem item) {
|
||||
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
||||
drawerLayout.closeDrawer(START);
|
||||
clearBackStack();
|
||||
loadFragment(item.getItemId());
|
||||
@@ -311,6 +321,24 @@ public class NavDrawerActivity extends BriarActivity implements
|
||||
expiryWarning.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
@TargetApi(23)
|
||||
private void requestDozeWhitelisting() {
|
||||
new AlertDialog.Builder(this, R.style.BriarDialogTheme)
|
||||
.setMessage(R.string.setup_doze_intro)
|
||||
.setPositiveButton(R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
Intent i = getDozeWhitelistingIntent(
|
||||
NavDrawerActivity.this);
|
||||
startActivityForResult(i,
|
||||
REQUEST_DOZE_WHITELISTING);
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
private void initializeTransports(final LayoutInflater inflater) {
|
||||
transports = new ArrayList<>(3);
|
||||
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package org.briarproject.briar.android.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.PowerManager;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Html;
|
||||
import android.text.Spannable;
|
||||
@@ -23,14 +27,16 @@ import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.briar.BuildConfig;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.view.ArticleMovementMethod;
|
||||
import org.briarproject.briar.android.widget.LinkDialogFragment;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static android.content.Intent.*;
|
||||
import static android.content.Context.POWER_SERVICE;
|
||||
import static android.content.Intent.CATEGORY_DEFAULT;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS;
|
||||
import static android.text.format.DateUtils.DAY_IN_MILLIS;
|
||||
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
|
||||
import static android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE;
|
||||
@@ -38,7 +44,7 @@ import static android.text.format.DateUtils.FORMAT_ABBREV_TIME;
|
||||
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
|
||||
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
||||
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
|
||||
import static org.briarproject.briar.BuildConfig.*;
|
||||
import static org.briarproject.briar.BuildConfig.APPLICATION_ID;
|
||||
import static org.briarproject.briar.android.BriarApplication.EXPIRY_DATE;
|
||||
|
||||
public class UiUtils {
|
||||
@@ -149,4 +155,37 @@ public class UiUtils {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void showOnboardingDialog(Context ctx, String text) {
|
||||
new AlertDialog.Builder(ctx, R.style.OnboardingDialogTheme)
|
||||
.setMessage(text)
|
||||
.setNeutralButton(R.string.got_it,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
dialog.cancel();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
public static boolean needsDozeWhitelisting(Context ctx) {
|
||||
if (Build.VERSION.SDK_INT < 23) return false;
|
||||
PowerManager pm =
|
||||
(PowerManager) ctx.getSystemService(POWER_SERVICE);
|
||||
String packageName = ctx.getPackageName();
|
||||
if (pm == null) throw new AssertionError();
|
||||
return !pm.isIgnoringBatteryOptimizations(packageName);
|
||||
}
|
||||
|
||||
@TargetApi(23)
|
||||
@SuppressLint("BatteryLife")
|
||||
public static Intent getDozeWhitelistingIntent(Context ctx) {
|
||||
Intent i = new Intent();
|
||||
i.setAction(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
|
||||
i.setData(Uri.parse("package:" + ctx.getPackageName()));
|
||||
return i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user