diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 0000000..5352bdf --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 13c4629..3963879 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -30,20 +30,4 @@ - - - - - 1.8 - - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index ceb77c9..732c790 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 26 + compileSdkVersion 27 defaultConfig { applicationId "com.example.vladislav.menu" minSdkVersion 19 - targetSdkVersion 26 + targetSdkVersion 27 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { @@ -18,10 +18,35 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:appcompat-v7:26.1.0' - implementation 'com.android.support:design:26.1.0' + implementation 'com.android.support:appcompat-v7:27.1.0' + implementation 'com.android.support:design:27.1.0' implementation 'com.android.support.constraint:constraint-layout:1.0.2' + implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:0.5' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2' + androidTestImplementation 'com.android.support.test:runner:1.0.1' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' + + compile 'com.squareup.retrofit2:retrofit:2.3.0' + compile 'com.squareup.retrofit2:converter-gson:2.3.0' + + implementation "android.arch.persistence.room:runtime:1.0.0" + annotationProcessor "android.arch.persistence.room:compiler:1.0.0" + + compile 'com.google.firebase:firebase-core:11.8.0' + compile 'com.google.firebase:firebase-messaging:11.8.0' + + implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' + // Because RxAndroid releases are few and far between, it is recommended you also + // explicitly depend on RxJava's latest version for bug fixes and new features. + // (see https://github.com/ReactiveX/RxJava/releases for latest 2.x.x version) + implementation 'io.reactivex.rxjava2:rxjava:2.x.x' + // retrofit rxjava2 plugin + compile 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' + // https://mvnrepository.com/artifact/android.arch.persistence.room/rxjava2 + compile group: 'android.arch.persistence.room', name: 'rxjava2', version: '1.0.0' + + //implementation 'com.jakewharton:butterknife:8.8.1' + //annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' } + +apply plugin: 'com.google.gms.google-services' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b29d222..3c572c0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,10 +1,13 @@ + android:versionCode="2" + android:versionName="0.5.0-beta"> + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/vladislav/app/App.java b/app/src/main/java/com/example/vladislav/app/App.java new file mode 100644 index 0000000..0c722ce --- /dev/null +++ b/app/src/main/java/com/example/vladislav/app/App.java @@ -0,0 +1,23 @@ +package com.example.vladislav.app; + +import android.app.Application; +import android.content.Context; + +/** + * Created by d3m1d0v on 22.03.2018. + */ + +public class App extends Application { + + private static App INSTANCE; + + public App() { + super(); + + INSTANCE = this; + } + + public static Context getAppContext() { + return INSTANCE.getApplicationContext(); + } +} diff --git a/app/src/main/java/com/example/vladislav/app/Constant.java b/app/src/main/java/com/example/vladislav/app/Constant.java new file mode 100644 index 0000000..a5c8f3d --- /dev/null +++ b/app/src/main/java/com/example/vladislav/app/Constant.java @@ -0,0 +1,33 @@ +package com.example.vladislav.app; + +/** + * Created by Isa on 09.03.2018. + */ + +public class Constant { + //https://developer.android.com/reference/android/util/Log.html + public static final String TAG = "Crypto"; + + public static final String[] CURRENCIES_NAME = { + "BTC", + "ETH", + "LTC", + "XRP", + "BCH", + "TRX", + "ETC", + "EOS", + "NEO", + "XMR", + "DASH", + "XRB", + "HT", + "OMG", + "ZEC", + "ADA", + "BNB", + "ABT*", + "IOT", + "IOST", + }; +} diff --git a/app/src/main/java/com/example/vladislav/BasePresenter.java b/app/src/main/java/com/example/vladislav/base/BasePresenter.java similarity index 94% rename from app/src/main/java/com/example/vladislav/BasePresenter.java rename to app/src/main/java/com/example/vladislav/base/BasePresenter.java index a4b5d01..0f9a523 100644 --- a/app/src/main/java/com/example/vladislav/BasePresenter.java +++ b/app/src/main/java/com/example/vladislav/base/BasePresenter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.example.vladislav; +package com.example.vladislav.base; public interface BasePresenter { diff --git a/app/src/main/java/com/example/vladislav/BaseView.java b/app/src/main/java/com/example/vladislav/base/BaseView.java similarity index 95% rename from app/src/main/java/com/example/vladislav/BaseView.java rename to app/src/main/java/com/example/vladislav/base/BaseView.java index be2db67..91c6147 100644 --- a/app/src/main/java/com/example/vladislav/BaseView.java +++ b/app/src/main/java/com/example/vladislav/base/BaseView.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.example.vladislav; +package com.example.vladislav.base; public interface BaseView { diff --git a/app/src/main/java/com/example/vladislav/data/CryptoDatabase.java b/app/src/main/java/com/example/vladislav/data/CryptoDatabase.java new file mode 100644 index 0000000..649c8e7 --- /dev/null +++ b/app/src/main/java/com/example/vladislav/data/CryptoDatabase.java @@ -0,0 +1,28 @@ +package com.example.vladislav.data; + +import android.arch.persistence.room.Database; +import android.arch.persistence.room.Room; +import android.arch.persistence.room.RoomDatabase; + +import com.example.vladislav.app.App; + +/** + * Created by d3m1d0v on 22.03.2018. + */ + +@Database(entities = {CurrencyData.class}, version = 3) +public abstract class CryptoDatabase extends RoomDatabase { + + private static CryptoDatabase INSTANCE; + + public abstract CurrencyDataDao currencyDataDao(); + + public static CryptoDatabase getInstance() { + if (INSTANCE == null) { + INSTANCE = Room.databaseBuilder(App.getAppContext(), + CryptoDatabase.class, "Crypto.db") + .fallbackToDestructiveMigration().build(); + } + return INSTANCE; + } +} diff --git a/app/src/main/java/com/example/vladislav/data/CryptoRepository.java b/app/src/main/java/com/example/vladislav/data/CryptoRepository.java deleted file mode 100644 index 46d77be..0000000 --- a/app/src/main/java/com/example/vladislav/data/CryptoRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.example.vladislav.data; - -import java.util.List; - -/** - * Created by d3m1d0v on 04.03.2018. - */ - -public interface CryptoRepository { - - List getAllCurrenciesInfo(); - - void updateCurrenciesInfo(); -} diff --git a/app/src/main/java/com/example/vladislav/data/CurrencyBaseInfo.java b/app/src/main/java/com/example/vladislav/data/CurrencyBaseInfo.java deleted file mode 100644 index 4164828..0000000 --- a/app/src/main/java/com/example/vladislav/data/CurrencyBaseInfo.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.example.vladislav.data; - -import java.math.RoundingMode; -import java.text.DecimalFormat; - -/** - * Created by d3m1d0v on 04.03.2018. - */ - -public class CurrencyBaseInfo { - - private static final String FORMAT = "#.###"; - private static final DecimalFormat FORMATTER; - - static { - FORMATTER = new DecimalFormat(); - FORMATTER.setRoundingMode(RoundingMode.CEILING); - } - - private String name; - private float price; - private float change; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getPriceValue() { - return "$" + FORMATTER.format(price); - } - - public void setPrice(float price) { - this.price = price; - } - - public String getChangeValue() { - String value = FORMATTER.format(change); - value = Float.parseFloat(value) > 0 ? '+' + value : value; - value = value + '%'; - - return value; - } - - public void setChange(float change) { - this.change = change; - } -} diff --git a/app/src/main/java/com/example/vladislav/data/CurrencyData.java b/app/src/main/java/com/example/vladislav/data/CurrencyData.java new file mode 100644 index 0000000..dc126ba --- /dev/null +++ b/app/src/main/java/com/example/vladislav/data/CurrencyData.java @@ -0,0 +1,118 @@ +package com.example.vladislav.data; + +import android.arch.persistence.room.ColumnInfo; +import android.arch.persistence.room.Entity; +import android.arch.persistence.room.Ignore; +import android.arch.persistence.room.PrimaryKey; +import android.support.annotation.NonNull; + +/** + * Created by d3m1d0v on 22.03.2018. + */ + +@Entity(tableName = "currencies") +public final class CurrencyData { + + @PrimaryKey + @NonNull + @ColumnInfo(name = "name") + private final String mName; + + @ColumnInfo(name = "price") + private final float mPrice; + + @ColumnInfo(name = "change") + private final float mChange; + + @ColumnInfo(name = "change1H") + private final float mChange1H; + + @ColumnInfo(name = "change7D") + private final float mChange7D; + + @ColumnInfo(name = "supply") + private final String mSupply; + + @ColumnInfo(name = "capitalization") + private final String mCapitalization; + + @ColumnInfo(name = "volume") + private final String mVolume24H; + + @NonNull + @ColumnInfo(name = "last_update") + private final String mLastUpdate; + + @Ignore private final String mFormattedPrice; + @Ignore private final String mFormattedChange; + + public CurrencyData(@NonNull String name, float price, float change, float change1H, float change7D, + @NonNull String supply, @NonNull String capitalization, @NonNull String volume24H, + @NonNull String lastUpdate) { + mName = name; + mPrice = price; + mChange = change; + mChange1H = change1H; + mChange7D = change7D; + mSupply = supply + " " + mName; + mCapitalization = capitalization; + mVolume24H = volume24H; + mLastUpdate = lastUpdate; + + mFormattedPrice = String.format("$%,.2f", mPrice); + mFormattedChange = String.format("%+,.3g%%", mChange); + } + + @NonNull + public String getName() { + return mName; + } + + public float getPrice() { + return mPrice; + } + + public float getChange() { + return mChange; + } + + public float getChange1H() { + return mChange1H; + } + + public float getChange7D() { + return mChange7D; + } + + @NonNull + public String getSupply() { + return mSupply; + } + + @NonNull + public String getCapitalization() { + return mCapitalization; + } + + @NonNull + public String getVolume24H() { + return mVolume24H; + } + + @NonNull + public String getLastUpdate() { + return mLastUpdate; + } + + @Ignore + @NonNull + public String getFormattedPrice() { + return mFormattedPrice; + } + + @Ignore + @NonNull + public String getFormattedChange() { + return mFormattedChange; + } +} diff --git a/app/src/main/java/com/example/vladislav/data/CurrencyDataDao.java b/app/src/main/java/com/example/vladislav/data/CurrencyDataDao.java new file mode 100644 index 0000000..6e6eef2 --- /dev/null +++ b/app/src/main/java/com/example/vladislav/data/CurrencyDataDao.java @@ -0,0 +1,52 @@ +package com.example.vladislav.data; + +import android.arch.persistence.room.Dao; +import android.arch.persistence.room.Delete; +import android.arch.persistence.room.Insert; +import android.arch.persistence.room.OnConflictStrategy; +import android.arch.persistence.room.Query; +import android.arch.persistence.room.Update; + +import java.util.List; + +import io.reactivex.Flowable; + +/** + * Created by d3m1d0v on 22.03.2018. + */ + +@Dao +public interface CurrencyDataDao { + + @Deprecated + @Query("SELECT * FROM currencies") + List getCurrenciesData(); + + @Deprecated + @Query("SELECT * FROM currencies WHERE name = :name") + CurrencyData getCurrencyDataByName(String name); + + @Query("SELECT * FROM currencies") + Flowable> getCurrencyDataAll_Rx(); + + @Query("SELECT * FROM currencies WHERE name = :name LIMIT 1") + Flowable getCurrencyDataByName_Rx(String name); + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insertCurrencyData(CurrencyData data); + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insertCurrenciesData(List dataList); + + @Update + void updateCurrencyData(CurrencyData data); + + @Update + void updateCurrenciesData(List dataList); + + @Delete + void deleteCurrencyDataByName(CurrencyData data); + + @Delete + void deleteCurrenciesData(List dataList); +} diff --git a/app/src/main/java/com/example/vladislav/data/TestCryptoRepository.java b/app/src/main/java/com/example/vladislav/data/TestCryptoRepository.java deleted file mode 100644 index 0c15df5..0000000 --- a/app/src/main/java/com/example/vladislav/data/TestCryptoRepository.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.example.vladislav.data; - -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -/** - * Created by d3m1d0v on 04.03.2018. - */ - -public class TestCryptoRepository implements CryptoRepository { - - private static TestCryptoRepository INSTANCE; - - private List currencies; - private String[] currenciesName = { - "Bitcoin", - "Ethereum", - "Ripple", - "Bitcoin Cash", - "Litecoin", - "NEO", - "Cardano", - "Stellar", - "EOS", - "Monero", - "IOTA", - "Dash", - "NEM", - "TRON", - "Zcash", - "GOLOS" - }; - - private TestCryptoRepository() { - currencies = new ArrayList<>(currenciesName.length); - updateCurrenciesInfo(); - } - - public static TestCryptoRepository getInstance() { - if (INSTANCE == null){ - INSTANCE = new TestCryptoRepository(); - } - return INSTANCE; - } - - @Override - public List getAllCurrenciesInfo() { - return currencies; - } - - @Override - public void updateCurrenciesInfo() { - currencies.clear(); - - for (String name: currenciesName) { - CurrencyBaseInfo info = new CurrencyBaseInfo(); - info.setName(name); - info.setPrice(genPriceValue()); - info.setChange(genChangeValue()); - currencies.add(info); - } - } - - private float genPriceValue() { - float leftLimit = 0.1F; - float rightLimit = 1000F; - float generatedFloat = leftLimit + new Random().nextFloat() * (rightLimit - leftLimit); - return generatedFloat; - } - - private float genChangeValue() { - float leftLimit = -10F; - float rightLimit = 10F; - float generatedFloat = leftLimit + new Random().nextFloat() * (rightLimit - leftLimit); - return generatedFloat; - } -} diff --git a/app/src/main/java/com/example/vladislav/data/api/CryptoCompareApi.java b/app/src/main/java/com/example/vladislav/data/api/CryptoCompareApi.java new file mode 100644 index 0000000..9fd0504 --- /dev/null +++ b/app/src/main/java/com/example/vladislav/data/api/CryptoCompareApi.java @@ -0,0 +1,22 @@ +package com.example.vladislav.data.api; + +import com.example.vladislav.data.api.models.CurrencyDataModel; + +import io.reactivex.Single; +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Query; + +/** + * Created by d3m1d0v on 10.03.2018. + */ + +public interface CryptoCompareApi { + + @Deprecated + @GET("/data/pricemultifull") + Call getCurrencyData(@Query("fsyms") String fsyms, @Query("tsyms") String tsyms); + + @GET("/data/pricemultifull") + Single getCurrencyDataRx(@Query("fsyms") String fsyms, @Query("tsyms") String tsyms); +} diff --git a/app/src/main/java/com/example/vladislav/data/api/SendRefreshTokenApi.java b/app/src/main/java/com/example/vladislav/data/api/SendRefreshTokenApi.java new file mode 100644 index 0000000..240a38f --- /dev/null +++ b/app/src/main/java/com/example/vladislav/data/api/SendRefreshTokenApi.java @@ -0,0 +1,14 @@ + +package com.example.vladislav.data.api; + +import okhttp3.ResponseBody; +import retrofit2.Call; +import retrofit2.http.POST; +import retrofit2.http.Query; + + +public interface SendRefreshTokenApi { + + @POST("/api/tokens") + Call sendToken(@Query("registration_id") String token); +} diff --git a/app/src/main/java/com/example/vladislav/data/api/models/CurrencyDataModel.java b/app/src/main/java/com/example/vladislav/data/api/models/CurrencyDataModel.java new file mode 100644 index 0000000..9aa4e2f --- /dev/null +++ b/app/src/main/java/com/example/vladislav/data/api/models/CurrencyDataModel.java @@ -0,0 +1,329 @@ +package com.example.vladislav.data.api.models; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.util.Map; + +/** + * Created by d3m1d0v on 10.03.2018. + */ + +public class CurrencyDataModel { + + @SerializedName("FROMSYMBOL") + @Expose + private String fROMSYMBOL; + @SerializedName("TOSYMBOL") + @Expose + private String tOSYMBOL; + @SerializedName("MARKET") + @Expose + private String mARKET; + @SerializedName("PRICE") + @Expose + private String pRICE; + @SerializedName("LASTUPDATE") + @Expose + private String lASTUPDATE; + @SerializedName("LASTVOLUME") + @Expose + private String lASTVOLUME; + @SerializedName("LASTVOLUMETO") + @Expose + private String lASTVOLUMETO; + @SerializedName("LASTTRADEID") + @Expose + private String lASTTRADEID; + @SerializedName("VOLUMEDAY") + @Expose + private String vOLUMEDAY; + @SerializedName("VOLUMEDAYTO") + @Expose + private String vOLUMEDAYTO; + @SerializedName("VOLUME24HOUR") + @Expose + private String vOLUME24HOUR; + @SerializedName("VOLUME24HOURTO") + @Expose + private String vOLUME24HOURTO; + @SerializedName("OPENDAY") + @Expose + private String oPENDAY; + @SerializedName("HIGHDAY") + @Expose + private String hIGHDAY; + @SerializedName("LOWDAY") + @Expose + private String lOWDAY; + @SerializedName("OPEN24HOUR") + @Expose + private String oPEN24HOUR; + @SerializedName("HIGH24HOUR") + @Expose + private String hIGH24HOUR; + @SerializedName("LOW24HOUR") + @Expose + private String lOW24HOUR; + @SerializedName("LASTMARKET") + @Expose + private String lASTMARKET; + @SerializedName("CHANGE24HOUR") + @Expose + private String cHANGE24HOUR; + @SerializedName("CHANGEPCT24HOUR") + @Expose + private String cHANGEPCT24HOUR; + @SerializedName("CHANGEDAY") + @Expose + private String cHANGEDAY; + @SerializedName("CHANGEPCTDAY") + @Expose + private String cHANGEPCTDAY; + @SerializedName("SUPPLY") + @Expose + private String sUPPLY; + @SerializedName("MKTCAP") + @Expose + private String mKTCAP; + @SerializedName("TOTALVOLUME24H") + @Expose + private String tOTALVOLUME24H; + @SerializedName("TOTALVOLUME24HTO") + @Expose + private String tOTALVOLUME24HTO; + + public String getFROMSYMBOL() { + return fROMSYMBOL; + } + + public void setFROMSYMBOL(String fROMSYMBOL) { + this.fROMSYMBOL = fROMSYMBOL; + } + + public String getTOSYMBOL() { + return tOSYMBOL; + } + + public void setTOSYMBOL(String tOSYMBOL) { + this.tOSYMBOL = tOSYMBOL; + } + + public String getMARKET() { + return mARKET; + } + + public void setMARKET(String mARKET) { + this.mARKET = mARKET; + } + + public String getPRICE() { + return pRICE; + } + + public void setPRICE(String pRICE) { + this.pRICE = pRICE; + } + + public String getLASTUPDATE() { + return lASTUPDATE; + } + + public void setLASTUPDATE(String lASTUPDATE) { + this.lASTUPDATE = lASTUPDATE; + } + + public String getLASTVOLUME() { + return lASTVOLUME; + } + + public void setLASTVOLUME(String lASTVOLUME) { + this.lASTVOLUME = lASTVOLUME; + } + + public String getLASTVOLUMETO() { + return lASTVOLUMETO; + } + + public void setLASTVOLUMETO(String lASTVOLUMETO) { + this.lASTVOLUMETO = lASTVOLUMETO; + } + + public String getLASTTRADEID() { + return lASTTRADEID; + } + + public void setLASTTRADEID(String lASTTRADEID) { + this.lASTTRADEID = lASTTRADEID; + } + + public String getVOLUMEDAY() { + return vOLUMEDAY; + } + + public void setVOLUMEDAY(String vOLUMEDAY) { + this.vOLUMEDAY = vOLUMEDAY; + } + + public String getVOLUMEDAYTO() { + return vOLUMEDAYTO; + } + + public void setVOLUMEDAYTO(String vOLUMEDAYTO) { + this.vOLUMEDAYTO = vOLUMEDAYTO; + } + + public String getVOLUME24HOUR() { + return vOLUME24HOUR; + } + + public void setVOLUME24HOUR(String vOLUME24HOUR) { + this.vOLUME24HOUR = vOLUME24HOUR; + } + + public String getVOLUME24HOURTO() { + return vOLUME24HOURTO; + } + + public void setVOLUME24HOURTO(String vOLUME24HOURTO) { + this.vOLUME24HOURTO = vOLUME24HOURTO; + } + + public String getOPENDAY() { + return oPENDAY; + } + + public void setOPENDAY(String oPENDAY) { + this.oPENDAY = oPENDAY; + } + + public String getHIGHDAY() { + return hIGHDAY; + } + + public void setHIGHDAY(String hIGHDAY) { + this.hIGHDAY = hIGHDAY; + } + + public String getLOWDAY() { + return lOWDAY; + } + + public void setLOWDAY(String lOWDAY) { + this.lOWDAY = lOWDAY; + } + + public String getOPEN24HOUR() { + return oPEN24HOUR; + } + + public void setOPEN24HOUR(String oPEN24HOUR) { + this.oPEN24HOUR = oPEN24HOUR; + } + + public String getHIGH24HOUR() { + return hIGH24HOUR; + } + + public void setHIGH24HOUR(String hIGH24HOUR) { + this.hIGH24HOUR = hIGH24HOUR; + } + + public String getLOW24HOUR() { + return lOW24HOUR; + } + + public void setLOW24HOUR(String lOW24HOUR) { + this.lOW24HOUR = lOW24HOUR; + } + + public String getLASTMARKET() { + return lASTMARKET; + } + + public void setLASTMARKET(String lASTMARKET) { + this.lASTMARKET = lASTMARKET; + } + + public String getCHANGE24HOUR() { + return cHANGE24HOUR; + } + + public void setCHANGE24HOUR(String cHANGE24HOUR) { + this.cHANGE24HOUR = cHANGE24HOUR; + } + + public String getCHANGEPCT24HOUR() { + return cHANGEPCT24HOUR; + } + + public void setCHANGEPCT24HOUR(String cHANGEPCT24HOUR) { + this.cHANGEPCT24HOUR = cHANGEPCT24HOUR; + } + + public String getCHANGEDAY() { + return cHANGEDAY; + } + + public void setCHANGEDAY(String cHANGEDAY) { + this.cHANGEDAY = cHANGEDAY; + } + + public String getCHANGEPCTDAY() { + return cHANGEPCTDAY; + } + + public void setCHANGEPCTDAY(String cHANGEPCTDAY) { + this.cHANGEPCTDAY = cHANGEPCTDAY; + } + + public String getSUPPLY() { + return sUPPLY; + } + + public void setSUPPLY(String sUPPLY) { + this.sUPPLY = sUPPLY; + } + + public String getMKTCAP() { + return mKTCAP; + } + + public void setMKTCAP(String mKTCAP) { + this.mKTCAP = mKTCAP; + } + + public String getTOTALVOLUME24H() { + return tOTALVOLUME24H; + } + + public void setTOTALVOLUME24H(String tOTALVOLUME24H) { + this.tOTALVOLUME24H = tOTALVOLUME24H; + } + + public String getTOTALVOLUME24HTO() { + return tOTALVOLUME24HTO; + } + + public void setTOTALVOLUME24HTO(String tOTALVOLUME24HTO) { + this.tOTALVOLUME24HTO = tOTALVOLUME24HTO; + } + + /** + * Wrapper over {@link CurrencyDataModel} + */ + public class Response { + + @SerializedName("RAW") + @Expose + private Map> data; + + public Map> getData() { + return data; + } + + public void setData(Map> data) { + this.data = data; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/vladislav/data/repository/CryptoRepository.java b/app/src/main/java/com/example/vladislav/data/repository/CryptoRepository.java new file mode 100644 index 0000000..e071ac2 --- /dev/null +++ b/app/src/main/java/com/example/vladislav/data/repository/CryptoRepository.java @@ -0,0 +1,61 @@ +package com.example.vladislav.data.repository; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.example.vladislav.data.CurrencyData; + +import java.util.List; + +import io.reactivex.Flowable; +import io.reactivex.Single; + +/** + * Created by d3m1d0v on 04.03.2018. + */ + +public interface CryptoRepository { + + @Deprecated + void getCurrenciesDataList(@NonNull GetDataListCallback callback); + + @Deprecated + void updateCurrenciesData(@NonNull RefreshCallback callback); + + @Deprecated + void getCurrencyData(@NonNull String currencyName, @NonNull GetDataCallback callback); + + @Deprecated + void updateCurrencyData(@NonNull String currencyName, @NonNull RefreshCallback callback); + + @Deprecated + interface GetDataCallback { + + void onData(@Nullable CurrencyData data); + } + + @Deprecated + interface GetDataListCallback { + + void onData(@NonNull List dataList); + } + + @Deprecated + interface RefreshCallback { + + void notify(boolean successful); + } + + + /////////////////////////////// + /// Using reactive behavior /// + /////////////////////////////// + + Flowable> getCurrencyDataListFromDb_Rx(); + + Single> refreshCurrencyDataAll_Rx(); + + Flowable getCurrencyDataFromDb_Rx(@NonNull String currencyName); + + Single refreshCurrencyData_Rx(@NonNull String currencyName); +} diff --git a/app/src/main/java/com/example/vladislav/data/repository/MainRepository.java b/app/src/main/java/com/example/vladislav/data/repository/MainRepository.java new file mode 100644 index 0000000..7df322f --- /dev/null +++ b/app/src/main/java/com/example/vladislav/data/repository/MainRepository.java @@ -0,0 +1,301 @@ +package com.example.vladislav.data.repository; + +import android.os.Handler; +import android.os.Looper; +import android.support.annotation.NonNull; +import android.util.Log; + +import com.example.vladislav.app.Constant; +import com.example.vladislav.data.CryptoDatabase; +import com.example.vladislav.data.CurrencyData; +import com.example.vladislav.data.api.CryptoCompareApi; +import com.example.vladislav.data.api.models.CurrencyDataModel; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +import io.reactivex.Flowable; +import io.reactivex.Single; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; +import retrofit2.converter.gson.GsonConverterFactory; + +/** + * Created by d3m1d0v on 10.03.2018. + */ + +public class MainRepository implements CryptoRepository { + + private static MainRepository INSTANCE; + private static final String BASE_URL = "https://min-api.cryptocompare.com/"; + private static final String USD = "USD"; + + private final Executor dbExecutor; + + private Map currenciesMap; + + private final CryptoCompareApi api; + private final CryptoDatabase db; + private final String FSYMS; + + public static MainRepository getInstance() { + if (INSTANCE == null) { + INSTANCE = new MainRepository(); + } + return INSTANCE; + } + + private MainRepository() { + api = new Retrofit.Builder() + .baseUrl(BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .build() + .create(CryptoCompareApi.class); + + dbExecutor = Executors.newSingleThreadExecutor(); + db = CryptoDatabase.getInstance(); + currenciesMap = new TreeMap<>(); + + StringBuilder fsymsBuilder = new StringBuilder(); + for (String currency : Constant.CURRENCIES_NAME) { + fsymsBuilder.append(currency); + fsymsBuilder.append(','); + } + FSYMS = fsymsBuilder.toString(); + } + + @Override + public void getCurrenciesDataList(GetDataListCallback callback) { + if (currenciesMap.size() == 0) { + getCurrenciesDataFromDb(callback); + } else { + callback.onData(new ArrayList<>(currenciesMap.values())); + } + } + + @Override + public void updateCurrenciesData(final RefreshCallback callback) { + api.getCurrencyData(FSYMS, USD).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (!response.isSuccessful() || response.body().getData() == null) { + callback.notify(false); + Log.d(Constant.TAG, "response.isSuccessful(): false"); + return; + } + + int exCurrenciesSize = currenciesMap.size(); + currenciesMap.clear(); + for (String currency : Constant.CURRENCIES_NAME) { + CurrencyDataModel dataModel = response.body().getData().get(currency).get(USD); + CurrencyData data = MainRepository.DataModelToData(dataModel); + + currenciesMap.put(data.getName(), data); + } + + if (exCurrenciesSize == 0) { + insertDataListIntoDb(); + } else { + updateDataListIntoDb(); + } + + callback.notify(true); + } + + @Override + public void onFailure(Call call, Throwable t) { + callback.notify(false); + Log.d(Constant.TAG, "onFailure()"); + } + }); + } + + @Override + public void getCurrencyData(@NonNull final String currencyName, @NonNull final GetDataCallback callback) { + if (currenciesMap.containsKey(currencyName)) { + callback.onData(currenciesMap.get(currencyName)); + return; + } + + dbExecutor.execute(new Runnable() { + @Override + public void run() { + final CurrencyData data = db.currencyDataDao().getCurrencyDataByName(currencyName); + if (data == null) { + callback.onData(null); + return; + } + + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + currenciesMap.put(data.getName(), data); + callback.onData(data); + } + }); + } + }); + } + + @Override + public void updateCurrencyData(@NonNull final String currencyName, @NonNull final RefreshCallback callback) { + api.getCurrencyData(currencyName, USD).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (!response.isSuccessful() || response.body().getData() == null) { + callback.notify(false); + Log.d(Constant.TAG, "response.isSuccessful(): false"); + return; + } + + CurrencyDataModel dataModel = response.body().getData().get(currencyName).get(USD); + CurrencyData data = MainRepository.DataModelToData(dataModel); + + insertDataIntoDb(data); + currenciesMap.put(data.getName(),data); + callback.notify(true); + } + + @Override + public void onFailure(Call call, Throwable t) { + callback.notify(false); + Log.d(Constant.TAG, "onFailure()"); + } + }); + } + + private void getCurrenciesDataFromDb(final GetDataListCallback callback) { + dbExecutor.execute(new Runnable() { + @Override + public void run() { + final List dataList = db.currencyDataDao().getCurrenciesData(); + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + currenciesMap.clear(); + for (CurrencyData data : dataList) { + currenciesMap.put(data.getName(), data); + } + callback.onData(new ArrayList<>(currenciesMap.values())); + } + }); + } + }); + } + + private void insertDataIntoDb(final CurrencyData data) { + dbExecutor.execute(new Runnable() { + @Override + public void run() { + db.currencyDataDao().insertCurrencyData(data); + } + }); + } + + private void insertDataListIntoDb() { + dbExecutor.execute(new Runnable() { + @Override + public void run() { + db.currencyDataDao().insertCurrenciesData(new ArrayList<>(currenciesMap.values())); + } + }); + } + + private void updateDataListIntoDb() { + dbExecutor.execute(new Runnable() { + @Override + public void run() { + db.currencyDataDao().updateCurrenciesData(new ArrayList<>(currenciesMap.values())); + } + }); + } + + @NonNull + private static CurrencyData DataModelToData(@NonNull CurrencyDataModel dataModel) { + return new CurrencyData( + dataModel.getFROMSYMBOL(), + Float.parseFloat(dataModel.getPRICE()), + Float.parseFloat(dataModel.getCHANGEPCT24HOUR()), + Float.parseFloat(dataModel.getCHANGEPCT24HOUR()), + Float.parseFloat(dataModel.getCHANGEPCTDAY()), + dataModel.getSUPPLY(), + dataModel.getMKTCAP(), + dataModel.getVOLUME24HOURTO(), + dataModel.getLASTUPDATE() + ); + } + + + /////////////////////////////// + /// Using reactive behavior /// + /////////////////////////////// + + @Override + public Flowable> getCurrencyDataListFromDb_Rx() { + return db.currencyDataDao().getCurrencyDataAll_Rx(); + } + + @Override + public Single> refreshCurrencyDataAll_Rx() { + return api.getCurrencyDataRx(FSYMS, USD) + .subscribeOn(Schedulers.io()) + .map(new Function>() { + @Override + public List apply(CurrencyDataModel.Response res) throws Exception { + if (res.getData() == null) { + throw new Exception("Response body is null"); + } + + List dataList = new ArrayList<>(); + for (Map map : res.getData().values()) { + dataList.add(DataModelToData(map.get(USD))); + } + return dataList; + } + }) + .doOnSuccess(new Consumer>() { + @Override + public void accept(List dataList) throws Exception { + db.currencyDataDao().insertCurrenciesData(dataList); + } + }); + } + + @Override + public Flowable getCurrencyDataFromDb_Rx(@NonNull String currencyName) { + return db.currencyDataDao().getCurrencyDataByName_Rx(currencyName); + } + + @Override + public Single refreshCurrencyData_Rx(@NonNull final String currencyName) { + return api.getCurrencyDataRx(currencyName, USD) + .subscribeOn(Schedulers.io()) + .map(new Function() { + @Override + public CurrencyData apply(CurrencyDataModel.Response res) throws Exception { + if (res.getData() == null) { + throw new Exception("Response body is null"); + } + + return DataModelToData(res.getData().get(currencyName).get(USD)); + } + }) + .doOnSuccess(new Consumer() { + @Override + public void accept(CurrencyData data) throws Exception { + db.currencyDataDao().insertCurrencyData(data); + } + }); + } +} diff --git a/app/src/main/java/com/example/vladislav/data/repository/TestCryptoRepository.java b/app/src/main/java/com/example/vladislav/data/repository/TestCryptoRepository.java new file mode 100644 index 0000000..81cdf8b --- /dev/null +++ b/app/src/main/java/com/example/vladislav/data/repository/TestCryptoRepository.java @@ -0,0 +1,83 @@ +package com.example.vladislav.data.repository; + +import android.support.annotation.NonNull; + +import com.example.vladislav.app.Constant; +import com.example.vladislav.data.CurrencyData; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * Created by d3m1d0v on 04.03.2018. + */ + +public abstract class TestCryptoRepository implements CryptoRepository { + + private static TestCryptoRepository INSTANCE; + + private List currencies; + + private TestCryptoRepository() { + currencies = new ArrayList<>(Constant.CURRENCIES_NAME.length); + } + + public static TestCryptoRepository getInstance() { + if (INSTANCE == null){ +// INSTANCE = new TestCryptoRepository(); + } + return INSTANCE; + } + + @Override + public void getCurrenciesDataList(GetDataListCallback callback) { + callback.onData(currencies); + } + + @Override + public void updateCurrenciesData(RefreshCallback callback) { + currencies.clear(); + + for (String name: Constant.CURRENCIES_NAME) { + CurrencyData data = new CurrencyData( + name, + genPriceValue(), + genChangeValue(), + genChangeValue(), + genChangeValue(), + "0", + "0", + "0", + "-1" + ); + currencies.add(data); + } + + callback.notify(true); + } + + @Override + public void getCurrencyData(@NonNull String currencyName, @NonNull GetDataCallback callback) { + // TODO: implements method + } + + @Override + public void updateCurrencyData(@NonNull String currencyName, @NonNull RefreshCallback callback) { + // TODO: implements method + } + + private float genPriceValue() { + float leftLimit = 0.1F; + float rightLimit = 1000F; + float generatedFloat = leftLimit + new Random().nextFloat() * (rightLimit - leftLimit); + return generatedFloat; + } + + private float genChangeValue() { + float leftLimit = -10F; + float rightLimit = 10F; + float generatedFloat = leftLimit + new Random().nextFloat() * (rightLimit - leftLimit); + return generatedFloat; + } +} diff --git a/app/src/main/java/com/example/vladislav/menu/fragments/mainscreen/MainScreenContract.java b/app/src/main/java/com/example/vladislav/menu/fragments/mainscreen/MainScreenContract.java deleted file mode 100644 index 8bf7cd6..0000000 --- a/app/src/main/java/com/example/vladislav/menu/fragments/mainscreen/MainScreenContract.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.example.vladislav.menu.fragments.mainscreen; - -import com.example.vladislav.BasePresenter; -import com.example.vladislav.BaseView; -import com.example.vladislav.data.CurrencyBaseInfo; - -import java.util.List; - -/** - * Created by d3m1d0v on 04.03.2018. - */ - -public interface MainScreenContract { - - interface View extends BaseView { - - void showAllCurrenciesInfoItems(List currencies); - - void showInfoToast(String currencyName); - } - - interface Presenter extends BasePresenter { - - void onCurrencyItemClick(String currencyName); - } -} diff --git a/app/src/main/java/com/example/vladislav/menu/fragments/mainscreen/MainScreenFragment.java b/app/src/main/java/com/example/vladislav/menu/fragments/mainscreen/MainScreenFragment.java deleted file mode 100644 index 4eb57a0..0000000 --- a/app/src/main/java/com/example/vladislav/menu/fragments/mainscreen/MainScreenFragment.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.example.vladislav.menu.fragments.mainscreen; - -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; -import android.widget.Toast; - -import com.example.vladislav.data.CurrencyBaseInfo; -import com.example.vladislav.data.TestCryptoRepository; -import com.example.vladislav.menu.R; - -import java.util.List; - -/** - * Created by d3m1d0v on 03.03.2018. - */ - -public class MainScreenFragment extends Fragment implements MainScreenContract.View { - - private MainScreenContract.Presenter mPresenter; - private RecyclerView mRecyclerView; - private RecyclerView.Adapter mAdapter; - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - new MainScreenPresenter(this, TestCryptoRepository.getInstance()); - } - - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - - View view = inflater.inflate(R.layout.fragment_main_screen, container, false); - - mRecyclerView = (RecyclerView) view.findViewById(R.id.main_screen); - mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - - mPresenter.start(); - - return view; - } - - @Override - public void showAllCurrenciesInfoItems(List currencies) { - mAdapter = new CryptoCurrencyAdapter(currencies); - mRecyclerView.setAdapter(mAdapter); - } - - @Override - public void showInfoToast(String currencyName) { - Toast.makeText(this.getContext(), String.format("On %s clicked.", currencyName), Toast.LENGTH_SHORT).show(); - } - - @Override - public void setPresenter(MainScreenContract.Presenter presenter) { - mPresenter = presenter; - } - - /** - * Implementation RecyclerView.ViewHolder - */ - private class CryptoCurrencyHolder extends RecyclerView.ViewHolder - implements View.OnClickListener { - - private CurrencyBaseInfo mCurrencyInfo; - private TextView mTitle; - private TextView mValue; - private TextView mChange; - - public CryptoCurrencyHolder(View itemView) { - super(itemView); - - mTitle = (TextView) itemView.findViewById(R.id.currency_title); - mValue = (TextView) itemView.findViewById(R.id.currency_value); - mChange = (TextView) itemView.findViewById(R.id.currency_change); - - itemView.setOnClickListener(this); - } - - @Override - public void onClick(View v) { - MainScreenFragment.this.mPresenter.onCurrencyItemClick(mCurrencyInfo.getName()); - } - - public void setCurrencyData(CurrencyBaseInfo info) { - mCurrencyInfo = info; - - mTitle.setText(mCurrencyInfo.getName()); - mValue.setText(mCurrencyInfo.getPriceValue()); - mChange.setText(mCurrencyInfo.getChangeValue()); - - switch (mCurrencyInfo.getChangeValue().charAt(0)) { - case '+': - mChange.setTextColor(getResources().getColor(R.color.currency_item_change_positiv)); - break; - - case '-': - mChange.setTextColor(getResources().getColor(R.color.currency_item_change_negative)); - break; - - default: - mChange.setTextColor(getResources().getColor(R.color.currency_item_change_non)); - break; - } - } - } - - /** - * Implementation RecyclerView.Adapter - */ - private class CryptoCurrencyAdapter extends RecyclerView.Adapter { - - private List mCurrencies; - - public CryptoCurrencyAdapter(List mCurrencies) { - this.mCurrencies = mCurrencies; - } - - @Override - public CryptoCurrencyHolder onCreateViewHolder(ViewGroup parent, int viewType) { - return new CryptoCurrencyHolder(LayoutInflater - .from(getActivity()) - .inflate(R.layout.main_screen_currency_item, parent, false)); - } - - @Override - public void onBindViewHolder(CryptoCurrencyHolder holder, int position) { - holder.setCurrencyData(mCurrencies.get(position)); - } - - @Override - public int getItemCount() { - return mCurrencies.size(); - } - } -} diff --git a/app/src/main/java/com/example/vladislav/menu/fragments/mainscreen/MainScreenPresenter.java b/app/src/main/java/com/example/vladislav/menu/fragments/mainscreen/MainScreenPresenter.java deleted file mode 100644 index 679f8c5..0000000 --- a/app/src/main/java/com/example/vladislav/menu/fragments/mainscreen/MainScreenPresenter.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.example.vladislav.menu.fragments.mainscreen; - -import android.support.annotation.NonNull; - -import com.example.vladislav.data.CryptoRepository; - -/** - * Created by d3m1d0v on 04.03.2018. - */ - -public class MainScreenPresenter implements MainScreenContract.Presenter { - - private final MainScreenContract.View mView; - private final CryptoRepository mRepository; - - public MainScreenPresenter(@NonNull MainScreenContract.View view, @NonNull CryptoRepository repository) { - mView = view; - mRepository = repository; - - mView.setPresenter(this); - } - - @Override - public void onCurrencyItemClick(String currencyName) { - mView.showInfoToast(currencyName); - } - - @Override - public void start() { - mView.showAllCurrenciesInfoItems(mRepository.getAllCurrenciesInfo()); - } -} diff --git a/app/src/main/java/com/example/vladislav/menu/fragments/FragmentAboutApp.java b/app/src/main/java/com/example/vladislav/screen/about/FragmentAboutApp.java similarity index 89% rename from app/src/main/java/com/example/vladislav/menu/fragments/FragmentAboutApp.java rename to app/src/main/java/com/example/vladislav/screen/about/FragmentAboutApp.java index fd71c6e..0f06063 100644 --- a/app/src/main/java/com/example/vladislav/menu/fragments/FragmentAboutApp.java +++ b/app/src/main/java/com/example/vladislav/screen/about/FragmentAboutApp.java @@ -1,22 +1,22 @@ -package com.example.vladislav.menu.fragments; - -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.example.vladislav.menu.R; - -/** - * Created by vladislav on 24.02.2018. - */ - -public class FragmentAboutApp extends Fragment { - @Nullable - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.activity_about_app, null); - } -} +package com.example.vladislav.screen.about; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.example.vladislav.menu.R; + +/** + * Created by vladislav on 24.02.2018. + */ + +public class FragmentAboutApp extends Fragment { + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.activity_about_app, null); + } +} diff --git a/app/src/main/java/com/example/vladislav/screen/detailscreen/DetailScreenActivity.java b/app/src/main/java/com/example/vladislav/screen/detailscreen/DetailScreenActivity.java new file mode 100644 index 0000000..041a80f --- /dev/null +++ b/app/src/main/java/com/example/vladislav/screen/detailscreen/DetailScreenActivity.java @@ -0,0 +1,250 @@ +package com.example.vladislav.screen.detailscreen; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.util.Pair; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.util.Log; + +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.Toast; +import android.widget.TextView; + +import com.example.vladislav.app.Constant; +import com.example.vladislav.data.CurrencyData; +import com.example.vladislav.data.repository.CryptoRepository; +import com.example.vladislav.screen.notificationscreen.ICONotificationActivity; +import com.example.vladislav.menu.R; +import com.github.mikephil.charting.charts.LineChart; + +import com.example.vladislav.data.repository.MainRepository; + +import java.util.Timer; +import java.util.TimerTask; +import java.util.ArrayList; +import java.util.Locale; + +//import butterknife.BindView; +//import butterknife.BindViews; +//import butterknife.ButterKnife; + +public class DetailScreenActivity extends AppCompatActivity implements CryptoRepository.GetDataCallback, CryptoRepository.RefreshCallback { + + /*@BindView(R.id.dollarVal) TextView dolVal; + @BindView(R.id.rublVal) TextView rublVal; + @BindView(R.id.changeHours1Val) TextView change1Hval; + @BindView(R.id.changeHours24Val) TextView change24Hval; + @BindView(R.id.changeDays7) TextView change7Dval; + @BindView(R.id.lvData) ListView lvMain;*/ + TextView dolVal; + TextView rublVal; + TextView change1Hval; + TextView change24Hval; + TextView change7Dval; + ListView lvMain; + + + private String currencyName; + private DetailScreenChart mChart; + private CurrencyData currentCurrency; + private MyArrayAdapter adapter; + + private final CryptoRepository mRepository = MainRepository.getInstance(); + + private Timer mTimer; + private UpdateChart mUpdateChart; + + private final ArrayList> dataFields = new ArrayList<>(); + + + String[] fieldValues; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_detail_screen); + //ButterKnife.bind(this); + dolVal = (TextView ) findViewById(R.id.dollarVal); + rublVal = (TextView ) findViewById(R.id.rublVal); + change1Hval = (TextView ) findViewById(R.id.changeHours1Val); + change24Hval = (TextView) findViewById(R.id.changeHours24Val); + change7Dval = (TextView) findViewById(R.id.changeDays7); + lvMain = (ListView) findViewById(R.id.lvData); +// Toolbar toolbar = findViewById(R.id.toolbar); +// setSupportActionBar(toolbar); + + currencyName = getIntent().getStringExtra("currencyName"); + setTitle(currencyName); + + ActionBar actionBar = getSupportActionBar(); + if(actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + mChart = new DetailScreenChart((LineChart) findViewById(R.id.chart), currencyName); + mChart.initialize(); + + fieldValues = getResources().getStringArray(R.array.details_fields); + + dataFields.add(new Pair<>(fieldValues[0], "0")); + dataFields.add(new Pair<>(fieldValues[1], "0")); + dataFields.add(new Pair<>(fieldValues[2], "0")); + adapter = new MyArrayAdapter(this, dataFields); + + lvMain.setAdapter(adapter); + + if (mTimer != null) { + mTimer.cancel(); + } + + mTimer = new Timer(); + mUpdateChart = new UpdateChart(); + + mTimer.schedule(mUpdateChart, 0, 1000); + } + + @Override + public boolean onSupportNavigateUp(){ + finish(); + return true; + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) + { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.activity_menu_detail_screen, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case R.id.action_notification: + Intent intent = new Intent(this, ICONotificationActivity.class); + intent.putExtra("price", currentCurrency.getPrice()); + intent.putExtra("name", currentCurrency.getName()); + this.startActivity(intent); + break; + case android.R.id.home: + finish(); + return true; + } + + return true; + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mTimer.cancel(); + } + + @Override + public void onData(@Nullable CurrencyData data) { + if (currentCurrency == null || !currentCurrency.getLastUpdate().equals(data.getLastUpdate())) { + currentCurrency = data; + updateViewChart(); + updateViewFields(); + } + } + + @Override + public void notify(boolean successful) { + if (successful) { + updateChart(); + } else { + Toast.makeText(this, "Refresh failed", Toast.LENGTH_SHORT).show(); + } + } + + private void updateChart() { + mRepository.getCurrencyData(currencyName, this); + } + + private void updateRepository() { + mRepository.updateCurrencyData(currencyName, this); + } + + private void updateViewChart() { + mChart.addEntry(currentCurrency.getPrice()); + } + + private void updateViewFields() { + String tmp, + up = getResources().getString(R.string.arrow_up), + down = getResources().getString(R.string.arrow_down); + int tmpClr, + clr_up = getResources().getColor(R.color.color_up), + clr_down = getResources().getColor(R.color.color_down); + + dolVal.setText(String.format(Locale.getDefault(), "%,.2f $", currentCurrency.getPrice())); + rublVal.setText(String.format(Locale.getDefault(), "%,.2f %s", currentCurrency.getPrice() * 57, "\u20bd")); + + tmp = (currentCurrency.getChange() >= 0) ? up : down; + tmpClr = (currentCurrency.getChange() >= 0) ? clr_up : clr_down; + + change1Hval.setText(String.format(Locale.getDefault(), "%+.3f%% %s", currentCurrency.getChange(), tmp)); + change1Hval.setTextColor(tmpClr); + + tmp = (currentCurrency.getChange1H() >= 0) ? up : down; + tmpClr = (currentCurrency.getChange1H() >= 0) ? clr_up : clr_down; + + change24Hval.setText(String.format(Locale.getDefault(), "%+.3f%% %s", currentCurrency.getChange1H(), tmp)); + change24Hval.setTextColor(tmpClr); + + tmp = (currentCurrency.getChange7D() >= 0) ? up : down; + tmpClr = (currentCurrency.getChange7D() >= 0) ? clr_up : clr_down; + + change7Dval.setText(String.format(Locale.getDefault(), "%+.3f%% %s", currentCurrency.getChange7D(), tmp)); + change7Dval.setTextColor(tmpClr); + + dataFields.set(0, new Pair(fieldValues[0], currentCurrency.getCapitalization())); + dataFields.set(1, new Pair(fieldValues[1], currentCurrency.getSupply())); + dataFields.set(2, new Pair(fieldValues[2], currentCurrency.getVolume24H())); + + adapter.notifyDataSetChanged(); + } + + public class MyArrayAdapter extends ArrayAdapter> { + private final Context context; + private final ArrayList> values; + + public MyArrayAdapter(Context context, ArrayList> values) { + super(context, R.layout.detail_screen_list_item, values); + this.context = context; + this.values = values; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View rowView = inflater.inflate(R.layout.detail_screen_list_item, parent, false); + TextView titleText = (TextView) rowView.findViewById(R.id.detail_list_title); + TextView valText = (TextView) rowView.findViewById(R.id.detail_list_val); + titleText.setText(values.get(position).first); + valText.setText(values.get(position).second); + + return rowView; + } + } + + class UpdateChart extends TimerTask { + @Override + public void run() { + updateRepository(); +// Log.d(Constant.TAG, "Timer tick"); + } + } +} diff --git a/app/src/main/java/com/example/vladislav/screen/detailscreen/DetailScreenChart.java b/app/src/main/java/com/example/vladislav/screen/detailscreen/DetailScreenChart.java new file mode 100644 index 0000000..3572753 --- /dev/null +++ b/app/src/main/java/com/example/vladislav/screen/detailscreen/DetailScreenChart.java @@ -0,0 +1,143 @@ +package com.example.vladislav.screen.detailscreen; + +import android.graphics.Color; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.widget.Toast; + +import com.example.vladislav.data.CurrencyData; +import com.example.vladislav.data.api.CryptoCompareApi; +import com.example.vladislav.data.api.models.CurrencyDataModel; +import com.example.vladislav.data.repository.CryptoRepository; +import com.example.vladislav.data.repository.MainRepository; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.utils.ViewPortHandler; + +import java.text.DecimalFormat; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +/** + * Created by vladislav on 24.03.2018. + */ + +public class DetailScreenChart { + + private LineChart mChart; + private String currencyName; + + public DetailScreenChart(LineChart mChart, String currencyName) { + this.mChart = mChart; + this.currencyName = currencyName; + } + + public void initialize() { + mChart.getDescription().setEnabled(false); + mChart.setScaleEnabled(true); + mChart.setDragEnabled(true); + mChart.setTouchEnabled(true); + mChart.setPinchZoom(true); + mChart.setDrawGridBackground(false); + mChart.setAutoScaleMinMaxEnabled(true); + mChart.getLegend().setEnabled(false); + mChart.getAxisRight().setEnabled(false); + mChart.setData(new LineData()); + + XAxis xAxis = mChart.getXAxis(); + xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); + xAxis.setTextColor(Color.WHITE); + xAxis.setDrawGridLines(true); + xAxis.setDrawAxisLine(true); + + YAxis yAxisLeft = mChart.getAxisLeft(); + yAxisLeft.setValueFormatter(new YAxisValueFormatter()); + yAxisLeft.setTextColor(Color.WHITE); + yAxisLeft.setDrawGridLines(true); + yAxisLeft.setDrawAxisLine(true); + } + + private LineDataSet createSet() { + LineDataSet set = new LineDataSet(null, currencyName); + set.setAxisDependency(YAxis.AxisDependency.LEFT); + set.setColor(Color.CYAN); + set.setFillColor(Color.CYAN); + set.setDrawCircles(false); + set.setDrawValues(false); + set.setLineWidth(2f); + set.setFillAlpha(65); + set.setDrawFilled(true); + + return set; + } + + public void addEntry(float yValue) { + LineData data = mChart.getData(); + + ILineDataSet set = data.getDataSetByIndex(0); + + if (set == null) { + set = createSet(); + data.addDataSet(set); + } + + data.addEntry(new Entry(data.getDataSetByIndex(0).getEntryCount(), yValue), 0); + data.notifyDataChanged(); + mChart.notifyDataSetChanged(); + mChart.moveViewToX(data.getEntryCount()); + } + + class XAxisValueFormatter implements IAxisValueFormatter { + + private String[] mValues; + + public XAxisValueFormatter(String[] mValues) { + this.mValues = mValues; + } + + @Override + public String getFormattedValue(float value, AxisBase axis) { + return mValues[(int) value]; + } + } + + class YAxisValueFormatter implements IAxisValueFormatter { + + private DecimalFormat mFormat; + + public YAxisValueFormatter () { + mFormat = new DecimalFormat("###,###,##0.0"); + } + + @Override + public String getFormattedValue(float value, AxisBase axis) { + return "$" + mFormat.format(value); + } + } + + class ValueFormatter implements IValueFormatter { + + private DecimalFormat mFormat; + + public ValueFormatter() { + mFormat = new DecimalFormat("###,###,##0.000"); + } + + @Override + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return mFormat.format(value); + } + } +} diff --git a/app/src/main/java/com/example/vladislav/screen/mainscreen/CurrencySortType.java b/app/src/main/java/com/example/vladislav/screen/mainscreen/CurrencySortType.java new file mode 100644 index 0000000..ff48722 --- /dev/null +++ b/app/src/main/java/com/example/vladislav/screen/mainscreen/CurrencySortType.java @@ -0,0 +1,31 @@ +package com.example.vladislav.screen.mainscreen; + +/** + * Created by d3m1d0v on 28.03.2018. + */ + +enum CurrencySortType { + + /* + * Sort alphabetically + */ + ALPHABETICAL, + + /* + * Sort by price + */ + PRICE, + + /* + * Sort by 24h change + */ + CHANGE24H; + + /* + * Returns default sort type + */ + static CurrencySortType getDefault() { + return PRICE; + } + +} diff --git a/app/src/main/java/com/example/vladislav/screen/mainscreen/MainScreenContract.java b/app/src/main/java/com/example/vladislav/screen/mainscreen/MainScreenContract.java new file mode 100644 index 0000000..c5b21b4 --- /dev/null +++ b/app/src/main/java/com/example/vladislav/screen/mainscreen/MainScreenContract.java @@ -0,0 +1,44 @@ +package com.example.vladislav.screen.mainscreen; + +import com.example.vladislav.base.BasePresenter; +import com.example.vladislav.base.BaseView; +import com.example.vladislav.data.CurrencyData; + +import java.util.List; + +/** + * Created by d3m1d0v on 04.03.2018. + */ + +public interface MainScreenContract { + + interface View extends BaseView { + + void showCurrenciesData(List dataList); + + void showInfoToast(String currencyName); + + void notifyAdapter(); + + void showRefreshFailedToast(); + + void showRefreshAnimation(); + + void hideRefreshAnimation(); + } + + interface Presenter extends BasePresenter { + + void onCurrencyItemClick(String currencyName); + + void onRefreshRequested(); + + void onAlphabetSortSelected(); + + void onPriceSortSelected(); + + void onChangeSortSelected(); + + void onDestroy(); + } +} diff --git a/app/src/main/java/com/example/vladislav/screen/mainscreen/MainScreenFragment.java b/app/src/main/java/com/example/vladislav/screen/mainscreen/MainScreenFragment.java new file mode 100644 index 0000000..f4c35a5 --- /dev/null +++ b/app/src/main/java/com/example/vladislav/screen/mainscreen/MainScreenFragment.java @@ -0,0 +1,235 @@ +package com.example.vladislav.screen.mainscreen; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; + +import com.example.vladislav.data.CurrencyData; +import com.example.vladislav.data.repository.MainRepository; +import com.example.vladislav.menu.R; + +import java.util.List; + +/** + * Created by d3m1d0v on 03.03.2018. + */ + +public class MainScreenFragment extends Fragment implements MainScreenContract.View, SwipeRefreshLayout.OnRefreshListener { + + private MainScreenContract.Presenter mPresenter; + private RecyclerView mRecyclerView; + private CryptoCurrencyAdapter mAdapter; + private SwipeRefreshLayout mSwipeRefreshLayout; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + + new MainScreenPresenter(this, MainRepository.getInstance()); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + View view = inflater.inflate(R.layout.fragment_main_screen, container, false); + + mRecyclerView = view.findViewById(R.id.main_screen); + mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + + mSwipeRefreshLayout = view.findViewById(R.id.refresh); + mSwipeRefreshLayout.setOnRefreshListener(this); + mSwipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary); + + mPresenter.start(); + + return view; + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.menu, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.menu_alphabetical: + mPresenter.onAlphabetSortSelected(); + break; + + case R.id.menu_price: + mPresenter.onPriceSortSelected(); + break; + + case R.id.menu_change: + mPresenter.onChangeSortSelected(); + break; + + default: + return super.onOptionsItemSelected(item); + } + + return true; + } + + @Override + public void onDestroy() { + super.onDestroy(); + mPresenter.onDestroy(); + } + + @Override + public void showCurrenciesData(List currencies) { + if (mAdapter == null) { + mAdapter = new CryptoCurrencyAdapter(currencies); + mRecyclerView.setAdapter(mAdapter); + } else { + mAdapter.setDataList(currencies); + } + } + + @Override + public void showInfoToast(String currencyName) { + Toast.makeText(this.getContext(), String.format("On %s clicked.", currencyName), Toast.LENGTH_SHORT).show(); + } + + @Override + public void notifyAdapter() { + mAdapter.notifyDataSetChanged(); + } + + @Override + public void showRefreshFailedToast() { + Toast.makeText(this.getContext(), "Refresh failed =(", Toast.LENGTH_SHORT).show(); + } + + @Override + public void showRefreshAnimation() { + mSwipeRefreshLayout.setRefreshing(true); + } + + @Override + public void hideRefreshAnimation() { + mSwipeRefreshLayout.setRefreshing(false); + } + + @Override + public void setPresenter(MainScreenContract.Presenter presenter) { + mPresenter = presenter; + } + + + /** + * Implementation {@link SwipeRefreshLayout.OnRefreshListener} + */ + @Override + public void onRefresh() { + mSwipeRefreshLayout.setRefreshing(true); + mPresenter.onRefreshRequested(); + } + + + /** + * Implementation {@link RecyclerView.ViewHolder} + */ + private class CryptoCurrencyHolder extends RecyclerView.ViewHolder + implements View.OnClickListener { + + private CurrencyData mCurrencyData; + private TextView mTitle; + private TextView mValue; + private TextView mChange; + + public CryptoCurrencyHolder(View itemView) { + super(itemView); + + mTitle = (TextView) itemView.findViewById(R.id.currency_title); + mValue = (TextView) itemView.findViewById(R.id.currency_value); + mChange = (TextView) itemView.findViewById(R.id.currency_change); + + itemView.setOnClickListener(this); + } + + @Override + public void onClick(View v) { + MainScreenFragment.this.mPresenter.onCurrencyItemClick(mCurrencyData.getName()); + + OnSelectedRelativeLayoutListener listener = (OnSelectedRelativeLayoutListener) getActivity(); + listener.onSelectedRelativeLayout(mCurrencyData.getName()); + } + + public void setCurrencyData(CurrencyData data) { + mCurrencyData = data; + + mTitle.setText(mCurrencyData.getName()); + mValue.setText(mCurrencyData.getFormattedPrice()); + mChange.setText(mCurrencyData.getFormattedChange()); + + switch (mCurrencyData.getFormattedChange().charAt(0)) { + case '+': + mChange.setTextColor(getResources().getColor(R.color.currency_item_change_positiv)); + break; + + case '-': + mChange.setTextColor(getResources().getColor(R.color.currency_item_change_negative)); + break; + + default: + mChange.setTextColor(getResources().getColor(R.color.currency_item_change_non)); + break; + } + } + } + + /** + * Implementation {@link RecyclerView.Adapter} + */ + private class CryptoCurrencyAdapter extends RecyclerView.Adapter { + + private List mDataList; + + CryptoCurrencyAdapter(List mCurrencies) { + this.mDataList = mCurrencies; + } + + @Override + public CryptoCurrencyHolder onCreateViewHolder(ViewGroup parent, int viewType) { + return new CryptoCurrencyHolder(LayoutInflater + .from(getActivity()) + .inflate(R.layout.main_screen_currency_item, parent, false)); + } + + @Override + public void onBindViewHolder(CryptoCurrencyHolder holder, int position) { + holder.setCurrencyData(mDataList.get(position)); + } + + @Override + public int getItemCount() { + return mDataList.size(); + } + + public void setDataList(List dataList) { + mDataList = dataList; + notifyDataSetChanged(); + } + } + + public interface OnSelectedRelativeLayoutListener { + + void onSelectedRelativeLayout(String currencyName); + } +} diff --git a/app/src/main/java/com/example/vladislav/screen/mainscreen/MainScreenPresenter.java b/app/src/main/java/com/example/vladislav/screen/mainscreen/MainScreenPresenter.java new file mode 100644 index 0000000..ca790a7 --- /dev/null +++ b/app/src/main/java/com/example/vladislav/screen/mainscreen/MainScreenPresenter.java @@ -0,0 +1,144 @@ +package com.example.vladislav.screen.mainscreen; + +import android.support.annotation.NonNull; +import android.util.Log; + +import com.example.vladislav.app.Constant; +import com.example.vladislav.data.repository.CryptoRepository; +import com.example.vladislav.data.CurrencyData; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.functions.Action; +import io.reactivex.functions.Consumer; + + +/** + * Created by d3m1d0v on 04.03.2018. + */ + +public class MainScreenPresenter implements MainScreenContract.Presenter { + + private final MainScreenContract.View mView; + private final CryptoRepository mRepository; + private List mDataList; + + private CompositeDisposable mDisposables = new CompositeDisposable(); + + private CurrencySortType mSortType = CurrencySortType.getDefault(); + + public MainScreenPresenter(@NonNull MainScreenContract.View view, @NonNull CryptoRepository repository) { + mView = view; + mRepository = repository; + mDataList = new ArrayList<>(); + + mView.setPresenter(this); + } + + @Override + public void onCurrencyItemClick(String currencyName) { +// mView.showInfoToast(currencyName); + } + + @Override + public void onRefreshRequested() { + mView.showRefreshAnimation(); + mDisposables.add( + mRepository.refreshCurrencyDataAll_Rx() + .toCompletable() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action() { + @Override + public void run() throws Exception { + onRefreshSuccessful(); + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + Log.d(Constant.TAG, "Refresh failed", throwable); + onRefreshFailed(); + } + }) + ); + } + + @Override + public void onAlphabetSortSelected() { + updateSortType(CurrencySortType.ALPHABETICAL); + } + + @Override + public void onPriceSortSelected() { + updateSortType(CurrencySortType.PRICE); + } + + @Override + public void onChangeSortSelected() { + updateSortType(CurrencySortType.CHANGE24H); + } + + @Override + public void onDestroy() { + mDisposables.dispose(); + } + + @Override + public void start() { + mView.showCurrenciesData(mDataList); + mDisposables.add( + mRepository.getCurrencyDataListFromDb_Rx() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer>() { + @Override + public void accept(List dataList) throws Exception { + mDataList.clear(); + mDataList.addAll(dataList); + sortDataList(); + mView.notifyAdapter(); + Log.d(Constant.TAG, "Presenter. dataList.size() = " + dataList.size()); + } + }) + ); + + onRefreshRequested(); + } + + private void updateSortType(CurrencySortType sortType) { + mSortType = sortType; + sortDataList(); + mView.notifyAdapter(); + } + + private void sortDataList() { + Collections.sort(mDataList, new Comparator() { + @Override + public int compare(CurrencyData o1, CurrencyData o2) { + switch (mSortType) { + case ALPHABETICAL: + return o1.getName().compareTo(o2.getName()); + + case PRICE: + return o1.getPrice() > o2.getPrice() ? -1 : o2.getPrice() > o1.getPrice() ? 1 : 0; + + case CHANGE24H: + return o1.getChange() > o2.getChange() ? -1 : o2.getChange() > o1.getChange() ? 1 : 0; + } + return 0; + } + }); + } + + private void onRefreshSuccessful() { + mView.hideRefreshAnimation(); + } + + private void onRefreshFailed() { + mView.hideRefreshAnimation(); + mView.showRefreshFailedToast(); + } +} diff --git a/app/src/main/java/com/example/vladislav/menu/MenuActivity.java b/app/src/main/java/com/example/vladislav/screen/menu/MenuActivity.java similarity index 65% rename from app/src/main/java/com/example/vladislav/menu/MenuActivity.java rename to app/src/main/java/com/example/vladislav/screen/menu/MenuActivity.java index 73f9f9b..69ef71f 100644 --- a/app/src/main/java/com/example/vladislav/menu/MenuActivity.java +++ b/app/src/main/java/com/example/vladislav/screen/menu/MenuActivity.java @@ -1,126 +1,120 @@ -package com.example.vladislav.menu; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.design.widget.NavigationView; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentTransaction; -import android.support.v4.view.GravityCompat; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; -import android.view.Menu; -import android.view.MenuItem; -import android.widget.Toast; - -import com.example.vladislav.menu.fragments.FragmentAboutApp; -import com.example.vladislav.menu.fragments.mainscreen.MainScreenFragment; - -public class MenuActivity extends AppCompatActivity - implements NavigationView.OnNavigationItemSelectedListener, MenuContract.View { - - private MenuContract.Presenter mPresenter; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_menu); - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); - ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( - this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); - drawer.addDrawerListener(toggle); - toggle.syncState(); - - NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); - navigationView.setNavigationItemSelectedListener(this); - - new MenuPresenter(this).start(); - } - - @Override - public void onBackPressed() { - DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); - if (drawer.isDrawerOpen(GravityCompat.START)) { - drawer.closeDrawer(GravityCompat.START); - } else { - super.onBackPressed(); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu; this adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.menu, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // Handle action bar item clicks here. The action bar will - // automatically handle clicks on the Home/Up button, so long - // as you specify a parent activity in AndroidManifest.xml. - int id = item.getItemId(); - - //noinspection SimplifiableIfStatement -// if (id == R.id.action_settings) { -// return true; -// } - - return super.onOptionsItemSelected(item); - } - - @SuppressWarnings("StatementWithEmptyBody") - @Override - public boolean onNavigationItemSelected(MenuItem item) { - - // Handle navigation view item clicks here. - int id = item.getItemId(); - - if (id == R.id.main_menu) { - mPresenter.onMainMenuSelected(); - } else if (id == R.id.settings) { - mPresenter.onSettingsSelected(); - } else if (id == R.id.about_app) { - mPresenter.onAboutAppSelected(); - } - - DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); - drawer.closeDrawer(GravityCompat.START); - - return true; - } - - @Override - public void showMainScreen() { - replaceFragment(new MainScreenFragment()); - - setTitle(getResources().getString(R.string.main)); - } - - @Override - public void showAboutApp() { - replaceFragment(new FragmentAboutApp()); - - setTitle(getResources().getString(R.string.about_app)); - } - - @Override - public void showNotImplementedToast() { - Toast.makeText(this, R.string.item_not_implemented, Toast.LENGTH_SHORT).show(); - } - - @Override - public void setPresenter(@NonNull MenuContract.Presenter presenter) { - mPresenter = presenter; - } - - private void replaceFragment(Fragment newFragment) { - FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); - fragmentTransaction.replace(R.id.screen_area, newFragment); - fragmentTransaction.commit(); - } -} +package com.example.vladislav.screen.menu; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.NavigationView; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.Toast; + +import com.example.vladislav.menu.R; +import com.example.vladislav.screen.about.FragmentAboutApp; +import com.example.vladislav.screen.detailscreen.DetailScreenActivity; +import com.example.vladislav.screen.mainscreen.MainScreenFragment; + +public class MenuActivity extends AppCompatActivity + implements + NavigationView.OnNavigationItemSelectedListener, + MenuContract.View, + MainScreenFragment.OnSelectedRelativeLayoutListener { + + private MenuContract.Presenter mPresenter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_menu); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( + this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); + drawer.addDrawerListener(toggle); + toggle.syncState(); + + NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); + navigationView.setNavigationItemSelectedListener(this); + + new MenuPresenter(this).start(); + } + + @Override + public void onBackPressed() { + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + if (drawer.isDrawerOpen(GravityCompat.START)) { + drawer.closeDrawer(GravityCompat.START); + } else { + super.onBackPressed(); + } + } + + @SuppressWarnings("StatementWithEmptyBody") + @Override + public boolean onNavigationItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.main_menu: + mPresenter.onMainMenuSelected(); + break; + case R.id.settings: + mPresenter.onSettingsSelected(); + break; + case R.id.about_app: + mPresenter.onAboutAppSelected(); + break; + } + DrawerLayout drawer = findViewById(R.id.drawer_layout); + drawer.closeDrawer(GravityCompat.START); + return true; + } + + @Override + public void showMainScreen() { + replaceFragment(new MainScreenFragment()); + + setTitle(getResources().getString(R.string.main)); + } + + @Override + public void showAboutApp() { + replaceFragment(new FragmentAboutApp()); + + setTitle(getResources().getString(R.string.about_app)); + } + + @Override + public void showNotImplementedToast() { + Toast.makeText(this, R.string.item_not_implemented, Toast.LENGTH_SHORT).show(); + } + + @Override + public void setPresenter(@NonNull MenuContract.Presenter presenter) { + mPresenter = presenter; + } + + private void replaceFragment(Fragment newFragment) { + FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); + fragmentTransaction.replace(R.id.screen_area, newFragment); + fragmentTransaction.commit(); + } + + public void setActionBarTitle(String title) { + getSupportActionBar().setTitle(title); + } + + @Override + public void onSelectedRelativeLayout(String currencyName) { + Intent intent = new Intent(this, DetailScreenActivity.class); + intent.putExtra("currencyName", currencyName); + startActivity(intent); + + } +} diff --git a/app/src/main/java/com/example/vladislav/menu/MenuContract.java b/app/src/main/java/com/example/vladislav/screen/menu/MenuContract.java similarity index 73% rename from app/src/main/java/com/example/vladislav/menu/MenuContract.java rename to app/src/main/java/com/example/vladislav/screen/menu/MenuContract.java index da225a4..4b739a5 100644 --- a/app/src/main/java/com/example/vladislav/menu/MenuContract.java +++ b/app/src/main/java/com/example/vladislav/screen/menu/MenuContract.java @@ -1,29 +1,29 @@ -package com.example.vladislav.menu; - -import com.example.vladislav.BasePresenter; -import com.example.vladislav.BaseView; - -/** - * Created by d3m1d0v on 01.03.2018. - */ - -public interface MenuContract { - - interface View extends BaseView { - - void showMainScreen(); - - void showAboutApp(); - - void showNotImplementedToast(); - } - - interface Presenter extends BasePresenter { - - void onMainMenuSelected(); - - void onSettingsSelected(); - - void onAboutAppSelected(); - } -} +package com.example.vladislav.screen.menu; + +import com.example.vladislav.base.BasePresenter; +import com.example.vladislav.base.BaseView; + +/** + * Created by d3m1d0v on 01.03.2018. + */ + +public interface MenuContract { + + interface View extends BaseView { + + void showMainScreen(); + + void showAboutApp(); + + void showNotImplementedToast(); + } + + interface Presenter extends BasePresenter { + + void onMainMenuSelected(); + + void onSettingsSelected(); + + void onAboutAppSelected(); + } +} diff --git a/app/src/main/java/com/example/vladislav/menu/MenuPresenter.java b/app/src/main/java/com/example/vladislav/screen/menu/MenuPresenter.java similarity index 90% rename from app/src/main/java/com/example/vladislav/menu/MenuPresenter.java rename to app/src/main/java/com/example/vladislav/screen/menu/MenuPresenter.java index be7acae..8183878 100644 --- a/app/src/main/java/com/example/vladislav/menu/MenuPresenter.java +++ b/app/src/main/java/com/example/vladislav/screen/menu/MenuPresenter.java @@ -1,39 +1,39 @@ -package com.example.vladislav.menu; - -import android.support.annotation.NonNull; - -/** - * Created by d3m1d0v on 01.03.2018. - */ - -public class MenuPresenter implements MenuContract.Presenter { - - private final MenuContract.View mMenuView; - - - public MenuPresenter(@NonNull MenuContract.View menuView) { - mMenuView = menuView; - - mMenuView.setPresenter(this); - } - - @Override - public void onMainMenuSelected() { - mMenuView.showMainScreen(); - } - - @Override - public void onSettingsSelected() { - mMenuView.showNotImplementedToast(); - } - - @Override - public void onAboutAppSelected() { - mMenuView.showAboutApp(); - } - - @Override - public void start() { - mMenuView.showMainScreen(); - } -} +package com.example.vladislav.screen.menu; + +import android.support.annotation.NonNull; + +/** + * Created by d3m1d0v on 01.03.2018. + */ + +public class MenuPresenter implements MenuContract.Presenter { + + private final MenuContract.View mMenuView; + + + public MenuPresenter(@NonNull MenuContract.View menuView) { + mMenuView = menuView; + + mMenuView.setPresenter(this); + } + + @Override + public void onMainMenuSelected() { + mMenuView.showMainScreen(); + } + + @Override + public void onSettingsSelected() { + mMenuView.showNotImplementedToast(); + } + + @Override + public void onAboutAppSelected() { + mMenuView.showAboutApp(); + } + + @Override + public void start() { + mMenuView.showMainScreen(); + } +} diff --git a/app/src/main/java/com/example/vladislav/screen/notificationscreen/ICONotificationActivity.java b/app/src/main/java/com/example/vladislav/screen/notificationscreen/ICONotificationActivity.java new file mode 100644 index 0000000..863a6fb --- /dev/null +++ b/app/src/main/java/com/example/vladislav/screen/notificationscreen/ICONotificationActivity.java @@ -0,0 +1,109 @@ +package com.example.vladislav.screen.notificationscreen; + +import android.support.annotation.IdRes; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.SeekBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.example.vladislav.menu.R; + +import java.text.DecimalFormat; + +//import butterknife.BindView; +//import butterknife.ButterKnife; + +public class ICONotificationActivity extends AppCompatActivity { + /*@BindView(R.id.textView2) TextView cryptoNameText; + @BindView(R.id.textView3) TextView cryptoValueText;*/ + TextView cryptoNameText; + TextView cryptoValueText; + private float cash = 7000; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_iconotification); + ActionBar actionBar = getSupportActionBar(); + if(actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + //ButterKnife.bind(this); + cryptoNameText = (TextView) findViewById(R.id.textView2); + cryptoValueText = (TextView) findViewById(R.id.textView3); + + cash = getIntent().getFloatExtra("price", 0); + String name = getIntent().getStringExtra("name"); + cryptoNameText.setText(name); + cryptoValueText.setText(String.format("%,.2f $", cash)); + + setTitle("Уведомление"); + customSeekBar(R.id.priceplus, R.id.seekBar1, R.id.minus1, R.id.plus1, 0); + customSeekBar(R.id.priceminus, R.id.seekBar3, R.id.minus2, R.id.plus2, 100); + + } + + private void customSeekBar(@IdRes int priceplusId, + @IdRes int seekBarId, + @IdRes int minusId, + @IdRes int plusId, + int defaultValue){ + Button btnminus1; + Button btnplus1; + //subscribe to seek bar event + final TextView priceplus=findViewById(priceplusId); + priceplus.setText("0 $"); + final SeekBar sk= findViewById(seekBarId); + sk.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) { + // TODO Auto-generated method stub + if(progress==0) + progress=1; + DecimalFormat df = new DecimalFormat("###.### $"); + priceplus.setText(df.format(((cash*2)/100.0) * progress)); + } + }); + btnminus1 = findViewById(minusId); + View.OnClickListener oclBtnOk = new View.OnClickListener() { + @Override + public void onClick(View v) { + sk.setProgress(sk.getProgress()-1); + } + }; + btnminus1.setOnClickListener(oclBtnOk); + + btnplus1 = findViewById(plusId); + View.OnClickListener oclBtnOk1 = new View.OnClickListener() { + @Override + public void onClick(View v) { + sk.setProgress(sk.getProgress()+1); + } + }; + btnplus1.setOnClickListener(oclBtnOk1); + sk.setProgress(defaultValue); + } + + @Override + public boolean onSupportNavigateUp(){ + finish(); + return true; + } + + +} diff --git a/app/src/main/java/com/example/vladislav/service/TestFirebaseInstanceIdService.java b/app/src/main/java/com/example/vladislav/service/TestFirebaseInstanceIdService.java new file mode 100644 index 0000000..2aa4d1f --- /dev/null +++ b/app/src/main/java/com/example/vladislav/service/TestFirebaseInstanceIdService.java @@ -0,0 +1,54 @@ +package com.example.vladislav.service; +import com.example.vladislav.data.api.SendRefreshTokenApi; + +import android.util.Log; + +import com.google.firebase.iid.FirebaseInstanceId; +import com.google.firebase.iid.FirebaseInstanceIdService; + + +import okhttp3.ResponseBody; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +/** + * Created by user on 24.03.2018. + */ + +public class TestFirebaseInstanceIdService extends FirebaseInstanceIdService { + public static final String TAG = "TestFbseInstIdSvc"; + + @Override + public void onTokenRefresh() { + String refreshedToken = FirebaseInstanceId.getInstance().getToken(); + Log.d(TAG, "Refreshed token: " + refreshedToken); + + sendRegistrationToServer(refreshedToken); + } + + public void sendRegistrationToServer(String token) { + SendRefreshTokenApi api = new Retrofit.Builder() + .baseUrl("http://213.159.214.131") + .addConverterFactory(GsonConverterFactory.create()) + .build() + .create(SendRefreshTokenApi.class); + + api.sendToken(token).enqueue(new Callback() { + + public void onResponse(Call call, Response response) { + if(response.isSuccessful()) { + Log.d(TAG, "Sehr gut!"); + } else { + Log.d(TAG, "Sehr schlecht!"); + } + } + + public void onFailure(Call call, Throwable t) { + Log.d(TAG, "ppc"); + } + }); + } +} diff --git a/app/src/main/java/com/example/vladislav/service/TestFirebaseMessagingService.java b/app/src/main/java/com/example/vladislav/service/TestFirebaseMessagingService.java new file mode 100644 index 0000000..198640e --- /dev/null +++ b/app/src/main/java/com/example/vladislav/service/TestFirebaseMessagingService.java @@ -0,0 +1,64 @@ +package com.example.vladislav.service; + +import android.app.Notification; +import android.app.NotificationManager; +import android.content.Context; +import android.support.v4.app.NotificationCompat; +import android.util.Log; + +import com.example.vladislav.menu.R; +import com.google.firebase.messaging.FirebaseMessagingService; +import com.google.firebase.messaging.RemoteMessage; + +/** + * Created by user on 24.03.2018. + */ + +public class TestFirebaseMessagingService extends FirebaseMessagingService { + public static final String TAG = "TestFbseMsgngSvc"; + + @Override + public void onMessageReceived(RemoteMessage remoteMessage) { + Log.d(TAG, "From: " + remoteMessage.getFrom()); + + if (remoteMessage.getData().size() > 0) { + Log.d(TAG, "Message data payload: " + remoteMessage.getData()); + + String title = remoteMessage.getData().get("title"); + String text = remoteMessage.getData().get("text"); + int color = (1<<16)|(1<<8)|(0); + ShowNotification(title, text, color); + } + + if (remoteMessage.getNotification() != null) { + Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody()); + } + } + + + @Override + public void onDeletedMessages() {} + + + void ShowNotification(String title, String text, int color) { + NotificationCompat.Builder mNotify = new NotificationCompat.Builder(getApplicationContext(), ""); + mNotify.setLights(color, 100, 200); + mNotify.setSmallIcon(R.mipmap.ic_launcher); + mNotify.setContentTitle(title); + mNotify.setContentText(text); + mNotify.setDefaults(Notification.DEFAULT_SOUND); + mNotify.setAutoCancel(true); + + NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + int mId = 1001; + try { + Notification n = mNotify.build(); + mNotificationManager.notify(mId, n); + } + catch (Exception e) { + //e.printStackTrace(); + Log.d(TAG, "Error"); + } + } +} diff --git a/app/src/main/res/layout/activity_detail_screen.xml b/app/src/main/res/layout/activity_detail_screen.xml new file mode 100644 index 0000000..2d88107 --- /dev/null +++ b/app/src/main/res/layout/activity_detail_screen.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_iconotification.xml b/app/src/main/res/layout/activity_iconotification.xml new file mode 100644 index 0000000..2b93a8a --- /dev/null +++ b/app/src/main/res/layout/activity_iconotification.xml @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + +