diff --git a/.idea/caches/gradle_models.ser b/.idea/caches/gradle_models.ser index ce87bad..a915058 100644 Binary files a/.idea/caches/gradle_models.ser and b/.idea/caches/gradle_models.ser differ diff --git a/app/build.gradle b/app/build.gradle index 3b89585..5be5893 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,4 +33,5 @@ dependencies { implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.4.0' implementation 'com.android.support:recyclerview-v7:27.1.1' + implementation 'com.squareup.picasso:picasso:2.71828' } diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/ItemPresenter.java b/app/src/main/java/ru/volgorobot/vrcatalog/ItemPresenter.java new file mode 100644 index 0000000..a0b6cae --- /dev/null +++ b/app/src/main/java/ru/volgorobot/vrcatalog/ItemPresenter.java @@ -0,0 +1,92 @@ +package ru.volgorobot.vrcatalog; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.AsyncTask; +import android.provider.MediaStore; +import android.util.Base64; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; + +import ru.volgorobot.vrcatalog.additional.NetworkErrorException; +import ru.volgorobot.vrcatalog.additional.ResultWithErrorCode; +import ru.volgorobot.vrcatalog.model.CoreModel; +import ru.volgorobot.vrcatalog.model.ImageItemModel; + +public class ItemPresenter implements MainContract.ItemPresenter { + + // TODO + + private MainContract.ItemView mView; + private Context context; + private MainContract.MainModel coreModel; + + public ItemPresenter(Context context, MainContract.ItemView itemView) { + this.mView = itemView; + this.context = context; + this.coreModel = new CoreModel(context); + } + + @SuppressLint("StaticFieldLeak") + @Override + public void getImagesByItemID(int id) { + new AsyncTask>>() { + @Override + protected ResultWithErrorCode> doInBackground(Void... voids) { + ArrayList images = null; + try { + images = coreModel.fetchImagesByItemID(id); + } catch (NetworkErrorException networkErrorException) { + return new ResultWithErrorCode<>(images, networkErrorException.getErrorCode()); + } catch (NullPointerException nullPointerException) { + return new ResultWithErrorCode<>(images, 3); + } + return new ResultWithErrorCode<>(images, 0); + } + + @Override + protected void onPostExecute(ResultWithErrorCode> result) { + super.onPostExecute(result); + switch (result.getErrorCode()) { + case 0: { + //mView.setViewPagerContent(result.getData()); + ArrayList bitmaps = new ArrayList<>(); + ArrayList uriStrings = new ArrayList<>(); + for (ImageItemModel imageItem : result.getData()) { + byte[] imageStream = Base64.decode(imageItem.getImage(), Base64.DEFAULT); + bitmaps.add(BitmapFactory.decodeByteArray(imageStream, 0, imageStream.length)); + } + for (Bitmap bitmap : bitmaps) { + uriStrings.add(processImages(bitmap).toString()); + } + // TODO: setViewPagerContent() + break; + } + case 1: { + mView.onFailureAnswer(1); + break; + } + case 2: { + mView.onFailureAnswer(2); + break; + } + case 3: { + mView.onFailureAnswer(3); + break; + } + } + } + }.execute(); + } + + private Uri processImages(Bitmap bitmap) { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes); + String path = MediaStore.Images.Media.insertImage(context.getContentResolver(), bitmap, "Title", null); + return Uri.parse(path); + } +} diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java b/app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java index 4bf200d..5bba085 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java @@ -1,6 +1,7 @@ package ru.volgorobot.vrcatalog; import android.content.Intent; +import android.net.Uri; import java.util.ArrayList; @@ -9,6 +10,7 @@ import ru.volgorobot.vrcatalog.additional.NetworkErrorException; import ru.volgorobot.vrcatalog.model.CoreModel; import ru.volgorobot.vrcatalog.model.DetailModel; import ru.volgorobot.vrcatalog.model.FirstLevelModel; +import ru.volgorobot.vrcatalog.model.ImageItemModel; import ru.volgorobot.vrcatalog.model.SecondLevelModel; import ru.volgorobot.vrcatalog.model.ThirdLevelModel; @@ -42,10 +44,11 @@ public interface MainContract { ArrayList fetchThirdLevelByParentID(int parentID) throws NetworkErrorException, NullPointerException; ArrayList fetchDetailByID(int detailID) throws NetworkErrorException, NullPointerException; void reinitializeApi() throws IllegalStateException; - boolean getApiState(); + boolean isApiNotNull(); ArrayList fetchDetailsByName(String name) throws NetworkErrorException, NullPointerException; ArrayList fetchCategoryByID(int id) throws NetworkErrorException, NullPointerException; ArrayList fetchSubCategoryByID(int id) throws NetworkErrorException, NullPointerException; + ArrayList fetchImagesByItemID(int id) throws NetworkErrorException, NullPointerException; } interface SearchablePresenter { @@ -57,4 +60,13 @@ public interface MainContract { void onFailureAnswer(int errorCode); void swipeLayoutSetRefreshing(boolean state); } + + interface ItemPresenter { + void getImagesByItemID(int id); + } + + interface ItemView { + void onFailureAnswer(int errorCode); + void setViewPagerContent(Uri uri); + } } diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/additional/ImagePagerAdapter.java b/app/src/main/java/ru/volgorobot/vrcatalog/additional/ImagePagerAdapter.java new file mode 100644 index 0000000..fcefada --- /dev/null +++ b/app/src/main/java/ru/volgorobot/vrcatalog/additional/ImagePagerAdapter.java @@ -0,0 +1,58 @@ +package ru.volgorobot.vrcatalog.additional; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.v4.view.PagerAdapter; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import com.squareup.picasso.Picasso; + +public class ImagePagerAdapter extends PagerAdapter { + /** + * This class is designed to control the ViewPager (images of item) in the activity of viewing details of items. + */ + + private Context context; + private String[] imageUris; + + public ImagePagerAdapter(Context context, String[] imageUris) { + this.context = context; + this.imageUris = imageUris; + } + + @Override + public int getCount() { + return imageUris.length; + } + + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } + + /** + * This function initializes a new image from a URI. + * @return ImageView + */ + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + ImageView imageView = new ImageView(context); + Picasso.get() + .load(imageUris[position]) + .fit() + .centerCrop() + .into(imageView); + container.addView(imageView); + + return imageView; + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + container.removeView((View) object); + } +} diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/api/VRApi.java b/app/src/main/java/ru/volgorobot/vrcatalog/api/VRApi.java index f3bbd7a..cc29f58 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/api/VRApi.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/api/VRApi.java @@ -8,6 +8,7 @@ import retrofit2.http.Path; import retrofit2.http.Query; import ru.volgorobot.vrcatalog.model.DetailModel; import ru.volgorobot.vrcatalog.model.FirstLevelModel; +import ru.volgorobot.vrcatalog.model.ImageItemModel; import ru.volgorobot.vrcatalog.model.SecondLevelModel; import ru.volgorobot.vrcatalog.model.ThirdLevelModel; @@ -33,4 +34,7 @@ public interface VRApi { @GET("/api/item") Call> getDetailsByName(@Query("name") String name); + + @GET("/api/item/{id}/images") + Call> getImagesByItemID(@Path("id") int itemID); } diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/model/CoreModel.java b/app/src/main/java/ru/volgorobot/vrcatalog/model/CoreModel.java index 7a3ee03..22eba65 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/model/CoreModel.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/model/CoreModel.java @@ -32,7 +32,7 @@ public class CoreModel implements MainContract.MainModel { @Override public ArrayList fetchFirstLevel() throws NetworkErrorException, NullPointerException { - if(vrApi == null) { + if(!isApiNotNull()) { throw new NullPointerException(); } final ArrayList firstLevelModels = new ArrayList<>(); @@ -51,7 +51,7 @@ public class CoreModel implements MainContract.MainModel { @Override public ArrayList fetchSecondLevelByParentID(int parentID) throws NetworkErrorException, NullPointerException { - if(vrApi == null) { + if(!isApiNotNull()) { throw new NullPointerException(); } final ArrayList secondLevelModels = new ArrayList<>(); @@ -70,7 +70,7 @@ public class CoreModel implements MainContract.MainModel { @Override public ArrayList fetchThirdLevelByParentID(int parentID) throws NetworkErrorException, NullPointerException { - if(vrApi == null) { + if(!isApiNotNull()) { throw new NullPointerException(); } final ArrayList thirdLevelModels = new ArrayList<>(); @@ -89,7 +89,7 @@ public class CoreModel implements MainContract.MainModel { @Override public ArrayList fetchDetailByID(int detailID) throws NetworkErrorException, NullPointerException { - if(vrApi == null) { + if(!isApiNotNull()) { throw new NullPointerException(); } ArrayList detail = new ArrayList<>(); @@ -118,17 +118,13 @@ public class CoreModel implements MainContract.MainModel { } @Override - public boolean getApiState() { - if(vrApi != null) { - return true; - } else { - return false; - } + public boolean isApiNotNull() { + return vrApi != null; } @Override public ArrayList fetchDetailsByName(String name) throws NetworkErrorException, NullPointerException { - if(vrApi == null) { + if(!isApiNotNull()) { throw new NullPointerException(); } final ArrayList thirdLevelModels = new ArrayList<>(); @@ -147,7 +143,7 @@ public class CoreModel implements MainContract.MainModel { @Override public ArrayList fetchCategoryByID(int id) throws NetworkErrorException, NullPointerException { - if(vrApi == null) { + if(!isApiNotNull()) { throw new NullPointerException(); } final ArrayList firstLevelModels = new ArrayList<>(); @@ -166,7 +162,7 @@ public class CoreModel implements MainContract.MainModel { @Override public ArrayList fetchSubCategoryByID(int id) throws NetworkErrorException, NullPointerException { - if(vrApi == null) { + if(!isApiNotNull()) { throw new NullPointerException(); } final ArrayList secondLevelModels = new ArrayList<>(); @@ -182,4 +178,23 @@ public class CoreModel implements MainContract.MainModel { } return secondLevelModels; } + + @Override + public ArrayList fetchImagesByItemID(int id) throws NetworkErrorException, NullPointerException { + if(!isApiNotNull()) { + throw new NullPointerException(); + } + final ArrayList imageItemModels = new ArrayList<>(); + try { + Response> response = vrApi.getImagesByItemID(id).execute(); + if(response.isSuccessful()) { + imageItemModels.addAll(response.body()); + } else { + throw new NetworkErrorException(2); + } + } catch (IOException e) { + throw new NetworkErrorException(1); + } + return imageItemModels; + } } diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/model/ImageItemModel.java b/app/src/main/java/ru/volgorobot/vrcatalog/model/ImageItemModel.java new file mode 100644 index 0000000..cf14302 --- /dev/null +++ b/app/src/main/java/ru/volgorobot/vrcatalog/model/ImageItemModel.java @@ -0,0 +1,40 @@ +package ru.volgorobot.vrcatalog.model; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class ImageItemModel { + @SerializedName("DetailID") + @Expose + private Integer detailID; + @SerializedName("image") + @Expose + private String image; + @SerializedName("MD5") + @Expose + private String MD5; + + public Integer getDetailID() { + return detailID; + } + + public void setDetailID(Integer detailID) { + this.detailID = detailID; + } + + public String getImage() { + return image; + } + + public void setImage(String image) { + this.image = image; + } + + public String getMD5() { + return MD5; + } + + public void setMD5(String mD5) { + this.MD5 = mD5; + } +} diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/DetailActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/DetailActivity.java index 8af69ba..c8be4b5 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/DetailActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/DetailActivity.java @@ -1,18 +1,23 @@ package ru.volgorobot.vrcatalog.view; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.method.LinkMovementMethod; +import android.util.Log; import android.view.MenuItem; import android.widget.EditText; import android.widget.TextView; +import android.widget.Toast; import java.util.HashMap; +import ru.volgorobot.vrcatalog.ItemPresenter; +import ru.volgorobot.vrcatalog.MainContract; import ru.volgorobot.vrcatalog.R; -public class DetailActivity extends AppCompatActivity { +public class DetailActivity extends AppCompatActivity implements MainContract.ItemView { TextView nameView; TextView quantityView; TextView priceView; @@ -20,6 +25,7 @@ public class DetailActivity extends AppCompatActivity { TextView analogueView; TextView datasheetView; EditText notesView; + private MainContract.ItemPresenter mPresenter; @Override protected void onCreate(Bundle savedInstanceState) { @@ -28,6 +34,7 @@ public class DetailActivity extends AppCompatActivity { getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeButtonEnabled(true); initializeViews(); + mPresenter = new ItemPresenter(DetailActivity.this, this); Intent intent = getIntent(); @@ -110,4 +117,30 @@ public class DetailActivity extends AppCompatActivity { } return super.onOptionsItemSelected(item); } + + @Override + public void onFailureAnswer(int errorCode) { + switch (errorCode) { + case 1: { + Toast.makeText(DetailActivity.this, "Ошибка сети. Проверьте подключение к сети или данные подключения к API!", Toast.LENGTH_LONG).show(); + Log.e("DetailActivity", "Network Error! Re-check your connection credentials or network settings!"); + break; + } + case 2: { + Toast.makeText(DetailActivity.this, "Ответ от сервера неверен! Перепроверьте данные подключения!", Toast.LENGTH_LONG).show(); + Log.e("DetailActivity", "Answer of server is wrong! Re-check your connection credentials!"); + break; + } + case 3: { + Toast.makeText(DetailActivity.this, "Вы ввели неверный URL. Пример: http://example.ru", Toast.LENGTH_LONG).show(); + Log.e("DetailActivity", "Invalid-formatted URL. Please, check URL (change his if it need) and try again."); + break; + } + } + } + + @Override + public void setViewPagerContent(Uri uri) { + + } } diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index 5727204..e4adc21 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -1,155 +1,31 @@ - + android:orientation="vertical"> + + + android:textSize="30sp" /> - - + android:textSize="24sp" /> - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file