Show current step and total number of steps when adding a contact.

UI was transferred into XML files
and lots of redundant code was deleted such as the custom CodeEntryView.

Closes #33
This commit is contained in:
Torsten Grote
2015-12-08 18:26:04 -02:00
parent 04be7c9b92
commit 527ac0c1e0
21 changed files with 731 additions and 579 deletions

View File

@@ -1,13 +1,9 @@
package org.briarproject.android.invitation;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import java.util.Collection;
import java.util.logging.Logger;
import javax.inject.Inject;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import org.briarproject.R;
import org.briarproject.android.BriarActivity;
@@ -24,10 +20,17 @@ import org.briarproject.api.invitation.InvitationState;
import org.briarproject.api.invitation.InvitationTask;
import org.briarproject.api.invitation.InvitationTaskFactory;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import java.util.Collection;
import java.util.logging.Logger;
import javax.inject.Inject;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.android.invitation.ConfirmationCodeView.ConfirmationState.CONNECTED;
import static org.briarproject.android.invitation.ConfirmationCodeView.ConfirmationState.WAIT_FOR_CONTACT;
import static org.briarproject.android.invitation.ConfirmationCodeView.ConfirmationState.DETAILS;
public class AddContactActivity extends BriarActivity
implements InvitationListener {
@@ -86,9 +89,10 @@ implements InvitationListener {
} else if (remoteInvitationCode == -1) {
setView(new InvitationCodeView(this));
} else if (connectionFailed) {
setView(new ConnectionFailedView(this));
setView(new ErrorView(this, R.string.connection_failed,
R.string.could_not_find_contact));
} else if (contactName == null) {
setView(new CodesDoNotMatchView(this));
setView(new ErrorView(this, R.string.codes_do_not_match, R.string.interfering));
} else {
showToastAndFinish();
return;
@@ -113,24 +117,25 @@ implements InvitationListener {
} else if (remoteInvitationCode == -1) {
setView(new InvitationCodeView(this));
} else if (connectionFailed) {
setView(new ConnectionFailedView(this));
setView(new ErrorView(AddContactActivity.this, R.string.connection_failed,
R.string.could_not_find_contact));
} else if (connected && localConfirmationCode == -1) {
setView(new ConnectedView(this));
setView(new ConfirmationCodeView(this, CONNECTED));
} else if (localConfirmationCode == -1) {
setView(new ConnectionView(this));
setView(new InvitationCodeView(this, true));
} else if (!localCompared) {
setView(new ConfirmationCodeView(this));
} else if (!remoteCompared) {
setView(new WaitForContactView(this));
setView(new ConfirmationCodeView(this, WAIT_FOR_CONTACT));
} else if (localMatched && remoteMatched) {
if (contactName == null) {
setView(new ContactDetailsView(this));
setView(new ConfirmationCodeView(this, DETAILS));
} else {
showToastAndFinish();
return;
}
} else {
setView(new CodesDoNotMatchView(this));
setView(new ErrorView(this, R.string.codes_do_not_match, R.string.interfering));
}
}
}
@@ -276,7 +281,10 @@ implements InvitationListener {
if (localAuthorId == null) throw new IllegalStateException();
if (localInvitationCode == -1) throw new IllegalStateException();
remoteInvitationCode = code;
setView(new ConnectionView(this));
// change UI to show a progress indicator
setView(new InvitationCodeView(this, true));
task = invitationTaskFactory.createTask(localAuthorId,
localInvitationCode, code, enableBluetooth);
taskHandle = referenceManager.putReference(task, InvitationTask.class);
@@ -295,13 +303,14 @@ implements InvitationListener {
localCompared = true;
if (code == remoteConfirmationCode) {
localMatched = true;
if (remoteMatched) setView(new ContactDetailsView(this));
else if (remoteCompared) setView(new CodesDoNotMatchView(this));
else setView(new WaitForContactView(this));
if (remoteMatched) setView(new ConfirmationCodeView(this, DETAILS));
else if (remoteCompared) setView(new ErrorView(this, R.string.codes_do_not_match,
R.string.interfering));
else setView(new ConfirmationCodeView(this, WAIT_FOR_CONTACT));
task.localConfirmationSucceeded();
} else {
localMatched = false;
setView(new CodesDoNotMatchView(this));
setView(new ErrorView(this, R.string.codes_do_not_match, R.string.interfering));
task.localConfirmationFailed();
}
}
@@ -314,7 +323,7 @@ implements InvitationListener {
runOnUiThread(new Runnable() {
public void run() {
connected = true;
setView(new ConnectedView(AddContactActivity.this));
setView(new ConfirmationCodeView(AddContactActivity.this, CONNECTED));
}
});
}
@@ -323,7 +332,8 @@ implements InvitationListener {
runOnUiThread(new Runnable() {
public void run() {
connectionFailed = true;
setView(new ConnectionFailedView(AddContactActivity.this));
setView(new ErrorView(AddContactActivity.this, R.string.connection_failed,
R.string.could_not_find_contact));
}
});
}
@@ -343,7 +353,8 @@ implements InvitationListener {
runOnUiThread(new Runnable() {
public void run() {
connectionFailed = true;
setView(new ConnectionFailedView(AddContactActivity.this));
setView(new ErrorView(AddContactActivity.this, R.string.connection_failed,
R.string.could_not_find_contact));
}
});
}
@@ -354,7 +365,7 @@ implements InvitationListener {
remoteCompared = true;
remoteMatched = true;
if (localMatched)
setView(new ContactDetailsView(AddContactActivity.this));
setView(new ConfirmationCodeView(AddContactActivity.this, DETAILS));
}
});
}
@@ -365,7 +376,8 @@ implements InvitationListener {
remoteCompared = true;
remoteMatched = false;
if (localMatched)
setView(new CodesDoNotMatchView(AddContactActivity.this));
setView(new ErrorView(AddContactActivity.this, R.string.codes_do_not_match,
R.string.interfering));
}
});
}
@@ -382,7 +394,8 @@ implements InvitationListener {
public void pseudonymExchangeFailed() {
runOnUiThread(new Runnable() {
public void run() {
setView(new ConnectionFailedView(AddContactActivity.this));
setView(new ErrorView(AddContactActivity.this, R.string.connection_failed,
R.string.could_not_find_contact));
}
});
}

View File

@@ -1,31 +1,22 @@
package org.briarproject.android.invitation;
import static android.view.Gravity.CENTER_HORIZONTAL;
import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
import org.briarproject.android.util.LayoutUtils;
import android.content.Context;
import android.widget.LinearLayout;
abstract class AddContactView extends LinearLayout {
protected final int pad;
static final public int CODE_LEN = 6;
protected AddContactActivity container = null;
AddContactView(Context ctx) {
super(ctx);
pad = LayoutUtils.getPadding(ctx);
}
void init(AddContactActivity container) {
this.container = container;
setLayoutParams(MATCH_MATCH);
setOrientation(VERTICAL);
setGravity(CENTER_HORIZONTAL);
populate();
}
abstract void populate();
}

View File

@@ -49,6 +49,11 @@ implements OnItemSelectedListener, OnClickListener {
(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.invitation_bluetooth_start, this);
// current step
// TODO this could go into the ActionBar eventually
TextView step = (TextView) view.findViewById(R.id.stepView);
step.setText(String.format(ctx.getString(R.string.step), 1, 3));
adapter = new LocalAuthorSpinnerAdapter(ctx, false);
spinner = (Spinner) view.findViewById(R.id.spinner);
spinner.setAdapter(adapter);

View File

@@ -1,6 +0,0 @@
package org.briarproject.android.invitation;
interface CodeEntryListener {
void codeEntered(int remoteCode);
}

View File

@@ -1,103 +0,0 @@
package org.briarproject.android.invitation;
import static android.content.Context.INPUT_METHOD_SERVICE;
import static android.text.InputType.TYPE_CLASS_NUMBER;
import static android.view.Gravity.CENTER;
import static android.view.Gravity.CENTER_HORIZONTAL;
import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY;
import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP;
import org.briarproject.R;
import org.briarproject.android.util.LayoutUtils;
import android.content.Context;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
class CodeEntryView extends LinearLayout
implements OnEditorActionListener, OnClickListener {
private final int pad;
private CodeEntryListener listener = null;
private EditText codeEntry = null;
private Button continueButton = null;
public CodeEntryView(Context ctx) {
super(ctx);
pad = LayoutUtils.getPadding(ctx);
}
void init(CodeEntryListener listener, String prompt) {
this.listener = listener;
setOrientation(VERTICAL);
setGravity(CENTER_HORIZONTAL);
Context ctx = getContext();
TextView enterCode = new TextView(ctx);
enterCode.setGravity(CENTER_HORIZONTAL);
enterCode.setPadding(pad, pad, pad, 0);
enterCode.setText(prompt);
addView(enterCode);
LinearLayout innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
codeEntry = new EditText(ctx) {
@Override
protected void onTextChanged(CharSequence text, int start,
int lengthBefore, int lengthAfter) {
if (continueButton != null)
continueButton.setEnabled(getText().length() == 6);
}
};
codeEntry.setId(1); // FIXME: State is not saved and restored
codeEntry.setTextSize(26);
codeEntry.setOnEditorActionListener(this);
codeEntry.setMinEms(5);
codeEntry.setMaxEms(5);
codeEntry.setMaxLines(1);
codeEntry.setInputType(TYPE_CLASS_NUMBER);
innerLayout.addView(codeEntry);
continueButton = new Button(ctx);
continueButton.setLayoutParams(WRAP_WRAP);
continueButton.setText(R.string.continue_button);
continueButton.setEnabled(false);
continueButton.setOnClickListener(this);
innerLayout.addView(continueButton);
addView(innerLayout);
}
public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) {
if (!validateAndReturnCode()) codeEntry.setText("");
return true;
}
public void onClick(View view) {
if (!validateAndReturnCode()) codeEntry.setText("");
}
private boolean validateAndReturnCode() {
String remoteCodeString = codeEntry.getText().toString();
int remoteCode;
try {
remoteCode = Integer.parseInt(remoteCodeString);
} catch (NumberFormatException e) {
return false;
}
// Hide the soft keyboard
Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0);
listener.codeEntered(remoteCode);
return true;
}
}

