diff --git a/briar-android/artwork/bluetooth.svg b/briar-android/artwork/bluetooth.svg
new file mode 100644
index 000000000..951fa966c
--- /dev/null
+++ b/briar-android/artwork/bluetooth.svg
@@ -0,0 +1,99 @@
+
+
+
+
diff --git a/briar-android/res/drawable/bluetooth.png b/briar-android/res/drawable/bluetooth.png
index b5e6ef06f..f99091e67 100644
Binary files a/briar-android/res/drawable/bluetooth.png and b/briar-android/res/drawable/bluetooth.png differ
diff --git a/briar-android/res/layout/invitation_bluetooth_confirmation_code.xml b/briar-android/res/layout/invitation_bluetooth_confirmation_code.xml
new file mode 100644
index 000000000..bf0d3ee68
--- /dev/null
+++ b/briar-android/res/layout/invitation_bluetooth_confirmation_code.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/layout/invitation_bluetooth_invitation_code.xml b/briar-android/res/layout/invitation_bluetooth_invitation_code.xml
new file mode 100644
index 000000000..875a58d08
--- /dev/null
+++ b/briar-android/res/layout/invitation_bluetooth_invitation_code.xml
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/layout/invitation_bluetooth_start.xml b/briar-android/res/layout/invitation_bluetooth_start.xml
index 855e9d079..63bf3ea6d 100644
--- a/briar-android/res/layout/invitation_bluetooth_start.xml
+++ b/briar-android/res/layout/invitation_bluetooth_start.xml
@@ -1,53 +1,77 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/layout/invitation_error.xml b/briar-android/res/layout/invitation_error.xml
new file mode 100644
index 000000000..e1c94c393
--- /dev/null
+++ b/briar-android/res/layout/invitation_error.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/layout/view_code_entry.xml b/briar-android/res/layout/view_code_entry.xml
new file mode 100644
index 000000000..018915876
--- /dev/null
+++ b/briar-android/res/layout/view_code_entry.xml
@@ -0,0 +1,16 @@
+
+
\ No newline at end of file
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index 0076ca171..8a6c06144 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -42,7 +42,7 @@
Continue
Your invitation code is
Please enter your contact\'s invitation code:
- Searching for %06d\u2026
+ Searching for contact with invitation code %06d\u2026
Connection failed
Briar could not find your contact nearby
Try Again
@@ -111,8 +111,9 @@
Default ringtone
None
Choose ringtone
+ Step %1$d/%2$d
Lost password
Password recovery is not possible. Do you wish to delete your user, all contacts, and re-register ?
-
\ No newline at end of file
+
diff --git a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
index eb0a52e9d..ab318363b 100644
--- a/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
+++ b/briar-android/src/org/briarproject/android/invitation/AddContactActivity.java
@@ -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));
}
});
}
diff --git a/briar-android/src/org/briarproject/android/invitation/AddContactView.java b/briar-android/src/org/briarproject/android/invitation/AddContactView.java
index 2a6b97849..6a6b300be 100644
--- a/briar-android/src/org/briarproject/android/invitation/AddContactView.java
+++ b/briar-android/src/org/briarproject/android/invitation/AddContactView.java
@@ -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();
+
}
diff --git a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java b/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java
index fc2e4524a..f609eb93f 100644
--- a/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java
+++ b/briar-android/src/org/briarproject/android/invitation/ChooseIdentityView.java
@@ -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);
diff --git a/briar-android/src/org/briarproject/android/invitation/CodeEntryListener.java b/briar-android/src/org/briarproject/android/invitation/CodeEntryListener.java
deleted file mode 100644
index e63c8b177..000000000
--- a/briar-android/src/org/briarproject/android/invitation/CodeEntryListener.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.briarproject.android.invitation;
-
-interface CodeEntryListener {
-
- void codeEntered(int remoteCode);
-}
diff --git a/briar-android/src/org/briarproject/android/invitation/CodeEntryView.java b/briar-android/src/org/briarproject/android/invitation/CodeEntryView.java
deleted file mode 100644
index d15bfdab3..000000000
--- a/briar-android/src/org/briarproject/android/invitation/CodeEntryView.java
+++ /dev/null
@@ -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;
- }
-}
diff --git a/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java b/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java
index 7c52cd880..118744cc9 100644
--- a/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java
+++ b/briar-android/src/org/briarproject/android/invitation/ConfirmationCodeView.java
@@ -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);
}
+
}
diff --git a/briar-android/src/org/briarproject/android/invitation/ConnectedView.java b/briar-android/src/org/briarproject/android/invitation/ConnectedView.java
deleted file mode 100644
index b9a51abec..000000000
--- a/briar-android/src/org/briarproject/android/invitation/ConnectedView.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/briar-android/src/org/briarproject/android/invitation/ConnectionFailedView.java b/briar-android/src/org/briarproject/android/invitation/ConnectionFailedView.java
deleted file mode 100644
index 346d9788c..000000000
--- a/briar-android/src/org/briarproject/android/invitation/ConnectionFailedView.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/briar-android/src/org/briarproject/android/invitation/ConnectionView.java b/briar-android/src/org/briarproject/android/invitation/ConnectionView.java
deleted file mode 100644
index e85b100c0..000000000
--- a/briar-android/src/org/briarproject/android/invitation/ConnectionView.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/briar-android/src/org/briarproject/android/invitation/ContactDetailsView.java b/briar-android/src/org/briarproject/android/invitation/ContactDetailsView.java
deleted file mode 100644
index 9e8a83f78..000000000
--- a/briar-android/src/org/briarproject/android/invitation/ContactDetailsView.java
+++ /dev/null
@@ -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);
- }
-}
diff --git a/briar-android/src/org/briarproject/android/invitation/CodesDoNotMatchView.java b/briar-android/src/org/briarproject/android/invitation/ErrorView.java
similarity index 52%
rename from briar-android/src/org/briarproject/android/invitation/CodesDoNotMatchView.java
rename to briar-android/src/org/briarproject/android/invitation/ErrorView.java
index ea800ccfc..0f17a4ebf 100644
--- a/briar-android/src/org/briarproject/android/invitation/CodesDoNotMatchView.java
+++ b/briar-android/src/org/briarproject/android/invitation/ErrorView.java
@@ -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) {
diff --git a/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java b/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java
index 1f014fc0c..ebd6fcc13 100644
--- a/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java
+++ b/briar-android/src/org/briarproject/android/invitation/InvitationCodeView.java
@@ -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);
}
+
}
diff --git a/briar-android/src/org/briarproject/android/invitation/WaitForContactView.java b/briar-android/src/org/briarproject/android/invitation/WaitForContactView.java
deleted file mode 100644
index f417dd113..000000000
--- a/briar-android/src/org/briarproject/android/invitation/WaitForContactView.java
+++ /dev/null
@@ -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);
- }
-}