Skip to content

Commit

Permalink
Improved UI: show progress spinner, start request on keyboard enter.
Browse files Browse the repository at this point in the history
  • Loading branch information
tladesignz committed Apr 22, 2020
1 parent a46e463 commit a34ee22
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 43 deletions.
Expand Up @@ -2,22 +2,27 @@
/* See LICENSE for licensing information */
package org.torproject.android.ui.onboarding;

import android.app.Dialog;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
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.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
Expand Down Expand Up @@ -50,12 +55,14 @@ supported bridge type, the latter should be the same as we requested (0.1.0) any
API description:
https://github.com/NullHypothesis/bridgedb#accessing-the-moat-interface
*/
public class MoatActivity extends AppCompatActivity implements View.OnClickListener {
public class MoatActivity extends AppCompatActivity implements View.OnClickListener, TextView.OnEditorActionListener {

private static String moatBaseUrl = "https://bridges.torproject.org/moat";

private ImageView mCaptchaIv;
private ProgressBar mProgressBar;
private EditText mSolutionEt;
private Button mRequestBt;

private String mChallenge;

Expand Down Expand Up @@ -103,9 +110,14 @@ protected void onCreate(Bundle savedInstanceState) {
setTitle(getString(R.string.request_bridges));

mCaptchaIv = findViewById(R.id.captchaIv);
mProgressBar = findViewById(R.id.progressBar);
mSolutionEt = findViewById(R.id.solutionEt);
mRequestBt = findViewById(R.id.requestBt);

findViewById(R.id.requestBt).setOnClickListener(this);
mCaptchaIv.setVisibility(View.GONE);
mSolutionEt.setOnEditorActionListener(this);
mRequestBt.setEnabled(false);
mRequestBt.setOnClickListener(this);

LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver,
new IntentFilter(TorServiceConstants.ACTION_STATUS));
Expand Down Expand Up @@ -159,6 +171,27 @@ public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}


@Override
public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
Log.d(MoatActivity.class.getSimpleName(), "Editor Action: actionId=" + actionId + ", IME_ACTION_GO=" + EditorInfo.IME_ACTION_GO);

if (keyEvent != null && keyEvent.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
if (keyEvent.getAction() == KeyEvent.ACTION_UP) {
InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(textView.getWindowToken(), 0);
}

onClick(mSolutionEt);
}

return true;
}

return false;
}

@Override
protected void onDestroy() {
super.onDestroy();
Expand All @@ -167,6 +200,10 @@ protected void onDestroy() {
}

private void fetchCaptcha() {
mProgressBar.setVisibility(View.VISIBLE);
mCaptchaIv.setVisibility(View.GONE);
mRequestBt.setEnabled(false);

JsonObjectRequest request = buildRequest("fetch",
"\"type\": \"client-transports\", \"supported\": [\"obfs4\"]",
new Response.Listener<JSONObject>() {
Expand All @@ -179,19 +216,14 @@ public void onResponse(JSONObject response) {
byte[] image = Base64.decode(data.getString("image"), Base64.DEFAULT);
mCaptchaIv.setImageBitmap(BitmapFactory.decodeByteArray(image, 0, image.length));

mProgressBar.setVisibility(View.GONE);
mCaptchaIv.setVisibility(View.VISIBLE);
mRequestBt.setEnabled(true);

} catch (JSONException e) {
Log.d(MoatActivity.class.getSimpleName(), "Error decoding answer.");

new AlertDialog.Builder(MoatActivity.this)
.setTitle(R.string.error)
.setMessage(e.getLocalizedMessage())
.setNegativeButton(R.string.btn_cancel, new Dialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//Do nothing.
}
})
.show();
Log.d(MoatActivity.class.getSimpleName(), "Error decoding answer: " + response.toString());

displayError(e, response);
}
}
});
Expand All @@ -202,6 +234,9 @@ public void onClick(DialogInterface dialog, int which) {
}

private void requestBridges(String solution) {
mProgressBar.setVisibility(View.VISIBLE);
mRequestBt.setEnabled(false);

JsonObjectRequest request = buildRequest("check",
"\"id\": \"2\", \"type\": \"moat-solution\", \"transport\": \"obfs4\", \"challenge\": \""
+ mChallenge + "\", \"solution\": \"" + solution + "\", \"qrcode\": \"false\"",
Expand All @@ -222,21 +257,14 @@ public void onResponse(JSONObject response) {
Prefs.setBridgesList(sb.toString());
Prefs.putBridgesEnabled(true);

MoatActivity.this.finish();
mProgressBar.setVisibility(View.GONE);

} catch (JSONException e) {
MoatActivity.this.finish();
}
catch (JSONException e) {
Log.d(MoatActivity.class.getSimpleName(), "Error decoding answer: " + response.toString());

new AlertDialog.Builder(MoatActivity.this)
.setTitle(R.string.error)
.setMessage(e.getLocalizedMessage())
.setNegativeButton(R.string.btn_cancel, new Dialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//Do nothing.
}
})
.show();
displayError(e, response);
}
}
});
Expand Down Expand Up @@ -267,16 +295,7 @@ private JsonObjectRequest buildRequest(String endpoint, String payload, Response
public void onErrorResponse(VolleyError error) {
Log.d(MoatActivity.class.getSimpleName(), "Error response.");

new AlertDialog.Builder(MoatActivity.this)
.setTitle(R.string.error)
.setMessage(error.getLocalizedMessage())
.setNegativeButton(R.string.btn_cancel, new Dialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//Do nothing.
}
})
.show();
displayError(error, null);
}
}
) {
Expand Down Expand Up @@ -322,4 +341,27 @@ private void setUp(String host, int port, String status) {
sendIntentToService(TorServiceConstants.ACTION_STATUS);
}
}

private void displayError(Exception exception, JSONObject response) {

String detail = null;

// Try to decode potential error response.
if (response != null) {
try {
detail = response.getJSONArray("errors").getJSONObject(0).getString("detail");
} catch (JSONException e2) {
// Ignore. Show first exception instead.
}
}

mProgressBar.setVisibility(View.GONE);
mRequestBt.setEnabled(mCaptchaIv.getVisibility() == View.VISIBLE);

new AlertDialog.Builder(this)
.setTitle(R.string.error)
.setMessage(TextUtils.isEmpty(detail) ? exception.getLocalizedMessage() : detail)
.setNegativeButton(R.string.btn_cancel, null)
.show();
}
}
23 changes: 18 additions & 5 deletions app/src/main/res/layout/activity_moat.xml
Expand Up @@ -28,20 +28,33 @@
android:layout_margin="12dp"
android:text="@string/solve_captcha_instruction" />

<ImageView
android:id="@+id/captchaIv"
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="240dp"
android:contentDescription="@string/captcha"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
android:layout_margin="12dp">

<ImageView
android:id="@+id/captchaIv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/captcha"
tools:srcCompat="@tools:sample/backgrounds/scenic" />

<ProgressBar
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</RelativeLayout>

<EditText
android:id="@+id/solutionEt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints=""
android:hint="@string/enter_characters_from_image"
android:ems="10"
android:hint="@string/enter_characters_from_image"
android:imeOptions="actionSend"
android:inputType="textShortMessage|text" />

<Button
Expand Down

0 comments on commit a34ee22

Please sign in to comment.