Start applying MVP

This commit is contained in:
Paul Schaub 2018-02-01 08:24:08 +01:00
parent 6067d70189
commit 70b44820fd
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
10 changed files with 245 additions and 21 deletions

View File

@ -24,7 +24,7 @@
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View File

@ -0,0 +1,19 @@
package de.vanitasvitae.slam;
import android.text.Editable;
import android.text.TextWatcher;
/**
* Abstract TextWatcher, that has method stubs for all methods except {@link TextWatcher#afterTextChanged(Editable)}.
*/
public abstract class AfterTextChangedListener implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Do nothing
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Do nothing
}
}

View File

@ -0,0 +1,21 @@
package de.vanitasvitae.slam;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
/**
* Abstract listener, that listens on a TextView for ActionDone events.
*/
public abstract class EditorActionDoneListener implements TextView.OnEditorActionListener {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
onEditorActionDone(v);
return true;
}
return false;
}
public abstract void onEditorActionDone(TextView v);
}

View File

@ -0,0 +1,62 @@
package de.vanitasvitae.slam.activity;
import android.os.Handler;
import de.vanitasvitae.slam.mvp_contracts.LoginContract;
/**
* Dummy presenter, that has no model.
* This is used to demonstrate the capabilities of the view.
* Created by Paul Schaub on 01.02.18.
*/
public class DummyLoginPresenter implements LoginContract.Presenter {
private LoginContract.View view;
public DummyLoginPresenter(LoginContract.View view) {
this.view = view;
}
@Override
public void jidChanged(String jid) {
if (jid.length() < 10) {
view.showInvalidJidError();
} else {
view.hideInvalidJidError();
}
}
@Override
public void passwordChanged(String password) {
if (password.length() < 5) {
view.showInvalidPasswordError();
} else if(!password.equals("swordfish")) {
view.showIncorrectPasswordError();
} else {
view.hidePasswordError();
}
}
@Override
public void loginClicked() {
// show indicator
view.showProgressIndicator();
final Handler handler = new Handler();
// Hide indicator
handler.postDelayed(new Runnable() {
@Override
public void run() {
view.hideProgressIndicator();
}
}, 2000);
// startActivity
handler.postDelayed(new Runnable() {
@Override
public void run() {
view.navigateToMainActivity();
}
}, 2500);
}
}

View File