View File

@@ -1,60 +1,126 @@
package org.briarproject.android.invitation;
import static android.view.Gravity.CENTER;
import static android.view.Gravity.CENTER_HORIZONTAL;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.briarproject.R;
import android.content.Context;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import static android.content.Context.INPUT_METHOD_SERVICE;
import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY;
class ConfirmationCodeView extends AddContactView implements CodeEntryListener {
class ConfirmationCodeView extends AddContactView {
public enum ConfirmationState { CONNECTED, ENTER_CODE, WAIT_FOR_CONTACT, DETAILS }
private ConfirmationState state;
ConfirmationCodeView(Context ctx) {
super(ctx);
this.state = ConfirmationState.ENTER_CODE;
}
ConfirmationCodeView(Context ctx, ConfirmationState state) {
super(ctx);
this.state = state;
}
void populate() {
removeAllViews();
Context ctx = getContext();
LinearLayout innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
ImageView icon = new ImageView(ctx);
icon.setImageResource(R.drawable.navigation_accept);
innerLayout.addView(icon);
LayoutInflater inflater = (LayoutInflater) ctx.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.invitation_bluetooth_confirmation_code, this);
TextView connected = new TextView(ctx);
connected.setTextSize(22);
connected.setPadding(pad, pad, pad, pad);
connected.setText(R.string.connected_to_contact);
innerLayout.addView(connected);
addView(innerLayout);
// current step
// TODO this could go into the ActionBar eventually
TextView step = (TextView) view.findViewById(R.id.stepView);
step.setText(String.format(ctx.getString(R.string.step), 3, 3));
TextView yourCode = new TextView(ctx);
yourCode.setGravity(CENTER_HORIZONTAL);
yourCode.setPadding(pad, pad, pad, pad);
yourCode.setText(R.string.your_confirmation_code);
addView(yourCode);
TextView code = new TextView(ctx);
code.setGravity(CENTER_HORIZONTAL);
code.setTextSize(50);
code.setPadding(pad, 0, pad, pad);
// local confirmation code
TextView code = (TextView) view.findViewById(R.id.codeView);
int localCode = container.getLocalConfirmationCode();
code.setText(String.format("%06d", localCode));
addView(code);
CodeEntryView codeEntry = new CodeEntryView(ctx);
String enter = container.getString(R.string.enter_confirmation_code);
codeEntry.init(this, enter);
addView(codeEntry);
if (state != ConfirmationState.ENTER_CODE) {
// hide views we no longer need
view.findViewById(R.id.enterCodeTextView).setVisibility(View.GONE);
view.findViewById(R.id.codeEntryView).setVisibility(View.GONE);
view.findViewById(R.id.continueButton).setVisibility(View.GONE);
// show progress indicator
view.findViewById(R.id.progressBar).setVisibility(View.VISIBLE);
// show what we are waiting for
TextView connecting = (TextView) view.findViewById(R.id.waitingView);
int textId;
if (state == ConfirmationState.CONNECTED) {
textId = R.string.calculating_confirmation_code;
view.findViewById(R.id.yourConfirmationCodeView).setVisibility(View.GONE);
view.findViewById(R.id.codeView).setVisibility(View.GONE);
} else if (state == ConfirmationState.WAIT_FOR_CONTACT) {
textId = R.string.waiting_for_contact;
} else {
textId = R.string.exchanging_contact_details;
}
connecting.setText(ctx.getString(textId));
connecting.setVisibility(View.VISIBLE);
}
else {
// handle click on continue button
final EditText codeEntry = (EditText) view.findViewById(R.id.codeEntryView);
final Button continueButton = (Button) view.findViewById(R.id.continueButton);
continueButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
send(codeEntry);
}
});
// activate continue button only when we have a 6 digit (CODE_LEN) code
codeEntry.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) {
continueButton.setEnabled(codeEntry.getText().length() == CODE_LEN);
}
@Override
public void afterTextChanged(Editable s) {
}
});
codeEntry.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_GO && v.getText().length() == CODE_LEN) {
send(v);
return true;
}
return false;
}
});
}
}
public void codeEntered(int remoteCode) {
container.remoteConfirmationCodeEntered(remoteCode);
private void send(TextView codeEntry) {
int code = Integer.parseInt(codeEntry.getText().toString());
container.remoteConfirmationCodeEntered(code);
// Hide the soft keyboard
Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).hideSoftInputFromWindow(codeEntry.getWindowToken(), 0);
}
}

View File

@@ -1,51 +0,0 @@
package org.briarproject.android.invitation;
import static android.view.Gravity.CENTER;
import org.briarproject.R;
import android.content.Context;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
class ConnectedView extends AddContactView {
ConnectedView(Context ctx) {
super(ctx);
}
void populate() {
removeAllViews();
Context ctx = getContext();
LinearLayout innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
ImageView icon = new ImageView(ctx);
icon.setImageResource(R.drawable.navigation_accept);
innerLayout.addView(icon);
TextView connected = new TextView(ctx);
connected.setTextSize(22);
connected.setPadding(pad, pad, pad, pad);
connected.setText(R.string.connected_to_contact);
innerLayout.addView(connected);
addView(innerLayout);
innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
ProgressBar progress = new ProgressBar(ctx);
progress.setIndeterminate(true);
progress.setPadding(pad, pad, pad, pad);
innerLayout.addView(progress);
TextView connecting = new TextView(ctx);
connecting.setText(R.string.calculating_confirmation_code);
innerLayout.addView(connecting);
addView(innerLayout);
}
}

View File

@@ -1,64 +0,0 @@
package org.briarproject.android.invitation;
import static android.bluetooth.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
import static android.bluetooth.BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION;
import static android.view.Gravity.CENTER;
import static org.briarproject.android.invitation.AddContactActivity.REQUEST_BLUETOOTH;
import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP;
import org.briarproject.R;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
class ConnectionFailedView extends AddContactView implements OnClickListener {
private Button tryAgainButton = null;
ConnectionFailedView(Context ctx) {
super(ctx);
}
void populate() {
removeAllViews();
Context ctx = getContext();
LinearLayout innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
ImageView icon = new ImageView(ctx);
icon.setImageResource(R.drawable.alerts_and_states_error);
innerLayout.addView(icon);
TextView failed = new TextView(ctx);
failed.setTextSize(22);
failed.setPadding(pad, pad, pad, pad);
failed.setText(R.string.connection_failed);
innerLayout.addView(failed);
addView(innerLayout);
TextView couldNotFind = new TextView(ctx);
couldNotFind.setGravity(CENTER);
couldNotFind.setPadding(pad, 0, pad, pad);
couldNotFind.setText(R.string.could_not_find_contact);
addView(couldNotFind);
tryAgainButton = new Button(ctx);
tryAgainButton.setLayoutParams(WRAP_WRAP);
tryAgainButton.setText(R.string.try_again_button);
tryAgainButton.setOnClickListener(this);
addView(tryAgainButton);
}
public void onClick(View view) {
Intent i = new Intent(ACTION_REQUEST_DISCOVERABLE);
i.putExtra(EXTRA_DISCOVERABLE_DURATION, 120);
container.startActivityForResult(i, REQUEST_BLUETOOTH);
}
}

