8000 Synced branch with master and fixed bugs specific to accessing of fil… · misaochan/apps-android-commons@fe57db5 · GitHub
Skip to content

Commit fe57db5

Browse files
committed
Synced branch with master and fixed bugs specific to accessing of files in Nougat and above
2 parents 836a1e3 + 1bd782f commit fe57db5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+862
-258
lines changed

app/build.gradle

+5-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ dependencies {
1313
compile 'org.mediawiki:api:1.3'
1414
compile 'commons-codec:commons-codec:1.10'
1515
compile 'com.github.pedrovgs:renderers:3.3.3'
16-
compile 'com.google.code.gson:gson:2.8.0'
16+
compile 'com.google.code.gson:gson:2.8.1'
1717
compile 'com.jakewharton.timber:timber:4.5.1'
1818
compile 'info.debatty:java-string-similarity:0.24'
1919
compile ('com.mapbox.mapboxsdk:mapbox-android-sdk:5.1.0@aar'){
@@ -24,6 +24,8 @@ dependencies {
2424
compile "com.android.support:appcompat-v7:${project.supportLibVersion}"
2525
compile "com.android.support:design:${project.supportLibVersion}"
2626

27+
compile "com.android.support:cardview-v7:${project.supportLibVersion}"
28+
2729
compile "com.jakewharton:butterknife:$BUTTERKNIFE_VERSION"
2830
annotationProcessor "com.jakewharton:butterknife-compiler:$BUTTERKNIFE_VERSION"
2931

@@ -43,12 +45,12 @@ dependencies {
4345
compile 'com.facebook.stetho:stetho:1.5.0'
4446

4547
testCompile 'junit:junit:4.12'
46-
testCompile 'org.robolectric:robolectric:3.3.2'
48+
testCompile 'org.robolectric:robolectric:3.4'
4749

4850
testCompile 'com.squareup.okhttp3:mockwebserver:3.8.1'
4951
androidTestCompile 'com.squareup.okhttp3:mockwebserver:3.8.1'
5052
androidTestCompile "com.android.support:support-annotations:${project.supportLibVersion}"
51-
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
53+
androidTestCompile 'com.android.support.test.espresso:espresso-core:3.0.1'
5254

5355
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
5456
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'

app/src/main/AndroidManifest.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
android:name=".CommonsApplication"
2121
android:icon="@drawable/ic_launcher"
2222
android:label="@string/app_name"
23-
android:theme="@style/Theme.AppCompat"
23+
android:theme="@style/LightAppTheme"
2424
android:supportsRtl="true" >
2525
<activity android:name="org.acra.CrashReportDialog"
2626
android:theme="@android:style/Theme.Dialog"

app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java

+133-87
Original file line numberDiff line numberDiff line change
@@ -5,57 +5,66 @@
55
import android.content.Intent;
66
import android.content.SharedPreferences;
77
import android.os.Bundle;
8+
import android.support.annotation.ColorRes;
9+
import android.support.annotation.NonNull;
10+
import android.support.annotation.StringRes;
811
import android.support.v4.app.NavUtils;
12+
import android.support.v4.content.ContextCompat;
13+
import android.support.v7.app.AppCompatDelegate;
914
import android.text.Editable;
1015
import android.text.TextWatcher;
16+
import android.view.MenuInflater;
1117
import android.view.MenuItem;
1218
import android.view.View;
19+
import android.view.ViewGroup;
1320
import android.widget.Button;
1421
import android.widget.EditText;
1522
import android.widget.TextView;
16-
import android.widget.Toast;
1723

24+
import butterknife.BindView;
25+
import butterknife.ButterKnife;
1826
import fr.free.nrw.commons.BuildConfig;
1927
import fr.free.nrw.commons.CommonsApplication;
28+
import fr.free.nrw.commons.PageTitle;
2029
import fr.free.nrw.commons.R;
30+
import fr.free.nrw.commons.Utils;
2131
import fr.free.nrw.commons.WelcomeActivity;
22-
23-
import fr.free.nrw.commons.PageTitle;
2432
import fr.free.nrw.commons.contributions.ContributionsActivity;
2533
import timber.log.Timber;
2634

2735
import static android.view.KeyEvent.KEYCODE_ENTER;
2836
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
2937

30-
3138
public class LoginActivity extends AccountAuthenticatorActivity {
3239

3340
public static final String PARAM_USERNAME = "fr.free.nrw.commons.login.username";
3441

35-
private SharedPreferences prefs = null;
42+
@BindView(R.id.loginButton) Button loginButton;
43+
@BindView(R.id.signupButton) Button signupButton;
44+
@BindView(R.id.loginUsername) EditText usernameEdit;
45+
@BindView(R.id.loginPassword) EditText passwordEdit;
46+
@BindView(R.id.loginTwoFactor) EditText twoFactorEdit;
47+
@BindView(R.id.error_message_container) ViewGroup errorMessageContainer;
48+
@BindView(R.id.error_message) TextView errorMessage;
3649

37-
private Button loginButton;
38-
private EditText usernameEdit;
39-
private EditText passwordEdit;
40-
private EditText twoFactorEdit;
50+
private CommonsApplication app;
4151
ProgressDialog progressDialog;
52+
private AppCompatDelegate delegate;
53+
private SharedPreferences prefs = null;
4254
private LoginTextWatcher textWatcher = new LoginTextWatcher();
4355

44-
private CommonsApplication app;
45-
4656
@Override
4757
public void onCreate(Bundle savedInstanceState) {
58+
setTheme(Utils.isDarkTheme(this) ? R.style.DarkAppTheme : R.style.LightAppTheme);
59+
getDelegate().installViewFactory();
60+
getDelegate().onCreate(savedInstanceState);
4861
super.onCreate(savedInstanceState);
4962

5063
app = CommonsApplication.getInstance();
5164

5265
setContentView(R.layout.activity_login);
5366

54-
loginButton = (Button) findViewById(R.id.loginButton);
55-
Button signupButton = (Button) findViewById(R.id.signupButton);
56-
usernameEdit = (EditText) findViewById(R.id.loginUsername);
57-
passwordEdit = (EditText) findViewById(R.id.loginPassword);
58-
twoFactorEdit = (EditText) findViewById(R.id.loginTwoFactor);
67+
ButterKnife.bind(this);
5968

6069
prefs = getSharedPreferences("fr.free.nrw.commons", MODE_PRIVATE);
6170

@@ -64,45 +73,17 @@ public void onCreate(Bundle savedInstanceState) {
6473
twoFactorEdit.addTextChangedListener(textWatcher);
6574
passwordEdit.setOnEditorActionListener(newLoginInputActionListener());
6675

67-
loginButton.setOnClickListener(this::performLogin);
68-
signupButton.setOnClickListener(this::signUp);
69-
}
70-
71-
private class LoginTextWatcher implements TextWatcher {
72-
@Override
73-
public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
74-
}
75-
76-
@Override
77-
public void onTextChanged(CharSequence charSequence, int start, int count, int after) {
78-
}
79-
80-
@Override
81-
public void afterTextChanged(Editable editable) {
82-
if (usernameEdit.getText().length() != 0 && passwordEdit.getText().length() != 0 &&
83-
(BuildConfig.DEBUG || twoFactorEdit.getText().length() != 0 || twoFactorEdit.getVisibility() != View.VISIBLE)) {
84-
loginButton.setEnabled(true);
85-
} else {
86-
loginButton.setEnabled(false);
87-
}
88-
}
76+
loginButton.setOnClickListener(view -> performLogin());
77+
signupButton.setOnClickListener(view -> signUp());
8978
}
9079

91-
private TextView.OnEditorActionListener newLoginInputActionListener() {
92-
return (textView, actionId, keyEvent) -> {
93-
if (loginButton.isEnabled()) {
94-
if (actionId == IME_ACTION_DONE) {
95-
performLogin(textView);
96-
return true;
97-
} else if ((keyEvent != null) && keyEvent.getKeyCode() == KEYCODE_ENTER) {
98-
performLogin(textView);
99-
return true;
100-
}
101-
}
102-
return false;
103-
};
80+
@Override
81+
protected void onPostCreate(Bundle savedInstanceState) {
82+
super.onPostCreate(savedInstanceState);
83+
getDelegate().onPostCreate(savedInstanceState);
10484
}
10585

86+
@Override
10687
protected void onResume() {
10788
super.onResume();
10889
if (prefs.getBoolean("firstrun", true)) {
@@ -127,31 +108,31 @@ protected void onDestroy() {
127108
usernameEdit.removeTextChangedListener(textWatcher);
128109
passwordEdit.removeTextChangedListener(textWatcher);
129110
twoFactorEdit.removeTextChangedListener(textWatcher);
111+
delegate.onDestroy();
130112
super.onDestroy();
131113
}
132114

133-
private void performLogin(View view) {
134-
Timber.d("Login to start!");
135-
LoginTask task = getLoginTask();
136-
task.execute();
115+
@Override
116+
protected void onStart() {
117+
super.onStart();
118+
delegate.onStart();
137119
}
138120

139-
private LoginTask getLoginTask() {
140-
return new LoginTask(
141-
this,
142-
canonicializeUsername(usernameEdit.getText().toString()),
143-
passwordEdit.getText().toString(),
144-
twoFactorEdit.getText().toString()
145-
);
121+
@Override
122+
protected void onStop() {
123+
super.onStop();
124+
delegate.onStop();
146125
}
147126

148-
/**
149-
* Because Mediawiki is upercase-first-char-then-case-sensitive :)
150-
* @param username String
151-
* @return String canonicial username
152-
*/
153-
private String canonicializeUsername(String username) {
154-
return new PageTitle(username).getText();
127+
@Override
128+
protected void onPostResume() {
129+
super.onPostResume();
130+
getDelegate().onPostResume();
131+
}
132+
133+
@Override
134+
public void setContentView(View view, ViewGroup.LayoutParams params) {
135+
getDelegate().setContentView(view, params);
155136
}
156137

157138
@Override
@@ -164,36 +145,28 @@ public boolean onOptionsItemSelected(MenuItem item) {
164145
return super.onOptionsItemSelected(item);
165146
}
166147

167-
/**
168-
* Called when Sign Up button is clicked.
169-
* @param view View
170-
*/
171-
public void signUp(View view) {
172-
Intent intent = new Intent(this, SignupActivity.class);
173-
startActivity(intent);
148+
@Override
149+
@NonNull
150+
public MenuInflater getMenuInflater() {
151+
return getDelegate().getMenuInflater();
174152
}
175153

176154
public void askUserForTwoFactorAuth() {
177155
if (BuildConfig.DEBUG) {
178156
twoFactorEdit.setVisibility(View.VISIBLE);
179-
showUserToastAndCancelDialog(R.string.login_failed_2fa_needed);
157+
showMessageAndCancelDialog(R.string.login_failed_2fa_needed);
180158
} else {
181-
showUserToastAndCancelDialog(R.string.login_failed_2fa_not_supported);
159+
showMessageAndCancelDialog(R.string.login_failed_2fa_not_supported);
182160
}
183161
}
184162

185-
public void showUserToastAndCancelDialog(int resId) {
186-
showUserToast(resId);
163+
public void showMessageAndCancelDialog(@StringRes int resId) {
164+
showMessage(resId, R.color.secondaryDarkColor);
187165
progressDialog.cancel();
188166
}
189167

190-
private void showUserToast(int resId) {
191-
Toast.makeText(this, resId, Toast.LENGTH_LONG).show();
192-
}
193-
194-
public void showSuccessToastAndDismissDialog() {
195-
Toast successToast = Toast.makeText(this, R.string.login_success, Toast.LENGTH_SHORT);
196-
successToast.show();
168+
public void showSuccessAndDismissDialog() {
169+
showMessage(R.string.login_success, R.color.primaryDarkColor);
197170
progressDialog.dismiss();
198171
}
199172

@@ -207,4 +180,77 @@ public void startMainActivity() {
207180
finish();
208181
}
209182

183+
private void performLogin() {
184+
Timber.d("Login to start!");
185+
LoginTask task = getLoginTask();
186+
task.execute();
187+
}
188+
189+
private void signUp() {
190+
Intent intent = new Intent(this, SignupActivity.class);
191+
startActivity(intent);
192+
}
193+
194+
private TextView.OnEditorActionListener newLoginInputActionListener() {
195+
return (textView, actionId, keyEvent) -> {
196+
if (loginButton.isEnabled()) {
197+
if (actionId == IME_ACTION_DONE) {
198+
performLogin();
199+
return true;
200+
} else if ((keyEvent != null) && keyEvent.getKeyCode() == KEYCODE_ENTER) {
201+
performLogin();
202+
return true;
203+
}
204+
}
205+
return false;
206+
};
207+
}
208+
209+
private LoginTask getLoginTask() {
210+
return new LoginTask(
211+
this,
212+
canonicializeUsername(usernameEdit.getText().toString()),
213+
passwordEdit.getText().toString(),
214+
twoFactorEdit.getText().toString()
215+
);
216+
}
217+
218+
/**
219+
* Because Mediawiki is upercase-first-char-then-case-sensitive :)
220+
* @param username String
221+
* @return String canonicial username
222+
*/
223+
private String canonicializeUsername(String username) {
224+
return new PageTitle(username).getText();
225+
}
226+
227+
private void showMessage(@StringRes int resId, @ColorRes int colorResId) {
228+
errorMessage.setText(getString(resId));
229+
errorMessage.setTextColor(ContextCompat.getColor(this, colorResId));
230+
errorMessageContainer.setVisibility(View.VISIBLE);
231+
}
232+
233+
private AppCompatDelegate getDelegate() {
234+
if (delegate == null) {
235+
delegate = AppCompatDelegate.create(this, null);
236+
}
237+
return delegate;
238+
}
239+
240+
private class LoginTextWatcher implements TextWatcher {
241+
@Override
242+
public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
243+
}
244+
245+
@Override
246+
public void onTextChanged(CharSequence charSequence, int start, int count, int after) {
247+
}
248+
249+
@Override
250+
public void afterTextChanged(Editable editable) {
251+
boolean enabled = usernameEdit.getText().length() != 0 && passwordEdit.getText().length() != 0 &&
252+
(BuildConfig.DEBUG || twoFactorEdit.getText().length() != 0 || twoFactorEdit.getVisibility() != View.VISIBLE);
253+
loginButton.setEnabled(enabled);
254+
}
255+
}
210256
}

app/src/main/java/fr/free/nrw/commons/auth/LoginTask.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ protected void onPostExecute(String result) {
7272
}
7373

7474
private void handlePassResult() {
75-
loginActivity.showSuccessToastAndDismissDialog();
75+
loginActivity.showSuccessAndDismissDialog();
7676

7777
AccountAuthenticatorResponse response = null;
7878

@@ -99,27 +99,27 @@ private void handlePassResult() {
9999
private void handleOtherResults(String result) {
100100
if (result.equals("NetworkFailure")) {
101101
// Matches NetworkFailure which is created by the doInBackground method
102-
loginActivity.showUserToastAndCancelDialog(R.string.login_failed_network);
102+
loginActivity.showMessageAndCancelDialog(R.string.login_failed_network);
103103
} else if (result.toLowerCase().contains("nosuchuser".toLowerCase()) || result.toLowerCase().contains("noname".toLowerCase())) {
104104
// Matches nosuchuser, nosuchusershort, noname
105-
loginActivity.showUserToastAndCancelDialog(R.string.login_failed_username);
105+
loginActivity.showMessageAndCancelDialog(R.string.login_failed_username);
106106
loginActivity.emptySensitiveEditFields();
107107
} else if (result.toLowerCase().contains("wrongpassword".toLowerCase())) {
108108
// Matches wrongpassword, wrongpasswordempty
109-
loginActivity.showUserToastAndCancelDialog(R.string.login_failed_password);
109+
loginActivity.showMessageAndCancelDialog(R.string.login_failed_password);
110110
loginActivity.emptySensitiveEditFields();
111111
} else if (result.toLowerCase().contains("throttle".toLowerCase())) {
112112
// Matches unknown throttle error codes
113-
loginActivity.showUserToastAndCancelDialog(R.string.login_failed_throttled);
113+
loginActivity.showMessageAndCancelDialog(R.string.login_failed_throttled);
114114
} else if (result.toLowerCase().contains("userblocked".toLowerCase())) {
115115
// Matches login-userblocked
116-
loginActivity.showUserToastAndCancelDialog(R.string.login_failed_blocked);
116+
loginActivity.showMessageAndCancelDialog(R.string.login_failed_blocked);
117117
} else if (result.equals("2FA")) {
118118
loginActivity.askUserForTwoFactorAuth();
119119
} else {
120120
// Occurs with unhandled login failure codes
121121
Timber.d("Login failed with reason: %s", result);
122-
loginActivity.showUserToastAndCancelDialog(R.string.login_failed_generic);
122+
loginActivity.showMessageAndCancelDialog(R.string.login_failed_generic);
123123
}
124124
}
125125
}

0 commit comments

Comments
 (0)