├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── ru │ │ └── startandroid │ │ └── pincode │ │ ├── MainActivity.java │ │ ├── StartActivity.java │ │ ├── app │ │ ├── App.java │ │ ├── ComponentsHolder.java │ │ └── dagger │ │ │ ├── AppComponent.java │ │ │ ├── AppModule.java │ │ │ ├── AppScope.java │ │ │ └── AppSubComponentsModule.java │ │ ├── base │ │ ├── dagger │ │ │ ├── ActivityComponent.java │ │ │ ├── ActivityComponentBuilder.java │ │ │ └── ActivityModule.java │ │ └── mvp │ │ │ ├── MvpPresenter.java │ │ │ ├── MvpView.java │ │ │ └── PresenterBase.java │ │ ├── common │ │ └── Constants.java │ │ ├── pin │ │ ├── dagger │ │ │ ├── PinCodeActivityComponent.java │ │ │ ├── PinCodeActivityModule.java │ │ │ └── PinCodeActivityScope.java │ │ └── mvp │ │ │ ├── PinCodeActivity.java │ │ │ ├── PinCodeChangePresenter.java │ │ │ ├── PinCodeCheckPresenter.java │ │ │ ├── PinCodeContract.java │ │ │ └── PinCodeCreatePresenter.java │ │ └── storage │ │ └── Preferences.java │ └── res │ ├── layout │ ├── main_activity.xml │ └── pincode_activity.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.iws 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .idea/tasks.xml 8 | .idea/vcs.xml 9 | .DS_Store 10 | /build 11 | /captures 12 | .externalNativeBuild 13 | 14 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'com.neenbedankt.android-apt' 3 | 4 | android { 5 | compileSdkVersion 25 6 | buildToolsVersion "25.0.3" 7 | defaultConfig { 8 | applicationId "ru.startandroid.pincode" 9 | minSdkVersion 15 10 | targetSdkVersion 25 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | buildscript { 24 | repositories { 25 | mavenCentral() 26 | } 27 | dependencies { 28 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 29 | } 30 | } 31 | 32 | dependencies { 33 | compile fileTree(dir: 'libs', include: ['*.jar']) 34 | compile 'com.android.support:appcompat-v7:25.3.1' 35 | 36 | // rxjava 37 | compile 'io.reactivex.rxjava2:rxjava:2.1.0' 38 | compile 'io.reactivex.rxjava2:rxandroid:2.0.1' 39 | compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0' 40 | 41 | // dagger 42 | compile 'com.google.dagger:dagger:2.11-rc2' 43 | apt 'com.google.dagger:dagger-compiler:2.11-rc2' 44 | 45 | // butter knife 46 | compile 'com.jakewharton:butterknife:8.6.0' 47 | compile 'com.jakewharton:butterknife-compiler:8.6.0' 48 | 49 | } 50 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/MainActivity.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | import butterknife.ButterKnife; 7 | import butterknife.OnClick; 8 | import ru.startandroid.pincode.app.App; 9 | import ru.startandroid.pincode.pin.mvp.PinCodeActivity; 10 | 11 | public class MainActivity extends AppCompatActivity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.main_activity); 17 | ButterKnife.bind(this); 18 | } 19 | 20 | @OnClick(R.id.change_pin) 21 | void onChangePinClick() { 22 | PinCodeActivity.changePinCode(this); 23 | } 24 | 25 | @OnClick(R.id.reset_pin) 26 | void onResetPinClick() { 27 | App.getApp(this).getComponentsHolder().getAppComponent().getPreferences().setPin(""); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/StartActivity.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.text.TextUtils; 6 | 7 | import ru.startandroid.pincode.app.App; 8 | import ru.startandroid.pincode.pin.mvp.PinCodeActivity; 9 | import ru.startandroid.pincode.storage.Preferences; 10 | 11 | public class StartActivity extends AppCompatActivity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | 17 | Preferences preferences = App.getApp(this).getComponentsHolder().getAppComponent().getPreferences(); 18 | 19 | String pin = preferences.getPin(); 20 | 21 | // check current PIN 22 | if (TextUtils.isEmpty(pin)) { 23 | PinCodeActivity.createPinCode(this); 24 | } else { 25 | PinCodeActivity.checkPinCode(this); 26 | } 27 | finish(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/app/App.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.app; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | public class App extends Application { 7 | 8 | 9 | private ComponentsHolder componentsHolder; 10 | 11 | public static App getApp(Context context) { 12 | return (App)context.getApplicationContext(); 13 | } 14 | 15 | @Override 16 | public void onCreate() { 17 | super.onCreate(); 18 | componentsHolder = new ComponentsHolder(this); 19 | componentsHolder.init(); 20 | } 21 | 22 | public ComponentsHolder getComponentsHolder() { 23 | return componentsHolder; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/app/ComponentsHolder.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.app; 2 | 3 | import android.content.Context; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import javax.inject.Inject; 9 | import javax.inject.Provider; 10 | 11 | import ru.startandroid.pincode.app.dagger.AppComponent; 12 | import ru.startandroid.pincode.app.dagger.AppModule; 13 | import ru.startandroid.pincode.app.dagger.DaggerAppComponent; 14 | import ru.startandroid.pincode.base.dagger.ActivityComponent; 15 | import ru.startandroid.pincode.base.dagger.ActivityComponentBuilder; 16 | import ru.startandroid.pincode.base.dagger.ActivityModule; 17 | 18 | public class ComponentsHolder { 19 | 20 | private final Context context; 21 | 22 | @Inject 23 | Map, Provider> builders; 24 | 25 | private Map, ActivityComponent> components; 26 | private AppComponent appComponent; 27 | 28 | public ComponentsHolder(Context context) { 29 | this.context = context; 30 | } 31 | 32 | void init() { 33 | appComponent = DaggerAppComponent.builder().appModule(new AppModule(context)).build(); 34 | appComponent.injectComponentsHolder(this); 35 | components = new HashMap<>(); 36 | } 37 | 38 | public AppComponent getAppComponent() { 39 | return appComponent; 40 | } 41 | 42 | 43 | public ActivityComponent getActivityComponent(Class cls) { 44 | return getActivityComponent(cls, null); 45 | } 46 | 47 | public ActivityComponent getActivityComponent(Class cls, ActivityModule module) { 48 | ActivityComponent component = components.get(cls); 49 | if (component == null) { 50 | ActivityComponentBuilder builder = builders.get(cls).get(); 51 | if (module != null) { 52 | builder.module(module); 53 | } 54 | component = builder.build(); 55 | components.put(cls, component); 56 | } 57 | return component; 58 | } 59 | 60 | public void releaseActivityComponent(Class cls) { 61 | components.put(cls, null); 62 | 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/app/dagger/AppComponent.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.app.dagger; 2 | 3 | import dagger.Component; 4 | import ru.startandroid.pincode.app.ComponentsHolder; 5 | import ru.startandroid.pincode.storage.Preferences; 6 | 7 | @AppScope 8 | @Component(modules = {AppModule.class, AppSubComponentsModule.class}) 9 | public interface AppComponent { 10 | void injectComponentsHolder(ComponentsHolder componentsHolder); 11 | Preferences getPreferences(); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/app/dagger/AppModule.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.app.dagger; 2 | 3 | import android.content.Context; 4 | 5 | import dagger.Module; 6 | import dagger.Provides; 7 | import ru.startandroid.pincode.storage.Preferences; 8 | 9 | @Module 10 | public class AppModule { 11 | 12 | private final Context context; 13 | 14 | public AppModule(Context context) { 15 | this.context = context; 16 | } 17 | 18 | @AppScope 19 | @Provides 20 | Context provideContext() { 21 | return context; 22 | } 23 | 24 | @AppScope 25 | @Provides 26 | Preferences providePreferences(Context context) { 27 | return new Preferences(context); 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/app/dagger/AppScope.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.app.dagger; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Scope; 7 | 8 | @Scope 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface AppScope { 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/app/dagger/AppSubComponentsModule.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.app.dagger; 2 | 3 | import dagger.Module; 4 | import dagger.Provides; 5 | import dagger.multibindings.ClassKey; 6 | import dagger.multibindings.IntoMap; 7 | import ru.startandroid.pincode.base.dagger.ActivityComponentBuilder; 8 | import ru.startandroid.pincode.pin.dagger.PinCodeActivityComponent; 9 | import ru.startandroid.pincode.pin.mvp.PinCodeActivity; 10 | 11 | @Module(subcomponents = {PinCodeActivityComponent.class}) 12 | public class AppSubComponentsModule { 13 | 14 | @Provides 15 | @IntoMap 16 | @ClassKey(PinCodeActivity.class) 17 | ActivityComponentBuilder provideSplashViewBuilder(PinCodeActivityComponent.Builder builder) { 18 | return builder; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/base/dagger/ActivityComponent.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.base.dagger; 2 | 3 | public interface ActivityComponent { 4 | void inject(A activity); 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/base/dagger/ActivityComponentBuilder.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.base.dagger; 2 | 3 | public interface ActivityComponentBuilder { 4 | C build(); 5 | ActivityComponentBuilder module(M module); 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/base/dagger/ActivityModule.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.base.dagger; 2 | 3 | public interface ActivityModule { 4 | } 5 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/base/mvp/MvpPresenter.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.base.mvp; 2 | 3 | public interface MvpPresenter { 4 | 5 | void attachView(V mvpView); 6 | 7 | void viewIsReady(); 8 | 9 | void detachView(); 10 | 11 | void destroy(); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/base/mvp/MvpView.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.base.mvp; 2 | 3 | public interface MvpView { 4 | } 5 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/base/mvp/PresenterBase.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.base.mvp; 2 | 3 | public abstract class PresenterBase implements MvpPresenter { 4 | 5 | private T view; 6 | 7 | @Override 8 | public void attachView(T mvpView) { 9 | view = mvpView; 10 | } 11 | 12 | @Override 13 | public void detachView() { 14 | view = null; 15 | } 16 | 17 | public T getView() { 18 | return view; 19 | } 20 | 21 | protected boolean isViewAttached() { 22 | return view != null; 23 | } 24 | 25 | @Override 26 | public void destroy() { 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/common/Constants.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.common; 2 | 3 | public class Constants { 4 | 5 | public enum PinCodeMode { 6 | CREATE, CHECK, CHANGE; 7 | } 8 | 9 | public static final String EXTRA_MODE = "mode"; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/pin/dagger/PinCodeActivityComponent.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.pin.dagger; 2 | 3 | import dagger.Subcomponent; 4 | import ru.startandroid.pincode.base.dagger.ActivityComponent; 5 | import ru.startandroid.pincode.base.dagger.ActivityComponentBuilder; 6 | import ru.startandroid.pincode.pin.mvp.PinCodeActivity; 7 | 8 | @PinCodeActivityScope 9 | @Subcomponent(modules = PinCodeActivityModule.class) 10 | public interface PinCodeActivityComponent extends ActivityComponent { 11 | 12 | @Subcomponent.Builder 13 | interface Builder extends ActivityComponentBuilder { 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/pin/dagger/PinCodeActivityModule.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.pin.dagger; 2 | 3 | import dagger.Module; 4 | import dagger.Provides; 5 | import ru.startandroid.pincode.base.dagger.ActivityModule; 6 | import ru.startandroid.pincode.common.Constants; 7 | import ru.startandroid.pincode.pin.mvp.PinCodeChangePresenter; 8 | import ru.startandroid.pincode.pin.mvp.PinCodeCheckPresenter; 9 | import ru.startandroid.pincode.pin.mvp.PinCodeContract; 10 | import ru.startandroid.pincode.pin.mvp.PinCodeCreatePresenter; 11 | import ru.startandroid.pincode.storage.Preferences; 12 | 13 | @Module 14 | public class PinCodeActivityModule implements ActivityModule { 15 | 16 | private final Constants.PinCodeMode pinCodeMode; 17 | 18 | public PinCodeActivityModule(Constants.PinCodeMode pinCodeMode) { 19 | this.pinCodeMode = pinCodeMode; 20 | } 21 | 22 | @PinCodeActivityScope 23 | @Provides 24 | PinCodeContract.Presenter providePinCodePresenter(Preferences preferences) { 25 | switch (pinCodeMode) { 26 | case CREATE: 27 | return new PinCodeCreatePresenter(preferences); 28 | case CHANGE: 29 | return new PinCodeChangePresenter(preferences); 30 | case CHECK: 31 | return new PinCodeCheckPresenter(preferences); 32 | default: 33 | return null; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/pin/dagger/PinCodeActivityScope.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.pin.dagger; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Scope; 7 | 8 | @Scope 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface PinCodeActivityScope { 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/pin/mvp/PinCodeActivity.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.pin.mvp; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.View; 8 | import android.widget.EditText; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import com.jakewharton.rxbinding2.widget.RxTextView; 13 | import com.jakewharton.rxbinding2.widget.TextViewAfterTextChangeEvent; 14 | 15 | import javax.inject.Inject; 16 | 17 | import butterknife.BindView; 18 | import butterknife.ButterKnife; 19 | import io.reactivex.annotations.NonNull; 20 | import io.reactivex.functions.Consumer; 21 | import io.reactivex.functions.Predicate; 22 | import ru.startandroid.pincode.MainActivity; 23 | import ru.startandroid.pincode.R; 24 | import ru.startandroid.pincode.app.App; 25 | import ru.startandroid.pincode.common.Constants; 26 | import ru.startandroid.pincode.pin.dagger.PinCodeActivityModule; 27 | 28 | public class PinCodeActivity extends AppCompatActivity implements PinCodeContract.View { 29 | 30 | @BindView(R.id.first_label) 31 | TextView textViewFirstLabel; 32 | 33 | @BindView(R.id.first_value) 34 | EditText editTextFirstValue; 35 | 36 | @BindView(R.id.second_label) 37 | TextView textViewSecondLabel; 38 | 39 | @BindView(R.id.second_value) 40 | EditText editTextSecondValue; 41 | 42 | @BindView(R.id.third_label) 43 | TextView textViewThirdLabel; 44 | 45 | @BindView(R.id.third_value) 46 | EditText editTextThirdValue; 47 | 48 | @Inject 49 | PinCodeContract.Presenter presenter; 50 | 51 | 52 | public static void createPinCode(Context context) { 53 | startActivity(context, Constants.PinCodeMode.CREATE); 54 | } 55 | 56 | public static void checkPinCode(Context context) { 57 | startActivity(context, Constants.PinCodeMode.CHECK); 58 | } 59 | 60 | public static void changePinCode(Context context) { 61 | startActivity(context, Constants.PinCodeMode.CHANGE); 62 | } 63 | 64 | private static void startActivity(Context context, Constants.PinCodeMode pinCodeMode) { 65 | Intent intent = new Intent(context, PinCodeActivity.class); 66 | intent.putExtra(Constants.EXTRA_MODE, pinCodeMode); 67 | context.startActivity(intent); 68 | } 69 | 70 | 71 | @Override 72 | protected void onCreate(Bundle savedInstanceState) { 73 | super.onCreate(savedInstanceState); 74 | setContentView(R.layout.pincode_activity); 75 | initView(); 76 | 77 | // extract PIN code screen mode from intent 78 | Constants.PinCodeMode pinCodeMode = (Constants.PinCodeMode) 79 | getIntent().getSerializableExtra(Constants.EXTRA_MODE); 80 | 81 | // inject activity 82 | App.getApp(this) 83 | .getComponentsHolder() 84 | .getActivityComponent(getClass(), new PinCodeActivityModule(pinCodeMode)) 85 | .inject(this); 86 | 87 | // attach view to presenter 88 | presenter.attachView(this); 89 | 90 | // view is ready to work 91 | presenter.viewIsReady(); 92 | } 93 | 94 | private void initView() { 95 | ButterKnife.bind(this); 96 | } 97 | 98 | @Override 99 | protected void onDestroy() { 100 | super.onDestroy(); 101 | presenter.detachView(); 102 | if (isFinishing()) { 103 | presenter.destroy(); 104 | App.getApp(this).getComponentsHolder().releaseActivityComponent(getClass()); 105 | } 106 | } 107 | 108 | @Override 109 | public void showFirst(int labelResId) { 110 | // set text to label and show it 111 | textViewFirstLabel.setText(labelResId); 112 | textViewFirstLabel.setVisibility(View.VISIBLE); 113 | 114 | // show field 115 | editTextFirstValue.setVisibility(View.VISIBLE); 116 | 117 | // set textChange listener 118 | RxTextView.afterTextChangeEvents(editTextFirstValue) 119 | .skipInitialValue() 120 | .filter(new Predicate() { 121 | @Override 122 | public boolean test(@NonNull TextViewAfterTextChangeEvent textViewAfterTextChangeEvent) throws Exception { 123 | return (textViewAfterTextChangeEvent.editable().toString().length() == 4); 124 | } 125 | }) 126 | .subscribe(new Consumer() { 127 | @Override 128 | public void accept(@NonNull TextViewAfterTextChangeEvent textViewAfterTextChangeEvent) throws Exception { 129 | presenter.onTextFirst(); 130 | } 131 | }); 132 | } 133 | 134 | @Override 135 | public void showSecond(int labelResId) { 136 | textViewSecondLabel.setText(labelResId); 137 | textViewSecondLabel.setVisibility(View.VISIBLE); 138 | editTextSecondValue.setVisibility(View.VISIBLE); 139 | RxTextView.afterTextChangeEvents(editTextSecondValue) 140 | .skipInitialValue() 141 | .filter(new Predicate() { 142 | @Override 143 | public boolean test(@NonNull TextViewAfterTextChangeEvent textViewAfterTextChangeEvent) throws Exception { 144 | return (textViewAfterTextChangeEvent.editable().toString().length() == 4); 145 | } 146 | }) 147 | .subscribe(new Consumer() { 148 | @Override 149 | public void accept(@NonNull TextViewAfterTextChangeEvent textViewAfterTextChangeEvent) throws Exception { 150 | presenter.onTextSecond(); 151 | } 152 | }); 153 | } 154 | 155 | @Override 156 | public void showThird(int labelResId) { 157 | textViewThirdLabel.setText(labelResId); 158 | textViewThirdLabel.setVisibility(View.VISIBLE); 159 | editTextThirdValue.setVisibility(View.VISIBLE); 160 | RxTextView.afterTextChangeEvents(editTextThirdValue) 161 | .skipInitialValue() 162 | .filter(new Predicate() { 163 | @Override 164 | public boolean test(@NonNull TextViewAfterTextChangeEvent textViewAfterTextChangeEvent) throws Exception { 165 | return (textViewAfterTextChangeEvent.editable().toString().length() == 4); 166 | } 167 | }) 168 | .subscribe(new Consumer() { 169 | @Override 170 | public void accept(@NonNull TextViewAfterTextChangeEvent textViewAfterTextChangeEvent) throws Exception { 171 | presenter.onTextThird(); 172 | } 173 | }); 174 | } 175 | 176 | @Override 177 | public String getTextFirst() { 178 | return editTextFirstValue.getText().toString(); 179 | } 180 | 181 | @Override 182 | public String getTextSecond() { 183 | return editTextSecondValue.getText().toString(); 184 | } 185 | 186 | @Override 187 | public String getTextThird() { 188 | return editTextThirdValue.getText().toString(); 189 | } 190 | 191 | @Override 192 | public void focusFirst() { 193 | editTextFirstValue.requestFocus(); 194 | } 195 | 196 | @Override 197 | public void focusSecond() { 198 | editTextSecondValue.requestFocus(); 199 | } 200 | 201 | @Override 202 | public void focusThird() { 203 | editTextThirdValue.requestFocus(); 204 | } 205 | 206 | @Override 207 | public void clearAll() { 208 | editTextFirstValue.setText(""); 209 | editTextSecondValue.setText(""); 210 | editTextThirdValue.setText(""); 211 | } 212 | 213 | @Override 214 | public void showMessage(int messageResId) { 215 | Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show(); 216 | } 217 | 218 | @Override 219 | public void next() { 220 | startActivity(new Intent(this, MainActivity.class)); 221 | } 222 | 223 | @Override 224 | public void close() { 225 | finish(); 226 | } 227 | 228 | 229 | } 230 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/pin/mvp/PinCodeChangePresenter.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.pin.mvp; 2 | 3 | import ru.startandroid.pincode.R; 4 | import ru.startandroid.pincode.base.mvp.PresenterBase; 5 | import ru.startandroid.pincode.storage.Preferences; 6 | 7 | public class PinCodeChangePresenter extends PresenterBase implements PinCodeContract.Presenter { 8 | 9 | private final Preferences preferences; 10 | 11 | public PinCodeChangePresenter(Preferences preferences) { 12 | this.preferences = preferences; 13 | } 14 | 15 | @Override 16 | public void viewIsReady() { 17 | getView().showFirst(R.string.enter_old_pin); 18 | getView().showSecond(R.string.create_new_pin); 19 | getView().showThird(R.string.repeat_new_pin); 20 | } 21 | 22 | @Override 23 | public void onTextFirst() { 24 | getView().focusSecond(); 25 | } 26 | 27 | @Override 28 | public void onTextSecond() { 29 | getView().focusThird(); 30 | } 31 | 32 | @Override 33 | public void onTextThird() { 34 | if (!getView().getTextFirst().equals(preferences.getPin())) { 35 | getView().showMessage(R.string.wrong_pin); 36 | getView().clearAll(); 37 | getView().focusFirst(); 38 | return; 39 | } 40 | 41 | if (getView().getTextSecond().equals(getView().getTextThird())) { 42 | preferences.setPin(getView().getTextSecond()); 43 | getView().showMessage(R.string.pin_changed); 44 | getView().close(); 45 | } else { 46 | getView().showMessage(R.string.no_match); 47 | getView().clearAll(); 48 | getView().focusFirst(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/pin/mvp/PinCodeCheckPresenter.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.pin.mvp; 2 | 3 | import ru.startandroid.pincode.R; 4 | import ru.startandroid.pincode.base.mvp.PresenterBase; 5 | import ru.startandroid.pincode.storage.Preferences; 6 | 7 | public class PinCodeCheckPresenter extends PresenterBase implements PinCodeContract.Presenter { 8 | 9 | private final Preferences preferences; 10 | 11 | public PinCodeCheckPresenter(Preferences preferences) { 12 | this.preferences = preferences; 13 | } 14 | 15 | @Override 16 | public void viewIsReady() { 17 | getView().showFirst(R.string.enter_pin); 18 | } 19 | 20 | @Override 21 | public void onTextFirst() { 22 | if (getView().getTextFirst().equals(preferences.getPin())) { 23 | getView().next(); 24 | getView().close(); 25 | } else { 26 | getView().showMessage(R.string.wrong_pin); 27 | getView().clearAll(); 28 | } 29 | } 30 | 31 | @Override 32 | public void onTextSecond() { 33 | //do nothing 34 | } 35 | 36 | @Override 37 | public void onTextThird() { 38 | //do nothing 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/pin/mvp/PinCodeContract.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.pin.mvp; 2 | 3 | import ru.startandroid.pincode.base.mvp.MvpPresenter; 4 | import ru.startandroid.pincode.base.mvp.MvpView; 5 | 6 | public interface PinCodeContract { 7 | 8 | interface View extends MvpView { 9 | 10 | // show field with label 11 | void showFirst(int labelResId); 12 | void showSecond(int labelResId); 13 | void showThird(int labelResId); 14 | 15 | // get text from field 16 | String getTextFirst(); 17 | String getTextSecond(); 18 | String getTextThird(); 19 | 20 | // set focus on field 21 | void focusFirst(); 22 | void focusSecond(); 23 | void focusThird(); 24 | 25 | // clear all fields 26 | void clearAll(); 27 | 28 | // show message to user 29 | void showMessage(int messageResId); 30 | 31 | // go to next screen 32 | void next(); 33 | 34 | // close screen 35 | void close(); 36 | } 37 | 38 | 39 | interface Presenter extends MvpPresenter { 40 | 41 | // field is filled 42 | void onTextFirst(); 43 | void onTextSecond(); 44 | void onTextThird(); 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/pin/mvp/PinCodeCreatePresenter.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.pin.mvp; 2 | 3 | import ru.startandroid.pincode.R; 4 | import ru.startandroid.pincode.base.mvp.PresenterBase; 5 | import ru.startandroid.pincode.storage.Preferences; 6 | 7 | public class PinCodeCreatePresenter extends PresenterBase implements PinCodeContract.Presenter { 8 | 9 | private final Preferences preferences; 10 | 11 | public PinCodeCreatePresenter(Preferences preferences) { 12 | this.preferences = preferences; 13 | } 14 | 15 | 16 | @Override 17 | public void viewIsReady() { 18 | getView().showFirst(R.string.create_new_pin); 19 | getView().showSecond(R.string.repeat_new_pin); 20 | } 21 | 22 | @Override 23 | public void onTextFirst() { 24 | getView().focusSecond(); 25 | } 26 | 27 | @Override 28 | public void onTextSecond() { 29 | if (getView().getTextFirst().equals(getView().getTextSecond())) { 30 | preferences.setPin(getView().getTextFirst()); 31 | getView().showMessage(R.string.pin_created); 32 | getView().next(); 33 | getView().close(); 34 | } else { 35 | getView().showMessage(R.string.no_match); 36 | getView().clearAll(); 37 | getView().focusFirst(); 38 | } 39 | } 40 | 41 | @Override 42 | public void onTextThird() { 43 | // do nothing 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/ru/startandroid/pincode/storage/Preferences.java: -------------------------------------------------------------------------------- 1 | package ru.startandroid.pincode.storage; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | public class Preferences { 7 | 8 | final static String FILE_NAME = "preferences"; 9 | 10 | final static String PREF_PIN = "pin"; 11 | 12 | private SharedPreferences preferences; 13 | 14 | public Preferences(Context context) { 15 | preferences = context.getSharedPreferences(FILE_NAME, 0); 16 | } 17 | 18 | private SharedPreferences.Editor getEditor() { 19 | return preferences.edit(); 20 | } 21 | 22 | public void setPin(String data) { 23 | getEditor().putString(PREF_PIN, data).commit(); 24 | } 25 | 26 | public String getPin() { 27 | return preferences.getString(PREF_PIN, ""); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/main_activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 |