View File

@@ -1,53 +0,0 @@
package org.briarproject.android.invitation;
import static android.view.Gravity.CENTER;
import static android.view.Gravity.CENTER_HORIZONTAL;
import org.briarproject.R;
import android.content.Context;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
class ConnectionView extends AddContactView {
ConnectionView(Context ctx) {
super(ctx);
}
void populate() {
removeAllViews();
Context ctx = getContext();
TextView yourCode = new TextView(ctx);
yourCode.setGravity(CENTER_HORIZONTAL);
yourCode.setPadding(pad, pad, pad, pad);
yourCode.setText(R.string.your_invitation_code);
addView(yourCode);
TextView code = new TextView(ctx);
code.setGravity(CENTER_HORIZONTAL);
code.setTextSize(50);
code.setPadding(pad, 0, pad, pad);
int localCode = container.getLocalInvitationCode();
code.setText(String.format("%06d", localCode));
addView(code);
LinearLayout innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
ProgressBar progress = new ProgressBar(ctx);
progress.setPadding(pad, pad, pad, pad);
progress.setIndeterminate(true);
innerLayout.addView(progress);
TextView connecting = new TextView(ctx);
int remoteCode = container.getRemoteInvitationCode();
String format = container.getString(R.string.searching_format);
connecting.setText(String.format(format, remoteCode));
innerLayout.addView(connecting);
addView(innerLayout);
}
}

