From 6574df3d2f91f891b6223db31a3fa03e94d80d9e Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 22 Jan 2019 16:47:08 +0300 Subject: [PATCH 01/14] [LogCat] Changed tag and added log message for invalid-formatted URL situation. --- .../main/java/ru/volgorobot/vrcatalog/view/MainActivity.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java index a89b0f9..01295d9 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java @@ -118,18 +118,19 @@ public class MainActivity extends AppCompatActivity switch (errorCode) { case 1: { Toast.makeText(MainActivity.this, "Ошибка сети. Проверьте подключение к сети или данные подключения к API!", Toast.LENGTH_LONG).show(); - Log.e("VRCatalog", "Network Error! Re-check your connection credentials or network settings! Technical info: null"); + Log.e("MainActivity", "Network Error! Re-check your connection credentials or network settings!"); mSwipeRefreshLayout.setRefreshing(false); break; } case 2: { Toast.makeText(MainActivity.this, "Ответ от сервера неверен! Перепроверьте данные подключения!", Toast.LENGTH_LONG).show(); - Log.e("VRCatalog", "Answer of server is wrong! Re-check your connection credentials! Technical info: null"); + Log.e("MainActivity", "Answer of server is wrong! Re-check your connection credentials!"); mSwipeRefreshLayout.setRefreshing(false); break; } case 3: { Toast.makeText(this, "Вы ввели неверный URL. Пример: http://example.ru", Toast.LENGTH_LONG).show(); + Log.e("MainActivity", "Invalid-formatted URL. Please, check URL (change his if it need) and try again."); mSwipeRefreshLayout.setRefreshing(false); break; } From 3b92ca5bd6ae263da9331fc295ed93d4df5fd7a4 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Sun, 27 Jan 2019 21:47:15 +0400 Subject: [PATCH 02/14] Made error icon when error occured (network error, etc.) --- .idea/assetWizardSettings.xml | 6 +-- .idea/vcs.xml | 1 + .../vrcatalog/view/MainActivity.java | 30 ++++++++++- .../vrcatalog/view/SearchableActivity.java | 32 ++++++++++-- .../main/res/layout/activity_searchable.xml | 43 ++++++++++++++-- app/src/main/res/layout/content_main.xml | 51 +++++++++++++++++-- 6 files changed, 145 insertions(+), 18 deletions(-) diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml index 978ee3f..4367245 100644 --- a/.idea/assetWizardSettings.xml +++ b/.idea/assetWizardSettings.xml @@ -18,7 +18,7 @@ @@ -28,8 +28,8 @@ diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 35eb1dd..8306744 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java index 01295d9..2cbde48 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java @@ -9,6 +9,7 @@ import android.support.design.widget.NavigationView; import android.support.v4.view.GravityCompat; import android.support.v4.view.MenuItemCompat; import android.support.v4.widget.DrawerLayout; +import android.support.v4.widget.NestedScrollView; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; @@ -16,10 +17,14 @@ import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.SearchView; 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.ImageView; +import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; @@ -39,6 +44,9 @@ public class MainActivity extends AppCompatActivity private TreeView treeView; private TreeNode rootNode = TreeNode.root(); private SwipeRefreshLayout mSwipeRefreshLayout; + private ImageView mConnectionErrorImageView; + private ViewGroup mTreeViewContainer; + private TextView mErrorTextView; @Override protected void onCreate(Bundle savedInstanceState) { @@ -56,7 +64,7 @@ public class MainActivity extends AppCompatActivity NavigationView navigationView = findViewById(R.id.nav_view); navigationView.setNavigationItemSelectedListener(this); - mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout); + mSwipeRefreshLayout = findViewById(R.id.swipeRefreshLayout); mSwipeRefreshLayout.setOnRefreshListener(MainActivity.this); mSwipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary); @@ -64,11 +72,14 @@ public class MainActivity extends AppCompatActivity treeView = new TreeView(rootNode, MainActivity.this, new NodeViewFactory(MainActivity.this, this, this.mPresenter.getCoreModel())); treeView.setItemAnimator(new DefaultItemAnimator()); - ((ViewGroup) findViewById(R.id.treeViewContainer)).addView(treeView.getView()); + mTreeViewContainer = findViewById(R.id.treeViewContainer); + mTreeViewContainer.addView(treeView.getView()); mSwipeRefreshLayout.setRefreshing(true); mPresenter.getFirstLevel(); } + + @Override public void onBackPressed() { DrawerLayout drawer = findViewById(R.id.drawer_layout); @@ -111,27 +122,42 @@ public class MainActivity extends AppCompatActivity @Override public void onRefresh() { + mConnectionErrorImageView.setVisibility(View.INVISIBLE); + mErrorTextView.setVisibility(View.INVISIBLE); + mTreeViewContainer.setVisibility(View.VISIBLE); mPresenter.getFirstLevel(); } public void onFailureAnswer(int errorCode) { switch (errorCode) { case 1: { + mErrorTextView.setText("Ошибка сети. Проверьте подключение к сети или данные подключения к API!"); Toast.makeText(MainActivity.this, "Ошибка сети. Проверьте подключение к сети или данные подключения к API!", Toast.LENGTH_LONG).show(); Log.e("MainActivity", "Network Error! Re-check your connection credentials or network settings!"); mSwipeRefreshLayout.setRefreshing(false); + mTreeViewContainer.setVisibility(View.GONE); + mConnectionErrorImageView.setVisibility(View.VISIBLE); + mErrorTextView.setVisibility(View.VISIBLE); break; } case 2: { + mErrorTextView.setText("Ответ от сервера неверен! Перепроверьте данные подключения!"); Toast.makeText(MainActivity.this, "Ответ от сервера неверен! Перепроверьте данные подключения!", Toast.LENGTH_LONG).show(); Log.e("MainActivity", "Answer of server is wrong! Re-check your connection credentials!"); mSwipeRefreshLayout.setRefreshing(false); + mTreeViewContainer.setVisibility(View.GONE); + mConnectionErrorImageView.setVisibility(View.VISIBLE); + mErrorTextView.setVisibility(View.VISIBLE); break; } case 3: { + mErrorTextView.setText("Вы ввели неверный URL. Пример: http://example.ru"); Toast.makeText(this, "Вы ввели неверный URL. Пример: http://example.ru", Toast.LENGTH_LONG).show(); Log.e("MainActivity", "Invalid-formatted URL. Please, check URL (change his if it need) and try again."); mSwipeRefreshLayout.setRefreshing(false); + mTreeViewContainer.setVisibility(View.GONE); + mConnectionErrorImageView.setVisibility(View.VISIBLE); + mErrorTextView.setVisibility(View.VISIBLE); break; } } diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java index 612fe25..a83a8e1 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java @@ -2,13 +2,17 @@ package ru.volgorobot.vrcatalog.view; import android.app.SearchManager; import android.content.Intent; +import android.support.v4.widget.NestedScrollView; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.DefaultItemAnimator; import android.util.Log; import android.view.MenuItem; +import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; @@ -27,6 +31,9 @@ public class SearchableActivity extends AppCompatActivity implements MainContrac private String detailName; private TreeView treeView; private TreeNode rootNode = TreeNode.root(); + private ImageView mConnectionErrorImageView; + private NestedScrollView mTreeViewContainer; + private TextView mErrorTextView; @Override protected void onCreate(Bundle savedInstanceState) { @@ -41,6 +48,10 @@ public class SearchableActivity extends AppCompatActivity implements MainContrac mSwipeRefreshLayout.setOnRefreshListener(SearchableActivity.this); mSwipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary); + mConnectionErrorImageView = findViewById(R.id.searchableConnectionErrorImageView); + mTreeViewContainer = findViewById(R.id.searchableTreeViewContainer); + mErrorTextView = findViewById(R.id.searchableErrorTextView); + treeView = new TreeView(rootNode, SearchableActivity.this, new SearchableNodeViewFactory(SearchableActivity.this, this)); treeView.setItemAnimator(new DefaultItemAnimator()); ((ViewGroup) findViewById(R.id.searchableTreeViewContainer)).addView(treeView.getView()); @@ -62,20 +73,32 @@ public class SearchableActivity extends AppCompatActivity implements MainContrac public void onFailureAnswer(int errorCode) { switch (errorCode) { case 1: { - Toast.makeText(SearchableActivity.this, "Ошибка сети. Проверьте подключение к сети или данные подключения к API!", Toast.LENGTH_LONG).show(); + mErrorTextView.setText("Ошибка сети. Проверьте подключение к сети или данные подключения к API!"); + //Toast.makeText(SearchableActivity.this, "Ошибка сети. Проверьте подключение к сети или данные подключения к API!", Toast.LENGTH_LONG).show(); Log.e("VRCatalog", "Network Error! Re-check your connection credentials or network settings! Technical info: null"); mSwipeRefreshLayout.setRefreshing(false); + mTreeViewContainer.setVisibility(View.GONE); + mConnectionErrorImageView.setVisibility(View.VISIBLE); + mErrorTextView.setVisibility(View.VISIBLE); break; } case 2: { - Toast.makeText(SearchableActivity.this, "Ответ от сервера неверен! Перепроверьте данные подключения!", Toast.LENGTH_LONG).show(); + mErrorTextView.setText("Ответ от сервера неверен! Перепроверьте данные подключения!"); + //Toast.makeText(SearchableActivity.this, "Ответ от сервера неверен! Перепроверьте данные подключения!", Toast.LENGTH_LONG).show(); Log.e("VRCatalog", "Answer of server is wrong! Re-check your connection credentials! Technical info: null"); mSwipeRefreshLayout.setRefreshing(false); + mTreeViewContainer.setVisibility(View.GONE); + mConnectionErrorImageView.setVisibility(View.VISIBLE); + mErrorTextView.setVisibility(View.VISIBLE); break; } case 3: { - Toast.makeText(SearchableActivity.this, "Вы ввели неверный URL. Пример: http://example.ru", Toast.LENGTH_LONG).show(); + mErrorTextView.setText("Вы ввели неверный URL. Пример: http://example.ru"); + //Toast.makeText(SearchableActivity.this, "Вы ввели неверный URL. Пример: http://example.ru", Toast.LENGTH_LONG).show(); mSwipeRefreshLayout.setRefreshing(false); + mTreeViewContainer.setVisibility(View.GONE); + mConnectionErrorImageView.setVisibility(View.VISIBLE); + mErrorTextView.setVisibility(View.VISIBLE); break; } } @@ -83,6 +106,9 @@ public class SearchableActivity extends AppCompatActivity implements MainContrac @Override public void onRefresh() { + mConnectionErrorImageView.setVisibility(View.INVISIBLE); + mErrorTextView.setVisibility(View.INVISIBLE); + mTreeViewContainer.setVisibility(View.VISIBLE); searchablePresenter.fetchDetailsTreeByName(detailName); } diff --git a/app/src/main/res/layout/activity_searchable.xml b/app/src/main/res/layout/activity_searchable.xml index 3af0744..8afd301 100644 --- a/app/src/main/res/layout/activity_searchable.xml +++ b/app/src/main/res/layout/activity_searchable.xml @@ -10,12 +10,45 @@ android:orientation="horizontal" android:id="@+id/searchableSwipeRefreshLayout"> - - + android:layout_height="match_parent"> + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml index 88dce18..98a6740 100644 --- a/app/src/main/res/layout/content_main.xml +++ b/app/src/main/res/layout/content_main.xml @@ -10,12 +10,53 @@ android:orientation="horizontal" android:id="@+id/swipeRefreshLayout"> - - + android:layout_height="match_parent"> + + + + + + + + + \ No newline at end of file From e62ddd8e5921fd4a7591731d6126c7d06af23a53 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Sun, 27 Jan 2019 21:52:09 +0400 Subject: [PATCH 03/14] Fixed bug related with crash app (null on error views) --- .../java/ru/volgorobot/vrcatalog/view/MainActivity.java | 3 +++ app/src/main/res/layout/activity_searchable.xml | 8 ++++---- app/src/main/res/layout/content_main.xml | 8 ++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java index 2cbde48..1bbe158 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java @@ -68,6 +68,9 @@ public class MainActivity extends AppCompatActivity mSwipeRefreshLayout.setOnRefreshListener(MainActivity.this); mSwipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary); + mErrorTextView = findViewById(R.id.errorTextView); + mConnectionErrorImageView = findViewById(R.id.connectionErrorImageView); + mPresenter = new MainPresenter(this, MainActivity.this); treeView = new TreeView(rootNode, MainActivity.this, new NodeViewFactory(MainActivity.this, this, this.mPresenter.getCoreModel())); diff --git a/app/src/main/res/layout/activity_searchable.xml b/app/src/main/res/layout/activity_searchable.xml index 8afd301..4bdcf45 100644 --- a/app/src/main/res/layout/activity_searchable.xml +++ b/app/src/main/res/layout/activity_searchable.xml @@ -22,20 +22,20 @@ + app:layout_constraintTop_toBottomOf="@+id/searchableConnectionErrorImageView" /> diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml index 98a6740..e3e2877 100644 --- a/app/src/main/res/layout/content_main.xml +++ b/app/src/main/res/layout/content_main.xml @@ -30,20 +30,20 @@ + app:layout_constraintTop_toBottomOf="@+id/connectionErrorImageView" /> From c63386bb12e2814eac93915c2842ef22ea179c41 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Sun, 27 Jan 2019 21:55:58 +0400 Subject: [PATCH 04/14] Added cloud icon --- .idea/assetWizardSettings.xml | 2 +- app/src/main/res/drawable/ic_cloud_off_gray_24dp.xml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/drawable/ic_cloud_off_gray_24dp.xml diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml index 4367245..56880e2 100644 --- a/.idea/assetWizardSettings.xml +++ b/.idea/assetWizardSettings.xml @@ -29,7 +29,7 @@ diff --git a/app/src/main/res/drawable/ic_cloud_off_gray_24dp.xml b/app/src/main/res/drawable/ic_cloud_off_gray_24dp.xml new file mode 100644 index 0000000..821958f --- /dev/null +++ b/app/src/main/res/drawable/ic_cloud_off_gray_24dp.xml @@ -0,0 +1,5 @@ + + + From 5bc86ce49a459007b053e75fc23b91d6a444f3ad Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Mon, 28 Jan 2019 19:01:03 +0400 Subject: [PATCH 05/14] Added clearing tree view before refreshing. --- .../main/java/ru/volgorobot/vrcatalog/view/MainActivity.java | 2 ++ .../java/ru/volgorobot/vrcatalog/view/SearchableActivity.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java index 1bbe158..bb41b27 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java @@ -128,6 +128,8 @@ public class MainActivity extends AppCompatActivity mConnectionErrorImageView.setVisibility(View.INVISIBLE); mErrorTextView.setVisibility(View.INVISIBLE); mTreeViewContainer.setVisibility(View.VISIBLE); + rootNode.setChildren(new ArrayList()); + treeView.refreshTreeView(); mPresenter.getFirstLevel(); } diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java index a83a8e1..f3a1de9 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java @@ -109,6 +109,8 @@ public class SearchableActivity extends AppCompatActivity implements MainContrac mConnectionErrorImageView.setVisibility(View.INVISIBLE); mErrorTextView.setVisibility(View.INVISIBLE); mTreeViewContainer.setVisibility(View.VISIBLE); + rootNode.setChildren(new ArrayList()); + treeView.refreshTreeView(); searchablePresenter.fetchDetailsTreeByName(detailName); } From 0a52ef6b42e220ee660cefc56b41181352d5cb60 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Sun, 3 Feb 2019 20:11:56 +0400 Subject: [PATCH 06/14] Transfered to new version of API (which is more RESTful) --- .idea/caches/gradle_models.ser | Bin 0 -> 101938 bytes .../ru/volgorobot/vrcatalog/api/VRApi.java | 25 +++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) create mode 100644 .idea/caches/gradle_models.ser diff --git a/.idea/caches/gradle_models.ser b/.idea/caches/gradle_models.ser new file mode 100644 index 0000000000000000000000000000000000000000..ce87bad42bb664d2b87d70283b3f8e164249a4d3 GIT binary patch literal 101938 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 w-H+{Jwv> getFirstLevel(); - @GET("/API/Api.php?action=getSecondLevel") - Call> getSecondLevel(@Query("parentTypeID") int parentTypeID); + @GET("/api/level/2") + Call> getSecondLevel(@Query("categoryID") int categoryID); - @GET("/API/Api.php?action=getDetailsByParentID") - Call> getDetails(@Query("parentID") int parentID); + @GET("/api/level/3") + Call> getDetails(@Query("subcategoryID") int subcategoryID); - @GET("/API/Api.php?action=getDetailByID") - Call> getDetailByID(@Query("detailID") int detailID); + @GET("/api/item/{id}") + Call> getDetailByID(@Path("id") int itemID); - @GET("/API/Api.php?action=getCategoryByID") - Call> getCategoryByID(@Query("id") int id); + @GET("/api/level/1/{id}") + Call> getCategoryByID(@Path("id") int categoryID); - @GET("/API/Api.php?action=getSubCategoryByID") - Call> getSubCategoryByID(@Query("id") int id); + @GET("/api/level/2/{id}") + Call> getSubCategoryByID(@Path("id") int subcategoryID); - @GET("/API/Api.php?action=getDetailsByName") + @GET("/api/item") Call> getDetailsByName(@Query("name") String name); } From efd2ad054b6737f577bbbe3eb1e37cc8eb8de530 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Tue, 5 Feb 2019 15:07:04 +0400 Subject: [PATCH 07/14] [WIP] Image loading and new UI for ItemActivity (Old DetailActivity) --- .idea/caches/gradle_models.ser | Bin 101938 -> 108662 bytes app/build.gradle | 1 + .../volgorobot/vrcatalog/ItemPresenter.java | 92 ++++++++++ .../ru/volgorobot/vrcatalog/MainContract.java | 14 +- .../additional/ImagePagerAdapter.java | 58 +++++++ .../ru/volgorobot/vrcatalog/api/VRApi.java | 4 + .../volgorobot/vrcatalog/model/CoreModel.java | 41 +++-- .../vrcatalog/model/ImageItemModel.java | 40 +++++ .../vrcatalog/view/DetailActivity.java | 35 +++- app/src/main/res/layout/activity_detail.xml | 158 ++---------------- 10 files changed, 287 insertions(+), 156 deletions(-) create mode 100644 app/src/main/java/ru/volgorobot/vrcatalog/ItemPresenter.java create mode 100644 app/src/main/java/ru/volgorobot/vrcatalog/additional/ImagePagerAdapter.java create mode 100644 app/src/main/java/ru/volgorobot/vrcatalog/model/ImageItemModel.java diff --git a/.idea/caches/gradle_models.ser b/.idea/caches/gradle_models.ser index ce87bad42bb664d2b87d70283b3f8e164249a4d3..a915058cf2bc424ad08ae569d038f68004241919 100644 GIT binary patch delta 8334 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 V!@m8+Fo%QVQu3?t1NZlW{{Ya1BM<-p delta 4517 zcmc(iX;c+Q7RTT1*Zl;9BU?~hA{;g1um~FTp$HEZL5zw~$Bl^aP(wfk0mY5QsH3<< zEVWQ@&@pN-j-u~KyT;|jh3F)p$2~frGbZT7fQi8+k?E?^zVCSaGM|PIx8D8Te|P=s zRxk8#HKqe)rpjL(pxXEObUb<;(%{D9{zPASv z%a#xlS>{TIcLq&iIp_hKjS!#?cY-4(B_O(>D43q=1mWv0^rj2kpqFHPMCuQlS=!zm zUP{Ktw0;c4QHvM&lAw#OG-2$ktjZH&G*2Bnwwq7O%@9s~yunOQw$;ud-6u_#%^Z-7 zLS; zWyfb5=8&e9v+2lQ5GF}4N$u|z;<_?aZRrIbAWPYX#jH#UmbN5g zwQ3!yE!Hm8eNpP|Nzht>k+fk7^w9>NBWgH!FGCK!I~}HxQ>ES;(;$MDe+=Uya@map zds?(V?T519jr$51%-!($!+sg;*E}s4Vp$lX1-Tpf!@*xoOoj0v8$+sV>CsQ%hTPe? z?;%=}2Jt{>LmK#LgL^t3`imh&46DUZC5C^B!C?k;2X`7g1Kx=w+8omKhL)De+?6+* zvU09u=$Xq3=?M4hFax2DHfDo&ca_)d_)!5Kc73!G#Rq9{4tRcYh}RGw)^o{PvxjPNVpgB0OeD-oE4TJOw!?UgjQj0I5II7@3>cV0qoioXDtCI`NU+HTY`OKY4T zuOaTC=aMxnBQukG+lSsNv*J$f(&e&+%bB+-gi$&?f^d*%Tnw+FIeC}>QHK^^Lvgfd zTr9649;)Y()xW4mXKt<<&3*Hrc>Q&h7jQW<_btLg9bQ8CsWA5!Ub8c|Qh>Do9NUND zrNZ2DUPHV>&n0Wd%=g{6xq38rx9pfH8|7QMoSD0iaGMV8F3#=3+%8_TGxwzc*VjL> z;Td)ab6@Zp;tD;NtdG{G6mxUW(A@K3^{2~GUdQFk+)IS@uc1*wc#oTN|AE)+%sr&_ zv%y1>|1JFdsLyZUPlEpAny%3Jlq4=kQpLn!r z);M0X^D{|+%jK1$@C;*xx$(S)c!Hiw*3zy!5?Py!J@jT7|1_uh+*6bXb2-xlAq>%B zFND2?xxTz+XRf~ho|jylQ5-7FnRyLyn4U}4@|80~xVb1aH?U^#3%loI2A4B)L+~7# zI*db@CCts`H9K<)1Xx&p`Ue!}2y?l-hIpQyOV;Xx5&Q-%4~ehMr5-KR&YV=bg($bF+WxH@*(#ja<&m z%|Y0t!}$n*5$2kC&Cc8l0TPB!%0uxJZqDr~uOWU$Yv+Jx^a`|7G{QF(FDONS(i+$3 zM=AP~*0>JgApRD3^Fgb;deHWN(Yh;YqxoAP@r?(qV*j8m>iV4Dn8t1B?Qcp&!Wa5k zB+B2#s_yq3$Ew?_zzb@&(|5m!FtH8dxe3b2GW_CWClzNv{NyoPv_o=esb zfAn0`OfYt3FSR| z*UW2p%COg`G+43?9ccX;=-{Nys(i+#_Etj|LNw(2z3q#Z2?ALdz`}4AK4M`83yWA- z&B7KI{?5X27XHD)Z5DoF;SVh+E-Z9nA&`Xu+#P;9I}Ttpo`nxt7{kJ!Ss2g4L>3ZQ zn9RZyEf_4UuZD#gi_U&?mNcbA()>IaC_lLIE}>`g;DqmI*#-~mtQi@p=~D+!P0pD< zdRESC>r^)H>xJ*ghi2*jz3?bz=zm;zw!xG*BPn%eV#d8QUyo6zeF~8P>2&83*b|Vo z>-dWp_F>C=qy_jFU-R5OC#uqsX}?VKXx>uD8}YX9Eff37f}geU*3U81ye!Y!K5PR_ z^R>>() { + @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 From b987854fb22d97598523ef844149df2762fa062a Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Tue, 5 Feb 2019 17:56:52 +0400 Subject: [PATCH 08/14] Made setting content of ViewPager in ItemActivity (old DetailActivity) (this sets images) --- .../java/ru/volgorobot/vrcatalog/ItemPresenter.java | 4 +++- .../java/ru/volgorobot/vrcatalog/MainContract.java | 3 +-- .../volgorobot/vrcatalog/ViewBinderPresenter.java | 1 + .../additional/SearchableNodeViewFactory.java | 2 +- .../ru/volgorobot/vrcatalog/view/AboutActivity.java | 1 - .../volgorobot/vrcatalog/view/DetailActivity.java | 13 +++++++++---- .../ru/volgorobot/vrcatalog/view/MainActivity.java | 2 -- .../vrcatalog/view/SearchableActivity.java | 3 +-- .../volgorobot/vrcatalog/view/SettingsActivity.java | 1 - 9 files changed, 16 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/ItemPresenter.java b/app/src/main/java/ru/volgorobot/vrcatalog/ItemPresenter.java index a0b6cae..876fd96 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/ItemPresenter.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/ItemPresenter.java @@ -63,7 +63,9 @@ public class ItemPresenter implements MainContract.ItemPresenter { for (Bitmap bitmap : bitmaps) { uriStrings.add(processImages(bitmap).toString()); } - // TODO: setViewPagerContent() + String[] uriStringsArray = new String[uriStrings.size()]; + uriStrings.toArray(uriStringsArray); + mView.setViewPagerContent(uriStringsArray); break; } case 1: { diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java b/app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java index 5bba085..62247c0 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/MainContract.java @@ -1,7 +1,6 @@ package ru.volgorobot.vrcatalog; import android.content.Intent; -import android.net.Uri; import java.util.ArrayList; @@ -67,6 +66,6 @@ public interface MainContract { interface ItemView { void onFailureAnswer(int errorCode); - void setViewPagerContent(Uri uri); + void setViewPagerContent(String[] uris); } } diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/ViewBinderPresenter.java b/app/src/main/java/ru/volgorobot/vrcatalog/ViewBinderPresenter.java index 5f02f40..9d1d236 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/ViewBinderPresenter.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/ViewBinderPresenter.java @@ -170,6 +170,7 @@ public class ViewBinderPresenter implements MainContract.ViewBinderPresenter { switch (result.getErrorCode()) { case 0: { Intent intent = new Intent(context, DetailActivity.class); + intent.putExtra("itemID", result.getData().getID().toString()); intent.putExtra("detailName", result.getData().getName()); intent.putExtra("detailQuantity", result.getData().getNumber().toString()); intent.putExtra("detailPrice", result.getData().getPrice()); diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/additional/SearchableNodeViewFactory.java b/app/src/main/java/ru/volgorobot/vrcatalog/additional/SearchableNodeViewFactory.java index 15274d1..baca273 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/additional/SearchableNodeViewFactory.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/additional/SearchableNodeViewFactory.java @@ -7,8 +7,8 @@ import me.texy.treeview.base.BaseNodeViewBinder; import me.texy.treeview.base.BaseNodeViewFactory; import ru.volgorobot.vrcatalog.MainContract; import ru.volgorobot.vrcatalog.nodeViewBinders.ThirdLevelNodeViewBinder; -import ru.volgorobot.vrcatalog.searchNodeViewBinders.SecondLevelNodeViewBinder; import ru.volgorobot.vrcatalog.searchNodeViewBinders.FirstLevelNodeViewBinder; +import ru.volgorobot.vrcatalog.searchNodeViewBinders.SecondLevelNodeViewBinder; public class SearchableNodeViewFactory extends BaseNodeViewFactory { private Context context; diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/AboutActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/AboutActivity.java index 77ef4fe..6dc752c 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/AboutActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/AboutActivity.java @@ -2,7 +2,6 @@ package ru.volgorobot.vrcatalog.view; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; -import android.view.Menu; import android.view.MenuItem; import ru.volgorobot.vrcatalog.R; 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 c8be4b5..bf9d6e8 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/DetailActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/DetailActivity.java @@ -1,8 +1,8 @@ package ru.volgorobot.vrcatalog.view; import android.content.Intent; -import android.net.Uri; import android.os.Bundle; +import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.text.method.LinkMovementMethod; import android.util.Log; @@ -16,6 +16,7 @@ import java.util.HashMap; import ru.volgorobot.vrcatalog.ItemPresenter; import ru.volgorobot.vrcatalog.MainContract; import ru.volgorobot.vrcatalog.R; +import ru.volgorobot.vrcatalog.additional.ImagePagerAdapter; public class DetailActivity extends AppCompatActivity implements MainContract.ItemView { TextView nameView; @@ -26,6 +27,7 @@ public class DetailActivity extends AppCompatActivity implements MainContract.It TextView datasheetView; EditText notesView; private MainContract.ItemPresenter mPresenter; + private ViewPager viewPager; @Override protected void onCreate(Bundle savedInstanceState) { @@ -35,7 +37,6 @@ public class DetailActivity extends AppCompatActivity implements MainContract.It getSupportActionBar().setHomeButtonEnabled(true); initializeViews(); mPresenter = new ItemPresenter(DetailActivity.this, this); - Intent intent = getIntent(); HashMap extrasMap = getIntentExtras(intent); @@ -47,6 +48,7 @@ public class DetailActivity extends AppCompatActivity implements MainContract.It analogueView.setText(extrasMap.get("detailAnalogue")); datasheetView.setText(extrasMap.get("detailDatasheet")); notesView.setText(extrasMap.get("detailNotes")); + mPresenter.getImagesByItemID(Integer.parseInt(extrasMap.get("itemID"))); } void initializeViews() { @@ -58,6 +60,7 @@ public class DetailActivity extends AppCompatActivity implements MainContract.It analogueView = findViewById(R.id.analogue); datasheetView = findViewById(R.id.datasheet); datasheetView.setMovementMethod(LinkMovementMethod.getInstance()); + viewPager = findViewById(R.id.viewPager); } HashMap getIntentExtras(Intent intent) { @@ -140,7 +143,9 @@ public class DetailActivity extends AppCompatActivity implements MainContract.It } @Override - public void setViewPagerContent(Uri uri) { - + public void setViewPagerContent(String[] uris) { + ImagePagerAdapter imagePagerAdapter = new ImagePagerAdapter(DetailActivity.this, uris); + viewPager.setAdapter(imagePagerAdapter); + imagePagerAdapter.notifyDataSetChanged(); } } diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java index bb41b27..117e17d 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/MainActivity.java @@ -9,7 +9,6 @@ import android.support.design.widget.NavigationView; import android.support.v4.view.GravityCompat; import android.support.v4.view.MenuItemCompat; import android.support.v4.widget.DrawerLayout; -import android.support.v4.widget.NestedScrollView; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; @@ -17,7 +16,6 @@ import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.SearchView; 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; diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java index f3a1de9..19d1a40 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/SearchableActivity.java @@ -2,10 +2,10 @@ package ru.volgorobot.vrcatalog.view; import android.app.SearchManager; import android.content.Intent; +import android.os.Bundle; import android.support.v4.widget.NestedScrollView; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; import android.support.v7.widget.DefaultItemAnimator; import android.util.Log; import android.view.MenuItem; @@ -13,7 +13,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import android.widget.Toast; import java.util.ArrayList; diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/view/SettingsActivity.java b/app/src/main/java/ru/volgorobot/vrcatalog/view/SettingsActivity.java index 0e0714b..8f57d8a 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/SettingsActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/SettingsActivity.java @@ -1,7 +1,6 @@ package ru.volgorobot.vrcatalog.view; import android.os.Bundle; -import android.view.Menu; import android.view.MenuItem; import ru.volgorobot.vrcatalog.R; From d513b0071183a4516d7712e039be54c021255349 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Fri, 8 Feb 2019 21:49:44 +0400 Subject: [PATCH 09/14] New UI finished, and image showing! --- .idea/caches/gradle_models.ser | Bin 108662 -> 108688 bytes .../volgorobot/vrcatalog/ItemPresenter.java | 28 +++++--- .../additional/ImagePagerAdapter.java | 4 +- .../vrcatalog/view/DetailActivity.java | 68 ++++++++---------- app/src/main/res/layout/activity_detail.xml | 8 ++- build.gradle | 2 +- 6 files changed, 57 insertions(+), 53 deletions(-) diff --git a/.idea/caches/gradle_models.ser b/.idea/caches/gradle_models.ser index a915058cf2bc424ad08ae569d038f68004241919..6fe1fd92dc8a445cc873f37c81c56ff4e4f8dad3 100644 GIT binary patch literal 108688 zcmdUY37lM2mG|rFB_xCpNC+qbLRbV$?P~`EO%`bAKum`)1~tBV?^UOg+IaP<(+vm$ z3M%O6D2)4#;)wb=qvL=qA_{}f5_DWf=Nm*Bmv26|0R1MsGN3D9j(u|gMLybu}d)wGnA z6MNNZHP*7qmDohNX|117R##_P_4CQUt%`ApS~V=?NLR_NYGeIO1GugtwWFkVbj&o> zS<=MJ_1`?<-H)j6A5;d$m7!+&Dr2TW5ZOOOzB8zGlvC?MwYdka4KMlrgAc8F&0~W~ zWQ($_QdjjYs%F*Aab>Bs$26LI>J@#aaqfAf1!ejE!|+{+|3@rkP;C%IE(}97)=dx1 zhA7QIiVG;!1wnSqHjFEkYY9D{IgvVtK~uE$6k#uUi1Hb_1}Y8kD@(<-g0 za*g6T;7ZceS z_rMnp-1pcGkKGc}K%3ak?Hg4~t<oxpSsgTJvUaht)wOBC-L!UZnm}RvBM%K5~%_<{3m`@qFLOIN+7*&H# zrBzqBSm4qknWSKW7A6VHh!Wn2@{G6r%U^tOW%JBR1T%unj>9Y^?&b(eB{ul92ZkBF z2vcpMTr^d4b{icrOF6x6P6@f7HpA6)|923(4Oe2^uqT1%W7qdwYb`oxg89Q zVYQSO1tmMRmeFj=Is#w%gJQJJG|q3;pq(s*wa&9xpNXD1#;Lx!HeJS~CbI_m$4S4$ zFmyw=6ox!)fg|T?{%~HN0TZ>!FHV|MTm@*7i!d82Do6}$PVG`?yV0z-OpO#f)?dtS z;0691SFMx$d4h;`Z8oMwN->-M?k0JnUEz3FlRVD_@Z|Q~Hjr%iU?FJxM8D_{N}{c5 z4U?I08$*KTa5zpLZvyO66T^(zuhz~d5|&yYVwf=(8<6gd{AImjDKDlddeWJUCM-Ed zi=5f52$}Aem#sbIU(He&i90lRiHFl(QL9G=o#5OEX8&(z-{P zv8L^`+3{MlJhcb>!8lW7Sfp7&CQ)a)tQj5}F*ef;lEDeYnlWZ96H|Yzv9Aduj8aLc z3U3zggpg%C6YC<_Fs4qdPJ1>_88yQc#B-rB1}#C97GsxArI_5K;{i*I5~fp828MUE+APSZ<1NO~XF|o3<-wWh4Nv|S@KVb(wi=eI!>qQHGur#b%j_^! z4763A2Jbb{F{YzDt+~1#oGbduW{sz=-9aWxJb7Xsig98RJg`WcnhY#u17p%dl;Nx- zz%a?=%k)sxiwLjYMpHI#eeHChs&@=|i!Qo$$`_RN(w*10yUT=}4--FiPxG(*kto8>5E?ol%hLd3 zr+`udQz2EnMR>O@g^?^U(`kWqvO=}w3ff`vH}BzcJ7G&1t5GKLNWKk&8OtPTXBnii z(;4nnwOoT3BrDTxWQpFiu&fZ~FB9ioig<{@Iul&lhRPIFRo!O*>K3zJWv0F(g#}ve z1?)C>5yPC~R-w!K~9p^bda7-wkY96#&5sH#PiuAOXTxJMoN(=CM?fnwmC96#ypuZgOlv5#jHAHH&heuqMAj`Dkco! ztHnaH>BsOQh%XGGSci5fC9F3~VG_7Qu{K_Cm$M;p+Pm;^nioWIaCNoGX0E$U(SN&b zPkq6{qKixc@%lW|0WD}tLGxS}a3-I;mD|7z#-MI-5S1C_sMIjvP9kJxGYlgH{}LV4 zF=UirO|p>@%hR9&94BE5vLZ~GO&S)pflBZRdgjeKD&Xf(lq&?*%TDEaAtuf`71|1& zAlRu>8M`apn_^BPW~O#(ij?7aF&nvCK^rcUjVAmnm1)mHhKUob8fx(Vu@%ncX4x`? zna^N!%Je!|$(W%WX_$^a%~JlETWL?{8RPY=Xp_QM9=ME|*i4!> zIA&XkPI4iZ_afG#ya%<|T&vp16}r{fJOl2isTG(7n8P!EL^ny-^&q`orWv~fac}KQ zuri;9f+#i#bt%S7&%4&MK7hTec+gGG1E7tiZ(wZU>mbP_xx=2LUNAjtcyP?kv$8XX z5_7Lmt8O)~|$pGZqu5xX6gvIbVG*T!ul$;rm%A=yH-m-h^Hn$NNFHNfPl zyMVWe8Ej>4&|I5Koj0u6ZWhO$w?cL|`F`5apt5|Ia$I%xvL>{^B>rD9cBYh-r+sG?#W1HNTlA8eNn98^NuuG0TL9&k*o1(k6F$yv^t_vR%uZRuNqxqgG+0bpC zKTEbM$+i&obx)|yLb{mh1>8BLGi`6LKHU4@P!()*m32q7g3Z+zR%b7TL2Lr2rZ9K5 zG2&%k860T&g#m^OZ7 z*LdWD?PHrJHj_Un2Y9ynwuIm6BU{RByN`E^^B#%N5PQgs_jrfecyGMg5F9@oQC>7o zw&uqgWxm$f-`_m|s0xae`n^l|2*mxvy4I&3I9%LoMk+KOG?E=2NJR=TS{n-t4 z8v$2A)C4m_ei#)m@kXk)RDwJK{>&O6WY+eezb^a{($h3_cN>hRmv z&Dj{6BOELc0T8xT&Sf8{^XMi^5?h#^{T##CNP1kW61D5abuYgk0a z;J__Ue|4IsLWU*h*pzE-U3=dXTi*5d;$0DC7<#RwmMfRmww9YjyD=JUu36?R;;mF& zhabHTa~1?yhqHT)Me>>juC{sT_^q7E@WV7t@Oczih6x z?C=?q35k8!rt!(K^CvcMV!=|!v`8X2W_-J(G+LwVCo`5C*?4%%V zOdT35*+ujswP>e^lJ}5gmjZ2pwUd)gQ?`~7#W1_MM#}5dl5}qyJB7!Ik?GDNBD*?a zOdFM5M1kxoH^wTMcf2KVuxAEz>j)G#o7zrKmU>X1P+(wrOzg>4$&r%BR%cP4?DLu! z3unWU@G=Gp!)V)*6;(4xR3slp7_LBlEA%JGGQ&|P)qXvpcr^)V7t}WF4hU|xOG)an zh*7Q^i12VB%0~I?-@5BK|D;tg>=`02dW6*>KIFU*m8kOqUFU?aoR~r@x*my;D^&58m$4?K?*t^ES zmv8^*d)asm4g^eT&+4Yj;Cp96z`P#xaRSts@Iw;%l8!;Tw@pUUsWpt^pKYD?O9XfB z<^pCn@ipxh6rY3C@uJ9i6w$#)_%H(}kvI;l46qQWoA99$cISQ$F5dyaWyOnm%curl|=9w?lXzV=BhUi9d9dkqy1LpwQ`lSy%YG z7ZU#7TKUigzM$hyBwW|7YYR+w;>dIm0Grnr5+Jwy#PpBOR2kP}`<%-?drEYghOb^o z{7e@u0w&>tP6E^D4%}GKjtiOT@IpZU7nB*BEJV{rVBqvM)n~tCDTnWd$JOFWl4#L0 ze|GkBhj(I+SM-reL@!f&v$uG@Vqw7cmdk&!Ab@)b4k+@Cv?pY8> zorUgFo5MRzr^^=vqaI>*VYsW8eC?-VvFREERA!9Ya!m;ktP8_pZ4&j&pWOA29qrr8 z`Z&~d8P{8C_LI9f$leljN8kI|OIj{I#Qu+EPbt~YNz29(WNnj>dfx}HlXN7O#>t(; zV!uu`lC>b~Y!8vxe-`Q`4tMpP(sL7q{pX`LF}V8XTmSa6WM~JD`{A9}KG`6D9Zx5BH!@uEp1=b z#}Oq8&Ia6D=Ju1B+@O0&-h%~qp~kqU6z;bXBgQyL7Vljke(EHVu@rQTeJ9b}??r;3 zKo0@EP@L9FO!w0}<)ZE!?bd~2w>FV|=8380`#KGIKg~#!N&nu`w4Z!t1MMwIclL48 z39!AS=)r)w5M$a?diHY?yNKIn#g-Oe5IadtVwHTZ)6D7TIze=}hoD>tX6hv*`?-W^R#Ijc)`Z&@Cyu=de=xBHkpLVgdNe#_TydMo+kCG_W+$9(Oyi+u&{J+^*Y zZG2RAz)tS1OZsV8v?;#nwmb1NSvU@yMoh1pA%E;_)zk7G~i+0W&GplO@f?C1721=3kw4w3v$ z(`0)emj@J&9ul(e{L@P`_EQtE4$es?_MM45!q8OG?g;C-8sAR%-U?s%9;|9lh$)0D zjT=WmtvLL^lTdQ2I)iX(=jg!zy8;ryv`#W^t?6P{JEvD*lhe>zwsXlMVOzLh$938Q z5IyGrx?B97qG%ll6xgW|2RHO2QlpWHJ1{eX`h7eqA!{7RVoXHV;;;xoXnPA6E}5JT zr*Q~( zV%+4aD90g8By$aHsMsernym&oxgRAnHfqvwi*gBh(Paqnv4?Wt#Cfb_gU7|` zuRmOu+yyI+1a2Znh{)Xnq^~#vhq&0waAu3)3H3nk=p9T&B3S^=zuF1zBF0RQ(VJ@c0Hz$C7AIC*C z`9v2N)a0W;I+=W!C=qs2Cm{T%p9UYrVi65K2Cql#YCjD=0dNjsRsA&hC|I|_M?@c0 z+2p7SJsZte>D>+yUj(_jk)5067KEdz{61G`-pw^!j*atyL`~pO2|3kGyG@#a`BN<8 zbTQRXERz{k?U_t{tv&Fe&*6y8WjnU4%Tw{4Cro)au%GLxNY{B+7uvgsJx4EjB=#9Y zu<0`_aOQ&?hpym!uj|YQ^z9_hYvI-d=afC^YQ#1&X4Axk7*0h~(S&_T{7Fy+urgG5fgZq%lSB4kxHn+i$D7w{G%OOF7SDbOU~`BfO__Ja`M# z#@t%g%sNjX!}cJtF=5@?aCqW!fv&jXo}4tTzPyFYDN1F2$P7tKtJ~H6^pqGudKtUf zU%}t>;8mxyQk@9qLwM8ve>&=di!&d_asP3g>!DyKl;P?Q+!f$}8?=-GdiFB%5SR%D z#Xy1>5%d?$YY@9KaxYE1nG_*EAMhVl8^8e1b>Zb%hj0$Yxv3E!vtr_1Y|P^Dph~S8 zkjr~G30CqX&QrNLnXHFM(l)i(++R1v{RWsAI};qL`!FBl@1fe+58}=ut}-@}qi=wV zUh=>*oW?la=L!&P%%aAkcI&uj_N%jV|ui-uhOw+F+0A56U=BOgr?dwf_#tWn7Lj-3b?TenUaCA;v;=YedTUMjR{Cz+u_>8Vc zIN4qUx+rBj72WiK#IzuY*mqT==gP&dTI+EzIyXoDAu2qWd5-ij5A`28+(GXoag7PM z2ZE8DKqb#6`1%CS;P4kLm0#N~ZIF zQGD%G@&rp`58OrF?rf-#bLh#KzY-wBwPrIc8(0@<*x}r9-GBq3Mc@7)oIvLQs0Jbs zX(relH;$2m0~U){cPl4EvB(oE!a7cxz9=Wc)0{R%$i}}oW#r` zkeFY~5l;{zBpH{d;7Tzez9FLg@eRnq&xccvA&_llcQ zHo1^SWjI}Oa2kPV7nt={!!AUqh?~@$)h!bE!iQF2{PmaL|Ij(OE5X|_P+(0k1+Yd$ zcVQ~guAjAJ2U$8t9uRZ?gTA@XA6<%($Ja1@t85OeOU6p%eSvk!Xrcq9k?f{)jDm|L zGI}moh#N*KkfEC3Np8M;<7(gi)KW#gHYnv1JRHJvlkMnX%L3h6>2ucixHiPixzP{&7% zCx5&29CYW*;6Wc16QGUZDM=o`_f^;9f+A6f&V@fxB9PCYwrt*VwTA-lkfT8RbVLv} zo0yzEN?KY~Q~6{zl`NK2HCHrp#dIQ*D;TAsnoj5$HJ327Qp&Cu$QU=gWgT=1#dI zf3AmUcghjX2P77NPmDo~r3w(Qxoj~5uEGB@#bh?0Hxha>qv={QZfKZx$#^^$)CPhh z2@!l;b@jEM+J)YZ1@soGgzPh7!@(j#mH)X83($JYT1N%DIZ9eg`3bw}{{7Fx3h7h{ z@J{Rwj}v;Bw*HwD?*3a3oxjuNxcuTC^+gEr>~)W8 z9|0S(GH8N|ID78#CO8d8SQFnrE&4JK5&u$-h<+$B1}(;*#BxR{UV_}u6iaC>UQ89$ zRJ>SJjbz4%8<}jf7|&>>T*lzl*0E|n!aVUBWes|DvX3z3I;esVXz5kylqUB-Rj5Pg zlM<+VR9js^4pw`3*=-Md$nnO|J7Lg!ih(YL+!0uN2zI)9o3gTcI@SJ|SMpp2oHQl(t6RLrN& z6N!`x)1eSAB(ZcR462} zxnLqV$T=&H)v#>ob!DPsu*At?fIJ1-!3XAD17OkNUoF8JCEFcXVgMppUy~(KT~jMa zVGE!M1uH5n1nB*4+r{DuCE;7x)+*xuW_zJdo4^WXu8!(4rhA#gi`(9C(Jl9_=&&$i z_jq|60dU;0iX3rrc^6xN0(E=6G=ZIsSx-Im*joTj8nQlfuP{lI@KIoS!wKlm#KH`# zArT?$V89nl+%-Vbv2J3HFb@)d393yJ<3-~jXd`4b5PAADf4=0e!N8|sZ2k7hC~jzm zyHc1ts=eqT6`#Fw^RHe8nZU{r3vlpgvYkW+cW~9-OHR2}ED>tm`Q5&izqu~KR|%Ne zaK{ti!puOsu|&R*EtN3QQ^iyPhF?5`bwE6w&=R^{GGL|NOAi!3{T`y!#nQ<+B515qazZ z$p}_hH=XMsn|JbZC-Q7mSX zDlGOyDUZcYGE>Tz)O3)TeouF5ck&_$?q20Mf*5RorvCv_JXS7_p zl*z?2MlqgDzW@e)n9sW-Ia0?njs!dpXbvI>)v`dj=(H;7eq@d{Vh=yfh|nh z#)HRgeuH3;rW6U>;2_|D7gZ36teVeY2R9$js-yAK> zg79}P=0*qF0O-IsQ^@H?PQ_~xdN!3VsKs15qhm8sHMD|J)C}x2=Zi+kQ`hN=NA$h6 zJBl4Nfg35O;aE=^byWhD#YE*$BSO3Af8An|qxX`av8d?S0{@|h9$GEtvz!ecidQ=? z2xb?R9v#K}{>4QjXgTns6My?(kjrF`#lIXtForg(RSc6z{LW6F`({7-8^pf*3j6&& z>6?zZRdpUU$0-ZyV80}L3_1$@@gFX&Hmfn(I&Z8X$C0qJmdEN9wV#>=I*J04;VeQMA zPGJ!0s0HMFWuZ_B(gb(j{_DSkCU^;va&~-715Xz>oApugZ!!v>MKbR<_J8!()5~$* zh?hbu-dG-<&TaiAypfZvXYH*3If264MQ|O(ikkX*(#WPW#k87EXAy^&M3hr0Z=`fY zDWtS`8vge7-P*8mf*g;S_?P1oOBVG+Tu&k{qL5Bz5$BdRQUxQ2P1;;GsTn0WtJ1(# z6BXSZ@kl&5<4KA+G zcn2Y2yccuH41)dBIX$5kjUIzI@*I?0 z?Z$f2sH^Cf3-FM``T`%f*h*?8oGQ?=S|*tfT-9%1W7u@p~1w`8(7yi_nU24s6Wn@z)C6VH@VB);EIIaj|tGEQzwwoB`=o>c29 z?B%v(!{BpBlA~Sl%WcVqAxv-aFSjKd3MX3$yl(fcrwV&6oKh5X%r!;k$i$u9^m1OK zP?YJY5W-n5* z(Fr}FHu8BKaxLcbaW!S+HAM0h^Q9yf2ZdZFUeMD}YIy{D#uIoHJa`;j{q)Go9w&1; z7=Uwt66;CLu4+WiEbIqfhctQG)yiACGvGoFV9$sjIagIb2GNQ9dH9j9e_e=JSY|mI8mwED-up)SFb!GQ*OW5hn%bN-X!a) zNaVJ6LZEXf5~E#h$W87LWa+&ak#k>%LCIc=JZVLLE~b1q%fEec%#nXPFGb|EXc)S5 zR0(qX#i39M@=xu2@#r(q1fCo0IS_lJfenOJuGp8C_@YFAT>2TV$UoYP94YVD2f07R z-XxeqZa1_YhFiWRabhe-(dH^ey+ZGWMMxYB}5*l-F@X1kU&BhMFpnE96R8XQ;(Mx7GjZum131CzJ@bt&4_{h2p@TM+RFj zB}8x;nM^@dlet1MpD3ns$z(ifD-mBiu3mb?W{>OTI`}*~jF}5aZ&G$uC*d}*I`_RN zT8A=m+7-*K-Fa^TN3W;DDx9Z1#0Wb6s?RBBo+LzuoL8uCeBOCU5^gUm44pbEn;Q=r zR|RUEzx$u~erTM)SSZTjcruDyuFCFJ^es)k_wB>BAQs9g=hrLNX{S9bm_#lX%4ypp z|Kg=o0=9htK}My#hLdZ>Jh`I}*J|a{#dIcUDblA{C0B_mO#B# zgq(m5JsoXjv3k$*TZCu`XYfkXsE67J7mg^6RYwI9&Lbv|Pmn4(@9u}c3spiCMYPlT zh^|Vc{@PQn#ybXrpIBMH`nZ4Fw9O-O>eJi4OR&ZYseGK=wh#ABNzWH?n_Ce#5hn{c zCy`C!c8Q?%!3X-QI9R8J%1|>IRnKJNdK{M_!wY6;IYZObIPN$q;4nuvj>B$ooXWFR z2CMGslSe9sF); zLFVJntP|=W>@M-VvFM=)!db2obJ#D}Qkk@_#c}a!vXm$$b-bOB z*0fxvkjK+7MHN?JWMiJ%t{!;=o}4qHQ`51Y#Of;gdOTP$)nRz=*z9tLLd@k@IU>_{Z;-$S(wphyMa~U~)OLEzXC)s}Seo185tXW*Bk5^T2cU)0Vs(HA?jdVVz>xicbzF+8;kP?}YKuA^L z6j6&>Jf6j^qv>2eso@$3Y=z<$YTPSS09rY6wUCxhh+2+HSrCELlPHTKi+f>l2z7no zWN|MdES@axiHR+Xm%RO_w&m0>S=iW9tq|T zvgsEBYFV%BW?1a5x2#6X+O3yOhJcF?$W4Jk{4s{=G1T+m>bEreg)1i(rQybUtyG@s zLA1~KRB^u$F$pi4P0cJftPsT8?rO#+;tXZOYg%AN=TBaZx5n!_-d^{Mk>_R_cU|+*>nH)e55=D|Kjc05%yQHR zBg$$I>f_2tb#}*W!i3bD!!|-SxWSyL? z7V8y3C#0D{H zrB54Jirltc7|8zRgr$Uy;*=OGXUascDwCz>&>4pYE#%w?p~j!-GV~EJv{q#FyDgC&8q&%+)%!R)D;d@Jw+YAXq826gOQvAl({4V@v_r%PP3{Etp zrTFdSg@MOmordP**KPZqw~rlSULla)uZIJDD1E}TIcKG98b0Rqw>d*~%O zV?`F5K%FEPD=CYDS0Bk)s?xA+@0O*=ovx9EO!Uy=@;cQ)a(g(kopkG;>z@9{8=3x* z+ij70mWU~zIlm)Ew9iAb<06M3S3PnvND5@T%$1w(QosY0&LgrCSPFsm-phpm$pI(o zMoz-X!Rw)GYThRseE>AqWWe(|VtzsMA)+_Df63fT6<9arn7b8b&Kt^rXI2$zee za0(ljna7L8LQ%m!IMTD&0 z*2{Xa!s5(Tl$>D~5_r3a4tpCD3ALF2xV5j<&h5_z|GZIYr-+=pFYLe&)g`AZ!b0w$ zz~mNQC} zEjdde6xbf>O3o(`2BW}*mYnlC3>sdQCFjBo1>dE#)A7Q{0~!Ia)CAyS5>ej)toO3BFm}gEJZE?QU*P)qU7AE5&+w!vD`{u0(84V8dfaj zAohIG?yaF~B}r?IU1{Z90W!y{le!$Nk`%Y|Maeg>*MIz^skp$YVOyp#XB=~lPGWfWq z9ApZ}#n?(xfGQR_kB=>ppeACt7PP?Ygy2)HH@6SDhZebv zs&M3di;`V*E1kD~>PzHEI__);W`c%~SS$I}Td zq3b0hE)>pbLE(3-HJ`G%Kz79zVNN9Wk8Wqxm068G18!(W6k?+4gau2kf9NkR~*UBrenU}eUs zJvi=zvM0^@N(ni~co-Cj(vjPY2m`f;@(CL;Iq%63sD#3;Y9-jxtBmAA%0rBb+l?lt z2}1xU%4yNLpRRJ`Os)`Jbt|iXH_pGFDXVakaN5wUy17m_)%|L*Vz~WSnM@Xs{>Dpr z9qXP#&d?1tRmkNE@lrfvs70Oo+Ok1QAJI!+^WL@4(4=fIR)^;2hdtM0a_3_EfkC@M zd!v*Sx*xc-FQ0}kmpwDw4}98b6Hco77;#>lLOpkKr%wAuiY|LZw;nX63DkaXIB4j2 z)nGVVAPm2_^`YEyxF2jo6yw30GgL#$Me+2b^KMmn`R6~dpQ*}lKHrk5PF0PX<(3^u zt&~jVw5*m%=1U2@uvRFh@&zM~XVnUNjyzI9_oK)a-cglZG9Kmq8x{Q&?Ru5t;8U{R zD}TH5!klMAV^ zOtsc5le_2LLLd__r4qShs$dveDX*z{JPukYq_jjapHCOlnQkE!PK#dUHMCDQq{3-& zemHWqB{v@=fwn6wIcrZ6e7mX|s>_;uk|?xOKyI^H7Cdo6%7s+OLhPZK}9iZC~}P>=WUk)*)DD6WSZRa&b&TAKLk_S@!^nk`Nr5H$Wf3`>Y8N?uCe=N+Zb_eW?~9pkk=r(` zl&1|HZ~h^00(adcqKRlcs;XuzVZ=*`QlS`6W^>7$rfcyGUTrmuY%!H7CDR4Iq_I76 zs;TXXR>~!I+IG~_tn(5s(J}uddm7Bs=DbkldPdIGAPu%%+RBL>X#@iF%>mhSq0&gS zQ$a4YRUQGNcjQ);@-Tbo9yzb9G&+I$N6zY!#=)zD>e&c@O3vLlvVcq?sPMV-a-tW?;is9r+6ct*>mOPL%ZD4?AZ zIW3+U6Ix2M@R3CKI;C|VSqqcVEg?gxsqfnsR zrL>%g3WY?wz8bt*cH<}%BJI?WbC-uhg6J(dXIMD6J#?4c#!)Dg0`-@iH5UpGuMU%Q zl!rsWrN`u!aiPG=ZybdKOXAt(JO`oRx^>#tmyN7oI!$gJ+kOL|Ny1$R*IX`>$)$>F0s-e*GMh>k#Pb%ZfF+R~ zK<94T7l&}8?1p%Fyt$eQ7dPzgnmZt(C)wIXubk-{o(}Ctrf#;BLxw7HJ7}S)LIdl< zMJR`3jV|%z;SNMdqZO#S!UbMRi>&=9S1kc>MecaX;-m& zYYDiidVQ)w=m#QBHS4ue`bkFf(WJn0gjIasvZuGRif4ELI{S4&P}8jP<9|-SomHk+ zLfHf|4a=;T%2skz{56`4x;nd@Ro~h8(;8NtM(_tz#~OXwFfGGe$2;IO68ST0+yQt?0C=VMn%7pNd+@CXKJPlr_axO|KaK$`qV4!y@$eQSISX2i|$${sZ?scH@D2 z4}9UkeUIJn*ew_i-H7enzLCLl{(3RTErvIAV#QXuqQ|C;nqjJzp~o<%VrDbOM}VLo z(@B5!N0iu%0Pc7D_Z7I&+^JStK%)Z=rs8=qr;~_*Y#GNMfLgP*w`yd#@ZUhYXgRVv zJK1V9>ZUbmsaC7GOF70)G4%6oaWg?A(s->@_lcM9edXoPqvePqXyZ5A!qEnMB!)@V zBUptE*19sVXeW*zOxhPhwG0oomEbKfOul?rKy?&Z~4R@tGfsifzK#ZJ{MV~G9G zmw2F$D@RmkcN%6BVckTbOpxDz2GSC>LW%I)gtAm5iiDNb*{#^6a z`RiT1AuSV8fgYk^R)#gq^wO%g{ms{&$A4t{AI}D3?wsv_bSQq9r_a)T1S%sRb@js@ z6<1p4zEQ9)Qj^{dunxcclHZ-`be4emIHd=Kng8PGaC4?kSrPK1u}_SYBgcr)TSq0@ zI+uKjqAZ^=LtDqjFQJGzQg^_{HgYo`vyo2*mbvX?|2<07#mFZ}SJ#ry$@mPXFta>5 zsLRYE$X?nYXAqjs=nn2uR$~g)%2k!-Y$`X&VRYR$=n!X{XABK*TGeZtYptrKB-%OF zFk{pVi@6}3YFAs&hD$m5@7FKC)>J&_@~E~jOm4*mR_7=yM=J_#XsM+PU3lr_4nMg- z5Rb>A3qgpDDCCSok%+JBklS19+CD;+Z57oj)y?Wf)S6?KVC2dCy?^)+!6NeW{maqJ z%5%?SjX{GSLvCy#vWZH`%itI#eWNIYJ>TU!t{aX$y&`=t`lc}zE5H(pH(*JYP&?nSzTfX~AQig2#R4gadiIAhqctPg!q! z=o(t^B&Xnuzkk}MhwOsXc#k~w#B0{Pj}|<`Dfp7%Wp_>31*y3nd1~oTFFTADj5!74 zkG}04|7;hemU85&_4Q|V(t{ zdzcnK3N?rSlMX2U8oa< z)K0wGNqo6T^kYAA8O?F9A9)2!xcB1nuv33h)OTS&vXdq{g)X;$4{j(luDp_B|7HjK zTbA88;~I4b`?uR|3_IB0<|KB+e%O!wFvtFg=SqP-Kv4RSM{{cH*a_!<(f&QS;eR4)e?e(~uY>)4dwzJfi|=18+8lhyX=AsY_=uCJio`bT4VvS^ zzRVIfzW#|%IQ2DA-;I5VCOUdZYopkhejCfNvX)QUw!1#m*I~grg4rYvVIf!tXlEUCtG$y!!-eI=x`^o zZYLh;Bwi^J{rwtl(Hy5=!?P@5W%AEMPW`5+@9Nj^G);60?YDmqZg}shckCuT8amPD zsiBi{|MQIlPVo(*&7rkU;<8BXGuNNmG?GtF^fKh6@?JzjJ*x>3}3W50zaIzTS4 ze-Cc>;4QTT#Xjp`pSylf(KU77D%u=c@3irkcH+5C;@d@H8}_%+92fTQW(mK$+Wdfc&-ndvL>}U)Vrp>Chz(_Lts%{Lv|=_@70aLz7P8^LFCpcH+o@ zNc3YrGE8$E>_?Wegg@+i1X{a-Kn(kGoZhkq$3GW1>>(D1M9L`Uil|3)PGX+Qj1n&Z%Z`1dT~ zx}(pUavFU~)OXQ-_;)nXDfEo}dvL?)nH7xhKjUEk*&o*@UhfqDfM|2brQAMfC%UYS z4~xV$?C+pCF6=+a5^gx`E$2CqJ}TQrbV_VE>QbzI~}n zWjPY_pX@e99Eo|rN$e;wNBk0VgiFliTkqcL)DM!FBR+{a;+B{+KdW{3_a;2#_YtOIf)68=%@WihUPf5A1SbeN6$L*Kb-n0QQt-Tkt|Jg3gztI zgB$+w_J`L|?4NP4fA;Gy|IGDv@!|VLn?uhzi4TaxVMjU*KPVFY*bje=<~Z07Kgtr` z|2MC?$Z7N;QQw9A@WV9GDfEc_dvL?{pRIli!F$+QJ`b<_z?-%^d_VGP(dO_fyN!|E zcH*&4qAC*o*pC=A$H9K2%o4W!>4grRMl@01h5bm0COSZ-oI;jze2^z&vfeT^>U15s zk93V%13sV30Bf-Qj{0z}7iXKJNs)jv(27~!Jr26b5xK_R)5JyjM`@;k%@N^Uf>%kP z=MUcwho09n#8BK)ujqzJygu6vmeTZNOpqDQ-gV7KucK%=ZcE~}8D3957n9Ew&z`c`H7Ad+qYZ&KrJwlc1|y92a-!MzMJp%cl!@J#8RN zDuvrya)oRzk7scbMlq{ui9{Z6fAX+f6t-D7^2Eedmr)Vs<3|NP!XrFBLV>COI?8@> zfXg@N@d5O5_*eT&LkB1cu-?rk&2F|S zuv;&i%-QN8=okvdP{M5q2=1|h5p z2tt53paBCUzTj|Id;uL7M`qhW1=<45ejZfd9S}0}{h`R=7(=iik7BR`3A}Je-t*m= z*l)?!k8NcvB!AK^Gqz_>@d(xyoXFQZXE#?rMjbIrzJxN)e(92rP-8Sw zHSf6m_k=pM>jTu|6d@5>?DyKnmp}jXF8qu%8MM-fSfCdhw-5oP%<6Ftr=@nT2tiTDN{vQ6W?&&JY$WcYu>tunxO3wRmkB}nhnsfKHz2HM%nH4I&+UA zP~*7jENpNdHMq%W5EWI^%61?J%@G-*vAqREsEXtN_3)J+h^z`W^t?9NPqc~SFWsl`HvB00902s ztaqB1n$WzIO#~Y#HXA52e3fY_7xqC0Q<+1J8MdZ#hpPeWQyi=})+-e-7l}1Eb+TMT zyrEUEO&Zoqw~xK+%rAfL0d!zOSz=TSa;vYU96dp*#wws*?9w7(%k`j#sch)Z!d1em zFv~%!i){XN4J>0~5}tJ!WxCBXTBW5Mo608PIY##hWmR?d0;9%E3ttxELXk!G?0p#s zI}+xgI5oD>FzAfqhJfg}Zxdj~b;gBZMrTHG85wb0`2Kf$TfM64zOTB;$4_6n z?sm>S_uO;NJ@?#u@B6tj+%%POtzM0)HQlV2^{7>^SDMkXZm7{IQ`IX*v|-lw8JZPs z&epVOZ7Qm%+TJq$9mBtdzMbW6t?Ndmsj&Yd5hXIAtgg;p&?;B-?W$>&wQ@tPSxrk> zHL*{fR%0!zT!~GTo7RR2WleRKRlk7z+o~Ab)T&`AN4iRGRT~>-8o+fmsU0P?qoby& z&XOi(Uj5h!fAJ;tF9(%@ab>7kzQ&ko5JV0Pk?#y@9p%)zNNw&#Yr}_q@3a4K%+-$$ zDv>S9@=9IRx2T#`H^-G_)?U+S?yXn!na24WNejw~155E;h5tt^Wl(JpL@o+LG}cWI z&4wt=K#B_~)dfLz&Nhr!DAyBuuApSH$#XO#PerXw#U?EiBSI)d$}VX~d)idan;XJa zGLX?x#tkk!2_5j?(4ewnx3ac6dwCNOC-MJ^u}d|}7~Dzl$Aq$~I?F3_&ajl+1VG0) zgT=sFG5oI9Yca-PF$yv^t{dKp;Eba=3lSv}@{v}SPbkl?&R#lgm?m&)ZdGgLlF_ubtJ;2b3jDX)Mc@lC zD-5-UW{#=OqGNhXv$j;!>ALAf>nNH_rpx4P(=w{#x}|KO-7nWHqf#mFi`5%OO>LB8 z#*Af{HMPPDaw2e=iOPU?M0IvYy>4wPo7+`uucfSHSe5IsE#-=V0?(_?P8t%P@kz!~ps<2Y*>XKfx;eD|?#(NYc=B1y@Cjw8 z0YcdIx5W0=tKg`;X1!K#&cqJhaq!`T4?OysgAX43*ujS$z46goz-?f;T|359ORdzW zoWD-u{1(HEJ`ho2L{iY6b5tT(HgyPHk9K7DPNEHX zHz>*JJfh|4oFr){QgCDSY6By+Q#CPncu`=n$tbCuM2;u&8DHd+pv^`2Y;}qkff&3 zs5i^dU$ZebjW}2!0wCKft*LU2i%L+*E8E5)nWiYAA-g?;Ah1FD4x>p0>~_;Am1p?) zB7L$vRf7^><15O8`-w6bZ#G-@SP_*`!_d_$(}upufDqJ;npU>+10)p~3sXf%Dmvyf zrgAoBq;0KqnW2<&jyO`NO)xmH`WI&`r>U6i$vHOVnp@XD^y4k>cuVoVh%yW{SW?TC zOKV%pO`;4L4K~*-a~3v@s_SJk!_*1}lGrnl1*8iQU@Jhgx@n9yn}$WxzzTNH4F|3B!ZPY#`_`tyAa^Y6@|KsByiiB-~x+0JubV_0|o5 zlTtYvCY7nIq~e(vAJNUVR@I#ep}us}_~hsX6Pq^?ODRi0P1WnL6ofR@m;j27SF0_H zs03oht(!DpM^s?G>09ci-DE@=xKddP4TmXC49L}2y7cm;MWSnA__SaevWzH2if7#R z&6nJ@s(EH50;GveH~@9*Qy4-COzQh%jf!fO0J|xymG#M-_%pf>6OxSJah5XSYeQ1$ z#3Vf`C=A-dwih_u?2%rQIj?6WnU1HBbDFg_kxa{aj=M%>M~U8cW{sY8Rqb`!n4 z$tbp_rU=t{NU~djwz{}hcCu;8)-tTZ+08XlUZ;ld4kEeCre>BKmQ#3~*u?HEqB5!z z#8*m=PyXHVV$rF$=e7FPNWi#t~?$4skv@*wPDQy@=LR8Ubp*SesYjX zn#RB*Z+qXn*mw;N1WakqVyw&HduKwxydLy%0@UazmfIyPW(j=>^3X1AlaZwJdG+De zX-{EUv4} zQ_-8TMx#9)5Qq`io|ZZ;ALpIg?Tr8<@OgVWL?qIw z7!1e-T9bQKGTHn!*<2{pKmXT0-eJ514Rm#%G*Hvjgo4|Nfu{m3red7ff{2jAnTR&@ z;(|h_c2QUOdlnM@zFPUv1-_u;P9$8{u4@ZScQQpC1i9bO3N|AI1OlL=-AflH35KJ#fyIebs6 zR<^j3B+_x)PtW?p;hosyrG2Cl(aUob&sQ!C*xqvaB?|($mq31Qpf1eV_7uTaEfk5{ zWbfVufz(;(F0(nj({#FGK``neW*3ILddb&*Di)irF+gR;s3X?`1na`ESer!M_8<3s zxubo1c^`+GF5`L|wf*ES4zjnz+}Zbj_L7#153&Da*;7jPbJDW01Xm(hC zrLm=xSe)!T8a+f}|5>P)INaU;F3w35_Mea1#9-kKxBlIS>Cm40qkFG^vO$J=Bl(QM z1$CGS$2S~+cH%`1*o#S4;C+H|(lhYr(&^_{i?L|8gnwD~Amv9;nY(zD* zZIxQei@Q|!?tbzu)l^S*G}CBB089$P=HHa;pl zVJ9!HW$ppoTc7lkLEWHx>6GUR?m~@mPuP@L9F>Gabw_jGqoif5tN&8>WxfW73}FMZ$T`Z%HRwX-^LKtH`$ zWUB7bkPC!eH?pA&wefk1Wnt-WZO%n0iD3s4DJ<2aUMBC-~TRR}^mS~VP5;dEHnrO2o` zMQhPX$HHuP(Xhx(rh0(H8Y9rX+gTZ3VSYXZoxu?zPIhvIGJ{QYlsTgtI!D>_}TOx4YLv2I1DO#~W~vsCmXko|~9{3C7yg)hj zkFP>bGS|R{ihXjV*=jWErWGYKHfqvwi*gBh@#P5dafWhi9xK`4adGoZ#p7aeN)K_dm*dPB!xQR(oDm~rSj9U1_`RbE5vJSYbOjDTb_|SmAFd#+yThTE zU;}DqW@fM6C|k-lv5eErR70^$W>mFjGWB)p!T0%cG^MomX0PN>_D${k|)`j+NV$Y53HMIT2K4SUx1t49G*ha=|nwSv7sc0%1w=aTtA=OU7=Yq(w#%n%#?BAdBfp`CaDl2r49ND$4 z5ZBQk=Lm1qbA)%_FD`oYho5=TzeN`baey2gpTs=^xTwM+royOw+;q~I zq9-K@>NsqAM0KmWuWs^GOWEi#x&gn}5#n{+p5!f18*^(}GwVEo4BLNDIAxq_^(L+m z=!$DB=!)U87EXDV%KVTSl9p9>s0ZjNF@p4Rc6*0H{wCbq>8w;Ig82~Mbl~epU3f|6 zy||HJ9Orr{mq9v9wJHGar*y2 z-4s_aU}Ee_aH#IXe2l+`YG-{G_hxXFK_krpmr#fWp5Zjc={{G0VB;7Kk&BY^bp$L8 zE`{l+G6yXs*@xJ^hWi*YO@A)|FiLyoM55xB6?XQ{34o#{NbLc7h?&rNu5yAOAa~u- zfQ8559xCr9hgr#54%e7qwI^g2&Lw*e$`V{be=Mgqm76##>^{qnQdGK5ZvNOJ=RK~z9Rv#bi>(OW3<6yG(dfl-PpgytXD5+)o`cLPPMt; zUJ6s!M9>;vTwug}4qM7bMW@}xdL1MTYzY_2*z36++zrIF0yfA9MF5xUByIO)R9G%maxNqdrmepu6e;*JEKBMaqPA*arB}tV& zy6FRnX+aRN@5)Hem5W`qHsD}%ZjSszRCqA+9O+>m>OXS0gWiea8WV621S2_tT7}=m z*C$9)THa`Su1A6CLu3Tbi@I;Ju$0VPyX>xp@x*BH_I&U$o!v#jLlFod;A^Ln`=T0q z;V$ZSXGDdZLr=#1l>iy8HJf4Cz`95S?!b6ss=|TLY6#Tm901io1R~7@n|mn)c}HD3 zNgF0u&{EEs6M;Co0PL;}Y~gjIr_q^kWB5Xp(TfMj{6Z10a>T^vVl1FA(|dz|^~<9n zwT^YnI2e}u4V_%kgMNRf^6lMk{nr)!gdPktgjNN$)oumT!t z6~BHjuP9r4$-i1mBR2<$b=2JFqLXzZi+(%+6Pv1}fef`ia3x5r>9_+57GQ<9k35UUrfroEZ~ ztB|`+gn`uUCMni40WiP-MAPQZ9FN-6aQ-aI@NC!q5GAF3vhr1duQ^_nPH}8zq zVGovTgg-2$FsIpwX}DFLHfpY_JkI5Z%Rl{hSP&78iZ)+?izSR!BWfC!Sud5XBIXI0#v)+RK&$^&gvEkeBnc@F#dY;_ug|3?n>}>3=}vfm;zWMqPsAaXxCqS*iN!^9(YpB z{kwc~pIWOG_EXQ;l~fP--&x82x>#3E}?f9U&r(a%#!KW%3-Zbzd7%SSgK zO}a)GJ&l~O;f`zm2+uJofZA(m!t36F9}^k;G;@}n3d7=SDQ5lb1m zRx;8BJ*j2mnUtD~t4TGTGtx#vOO^`hLLslF3tEZR0Wna=M~o+*UUm+;b7t_MkBAA- z#_*IRKYZ|Iuf_#Qq7a!2k&`G9$mf(To3~txKO73&E=Pg(>4+d|HZeJSl(e*}rt-;b zDp@S4YOZMHis?iqS1?LNHJ#8iYA#`DrIcMSkTGt&{m<_OEj(*6zO^#K|6Q-vYIU|h z)*MOZqKRn2&nGJ{`|R1c*(sm`+FniQtg^Laloz1{BX=gz=1#dMf4+xk_sS8?2P77N zPmDo~r3w(Qxoj~5uEGB@#bh?0Hxha>qv={QZfKZx$#^^$)CPhh2@!l;b?xFXYv|dep2Bo46!0zON(DWaN~UtD zj_s_c?f6J<-FDyqf)uBFCUkxOUdw8vM%ce2sc0hZQD1~IC%o#1+FyYUSs64zMVvkN zcoUq4OIQ=%J1u&yhlp>MBcdNlj6sVrD6yPTikBewGsRL`ix*QxH5D%wRU?@(;zlN$ zEXFfhDVH&Lwe_r;k1#*JS~&*2I@w2& z@bb5Q(L;`#LX!h`qY~hRWq@8R5l`xnZs}YSQZ1KH7^Om{l*r^0I+&;!FQijY1Bq0e zRwDe-uKt$&X1`egh_h0_fN5CPh2--L% zxD8GeI?v)?x$Tt~dT8>d`O_pA4CV#Bc^AC|WemNPD&>l$Vm__rGRcG<&lDj3)l@N_ zNTgJl4uyCrpW&70)bSez8|ptgh+duI0jI$U*p(=Mx$1jwAU)ni7^JN#r3LxCcRSakSTORz@Cb_bRifJiQ=g4brEuBjEIum#YBf)y1O z0`z{j9b)l>lJG5TZxwMjoV`$|O<;vGS4Z_I)4j~$#cgl6=vMevbXXV>FN)=L1i*2} zDssf(IU8dOP@rzFmnN{YG3#-$pvT?--T$X;ZwCXPhOzbACnLB}8tzJA?x^;n zhg3Y_6`Ox?E@T2LLoL7@*-oN^8_B=tj<2s1ON3f?euqs^YtjoV*C+TY0W%v*ega&W z8E7|_O%<}5p3kI9#DQ?8|j2=%FGVOh^S0m&C&Y8uc%RbC6;SBL8M}o!F zB4Kd|bshXW@Fe{R7QJ?nh!EpqNX%wC-k!))aWb>|n%Em2ag}Wq^&>(N5Og{P52mbVtaMX6U?iSOi-zZ+N?WN$svO z?j!SA<6k&%R+{=Le4ZyN_K9DSiT#cL{=qx$7Q7)xg?8r_S%;^h)Ix_xCYwy9H7#Kz z;e?JSQ<-==S2EOODxQibf<*s)-Fae;qTfX_EOLEB;C{DcDW6w!={)?MNrGEJ%Vw~M z$QJcnB412uNtM|3>Gt~E--aG~q~ML+G4G%Z+OTt4j}ebnSNe5T2y*f!3_gb>IocJ& z>lS~YdfNGNmUfuI!X5})8#iwH_3wTrguts7pEf;ge>oc~6lFRpit84iI)TdKm&51f zpe)X)8aV4SGaI!`gGSJfh(GpJ%0*~~cr?Ayry172=~FlYv%*~vEv@pmL{$W~FlifS z{_u@e!5~d361c%ZzyU9+AoRFVC>C?Md?~5N<9aHk6>_N@`8!Fx+o>Q0@z(AL1StrA z=VESjpbdZyd^3fdZsb(F7NKWT>4I9!r87D<6IDYi7)1?h7%g8kN}jq-S3IKcmEBS7 zpb6YaISt2p(x|Hvs4ONbhZ+&uMgI+pNsiu2g2tkvV+;IewqE*|Vm`~+;GuZ6^MYV@ zQR&f9%pX`>G=i1`Pn`Jlze6sQJr@6R0Kph^i_RoxCOSKP9-4jMuMqq0EA03Cy!UkV z-GUY5y6pqtacGcDxMVz)EEw3MjHio9>{sTC*z7K9=|T?AP_=vL-_xD;LE=4tMlfzX zG!ovQlu^*tgqF)=!xZnyz-vz&L0RmXCbYbPZBtDz=-4px*LU^GBjn_K3_j#sjmL_; zNY+)_%gK`v=p2f~XqWo0?aosj^l=EX^p^Z`9_=tF+0y@%SN~Z{OnEuuIt&^;tbIAt zDGWj#wSb(jEEFn1n&95I{qm#G1TP{|&W?|1;90b0vpypJO-A9fNap><{u6JXUV-yQ zycAmT#`5rVZtEY$8+q-m-`OtsLr$RZb`e}hv7)BFR?<`zy8wvS%o%Zn>1DM{vXDzB zv+xZWiNI}uuyKMMkC^zE;}c63^+a4xA}*o;_=s~$8!4zLY|`ekNzEu_jAA;CT?$dr z-4Tz(lQW*A$kSEsm!$-p3?7G6_uD1CocNF-L~ju~ii!IxKbn7SoAm*-|IVT0b zhftqhH1>>jl;&~@SBe^eE}Jt3m2X1;(*SGVKBXO0Je}^afqVOj??=e%auK^bo%WmY zliMF35#uhmRqeFxHb+xg#QY+j(9jW0mO@O61}BZ0SCd)2luH|dF*a}OKH77&;2ng7 z@m|a&GYIxi=k$bHG?FBuEgjDpIT9qBFJ$9IJx?Nm5_Wv@blTMykK~eb$stC9cJVFeeU>9eZvpOqsLywnrNgp85*u5DzxmA1u_s*-_af&Hk;I^f z5SQB?l*FZ@7?)EevRDM!TYWJXb^%OfsKMCzDBR(&n*28_$sQi{a)`zhz@mq*6QZOL|NJ=T+IU4^~e zmTVY&4oPyf3x2sR*)W9ZE&k=UWJBR(D}h(O=y#tN_FOonDCU@Jip-ITJG<%SyhfoY z(@`OWv*e_x6KLPR@da6;7Cgs)d5=eMn|BqbllAq}^ghh>I=>LJgL?Sn4{-tgSfs>jOX z_0Jt<9o3H9mQr6vFHrql_9^o;sGq?7Vxf4+LBaK{atEz*-te=Zz<#l>uwU7%zx9rX z1;@xa7<~X-vNslw7t>lXn@c3(aKYoKxr%s9gy7_|rD93f1D7Oy+AsEDB~(kPplW&% zmnUc`wNNth`BX{ImDG$;(o>~4HV=x$0!~z__KJkl*wrhK$dubJ_95qLyf?|ZDiXQv zoe=08io|GF8*-C71X+47M&#VrVNkNyB3~r$xiirK3ua z+b<4Wbz1Fv9VMJ zdj|>lsnm2SkxJwfT2U{gGYKQB6R%NV*wIJ&t3Q0$2_=GUYg}BBh2p@TM<$goln}vX zWHJR+P38*4e4>bx5XpGbRwBN3T)p&&%^ugwb?|v~7&8};-lXiRPQq^47}%voC{&_=>%~+Jr^0fY7Pte_r&uTlA)!4IC2|*IGO6cF>1@%!YC}&a z3q>OZ=TtI>TQ7_Fi5pUJTn*PLQF^-i;*p7R^E$BISWg;t)e&;BP;!_YVkBtS1ac;k z95H$?E#zXMB(brV6h}YtqD^8d%WZl|V$fqLA!p1;;?hy7%f&*;ViDwPYDNFz6A0B_mO#B#gq(m5 zJsoXj@#{B#`@e)}2xst0)2N5q2p5hhja5el63!zgk57;)+4!k1ejBQUD2iyO^ATN@ zNd1+kT#I)M1V6E|e)aL-d1uxHkI1P{Z~HF63U@oM{=`wTd?}vP3Mm{^C}mY#Bb3B# zyNSG-3EHZ7cYhTJ>$FfAY9^!VnM_=d<501NYnQZ~p=oLycN`Vs*;E#H3u$p9o3>R3 ztM2NPM=FNnmbSKg)2pkRkTXc-NAD0MMZ0PUC-x+UsHf8?>@E_$*pk0307pP?rm@w* zj{3jbmSWgl;(24yLlK0tTqVY-qY4PSXFG4o1UiKN{1#VQ|*&pfe!HEg~cnncgdPz%V(z+JM{ztNuC?<8hoq)^u za+yLNPs0>d?5k&Ep4zS+c?6!EGon+|v7W^0D*ELv5SK>g&?7{<;Fq&3rAg9zF(Bu7 zl}E@H`wy-B`SD_k%ZXWeBzj1Fxd0(~bUF%sxs_T7M1lb&@jy;0WyEnCleekfbjx zzv*j`^e+w;Wh3MoJ9x;AO0bmw-F07FWhu+-Qho{lg2V6rfZzeScy_yKm%zePiYaWP z=CgPkpoFVGwPZdSPpCN^kvcdB7wF89xS2GVBrzK!F4=L_hLOr5C@7cKRfIETNO+Ke zi>ixxy%g8TA_JQPTHdMXbj2gi(BoOQu{^0B5K5J z)vR*0gJr(v^1@ZPcaE3wOYHaEwIU|QTy8DT8+M5!oc6_*EjC8ehKdX367gI-gV!Nd z1m+`HCzTI!zQ3h!);Pz9OY1@=okWOG30ue6d@iGA)kGqh(UW+HR!ikm_^IY$pl4!j z-S7x2In~|PW~?V^x=L!f_rT_l#Ua%7b}21qTh5;dy=Amqh?E2-wuIhr_Jh9=vsKP# zDgnKRe3p}q5_oi!&T{@O84QAC^RnxHJPFx+sz)|cM+t`zY)XIYum?^Ba}S+JCGyMh zC-;)vKQ{bgF~b$K4WAA`=n_sVbZz zYEg^Fv*~m;oy#XRTmylvPy;vlXN*D$7Bsn9NJ}R~Ek~s+h(PK|ltq!ny|6fhy1sC- zxEB!?PZsyY#FoXcxcN@oo7pc}+!OjD$>N@PEVwN0je%DdgEy6p?6vtuxngWGimj

H*-O>;6=(`S{ZfrZYV0CuwQJn-cHa--qTAy(vm{;V@4 zDFNt*D38d>11o^+s`EEel!t^u@rM8$yyM`*2OoI!H3uI&__2czJ$mD#x8N>4-H7el zF$RBsr9S2SbrL5hd5keuY?Ui|Y|5w^Cb>*0)}-`BmW7LbbhBR83DxnC3x>fX!Tdos z{X#%3>yniaPa}TDKLmXMo~S6dLCT;mS(?j<;0>i9IMw#<*6P- zyWgjZ`-O-}c+qTXX1QU7Al?pFGd2-t2+Iw;w?$Yo0VW)+NdO>xk5?NNIswuDh%)4R z&>Yj7v!-X_WxulvQwi8GC7#-2Er643il{5kVO-h!{WJJKObH_spfrKVO!YqdIgIvsBc5-vk#_eb7Q0B^8gTq}F9#Y6BD;E{{z>*)NQ z_KCWtR**v5#d!E0c}GJSq3!&A;vE1x|=hP-@qoBoGIeO;?Zk~Tw#a3Zv`Quciy)hfh>a;S&E#SF%-7+ zYCKDk+qMe>*}t5yl(12p5@Y2|ndmiTvh*CBI5cP>=SB!M9<{Qi$Zf5M0t>N%U4Qnx zI+YtkM9vXM6GkbVA+sjay_+X+-7 zAD86|X%xAxlADXNP}}vCTwSMIMlqN3uAy(?BkqK^i{MO>zMO(ja^2B{^e7 z7MnnwBo`|wi-K1l$yut>ux;;_rO2JGk%dh3(Bkqs)j@K5II^8|>z|1mM?TB+kKAsH z)U!lP`ONtpIih`jDmyN62y)dUCxfIww#!_(`7Q-KKHq=k@FhVcdQ{IZsDl z&>)KOIh;9EQOX@H?o0RGinDnBXIe~g$}I~Kp@3~q+;O#jI_LI;7c*HSSHQ#9xH>SM zCI|BHuynGJNMsVKVH9vokZxt2<=!*3m8Gjq*VS2MW%gQG&#gS3Tq#Q06|Sz#i#+XX z6iJ4aMId06c9ZNLjx_PxsUYXLmPddnIl282d6+#Eo7{G)G&+IGOwLy!je}Q#$(<08 z2ku(E$+_#KK@&x_$Q)0VliZ%1bT{1!>1Q*){W?=fa>MN1E1UOK@k}kv{}mCkdb?WI zixn1UuA<}&yO6-!MReHPm`JF_{Ku_*t)};9gMZ$rv{OXR-4}LXi0YEl6=5OwP+)S4 z#*jz_sxi5Zwvd>3m6@Df85RYXN|STIhD3lUw&!G4Q1vFa*%7kKZY5W}`+SorIXO)$ zeV+c&SR+C#O%foFK-*Qt_9)tF!*WkZe%5zT#IS+w69jJ#< z&P@~oXbQ+xrJoJBY zrk>=4zG-N)TE#HQtqgv@AnxQ>lCu;- zf$gELv`@EfXZT+#N-+Pb$hq0w~ca zi^k1Vk;sKEN_5SwKaM|s?KN!aBe&HjoP^V9_c|h##YL7yykn&&$aC)G5yezW&8x|* zUcx1pxD<#+Lj=AI>9puw@C+)lD^sV%`QgYFiJV795@@?Jk&`Ww;M*0-;E<&}#}tr@ zv6Z9%RV;EIA6bY!mNasXP)TG06^xugA&G%k$;esPvY=gS7&&`Y5-?FVi^}Cx;mG+G zCA;WWI^X=yJKxWgj@+U}H=5D>Q-!Ri=QC-%wXUgYHIc*}bfp5`=7P7)ND75> zT2S~MYt5@{BDi)!jss+H3$~hnd`p zMFv_Ar6OllNFWlZP~=uD641TML~g|*1J5~GQh~~4st6N321KR@#}k^ zx|b;rIW7|Vi-&Q~=g~Q~YMI~Ll_Z+rk?!Kp?tzdOwM~U1S+9$t6B-R^eQ8{kn#|t;&!9SX~Gb| ziE>(W?x(99Ig=|ySKZ3$2X}t`RHm%LO~PqIv+Cx0-Bb^##fsrx`lK?r+Zs~i; z3}*|3;TN|)lv@t>gKdaneD3B9)sS*gJpJgrTUEaD$eRx^RT<9bTQb$Ds!_AtGCo<# z#dF1iQA*~s>0~mgX^DJ1nTqF2rBXbXOz{0Ea)ozPWtWUcdH+U4KSjGf<+xVXd*yF; ze)w{&C>Na@3Us^3mkS0Ag+zcJJl;|c32KD1HwBl?iyNrs3umIq!R@im3#VhGPzuy_ z;RKu%9$qCEPQc3{;BrBRbCgMeCu;3Em93$ce{lGBxv$ONh+xgAeQ47|!n z&b*cd?NUQ>8|spPi2_A=yQ@()rl>J=>Vlk)yKIgR*QtY#tAOlUVR&vX{-u zp~y9koVQ&HWV^JLlYLUa+qKQm5wh2GNFmVPd%0a=Ip9Ro$eDj~@OtPOIj6rADuG%? zPSi`m_v#qA6^9&PmxhrGCzAq8^vfc0Hq|b2`b?^OZryV0ZSTCA=@z+d!%BJD(DCLU z0w-|SO(L3z#-plg#*&F-E}q5t*i0gs)^#JBO=;M@N~VlNDHGSk&Xw(vQ%!Aev{Ejy z)3zg?W}TOCNx;RgWKV;6+ME}vT+hh48l=ItOItaSBaJ}2z8QR4_FSkm675uw3vHE0 zfao2$Ri!-49=b=)D=Upop#G7wx}L9r#mOOBm9+GqXNP{N2XpuRd>La;;4(V>X zb<)#kTyYxHNpd!hhL;_&?7~}V>nrLko@b@PK1KCXHd%~klc_XziHu|#FPSG(nRq%^ zGE{6CrQ%|@Xe3~_2=_RMc9AXqlP@^DBHy(Q-i3kSD{?vmR$3WZXj{*triLgC@nVRDZ0a0s~c znA|ch6nOcKqi|qJJiDCdAQW7;PMf&=vKrHAa_iXkqrg3%x@R7|Q&k@GKv!5~l{UiL z@+_-{^0J4bWH953O3sRt0N5^&<=8<2bh}a-I!D$zkO1G_bGbuNGN6e9l2d##(0ZsH zxfPrQB7w?APS{F7_o^5a;phE}E)2iw4Mlk%%%h zt}L(4UZghnj-mLtvZOk@bGBhjC`VOiM@_3-QZ;K-*U^9S*1WQOLRsl#Y$;a^l6v$E z`L0{3-g*jY)lyC;m^EL~Qca`Ph}QS-wX8;Jg#9~`iYDUG_(tdi)QXIgc8C9J>0=`m zR`+CI-Etij@xg{#+NpLKt5!Y#P1mw&r?fBb7&-Xbj)U97>MgtJG;$vlP(77^o2u8R zDujL@;#9L<8=;?MG#^b0JkMek?_B*#xV;tMSKUSalk~A5a}@^l8Ji40Ap2fUA*HStB36@PZlE$SCQ# z=mh7|u8!UH&3XmRbN?%XiW zXpokbAt0+9pkEx&JJFbdI~y$7*x%ezH#Zr@))W`jJK@@}l;h1-bh=)ds+;v<-HJ|| z8g^tW^{J?ZY|`FEmU2w7RnsemzcK~q%&-XkeO!BZ)xkRsK78}0FasGHWL zrCP1#ZsmD)ilJX%i<=1|k;ZGKx=*}(=W~}miF`u;ryzh`xy&tH}Is7y9OY?&vDO`F2vf#2WWSy&HdZdDizWY-7BiItg=H{Q%TPei(RT&#t{3VALfBRt{hRF z-DQ|fgmn{zGC_U=8c0jj3MImc6Us7?C=ymxXSZUP%E1m(eFBIH;`7Pl+ogU{&$_zSpw#3lpYXf{)?l-&6zr7MaYlFelb#x93w(+J(XzdUGgQ0vV6u2 zZ5N2wkvX?f< z8HA=Yx`VrwHJC!Ra#f`{o61dc7+v=bI>g!L8AHRHR`uHETB~X)iFS@P%osJpVlGJQ z>}ng>a49=}{`Spy~YRxfAFtY5apA?o7EFvoptUxoX&fmxyg9d*d zxv_=FCMqQ_hhvoVjiL7wm!shUK-_fA&YT#dDm3=iYz9!Mt6N+H{e%)@}cA9WA)YDY*H2 zr)~NNyC5~*BWr(r^)YwSf)h@`t;5Ujo3IN~b3L+l*-tKCN(=6E3SRz|+iw4cU65MJ zk+mD@zuiR(UgZ>g**(Yn^iy`hJ@hZ%IIN*P)SfB7`cYcDFSAN!#X(HsZ+q5E0FtG}hc z)2V;2sPDpl=&xy_Q|LbXcSI{a^!;B^?BDKS|Bl$2Fa5wSKFlT)q5Yjsq9p)D-s2=r zi$p*6!`ILp2m9gcS;Av4Uw^t&e@4`IVLyB=O>_!fXaA09g~lshL9zd^gZ)RE7eDd= zyZDfU{l}d|2m1${#E#ex`LQ43*pGhl#&0|IgRmd+VL#-?{;ZqNd?CgDD-QNw{jay& z@g1kl#|1?qOsf(`9{MLc@iC|5w?v|!_Cw#JIS%cIe!vp;|LnmJJN3UK>bqz^^nIG> z6#5tYcSQSjbtSOg(fs`6vh7c4)%Yz^T8!twGlG^k7#p{FJVaHZ|uY& zr{Vt)iEk5$e(Z41& zRKF>7GQC68cVR#DE}G~7xzqj~(cZQ0o;{TIV-EJ4rhogTXPn}iXmju)CsDT(C!EBR zNNmG?AI))LUt`o!J_1Htok9=Vza!dLK6W0J zn1f9Rd+VP+aV}pkp@+k#iZ%ziQ-&n2vlFkg8y-GgB>J%*elg8)upf@Hgm>QhmAq5` zMWVh7`{A=_qEqN>`*%e9btSOgeE$LChXr4?cu-p`mZSV?{l!fd)vunW?WMX%bB(J zI&C(nKYS%kbP8Q%|Bh&1e%lw@HB&q4C}5&8TQpJ9c3 zR*}z1ZWKAy=Ii+N2;>smUMOX$T+x}@h4iHs31;5?)7 z|B}Ks3rCiuS6)LcBp*L2@B|*=@dOG?{g+PmlLK5HK#%9Iv&WAR^$AN^?VfjYnQvT= zTFO*k9h!mjjk?%vk}DYP{?gC^O2Vl3ut~Frx&HU)Ws|v7Jp>&^!5B(-u<{@44L7n5 zRtzDwLo`;emC92A`>6eOEIYtWqXu!()XZ|jniFYuxGLBr3XqX&1Ptn%<~%1Ri9h-= z94Y52CcTXI|Fwj)lqGwr*l^s_IQ#b}of{ZxusR^r0ODZa9Yn?=ir{cp6agI8O81^z#@!NrBfqTh^ z*ewIZZW*|re2CpL@JD?3IKU-_ETJN zGEo(bjo}e6nNLhDwUoG<#Kb(})D*kV#4_SBgWD-N5ZhNbr^FDbjdHZX$P~TEs5D6T znxY^HN3@5JHt4R#gIX?7o7h7pgtnBltL2JXn`)_3Mzn|mHjD{zD~7w;$*yW{gxqCb z+@Z`4gTy11Yg6vRr*$Yyh~X}GO2-b4HX5Q+OVT9VF+td6DWyN8^abI^*|DrhXxx`* zfZUfXWi1)z5pK6{G8)9#sA*-a$dn^k7Tjfn{wU*Ot$~ppH`h#M$-83$saeSh6p2hlXp~ug2s&B4M zm(6;OT$pSrtDN+0hM^m}r7+}a3miFD^M~{DBxum7ZHEwA$|3AZsMXby+ta**YRrJO`j z^rW-%pM=R-ku$p$@vI6hg^{>JbK7)u@kQNQbKCuhI__3AA z>eN5Ji_wXm^LaI5Jt{&bJW@$P(C`-iD3f3m;bP!y^jv#g3S29D@m{2%C*qUpTu2 z3^&j5fjq{I8!tjh;Tc<=;UxwW5F8a=!X`&xrXYxiD|k)OQy+dzj(CBHqBc>Ev^!C+ zL7ah2_yiK+r!L_G&jl~dLsQ4tWE3pZAz&3D(xO_kRW;b6depK^OW`wy`tRsG9>Y)| zP7VQGlkn;pH8FRA7jMMx>$8-zSnD){Q>05XN72%{N13sv?KFf7UfKB^qElcWO;CAdc%{y1-{^x zX>2ttm0X`@DQC3zinjddHBr=%Q<>S)K+MI|Y;ymfL2B2;+>s4mzZ{bINgmD*Cz;1(MZkSUHQ5P0sb}>m)4JvYRt&D{)Tf^JJJFujS z9hr0sEM*%DjL@z!TynCtkdy91fH9$y?Sje_o0DaOVrvPS!KorT&gn}!&U1X=m{4+8 zbpdqY!fV?gnZZtD-o;#Ns0bD3V<6_5JIysN!oG87i$xxjI_@0sK8~X`)e3k-SUNo4 zW&$SVy{V!_CR@FE-Zt5qxj|N%SZ|0mFn;^BH_vB_ERoL>87W1gn6NyP+2+XP81rPt z3{JAI7PIP*-M|UU3Cvk+p$cIHw-|PVn|=&0hWNq|igjp*Qo?$(6efW?6l>!JcR3pp zr@adwr+GmX2Uk~{Z05S#6#ci`_S6?FEV{@P5U#2aB zLs6~}ST8%3=Y^O!>r`kfxmJ+7H9D2CyVAWW=5}KCY^SD38IBjTk-HVN;WF81VyhoV zSKSL4CQh(wsKNWkGOjSoIH%@;(J9|UdnQK$irQE(xxh>8pgbXXrb(?Pj4QZ^2~UeS zQ7wh(bBnr2STD%m6g$C=V!1;yI4mcNEwXT0w$>!v!u>krV9O?BhH|7~I{GwA`DbpW zJ)LKa*R!Hc3SW8PGK%|-A;>vqTZv9`A(rSn#Hvl4`Nv9rrhN#k%kcKfK5C8s1O zl;=CQW;8FDW%{OtdjLQ)vNaT;7jDq1|$utgQyXIQw+1H2OB zdvLKSx(UjUoI+lWW4qK_7w4vFdn8PT!)JSu^kNU-g@v6(b}wlvj%u&1&ce9ldw}q| z*gHxDZILg?6p)YY)Cs9TK%roOJu;JcMz5KX8#D{S&jxy5#ks>I17(XayDHr#FTim extrasMap = getIntentExtras(intent); + ((TextView) findViewById(R.id.itemName)).setText(intent.getStringExtra("detailName")); + String tmp = intent.getStringExtra("detailPrice"); + if(tmp.equals("0")) { + tmp = "Уточните у продавца"; + } + ((TextView) findViewById(R.id.itemPrice)).setText(tmp); - nameView.setText(extrasMap.get("detailName")); - quantityView.setText(extrasMap.get("detailQuantity")); - priceView.setText(extrasMap.get("detailPrice")); - countryView.setText(extrasMap.get("detailCountry")); - analogueView.setText(extrasMap.get("detailAnalogue")); - datasheetView.setText(extrasMap.get("detailDatasheet")); - notesView.setText(extrasMap.get("detailNotes")); - mPresenter.getImagesByItemID(Integer.parseInt(extrasMap.get("itemID"))); + LinkedHashMap extrasMap = getIntentExtras(intent); + + propertiesList = findViewById(R.id.propertiesList); + PropertiesListAdapter propertiesListAdapter = new PropertiesListAdapter(extrasMap); + propertiesList.setAdapter(propertiesListAdapter); + + mPresenter.getImagesByItemID(Integer.parseInt(intent.getStringExtra("itemID"))); } void initializeViews() { - nameView = findViewById(R.id.name); - quantityView = findViewById(R.id.quantity); - priceView = findViewById(R.id.price); - notesView = findViewById(R.id.notes); - countryView = findViewById(R.id.country); - analogueView = findViewById(R.id.analogue); - datasheetView = findViewById(R.id.datasheet); - datasheetView.setMovementMethod(LinkMovementMethod.getInstance()); viewPager = findViewById(R.id.viewPager); } - HashMap getIntentExtras(Intent intent) { - HashMap hashMap = new HashMap<>(); + LinkedHashMap getIntentExtras(Intent intent) { + LinkedHashMap hashMap = new LinkedHashMap<>(); String tmp; - tmp = intent.getStringExtra("detailName"); - hashMap.put("detailName", tmp); - tmp = intent.getStringExtra("detailQuantity"); if(tmp.equals("0")) { tmp = "Под заказ"; } - hashMap.put("detailQuantity", tmp); - - tmp = intent.getStringExtra("detailPrice"); - if(tmp.equals("0")) { - tmp = "Уточните у продавца"; - } - hashMap.put("detailPrice", tmp); + hashMap.put("Количество", tmp); tmp = intent.getStringExtra("detailCountry"); if(tmp.equals("")) { tmp = "Не указано"; } - hashMap.put("detailCountry", tmp); + hashMap.put("Страна изготовления", tmp); tmp = intent.getStringExtra("detailAnalogue"); if(tmp.equals("")) { tmp = "Нет аналогов"; } - hashMap.put("detailAnalogue", tmp); + hashMap.put("Аналоги", tmp); tmp = intent.getStringExtra("detailDatasheet"); if(!tmp.matches("\\S")) { tmp = "Не указано"; } - hashMap.put("detailDatasheet", tmp); + hashMap.put("Техническая спецификация", tmp); tmp = intent.getStringExtra("detailNotes"); if(tmp != null && tmp.equals("")) { @@ -106,7 +93,7 @@ public class DetailActivity extends AppCompatActivity implements MainContract.It } else if (tmp == null){ tmp = "Нет описания"; } - hashMap.put("detailNotes", tmp); + hashMap.put("Описание", tmp); return hashMap; } @@ -148,4 +135,5 @@ public class DetailActivity extends AppCompatActivity implements MainContract.It viewPager.setAdapter(imagePagerAdapter); imagePagerAdapter.notifyDataSetChanged(); } + } diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index e4adc21..2fedf75 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_height="wrap_content" android:orientation="vertical"> - - + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 47d59f1..ab22a0a 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0' + classpath 'com.android.tools.build:gradle:3.3.1' // NOTE: Do not place your application dependencies here; they belong From 846ea7be393e4428580397e56b249b08c2d2edce Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Fri, 8 Feb 2019 21:50:26 +0400 Subject: [PATCH 10/14] New UI finished, and image showing! [#2] --- .idea/render.experimental.xml | 6 +++ .../additional/PropertiesListAdapter.java | 52 +++++++++++++++++++ .../res/layout/properties_list_adapter.xml | 19 +++++++ 3 files changed, 77 insertions(+) create mode 100644 .idea/render.experimental.xml create mode 100644 app/src/main/java/ru/volgorobot/vrcatalog/additional/PropertiesListAdapter.java create mode 100644 app/src/main/res/layout/properties_list_adapter.xml diff --git a/.idea/render.experimental.xml b/.idea/render.experimental.xml new file mode 100644 index 0000000..8ec256a --- /dev/null +++ b/.idea/render.experimental.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/additional/PropertiesListAdapter.java b/app/src/main/java/ru/volgorobot/vrcatalog/additional/PropertiesListAdapter.java new file mode 100644 index 0000000..15941d7 --- /dev/null +++ b/app/src/main/java/ru/volgorobot/vrcatalog/additional/PropertiesListAdapter.java @@ -0,0 +1,52 @@ +package ru.volgorobot.vrcatalog.additional; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import java.util.LinkedHashMap; + +import ru.volgorobot.vrcatalog.R; + +public class PropertiesListAdapter extends BaseAdapter { + private LinkedHashMap mData; + private String[] mKeys; + + public PropertiesListAdapter(LinkedHashMap data) { + mData = data; + mKeys = mData.keySet().toArray(new String[data.size()]); + } + + @Override + public int getCount() { + return mData.size(); + } + + @Override + public Object getItem(int position) { + return mData.get(mKeys[position]); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final View result; + + if (convertView == null) { + result = LayoutInflater.from(parent.getContext()).inflate(R.layout.properties_list_adapter, parent, false); + } else { + result = convertView; + } + + ((TextView) result.findViewById(R.id.propertyNameView)).setText(mKeys[position]); + ((TextView) result.findViewById(R.id.propertyValueView)).setText(getItem(position).toString()); + + return result; + } +} diff --git a/app/src/main/res/layout/properties_list_adapter.xml b/app/src/main/res/layout/properties_list_adapter.xml new file mode 100644 index 0000000..45011c0 --- /dev/null +++ b/app/src/main/res/layout/properties_list_adapter.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file From 1e20c8ebcc4d50ff0e5eb6d81a3caa9999a19f3a Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Sat, 9 Feb 2019 21:45:22 +0400 Subject: [PATCH 11/14] =?UTF-8?q?[DetailActivity]=20Made=20transparent=20t?= =?UTF-8?q?oolbar,=20dots=20(which=20indicates,=20how=20many=20images=20in?= =?UTF-8?q?=20slider),=20margin=209=20dp=20from=20the=20left=20and=20char?= =?UTF-8?q?=20"=D0=A0"=20in=20price.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 4 +- .../vrcatalog/view/DetailActivity.java | 6 ++ .../res/drawable/tab_indicator_default.xml | 8 ++ .../res/drawable/tab_indicator_selected.xml | 9 +++ app/src/main/res/drawable/tab_selector.xml | 8 ++ app/src/main/res/layout/activity_detail.xml | 73 ++++++++++++------- .../res/layout/properties_list_adapter.xml | 6 +- app/src/main/res/values-v21/styles.xml | 12 +++ app/src/main/res/values/styles.xml | 4 + 9 files changed, 101 insertions(+), 29 deletions(-) create mode 100644 app/src/main/res/drawable/tab_indicator_default.xml create mode 100644 app/src/main/res/drawable/tab_indicator_selected.xml create mode 100644 app/src/main/res/drawable/tab_selector.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f210ba2..e5aa12d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,7 +23,9 @@ - + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/tab_indicator_selected.xml b/app/src/main/res/drawable/tab_indicator_selected.xml new file mode 100644 index 0000000..83daff8 --- /dev/null +++ b/app/src/main/res/drawable/tab_indicator_selected.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/tab_selector.xml b/app/src/main/res/drawable/tab_selector.xml new file mode 100644 index 0000000..001747c --- /dev/null +++ b/app/src/main/res/drawable/tab_selector.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index 2fedf75..d7f98b3 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -1,33 +1,54 @@ - + android:layout_height="wrap_content"> - + - + - - - \ No newline at end of file + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/properties_list_adapter.xml b/app/src/main/res/layout/properties_list_adapter.xml index 45011c0..c0bc04c 100644 --- a/app/src/main/res/layout/properties_list_adapter.xml +++ b/app/src/main/res/layout/properties_list_adapter.xml @@ -9,11 +9,13 @@ android:layout_height="wrap_content" android:text="Property Name" android:textAppearance="@style/TextAppearance.AppCompat.Body1" - android:textSize="18sp" /> + android:textSize="18sp" + android:layout_marginLeft="9dp"/> + android:text="Property Value" + android:layout_marginLeft="9dp"/> \ No newline at end of file diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml index fd7a058..a005d20 100644 --- a/app/src/main/res/values-v21/styles.xml +++ b/app/src/main/res/values-v21/styles.xml @@ -5,4 +5,16 @@ true @android:color/transparent + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 545b9c6..f49f94b 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -17,4 +17,8 @@ + From 666e6b21861dea8b02692ba052b1f173a1f4a37d Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Sun, 10 Feb 2019 21:01:41 +0400 Subject: [PATCH 12/14] [UI][Detail Activity] Made background of viewpager is average color of ImageView, and scrolling down with parallax effect. --- .idea/caches/gradle_models.ser | Bin 108688 -> 108688 bytes app/build.gradle | 2 +- .../additional/ImagePagerAdapter.java | 16 +++ .../vrcatalog/view/DetailActivity.java | 104 +++++++++++++++++- app/src/main/res/layout/activity_detail.xml | 76 ++++++++++++- app/src/main/res/values-v21/styles.xml | 9 +- 6 files changed, 193 insertions(+), 14 deletions(-) diff --git a/.idea/caches/gradle_models.ser b/.idea/caches/gradle_models.ser index 6fe1fd92dc8a445cc873f37c81c56ff4e4f8dad3..66f54b50f3c8106e34b7058c3ecf723064d86caa 100644 GIT binary patch delta 71 zcmbPmk!`|7wha?hIkP%@moR|9WX5dm%|}!_?O3KvnC#jdn6f=Eh4GLS+k~YL{22?T aD{3(cZ`Y}3yvD}j-y-vDJ6juLml6P{_!&q5 delta 71 zcmbPmk!`|7wha?hIlI3cDPsVE$&A_Bn~$h=+OhmN_Wyo!V9NHu6vjhRY;G?+G8qe| aD{3(cZ`Y}3yvD|&xXqepJ6juLml6Q^nHoU= diff --git a/app/build.gradle b/app/build.gradle index 5be5893..bb15bf1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,4 +34,4 @@ dependencies { 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' -} +} \ No newline at end of file diff --git a/app/src/main/java/ru/volgorobot/vrcatalog/additional/ImagePagerAdapter.java b/app/src/main/java/ru/volgorobot/vrcatalog/additional/ImagePagerAdapter.java index 5c111d5..69a63bb 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/additional/ImagePagerAdapter.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/additional/ImagePagerAdapter.java @@ -1,6 +1,9 @@ package ru.volgorobot.vrcatalog.additional; import android.content.Context; +import android.graphics.Bitmap; +import android.net.Uri; +import android.provider.MediaStore; import android.support.annotation.NonNull; import android.support.v4.view.PagerAdapter; import android.view.View; @@ -9,6 +12,9 @@ import android.widget.ImageView; import com.squareup.picasso.Picasso; +import java.io.FileNotFoundException; +import java.io.IOException; + public class ImagePagerAdapter extends PagerAdapter { /** * This class is designed to control the ViewPager (images of item) in the activity of viewing details of items. @@ -57,4 +63,14 @@ public class ImagePagerAdapter extends PagerAdapter { public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { container.removeView((View) object); } + + public Bitmap getBitmap(int position) { + Bitmap bitmap = null; + try { + bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), Uri.parse(imageUris[position])); + } catch (IOException e) { + e.printStackTrace(); + } + return bitmap; + } } 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 ab0629e..992e744 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/DetailActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/DetailActivity.java @@ -1,22 +1,24 @@ package ru.volgorobot.vrcatalog.view; import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Color; import android.os.Bundle; import android.support.design.widget.TabLayout; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; -import android.text.method.LinkMovementMethod; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.EditText; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; -import java.util.HashMap; import java.util.LinkedHashMap; import ru.volgorobot.vrcatalog.ItemPresenter; @@ -29,11 +31,14 @@ public class DetailActivity extends AppCompatActivity implements MainContract.It private MainContract.ItemPresenter mPresenter; private ViewPager viewPager; private ListView propertiesList; + private ImagePagerAdapter imagePagerAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_detail); + Toolbar toolbar = findViewById(R.id.itemactivity_toolbar); + setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeButtonEnabled(true); getSupportActionBar().setDisplayShowTitleEnabled(false); @@ -135,11 +140,102 @@ public class DetailActivity extends AppCompatActivity implements MainContract.It @Override public void setViewPagerContent(String[] uris) { - ImagePagerAdapter imagePagerAdapter = new ImagePagerAdapter(DetailActivity.this, uris); + imagePagerAdapter = new ImagePagerAdapter(DetailActivity.this, uris); TabLayout tabLayout = (TabLayout) findViewById(R.id.tabDots); viewPager.setAdapter(imagePagerAdapter); + setViewPagerScrollListener(); tabLayout.setupWithViewPager(viewPager); imagePagerAdapter.notifyDataSetChanged(); } + private int getImageAverageColor(Bitmap bitmap) { + if (null == bitmap) return Color.TRANSPARENT; + + int redBucket = 0; + int greenBucket = 0; + int blueBucket = 0; + int alphaBucket = 0; + + boolean hasAlpha = bitmap.hasAlpha(); + int pixelCount = bitmap.getWidth() * bitmap.getHeight(); + int[] pixels = new int[pixelCount]; + bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight()); + + for (int y = 0, h = bitmap.getHeight(); y < h; y++) + { + for (int x = 0, w = bitmap.getWidth(); x < w; x++) + { + int color = pixels[x + y * w]; // x + y * width + redBucket += (color >> 16) & 0xFF; // Color.red + greenBucket += (color >> 8) & 0xFF; // Color.greed + blueBucket += (color & 0xFF); // Color.blue + if (hasAlpha) alphaBucket += (color >>> 24); // Color.alpha + } + } + + return Color.argb( + (hasAlpha) ? (alphaBucket / pixelCount) : 255, + redBucket / pixelCount, + greenBucket / pixelCount, + blueBucket / pixelCount); + } + + private void setViewPagerScrollListener() { + ViewPager.OnPageChangeListener listener = new ViewPager.OnPageChangeListener() { + boolean firstImageProcessed = false; + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + if(position == 0 && !firstImageProcessed) { + viewPager.setBackgroundColor(getImageAverageColor(imagePagerAdapter.getBitmap(position))); + firstImageProcessed = true; + } + } + + @Override + public void onPageSelected(int position) { + if(firstImageProcessed) { + viewPager.setBackgroundColor(getImageAverageColor(imagePagerAdapter.getBitmap(position))); + } + } + + @Override + public void onPageScrollStateChanged(int state) { + // + } + }; + viewPager.setOnPageChangeListener(listener); + } + + public static boolean setListViewHeightBasedOnItems(ListView listView) { + + ListAdapter listAdapter = listView.getAdapter(); + if (listAdapter != null) { + + int numberOfItems = listAdapter.getCount(); + + // Get total height of all items. + int totalItemsHeight = 0; + for (int itemPos = 0; itemPos < numberOfItems; itemPos++) { + View item = listAdapter.getView(itemPos, null, listView); + item.measure(0, 0); + totalItemsHeight += item.getMeasuredHeight(); + } + + // Get total height of all item dividers. + int totalDividersHeight = listView.getDividerHeight() * + (numberOfItems - 1); + + // Set list height. + ViewGroup.LayoutParams params = listView.getLayoutParams(); + params.height = totalItemsHeight + totalDividersHeight; + listView.setLayoutParams(params); + listView.requestLayout(); + + return true; + + } else { + return false; + } + + } } diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index d7f98b3..b57713f 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -5,7 +5,9 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - @@ -27,7 +29,7 @@ - + --> + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml index a005d20..1e3a2a3 100644 --- a/app/src/main/res/values-v21/styles.xml +++ b/app/src/main/res/values-v21/styles.xml @@ -5,16 +5,13 @@ true @android:color/transparent - From e28c083396cd08bfc58de586a6b6499dba5fcf80 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Fri, 15 Feb 2019 20:28:01 +0400 Subject: [PATCH 13/14] [UI][DetailActivity] Fixed black arrow, now datasheet link is clickable (and displaying correctly) --- .../vrcatalog/view/DetailActivity.java | 2 +- app/src/main/res/layout/activity_detail.xml | 52 ++----------------- .../res/layout/properties_list_adapter.xml | 3 +- app/src/main/res/values-v21/styles.xml | 4 ++ 4 files changed, 10 insertions(+), 51 deletions(-) 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 992e744..14ea6db 100644 --- a/app/src/main/java/ru/volgorobot/vrcatalog/view/DetailActivity.java +++ b/app/src/main/java/ru/volgorobot/vrcatalog/view/DetailActivity.java @@ -91,7 +91,7 @@ public class DetailActivity extends AppCompatActivity implements MainContract.It hashMap.put("Аналоги", tmp); tmp = intent.getStringExtra("detailDatasheet"); - if(!tmp.matches("\\S")) { + if(!(tmp.trim().length() > 0)) { tmp = "Не указано"; } hashMap.put("Техническая спецификация", tmp); diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index b57713f..05af980 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -5,53 +5,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - - - - - - @@ -79,7 +32,8 @@ android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" - app:popupTheme="@style/AppTheme" /> + app:popupTheme="@style/ThemeOverlay.AppCompat.Light" + android:theme="@style/ItemActionBar"/> diff --git a/app/src/main/res/layout/properties_list_adapter.xml b/app/src/main/res/layout/properties_list_adapter.xml index c0bc04c..5a36547 100644 --- a/app/src/main/res/layout/properties_list_adapter.xml +++ b/app/src/main/res/layout/properties_list_adapter.xml @@ -17,5 +17,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Property Value" - android:layout_marginLeft="9dp"/> + android:layout_marginLeft="9dp" + android:autoLink="web"/> \ No newline at end of file diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml index 1e3a2a3..5aff55f 100644 --- a/app/src/main/res/values-v21/styles.xml +++ b/app/src/main/res/values-v21/styles.xml @@ -14,4 +14,8 @@ @android:color/transparent @android:color/transparent + From 804bd7d8926e7cd41922d2710d8ef5488bdeb113 Mon Sep 17 00:00:00 2001 From: ChronosX88 Date: Fri, 15 Feb 2019 20:34:17 +0400 Subject: [PATCH 14/14] Releasing v0.3 --- .idea/caches/gradle_models.ser | Bin 108688 -> 108688 bytes app/build.gradle | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.idea/caches/gradle_models.ser b/.idea/caches/gradle_models.ser index 66f54b50f3c8106e34b7058c3ecf723064d86caa..efedd0290c58e3f772bb57651dcc00cf0dc74488 100644 GIT binary patch delta 17411 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 diff --git a/app/build.gradle b/app/build.gradle index bb15bf1..aa59440 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,8 +6,8 @@ android { applicationId "ru.volgorobot.vrcatalog" minSdkVersion 19 targetSdkVersion 27 - versionCode 1 - versionName "1.0" + versionCode 4 + versionName "0.3" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } compileOptions {