@ -3,28 +3,52 @@ package de.vanitasvitae.slam.activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
import android.support.v7.widget.Toolbar;
import android.view.KeyEvent;
import android.text.Editable;
import android.view.Menu;
import android.view.inputmethod.EditorInfo;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import de.vanitasvitae.slam.AfterTextChangedListener;
import de.vanitasvitae.slam.EditorActionDoneListener;
import de.vanitasvitae.slam.R;
import de.vanitasvitae.slam.activity.abstr.ThemedAppCompatActivity;
import de.vanitasvitae.slam.mvp_contracts.LoginContract;
public class LoginActivity extends ThemedAppCompatActivity {
public class LoginActivity extends ThemedAppCompatActivity implements LoginContract.View {
// Presenter of this view
private LoginContract.Presenter presenter;
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.progressbar)
ProgressBar progressBar;
@BindView(R.id.login_username_layout)
TextInputLayout inputUsernameLayout;
@BindView(R.id.login_username)
TextInputEditText inputUsername;
@BindView(R.id.login_password_layout)
TextInputLayout inputPasswordLayout;
@BindView(R.id.login_password)
TextInputEditText inputPassword;
@BindView(R.id.button_login)
Button buttonLogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -33,22 +57,34 @@ public class LoginActivity extends ThemedAppCompatActivity {
setSupportActionBar(toolbar);
inputPassword.setOnEditorActionListener(new TextView.OnEditorActionListener() {
this.presenter = new DummyLoginPresenter(this);
// attempt login on editor action done
inputPassword.setOnEditorActionListener(new EditorActionDoneListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
login();
return true;
}
return false;
public void onEditorActionDone(TextView v) {
login();
}
});
inputUsername.addTextChangedListener(new AfterTextChangedListener() {
@Override
public void afterTextChanged(Editable s) {
presenter.jidChanged(s.toString());
}
});
inputPassword.addTextChangedListener(new AfterTextChangedListener() {
@Override
public void afterTextChanged(Editable s) {
presenter.passwordChanged(s.toString());
}
});
}
@OnClick(R.id.button_login)
void login() {
startActivity(new Intent(this, MainActivity.class));
finish();
presenter.loginClicked();
}
@Override
@ -56,5 +92,54 @@ public class LoginActivity extends ThemedAppCompatActivity {
getMenuInflater().inflate(R.menu.menu_login, menu);
return true;
}
@Override
public void showInvalidJidError() {
inputUsernameLayout.setError(getResources().getText(R.string.error_invalid_jid));
}
@Override
public void showInvalidPasswordError() {
inputPasswordLayout.setError(getResources().getText(R.string.error_invalid_password));
}
@Override
public void showIncorrectPasswordError() {
inputPasswordLayout.setError(getResources().getText(R.string.error_incorrect_password));
}
@Override
public void hideInvalidJidError() {
inputUsernameLayout.setError(null);
}
@Override
public void hidePasswordError() {
inputPasswordLayout.setError(null);
}
@Override
public void showServerNotFoundError() {
Toast.makeText(this, R.string.error_server_not_found, Toast.LENGTH_LONG).show();
}
@Override
public void showProgressIndicator() {
progressBar.setVisibility(View.VISIBLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
@Override
public void hideProgressIndicator() {
progressBar.setVisibility(View.GONE);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
@Override
public void navigateToMainActivity() {
startActivity(new Intent(this, MainActivity.class));
finish();
}
}

View File

@ -7,16 +7,13 @@ import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import de.vanitasvitae.slam.R;
import de.vanitasvitae.slam.activity.abstr.ThemedAppCompatActivity;
/**
* Created by vanitas on 22.01.18.

View File

@ -1,4 +1,4 @@
package de.vanitasvitae.slam.activity;
package de.vanitasvitae.slam.activity.abstr;
import android.annotation.SuppressLint;
import android.content.Intent;
@ -13,7 +13,7 @@ import java.util.Arrays;
import de.vanitasvitae.slam.R;
/**
* Created by Paul Schaub on 27.01.18.
* AppCompatActivity that can easily be themed.
*/
public abstract class ThemedAppCompatActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {

View File

@ -0,0 +1,26 @@
package de.vanitasvitae.slam.mvp_contracts;
/**
* Model-View-Presenter contract of the login screen.
* Created by Paul Schaub on 01.02.18.
*/
public interface LoginContract {
interface View {
void showInvalidJidError();
void hideInvalidJidError();
void showInvalidPasswordError();
void showIncorrectPasswordError();
void hidePasswordError();
void showServerNotFoundError();
void showProgressIndicator();
void hideProgressIndicator();
void navigateToMainActivity();
}
interface Presenter {
void jidChanged(String jid);
void passwordChanged(String password);
void loginClicked();
}
}

View File

@ -52,8 +52,10 @@
<!-- Username -->
<android.support.design.widget.TextInputLayout
android:id="@+id/login_username_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
app:errorEnabled="true">
<android.support.design.widget.TextInputEditText
android:id="@+id/login_username"
@ -67,8 +69,10 @@
<!-- Password -->
<android.support.design.widget.TextInputLayout
android:id="@+id/login_password_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
app:errorEnabled="true">
<android.support.design.widget.TextInputEditText
android:id="@+id/login_password"
@ -98,6 +102,15 @@
</android.support.v7.widget.CardView>
<ProgressBar
android:id="@+id/progressbar"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:elevation="30dp"/>
</RelativeLayout>
</ScrollView>

View File

@ -27,5 +27,6 @@
<string name="item_navdrawer__contacts">Contacts</string>
<string name="item_navdrawer__bookmarks">Bookmarks</string>
<string name="item_navdrawer__settings">Settings</string>
<string name="error_server_not_found">Server not found</string>
</resources>