View File

@@ -1,66 +0,0 @@
package org.briarproject.android.invitation;
import static android.view.Gravity.CENTER;
import static android.view.Gravity.CENTER_HORIZONTAL;
import org.briarproject.R;
import android.content.Context;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
class ContactDetailsView extends AddContactView {
ContactDetailsView(Context ctx) {
super(ctx);
}
void populate() {
removeAllViews();
Context ctx = getContext();
LinearLayout innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
ImageView icon = new ImageView(ctx);
icon.setImageResource(R.drawable.navigation_accept);
innerLayout.addView(icon);
TextView connected = new TextView(ctx);
connected.setTextSize(22);
connected.setPadding(pad, pad, pad, pad);
connected.setText(R.string.connected_to_contact);
innerLayout.addView(connected);
addView(innerLayout);
TextView yourCode = new TextView(ctx);
yourCode.setGravity(CENTER_HORIZONTAL);
yourCode.setPadding(pad, 0, pad, pad);
yourCode.setText(R.string.your_confirmation_code);
addView(yourCode);
TextView code = new TextView(ctx);
code.setGravity(CENTER_HORIZONTAL);
code.setTextSize(50);
code.setPadding(pad, 0, pad, pad);
int localCode = container.getLocalConfirmationCode();
code.setText(String.format("%06d", localCode));
addView(code);
innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
ProgressBar progress = new ProgressBar(ctx);
progress.setIndeterminate(true);
progress.setPadding(pad, pad, pad, pad);
innerLayout.addView(progress);
TextView connecting = new TextView(ctx);
connecting.setText(R.string.exchanging_contact_details);
innerLayout.addView(connecting);
addView(innerLayout);
}
}

View File

@@ -10,6 +10,7 @@ import org.briarproject.R;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
@@ -17,41 +18,39 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
class CodesDoNotMatchView extends AddContactView implements OnClickListener {
class ErrorView extends AddContactView implements OnClickListener {
CodesDoNotMatchView(Context ctx) {
private final int error;
private final int explanation;
ErrorView(Context ctx) {
super(ctx);
this.error = R.string.connection_failed;
this.explanation = R.string.could_not_find_contact;
}
ErrorView(Context ctx, int error, int explanation) {
super(ctx);
this.error = error;
this.explanation = explanation;
}
void populate() {
removeAllViews();
Context ctx = getContext();
LinearLayout innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
ImageView icon = new ImageView(ctx);
icon.setImageResource(R.drawable.alerts_and_states_error);
innerLayout.addView(icon);
LayoutInflater inflater = (LayoutInflater) ctx.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.invitation_error, this);
TextView failed = new TextView(ctx);
failed.setTextSize(22);
failed.setPadding(pad, pad, pad, pad);
failed.setText(R.string.codes_do_not_match);
innerLayout.addView(failed);
addView(innerLayout);
TextView errorView = (TextView) view.findViewById(R.id.errorTextView);
errorView.setText(ctx.getString(error));
TextView interfering = new TextView(ctx);
interfering.setGravity(CENTER);
interfering.setPadding(pad, 0, pad, pad);
interfering.setText(R.string.interfering);
addView(interfering);
TextView explanationView = (TextView) view.findViewById(R.id.explanationTextView);
explanationView.setText(ctx.getString(explanation));
Button tryAgainButton = new Button(ctx);
tryAgainButton.setLayoutParams(WRAP_WRAP);
tryAgainButton.setText(R.string.try_again_button);
Button tryAgainButton = (Button) view.findViewById(R.id.tryAgainButton);
tryAgainButton.setOnClickListener(this);
addView(tryAgainButton);
}
public void onClick(View view) {

View File

@@ -1,42 +1,116 @@
package org.briarproject.android.invitation;
import static android.view.Gravity.CENTER_HORIZONTAL;
import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.briarproject.R;
import android.content.Context;
import android.widget.TextView;
import static android.content.Context.INPUT_METHOD_SERVICE;
import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY;
class InvitationCodeView extends AddContactView implements CodeEntryListener {
class InvitationCodeView extends AddContactView {
private boolean waiting;
InvitationCodeView(Context ctx, boolean waiting) {
super(ctx);
this.waiting = waiting;
}
InvitationCodeView(Context ctx) {
super(ctx);
this(ctx, false);
}
void populate() {
removeAllViews();
Context ctx = getContext();
TextView yourCode = new TextView(ctx);
yourCode.setGravity(CENTER_HORIZONTAL);
yourCode.setPadding(pad, pad, pad, pad);
yourCode.setText(R.string.your_invitation_code);
addView(yourCode);
TextView code = new TextView(ctx);
code.setGravity(CENTER_HORIZONTAL);
code.setTextSize(50);
code.setPadding(pad, 0, pad, pad);
LayoutInflater inflater = (LayoutInflater) ctx.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.invitation_bluetooth_invitation_code, this);
// current step
// TODO this could go into the ActionBar eventually
TextView step = (TextView) view.findViewById(R.id.stepView);
step.setText(String.format(ctx.getString(R.string.step), 2, 3));
// local invitation code
TextView code = (TextView) view.findViewById(R.id.codeView);
int localCode = container.getLocalInvitationCode();
code.setText(String.format("%06d", localCode));
addView(code);
CodeEntryView codeEntry = new CodeEntryView(ctx);
String enter = container.getString(R.string.enter_invitation_code);
codeEntry.init(this, enter);
addView(codeEntry);
if (waiting) {
// hide views we no longer need
view.findViewById(R.id.enterCodeTextView).setVisibility(View.GONE);
view.findViewById(R.id.codeEntryView).setVisibility(View.GONE);
view.findViewById(R.id.continueButton).setVisibility(View.GONE);
// show progress indicator
view.findViewById(R.id.progressBar).setVisibility(View.VISIBLE);
// show which code we are waiting for
TextView connecting = (TextView) view.findViewById(R.id.waitingView);
int remoteCode = container.getRemoteInvitationCode();
String format = container.getString(R.string.searching_format);
connecting.setText(String.format(format, remoteCode));
connecting.setVisibility(View.VISIBLE);
}
else {
// handle click on continue button
final EditText codeEntry = (EditText) view.findViewById(R.id.codeEntryView);
final Button continueButton = (Button) view.findViewById(R.id.continueButton);
continueButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
send(codeEntry);
}
});
// activate continue button only when we have a 6 digit (CODE_LEN) code
codeEntry.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) {
continueButton.setEnabled(codeEntry.getText().length() == CODE_LEN);
}
@Override
public void afterTextChanged(Editable s) {
}
});
codeEntry.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_GO && v.getText().length() == CODE_LEN) {
send(v);
return true;
}
return false;
}
});
}
}
public void codeEntered(int remoteCode) {
container.remoteInvitationCodeEntered(remoteCode);
private void send(TextView codeEntry) {
int code = Integer.parseInt(codeEntry.getText().toString());
container.remoteInvitationCodeEntered(code);
// Hide the soft keyboard
Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).hideSoftInputFromWindow(codeEntry.getWindowToken(), 0);
}
}

View File

@@ -1,66 +0,0 @@
package org.briarproject.android.invitation;
import static android.view.Gravity.CENTER;
import static android.view.Gravity.CENTER_HORIZONTAL;
import org.briarproject.R;
import android.content.Context;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
class WaitForContactView extends AddContactView {
WaitForContactView(Context ctx) {
super(ctx);
}
void populate() {
removeAllViews();
Context ctx = getContext();
LinearLayout innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
ImageView icon = new ImageView(ctx);
icon.setImageResource(R.drawable.navigation_accept);
innerLayout.addView(icon);
TextView connected = new TextView(ctx);
connected.setTextSize(22);
connected.setPadding(pad, pad, pad, pad);
connected.setText(R.string.connected_to_contact);
innerLayout.addView(connected);
addView(innerLayout);
TextView yourCode = new TextView(ctx);
yourCode.setGravity(CENTER_HORIZONTAL);
yourCode.setPadding(pad, 0, pad, pad);
yourCode.setText(R.string.your_confirmation_code);
addView(yourCode);
TextView code = new TextView(ctx);
code.setGravity(CENTER_HORIZONTAL);
code.setTextSize(50);
code.setPadding(pad, 0, pad, pad);
int localCode = container.getLocalConfirmationCode();
code.setText(String.format("%06d", localCode));
addView(code);
innerLayout = new LinearLayout(ctx);
innerLayout.setOrientation(HORIZONTAL);
innerLayout.setGravity(CENTER);
ProgressBar progress = new ProgressBar(ctx);
progress.setIndeterminate(true);
progress.setPadding(pad, pad, pad, pad);
innerLayout.addView(progress);
TextView connecting = new TextView(ctx);
connecting.setText(R.string.waiting_for_contact);
innerLayout.addView(connecting);
addView(innerLayout);
}
}