From f3ca0e21e8813937df1b5a705166e5472d9d59e7 Mon Sep 17 00:00:00 2001 From: anurag Date: Thu, 22 Jul 2021 12:04:52 +0530 Subject: [PATCH 1/2] added the changes for improve load time. --- .../main/java/com/zype/fire/api/ZypeApi.java | 2 +- Application/app/version.properties | 4 +- .../contentbrowser/ContentBrowser.java | 5 + .../android/contentbrowser/ContentLoader.java | 83 ++++++++ .../datadownloader/ZypeDataDownloader.java | 111 +++++----- .../ZypeDataDownloaderHelper.java | 37 +++- .../ui/activities/ContentBrowseActivity.java | 146 +++++++------ .../ui/fragments/ContentBrowseFragment.java | 12 +- .../tv/tenfoot/utils/BrowseHelper.java | 51 +++-- .../layout/content_browse_activity_layout.xml | 195 +++++++++--------- 10 files changed, 408 insertions(+), 238 deletions(-) diff --git a/Application/ZypeAPI/src/main/java/com/zype/fire/api/ZypeApi.java b/Application/ZypeAPI/src/main/java/com/zype/fire/api/ZypeApi.java index 1fa45165..a5f0b579 100644 --- a/Application/ZypeAPI/src/main/java/com/zype/fire/api/ZypeApi.java +++ b/Application/ZypeAPI/src/main/java/com/zype/fire/api/ZypeApi.java @@ -67,7 +67,7 @@ public class ZypeApi { private static final String USERNAME = "username"; public static final String UUID = "uuid"; - public static final int PER_PAGE_DEFAULT = 20; + public static final int PER_PAGE_DEFAULT = 10; private static ZypeApi instance; private static Retrofit retrofit; diff --git a/Application/app/version.properties b/Application/app/version.properties index f1878c8a..e463ca3d 100644 --- a/Application/app/version.properties +++ b/Application/app/version.properties @@ -1,3 +1,3 @@ -#Sat Jun 26 10:24:21 IST 2021 -VERSION_CODE=1310 +#Wed Jul 21 10:48:53 IST 2021 +VERSION_CODE=1313 adb=u diff --git a/ContentBrowser/src/main/java/com/amazon/android/contentbrowser/ContentBrowser.java b/ContentBrowser/src/main/java/com/amazon/android/contentbrowser/ContentBrowser.java index 62c6ca3a..e7f76fb4 100644 --- a/ContentBrowser/src/main/java/com/amazon/android/contentbrowser/ContentBrowser.java +++ b/ContentBrowser/src/main/java/com/amazon/android/contentbrowser/ContentBrowser.java @@ -77,6 +77,7 @@ import java.util.Stack; import rx.Observable; +import rx.Single; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; @@ -2714,6 +2715,10 @@ public void actionTriggered(Activity activity, Content content, int actionId, } } + public Single> loadNextPlaylists(String lastPlayListId) { + return getContentLoader().loadNextPlaylists(lastPlayListId, ZypeConfiguration.getRootPlaylistId(mAppContext)); + } + /** * Toggles the watch list action button text. * diff --git a/ContentBrowser/src/main/java/com/amazon/android/contentbrowser/ContentLoader.java b/ContentBrowser/src/main/java/com/amazon/android/contentbrowser/ContentLoader.java index 95e294d5..84089cbe 100644 --- a/ContentBrowser/src/main/java/com/amazon/android/contentbrowser/ContentLoader.java +++ b/ContentBrowser/src/main/java/com/amazon/android/contentbrowser/ContentLoader.java @@ -56,17 +56,24 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.List; import okhttp3.ResponseBody; +import org.json.JSONArray; +import org.json.JSONObject; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import rx.Observable; +import rx.Single; +import rx.Single.OnSubscribe; +import rx.SingleSubscriber; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; +import rx.functions.FuncN; import rx.schedulers.Schedulers; import static com.amazon.android.contentbrowser.ContentBrowser.BROADCAST_DATA_LOADED; @@ -791,6 +798,82 @@ public Observable getVideosFeedObservable(Object contentContainerAsObject, } } + public Single> loadNextPlaylists(String lastPlayListId, String parentContainerId) { + return Single.create((OnSubscribe>) emitter -> { + List playlists = ZypeDataDownloaderHelper.loadPlaylists(); + //sort the play lists based on priority first + Collections.sort(playlists, (a, b) -> { + Integer valA; + Integer valB; + try { + valA = a.priority; + valB = b.priority; + } + catch (Exception e) { + return 0; + } + return valA.compareTo(valB); + }); + List> playListVideosLoader = new ArrayList<>(); + boolean found = false; + + for (PlaylistData playlistData : playlists) { + if (TextUtils.isEmpty(playlistData.description)) { + playlistData.description = " "; + } + // Skip playlist that are not direct child of the root playlist + if (TextUtils.isEmpty(playlistData.parentId) + || !playlistData.parentId.equals(ZypeConfiguration.getRootPlaylistId(mContext))) { + continue; + } + if (playlistData.playlistItemCount > 0 && found) { + playListVideosLoader.add(loadContainer(playlistData)); + } + if(!found) { + found = playlistData.id.equalsIgnoreCase(lastPlayListId); + } + } + + if(playListVideosLoader.isEmpty()) { + emitter.onSuccess(Collections.emptyList()); + return; + } + + Single.zip(playListVideosLoader, (FuncN>) args -> { + ArrayList containers = new ArrayList<>(); + if(args != null) { + for (Object arg : args) { + if (arg instanceof ContentContainer) { + containers.add((ContentContainer)arg); + } + } + } + return containers; + }).subscribeOn(Schedulers.io()).subscribe(emitter::onSuccess, emitter::onError); + }).subscribeOn(Schedulers.io()); + } + + private Single loadContainer(PlaylistData playlistData) { + return Single.create((OnSubscribe) emitter -> { + Recipe recipeDynamicParserContainer = Recipe.newInstance(mContext, "recipes/ZypeCategoriesRecipe.json"); + HashMap map = new HashMap(); + map.put("categories", Arrays.asList(playlistData)); + GsonBuilder builder = new GsonBuilder(); + Gson gson = builder.create(); + String feed = gson.toJson(map); + String[] params = new String[] { playlistData.parentId }; + + mDynamicParser.cookRecipeObservable(recipeDynamicParserContainer, feed,null, params).flatMap(o -> { + ContentContainer contentContainer = (ContentContainer)o; + return Observable.just(contentContainer); + }).observeOn(Schedulers.io()).subscribe(container-> { + loadContentForContentContainer(container, mContext, () -> { + emitter.onSuccess(container); + }); + }); + }).subscribeOn(Schedulers.io()); + } + public Observable loadPlayList(ContentContainer root, String playListId) { return Observable.just(playListId).subscribeOn(Schedulers.io()).observeOn(Schedulers.io()).flatMap(id -> { PlaylistData playlistData = ZypeDataDownloaderHelper.loadPlayList(playListId); diff --git a/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloader.java b/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloader.java index ef402741..1294d9e2 100644 --- a/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloader.java +++ b/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloader.java @@ -3,7 +3,7 @@ import android.content.Context; import android.text.TextUtils; import android.util.Log; - +import android.util.Pair; import com.amazon.android.recipe.Recipe; import com.amazon.android.utils.Preferences; import com.amazon.dataloader.R; @@ -29,6 +29,14 @@ import java.util.Collections; import java.util.List; +import rx.Observable; +import rx.Scheduler; +import rx.Single; +import rx.Single.OnSubscribe; +import rx.SingleSubscriber; +import rx.functions.FuncN; +import rx.schedulers.Schedulers; + /** * Created by Evgeny Cherkasov on 04.03.2017. */ @@ -43,6 +51,8 @@ public class ZypeDataDownloader extends ADataDownloader { private static final String PREFERENCE_TERMS = "ZypeTerms"; + private final Object syncObject = new Object(); + /** * {@link AUrlGenerator} instance. */ @@ -108,12 +118,13 @@ protected Data fetchData(Recipe dataLoadRecipe) throws Exception { Log.d(TAG, "fetchData(): Started"); AppData appData = loadAppConfiguration(); - Log.d(TAG, "fetchData(): App configuration loaded"); ZypeConfiguration.update(appData, mContext); + Log.d(TAG, "fetchData(): App configuration loaded"); loadZobjectContents(); + Log.d(TAG, "fetchData(): ZObjects loaded"); - List playlists = loadPlaylists(); + List playlists = ZypeDataDownloaderHelper.loadPlaylists(); Log.d(TAG, "fetchData(): Playlists loaded"); addFavoritesPlaylist(playlists); if (ZypeSettings.LIBRARY_ENABLED) { @@ -127,29 +138,7 @@ protected Data fetchData(Recipe dataLoadRecipe) throws Exception { GsonBuilder builder = new GsonBuilder(); Gson gson = builder.create(); - for (PlaylistData playlistData : playlists) { - if (TextUtils.isEmpty(playlistData.description)) { - playlistData.description = " "; - } - // Skip playlist that are not direct child of the root playlist - if (TextUtils.isEmpty(playlistData.parentId) - || !playlistData.parentId.equals(ZypeConfiguration.getRootPlaylistId(mContext))) { - continue; - } - - if (playlistData.playlistItemCount > 0) { - Log.d(TAG, "fetchData(): Loading videos for " + playlistData.title); - - VideosResponse videosResponse = ZypeDataDownloaderHelper.loadPlaylistVideos(playlistData.id, 1); - if (videosResponse != null) { - for (VideoData videoData : videosResponse.videoData) { - jsonContents.put(new JSONObject(gson.toJson(videoData))); - } - } - } - } - Log.d(TAG, "fetchData(): Videos loaded"); - + //sort the play lists based on priority first Collections.sort(playlists, (a, b) -> { Integer valA; Integer valB; @@ -163,14 +152,57 @@ protected Data fetchData(Recipe dataLoadRecipe) throws Exception { return valA.compareTo(valB); }); + Log.d(TAG, "testData(): Videos loaded Started"); + List>> playListVideosLoader = new ArrayList<>(); + for (PlaylistData playlistData : playlists) { - String playlistId = playlistData.id; - if (playlistId.equals(ZypeConfiguration.getRootPlaylistId(mContext)) - || TextUtils.isEmpty(playlistData.parentId)) { + if (TextUtils.isEmpty(playlistData.description)) { + playlistData.description = " "; + } + // Skip playlist that are not direct child of the root playlist + if (TextUtils.isEmpty(playlistData.parentId) + || !playlistData.parentId.equals(ZypeConfiguration.getRootPlaylistId(mContext))) { continue; } - jsonCategories.put(new JSONObject(gson.toJson(playlistData))); + if (playlistData.playlistItemCount > 0) { + jsonCategories.put(new JSONObject(gson.toJson(playlistData))); + playListVideosLoader.add(ZypeDataDownloaderHelper.loadPlayListVideos(playlistData)); + } + + if(playListVideosLoader.size() > 20) { + break; + } + } + Single.zip(playListVideosLoader, (FuncN>) args -> { + ArrayList videosResponses = new ArrayList<>(); + if(args != null) { + for (Object arg : args) { + if (arg instanceof Pair) { + VideosResponse videosResponse = (VideosResponse) ((Pair)arg).second; + for (VideoData videoData : videosResponse.videoData) { + try { + jsonContents.put(new JSONObject(gson.toJson(videoData))); + } catch (Exception ignored) { + } + } + videosResponses.add(videosResponse); + } + } + } + return videosResponses; + }).subscribeOn(Schedulers.io()).subscribe(videosResponses -> { + synchronized (syncObject) { + syncObject.notify(); + } + }, throwable -> { + synchronized (syncObject) { + syncObject.notify(); + } + }); + synchronized (syncObject) { + syncObject.wait(); } + Log.d(TAG, "testData(): Videos loaded"); JSONObject jsonResult = new JSONObject(); jsonResult.put("categories", jsonCategories); @@ -212,25 +244,6 @@ private void loadZobjectContents() { } } - private List loadPlaylists() { - List result = new ArrayList<>(); - - int page = 1; - PlaylistsResponse playlistsResponse = ZypeApi.getInstance().getPlaylists(page); - if (playlistsResponse != null && playlistsResponse.response != null) { - result.addAll(playlistsResponse.response); - if (playlistsResponse.pagination != null && playlistsResponse.pagination.pages > 1) { - for (page = playlistsResponse.pagination.next; page <= playlistsResponse.pagination.pages; page++) { - playlistsResponse = ZypeApi.getInstance().getPlaylists(page); - if (playlistsResponse != null && playlistsResponse.response != null) { - result.addAll(playlistsResponse.response); - } - } - } - } - return result; - } - private void addFavoritesPlaylist(List playlists) { PlaylistData item = new PlaylistData(); item.id = ZypeSettings.ROOT_FAVORITES_PLAYLIST_ID; diff --git a/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloaderHelper.java b/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloaderHelper.java index 371e91e1..0440357e 100644 --- a/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloaderHelper.java +++ b/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloaderHelper.java @@ -2,7 +2,7 @@ import android.text.TextUtils; import android.util.Log; - +import android.util.Pair; import com.amazon.android.recipe.Recipe; import com.zype.fire.api.Model.PlaylistData; import com.zype.fire.api.Model.PlaylistsResponse; @@ -18,6 +18,9 @@ import java.util.ArrayList; import java.util.List; +import rx.Single; +import rx.Single.OnSubscribe; +import rx.schedulers.Schedulers; /** * Created by Evgeny Cherkasov on 20.11.2017. @@ -97,7 +100,7 @@ public static VideosResult loadFavoriteVideos(String favoritesPlaylistId, String while (loadNext) { VideoFavoritesResponse response = ZypeApi.getInstance() - .getVideoFavorites(consumerId, accessToken, result.nextPage); + .getVideoFavorites(consumerId, accessToken, result.nextPage); if (response != null) { Log.d(TAG, "loadFavoriteVideos(): size=" + response.videoFavorites.size()); @@ -140,4 +143,34 @@ public static VideosResult loadFavoriteVideos(String favoritesPlaylistId, String return result; } + public static List loadPlaylists() { + List result = new ArrayList<>(); + + int page = 1; + PlaylistsResponse playlistsResponse = ZypeApi.getInstance().getPlaylists(page); + if (playlistsResponse != null && playlistsResponse.response != null) { + result.addAll(playlistsResponse.response); + if (playlistsResponse.pagination != null && playlistsResponse.pagination.pages > 1) { + for (page = playlistsResponse.pagination.next; page <= playlistsResponse.pagination.pages; page++) { + playlistsResponse = ZypeApi.getInstance().getPlaylists(page); + if (playlistsResponse != null && playlistsResponse.response != null) { + result.addAll(playlistsResponse.response); + } + } + } + } + return result; + } + + public static Single> loadPlayListVideos(PlaylistData playlistData) { + return Single.create((OnSubscribe>) emitter -> { + Log.d(TAG, "fetchData(): Loading videos for " + playlistData.title); + + VideosResponse videosResponse = loadPlaylistVideos(playlistData.id, 1); + if(videosResponse == null) { + videosResponse = new VideosResponse(); + } + emitter.onSuccess(Pair.create(playlistData, videosResponse)); + }).subscribeOn(Schedulers.io()); + } } diff --git a/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/ui/activities/ContentBrowseActivity.java b/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/ui/activities/ContentBrowseActivity.java index 6b966789..8cd7eb41 100644 --- a/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/ui/activities/ContentBrowseActivity.java +++ b/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/ui/activities/ContentBrowseActivity.java @@ -29,6 +29,8 @@ package com.amazon.android.tv.tenfoot.ui.activities; +import static com.amazon.android.recipe.Recipe.KEY_DATA_TYPE_TAG; + import com.amazon.android.configuration.ConfigurationManager; import com.amazon.android.contentbrowser.ContentBrowser; import com.amazon.android.model.Action; @@ -74,6 +76,7 @@ import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.ProgressBar; import android.widget.TextView; import java.util.ArrayList; @@ -84,14 +87,16 @@ import rx.Observable; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; +import rx.subscriptions.CompositeSubscription; +import rx.subscriptions.Subscriptions; import uk.co.chrisjenx.calligraphy.CalligraphyUtils; /** * ContentBrowseActivity class that loads the ContentBrowseFragment. */ public class ContentBrowseActivity extends BaseActivity implements - ContentBrowseFragment.OnBrowseRowListener, - MenuFragment.IMenuFragmentListener + ContentBrowseFragment.OnBrowseRowListener, + MenuFragment.IMenuFragmentListener // TopMenuFragment.ITopMenuListener { @@ -105,6 +110,7 @@ public class ContentBrowseActivity extends BaseActivity implements private TextView mContentDescription; private ImageView mContentImage; private Subscription mContentImageLoadSubscription; + private ProgressBar progressBar; // View that contains the background private View mMainFrame; @@ -121,6 +127,9 @@ public class ContentBrowseActivity extends BaseActivity implements private Row lastSelectedRow = null; private boolean lastSelectedRowChanged = false; private int lastSelectedItemIndex = -1; + private boolean allContentLoaded = false; + private String lastPlaylistId = ""; + private final CompositeSubscription compositeSubscription = new CompositeSubscription(); private final Handler handler = new Handler(); @@ -134,13 +143,14 @@ public void onCreate(Bundle savedInstanceState) { Helpers.handleActivityEnterFadeTransition(this, ACTIVITY_ENTER_TRANSITION_FADE_DURATION); mContentTitle = (TextView) findViewById(R.id.content_detail_title); + progressBar = (ProgressBar) findViewById(R.id.progressBarLoadMore); CalligraphyUtils.applyFontToTextView(this, mContentTitle, ConfigurationManager - .getInstance(this).getTypefacePath(ConfigurationConstants.BOLD_FONT)); + .getInstance(this).getTypefacePath(ConfigurationConstants.BOLD_FONT)); mContentDescription = (TextView) findViewById(R.id.content_detail_description); CalligraphyUtils.applyFontToTextView(this, mContentDescription, ConfigurationManager - .getInstance(this).getTypefacePath(ConfigurationConstants.LIGHT_FONT)); + .getInstance(this).getTypefacePath(ConfigurationConstants.LIGHT_FONT)); mContentImage = (ImageView) findViewById(R.id.content_image); mContentImage.setImageURI(Uri.EMPTY); @@ -199,7 +209,7 @@ public void run() { new Handler().postDelayed(new Runnable() { @Override public void run() { - findViewById(R.id.hero_slider_ly).setAlpha(1); + findViewById(R.id.hero_slider_ly).setAlpha(1); } },700); @@ -312,7 +322,7 @@ public boolean onKeyDown(int keyCode, KeyEvent event) { handler.postDelayed(() -> { if (sliderHasFocus()) { if (!sliderShown - || (event.getKeyCode() == KeyEvent.KEYCODE_BACK && sliderShown && isMenuOpened)) { + || (event.getKeyCode() == KeyEvent.KEYCODE_BACK && sliderShown && isMenuOpened)) { sliderShown = false; showHeroSlider(); } @@ -350,16 +360,6 @@ else if (!sliderShown && event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) { // } // }, 50); } - else if(!processed) { - if(event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) { - if (ZypeSettings.SHOW_TOP_MENU && isTopRowSelected()) { - if (!isMenuOpened) { - showTopMenu(); - return true; - } - } - } - } return processed; } @@ -371,9 +371,7 @@ else if(!processed) { */ @Override public void onItemSelected(Object item, Row row, boolean isLastContentRow) { - if (item != null) { - lastRowSelected = isLastContentRow; - } + lastRowSelected = isLastContentRow; if (row != lastSelectedRow && item != null) { lastSelectedRow = row; lastSelectedRowChanged = true; @@ -385,38 +383,41 @@ public void onItemSelected(Object item, Row row, boolean isLastContentRow) { if (item instanceof Content) { Content content = (Content) item; callImageLoadSubscription(content.getTitle(), - content.getDescription(), - content.getBackgroundImageUrl()); + content.getDescription(), + content.getBackgroundImageUrl()); + lastPlaylistId = content.getExtraValueAsString(Content.EXTRA_PLAYLIST_ID); } /* Zype, Evgeny Cherkasov */ // Update screen background with selected playlist (category) image + else if (item instanceof ContentContainer) { ContentContainer contentContainer = (ContentContainer) item; callImageLoadSubscription(contentContainer.getName(), - contentContainer.getExtraStringValue("description"), - contentContainer.getExtraStringValue(Content.BACKGROUND_IMAGE_URL_FIELD_NAME)); + contentContainer.getExtraStringValue("description"), + contentContainer.getExtraStringValue(Content.BACKGROUND_IMAGE_URL_FIELD_NAME)); + lastPlaylistId = contentContainer.getExtraStringValue(KEY_DATA_TYPE_TAG); } else if (item instanceof Action) { Action settingsAction = (Action) item; // Terms of use action. if (ContentBrowser.TERMS.equals(settingsAction.getAction())) { callImageLoadSubscription(getString(R.string.terms_title), - getString(R.string.terms_description), - null); + getString(R.string.terms_description), + null); } // Login and logout action. else if (ContentBrowser.LOGIN_LOGOUT.equals(settingsAction.getAction())) { if (settingsAction.getState() == LogoutSettingsFragment.TYPE_LOGOUT) { callImageLoadSubscription(getString(R.string.logout_label), - getString(R.string.logout_description), - null); + getString(R.string.logout_description), + null); } else { callImageLoadSubscription(getString(R.string.login_label), - getString(R.string.login_description), - null); + getString(R.string.login_description), + null); } } } @@ -434,16 +435,16 @@ else if (ContentBrowser.LOGIN_LOGOUT.equals(settingsAction.getAction())) { public void callImageLoadSubscription(String title, String description, String bgImageUrl) { mContentImageLoadSubscription = Observable - .timer(UI_UPDATE_DELAY_IN_MS, TimeUnit.MILLISECONDS) - .observeOn(AndroidSchedulers.mainThread()) // This is a must for timer. - .subscribe(c -> { - mContentTitle.setText(title); - mContentDescription.setText(description); - GlideHelper.loadImageWithCrossFadeTransition(this, - mContentImage, - bgImageUrl, - CONTENT_IMAGE_CROSS_FADE_DURATION, - R.color.browse_background_color); + .timer(UI_UPDATE_DELAY_IN_MS, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) // This is a must for timer. + .subscribe(c -> { + mContentTitle.setText(title); + mContentDescription.setText(description); + GlideHelper.loadImageWithCrossFadeTransition(this, + mContentImage, + bgImageUrl, + CONTENT_IMAGE_CROSS_FADE_DURATION, + R.color.browse_background_color); // // If there is no image, remove the preview window // if (bgImageUrl != null && !bgImageUrl.isEmpty()) { @@ -452,7 +453,7 @@ public void callImageLoadSubscription(String title, String description, String b // else { // mMainFrame.setBackgroundColor(Color.TRANSPARENT); // } - }); + }); } @@ -471,7 +472,7 @@ protected void onResume() { super.onResume(); if (ContentBrowser.getInstance(this).getAuthHelper() != null) { ContentBrowser.getInstance(this).getAuthHelper() - .loadPoweredByLogo(this, (ImageView) findViewById(R.id.mvpd_logo)); + .loadPoweredByLogo(this, (ImageView) findViewById(R.id.mvpd_logo)); } reportFullyDrawn(); @@ -492,8 +493,8 @@ private void showMenu() { int paddingTop = (int) getResources().getDimension(R.dimen.lb_browse_padding_top); fragment.getView().setPadding(0, paddingTop, 0, 0); getFragmentManager().beginTransaction() - .show(fragment) - .commit(); + .show(fragment) + .commit(); fragment.getView().requestFocus(); } } @@ -503,8 +504,8 @@ private void hideMenu() { if (fragment != null) { isMenuOpened = false; getFragmentManager().beginTransaction() - .hide(fragment) - .commit(); + .hide(fragment) + .commit(); } } @@ -565,7 +566,7 @@ public boolean dispatchKeyEvent(KeyEvent event) { hideMenu(); findViewById(R.id.full_content_browse_fragment).requestFocus(); Object item = ((ListRow) lastSelectedRow).getAdapter() - .get(lastSelectedItemIndex == -1 ? 0 : lastSelectedItemIndex); + .get(lastSelectedItemIndex == -1 ? 0 : lastSelectedItemIndex); onItemSelected(item, lastSelectedRow, lastRowSelected); return true; } @@ -573,7 +574,7 @@ public boolean dispatchKeyEvent(KeyEvent event) { hideTopMenu(); findViewById(R.id.full_content_browse_fragment).requestFocus(); Object item = ((ListRow) lastSelectedRow).getAdapter() - .get(lastSelectedItemIndex == -1 ? 0 : lastSelectedItemIndex); + .get(lastSelectedItemIndex == -1 ? 0 : lastSelectedItemIndex); onItemSelected(item, lastSelectedRow, lastRowSelected); return true; } @@ -613,13 +614,42 @@ else if (ZypeSettings.SHOW_TOP_MENU) { hideTopMenu(); return true; } - } else { - if (!ZypeSettings.SETTINGS_PLAYLIST_ENABLED) { - if (lastRowSelected && findViewById(R.id.full_content_browse_fragment).hasFocus()) { - return true; - } - } } + + if(!allContentLoaded && !compositeSubscription.hasSubscriptions() && lastRowSelected) { + progressBar.setVisibility(View.VISIBLE); + compositeSubscription.add(ContentBrowser.getInstance(this).loadNextPlaylists(lastPlaylistId) + .observeOn(AndroidSchedulers.mainThread()).subscribe(containers -> { + //add all the containers to the root containers + + List contentContainers = new ArrayList<>(); + + for(ContentContainer contentContainer : containers) { + if(contentContainer.getContentContainerCount()> 0 || contentContainer.getContentCount() > 0) { + contentContainers.add(contentContainer); + } + } + + BrowseHelper.addToRootContainers(this, contentContainers); + ContentBrowseFragment contentBrowseFragment = + (ContentBrowseFragment) getFragmentManager().findFragmentById(R.id.full_content_browse_fragment); + if(contentBrowseFragment != null) { + contentBrowseFragment.addContentContainers(contentContainers); + } + allContentLoaded = true; + lastRowSelected = contentContainers.isEmpty(); + progressBar.setVisibility(View.GONE); + compositeSubscription.clear(); + }, throwable -> { + progressBar.setVisibility(View.GONE); + compositeSubscription.clear(); + })); + } + + if (!ZypeSettings.SETTINGS_PLAYLIST_ENABLED) { + if (lastRowSelected && !isMenuOpened) return true; + } + // break; case KeyEvent.KEYCODE_DPAD_RIGHT: Log.d(TAG, "Right button pressed"); @@ -661,16 +691,11 @@ else if (lastSelectedItemIndex == -1 ){ return super.dispatchKeyEvent(event); } - private boolean isTopRowSelected() { - ContentBrowseFragment fragment = (ContentBrowseFragment) getFragmentManager().findFragmentById(R.id.full_content_browse_fragment); - return fragment.getRowSelectedIndex() == 0; - } - @Override public void onItemSelected(Action item) { hideMenu(); ContentBrowser.getInstance(this) - .settingsActionTriggered(this, item); + .settingsActionTriggered(this, item); } @Override @@ -687,9 +712,8 @@ private void showExitAlert() { builder.setCancelable(true); AlertDialog alertDialog = builder.create(); - Button noBtn= (Button) customLayout.findViewById(R.id.noBtn); - noBtn.requestFocus(); Button yesBtn= (Button) customLayout.findViewById(R.id.yesBtn); + yesBtn.setPressed(true); yesBtn.setOnClickListener(v -> { alertDialog.dismiss(); finish(); diff --git a/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/ui/fragments/ContentBrowseFragment.java b/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/ui/fragments/ContentBrowseFragment.java index 77185ce4..a5609a23 100644 --- a/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/ui/fragments/ContentBrowseFragment.java +++ b/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/ui/fragments/ContentBrowseFragment.java @@ -73,6 +73,8 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager; import android.util.Log; +import java.util.List; + import static androidx.leanback.widget.FocusHighlight.ZOOM_FACTOR_NONE; import static com.amazon.android.contentbrowser.ContentBrowser.BROADCAST_DATA_LOADED; import static com.zype.fire.api.ZypeSettings.SHOW_TITLE; @@ -134,7 +136,7 @@ public void onActivityCreated(Bundle savedInstanceState) { mLoginButtonIndex = BrowseHelper.getLoginButtonIndex(mSettingsAdapter); } else { - addStubRow(mRowsAdapter); + //addStubRow(mRowsAdapter); } setAdapter(mRowsAdapter); @@ -265,6 +267,12 @@ public void onContentUpdateEvent(ContentUpdateEvent event) { } } + public void addContentContainers(List contentContainers) { + int size = mRowsAdapter.size(); + BrowseHelper.addContentContainers(mRowsAdapter, contentContainers); + mRowsAdapter.notifyArrayItemRangeChanged(size, mRowsAdapter.size() - size); + } + private final class ItemViewClickedListener implements OnItemViewClickedListener { @Override @@ -386,7 +394,7 @@ public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item, boolean isLastContentRow = false; lastRowSelected = row; if (!ZypeSettings.SETTINGS_PLAYLIST_ENABLED) { - if (mRowsAdapter.indexOf(row) == mRowsAdapter.size() - 2) { + if (mRowsAdapter.indexOf(row) == mRowsAdapter.size() - 1) { isLastContentRow = true; } else { diff --git a/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/utils/BrowseHelper.java b/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/utils/BrowseHelper.java index b8a24777..7bcc4a9e 100644 --- a/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/utils/BrowseHelper.java +++ b/TVUIComponent/lib/src/main/java/com/amazon/android/tv/tenfoot/utils/BrowseHelper.java @@ -57,12 +57,12 @@ public static void saveBrowseActivityState(Activity activity) { // Update the last activity preference value if an activity restore is not currently in // progress. if (activity.getIntent() == null || - !activity.getIntent().getBooleanExtra(ContentBrowser.RESTORE_ACTIVITY, false)) { + !activity.getIntent().getBooleanExtra(ContentBrowser.RESTORE_ACTIVITY, false)) { Preferences.setString(PreferencesConstants.LAST_ACTIVITY, - ContentBrowser.CONTENT_HOME_SCREEN); + ContentBrowser.CONTENT_HOME_SCREEN); Preferences.setLong(PreferencesConstants.TIME_LAST_SAVED, - DateAndTimeHelper.getCurrentDate().getTime()); + DateAndTimeHelper.getCurrentDate().getTime()); } } @@ -90,7 +90,7 @@ public static ArrayObjectAdapter addSettingsActionsToRowAdapter(Activity activit } // Create settings header and row. HeaderItem header = new HeaderItem(0, activity.getResources() - .getString(R.string.settings_title)); + .getString(R.string.settings_title)); rowAdapter.add(new ListRow(header, settingsAdapter)); return settingsAdapter; @@ -114,28 +114,41 @@ public static int getLoginButtonIndex(ArrayObjectAdapter settingsAdapter) { return -1; } + public static void loadRootContentContainer(Activity activity, ArrayObjectAdapter rowsAdapter) { + ContentContainer rootContentContainer = ContentBrowser.getInstance(activity) + .getRootContentContainer(); + addContentContainers(rowsAdapter, rootContentContainer.getContentContainers()); + } + + public static void addToRootContainers(Activity activity, List contentContainers) { + ContentContainer rootContentContainer = ContentBrowser.getInstance(activity) + .getRootContentContainer(); + + for (ContentContainer contentContainer : contentContainers) { + rootContentContainer.addContentContainer(contentContainer); + } + } + /** * Loads the content from the root content container into the rows adapter. * * @param activity The activity. * @param rowsAdapter The rows adapter. */ - public static void loadRootContentContainer(Activity activity, ArrayObjectAdapter rowsAdapter) { - - ContentContainer rootContentContainer = ContentBrowser.getInstance(activity) - .getRootContentContainer(); + public static void addContentContainers(ArrayObjectAdapter rowsAdapter, + List contentContainers) { CardPresenter cardPresenter = new CardPresenter(); /* Zype, Evgeny Cherkasov */ PosterCardPresenter posterCardPresenter = new PosterCardPresenter(); - for (ContentContainer contentContainer : rootContentContainer.getContentContainers()) { + for (ContentContainer contentContainer : contentContainers) { /* Zype, Evgeny Cherkasob */ // Don't show My Library and Favorites content container if (contentContainer.getExtraStringValue(Recipe.KEY_DATA_TYPE_TAG).equals(ZypeSettings.ROOT_MY_LIBRARY_PLAYLIST_ID) - || contentContainer.getExtraStringValue(Recipe.KEY_DATA_TYPE_TAG).equals(ZypeSettings.ROOT_FAVORITES_PLAYLIST_ID) - || contentContainer.getExtraStringValue(Recipe.KEY_DATA_TYPE_TAG).equals(ZypeSettings.ROOT_SLIDERS_PLAYLIST_ID)) { + || contentContainer.getExtraStringValue(Recipe.KEY_DATA_TYPE_TAG).equals(ZypeSettings.ROOT_FAVORITES_PLAYLIST_ID) + || contentContainer.getExtraStringValue(Recipe.KEY_DATA_TYPE_TAG).equals(ZypeSettings.ROOT_SLIDERS_PLAYLIST_ID)) { continue; } @@ -165,7 +178,7 @@ public static void loadRootContentContainer(Activity activity, ArrayObjectAdapte for (Content content : contentContainer.getContents()) { if (contentContainer.getExtraValueAsInt(ExtraKeys.NEXT_PAGE) > 0 && - contentContainer.getContents().indexOf(content) == contentContainer.getContentCount() - 1){ + contentContainer.getContents().indexOf(content) == contentContainer.getContentCount() - 1){ content.setExtraValue(ContentBrowser.NEXT_PAGE, true); content.setExtraValue(Content.EXTRA_PLAYLIST_ID, contentContainer.getExtraStringValue(Recipe.KEY_DATA_TYPE_TAG)); } @@ -199,13 +212,13 @@ public static ListRow updateContinueWatchingRow(Activity activity, ListRow recen if (ContentBrowser.getInstance(activity).getContentLoader().isContentLoaded()) { List recentContent = ContentBrowser.getInstance(activity) - .getRecentContent(); + .getRecentContent(); int maxItems = ContentBrowser.getInstance(activity).getMaxNumberOfRecentItems(); return updateListRow(activity.getApplicationContext(), rowsAdapter, recentListRow, - recentContent, rowsAdapter.size() - 1, R.string.recent_row, - maxItems); + recentContent, rowsAdapter.size() - 1, R.string.recent_row, + maxItems); } return null; @@ -223,19 +236,19 @@ public static ListRow updateContinueWatchingRow(Activity activity, ListRow recen */ public static ListRow updateWatchlistRow(Activity activity, ListRow watchlistListRow, ListRow recentListRow, ArrayObjectAdapter - rowsAdapter) { + rowsAdapter) { if (ContentBrowser.getInstance(activity).getContentLoader().isContentLoaded()) { List watchlistItems = ContentBrowser.getInstance(activity) - .getWatchlistContent(); + .getWatchlistContent(); // This row should be inserted before the settings row and the recent row if present. int rowIndex = recentListRow == null ? rowsAdapter.size() - 1 : rowsAdapter.size() - 2; Log.d(TAG, "Inserting watchlist row at index " + rowIndex); return updateListRow(activity.getApplicationContext(), rowsAdapter, watchlistListRow, - watchlistItems, rowIndex, R.string.watchlist_row, - watchlistItems.size()); + watchlistItems, rowIndex, R.string.watchlist_row, + watchlistItems.size()); } return null; } diff --git a/TVUIComponent/lib/src/main/res/layout/content_browse_activity_layout.xml b/TVUIComponent/lib/src/main/res/layout/content_browse_activity_layout.xml index 64195368..c253f1f8 100644 --- a/TVUIComponent/lib/src/main/res/layout/content_browse_activity_layout.xml +++ b/TVUIComponent/lib/src/main/res/layout/content_browse_activity_layout.xml @@ -1,26 +1,20 @@ + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/browse_background_color" + > + android:layout_width="@dimen/content_image_width" + android:layout_height="@dimen/content_image_height" + android:layout_alignParentTop="true" + android:gravity="top" + android:layout_alignParentRight="true" + > + android:id="@+id/content_image" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:adjustViewBounds="true" + android:layout_gravity="top" + android:background="@color/accent" + android:scaleType="fitCenter" /> - - + android:id="@+id/main_frame" + android:layout_width="match_parent" + android:layout_height="match_parent"> - + android:id="@+id/hero_slider_ly" + android:layout_width="match_parent" + android:layout_height="280dp" + android:layout_alignParentTop="true" + android:alpha="0" > - + android:id="@+id/hero_slider_fragment" + android:name="com.amazon.android.tv.tenfoot.ui.sliders.HeroSliderFragment" + android:layout_width="match_parent" + android:layout_height="match_parent" /> - - - + android:id="@+id/main_logo" + android:layout_width="116dp" + android:layout_height="46dp" + android:layout_marginLeft="@dimen/lb_browse_padding_start" + android:layout_marginTop="@dimen/lb_browse_padding_top" + android:layout_marginBottom="24dp" + android:scaleType="centerInside" + android:src="@drawable/company_logo" /> - - + android:id="@+id/content_details" + android:layout_width="352dp" + android:layout_height="192dp" + android:layout_marginBottom="0dp" + android:layout_marginLeft="@dimen/lb_browse_padding_start" + android:layout_below="@id/main_logo" + android:orientation="vertical"> - - + android:id="@+id/content_detail_title" + style="@style/Widget.Leanback.DetailsDescriptionTitleStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="10dp" + android:ellipsize="end" + android:maxLines="2" + android:textSize="@dimen/lb_details_description_title_text_size" /> - + android:id="@+id/content_detail_description" + style="@style/Widget.Leanback.DetailsDescriptionBodyStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="5dp" + android:ellipsize="end" + android:maxLines="5" + android:textSize="@dimen/lb_details_description_body_text_size" /> - - + - + android:id="@+id/full_content_browse_fragment" + android:name="com.amazon.android.tv.tenfoot.ui.fragments.ContentBrowseFragment" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginTop="0dp" + android:layout_above="@id/progressBarLoadMore" + android:layout_below="@id/hero_slider_ly" + tools:layout="@layout/action_widget_container" /> + android:id="@+id/fragmentMenu" + android:name="com.amazon.android.tv.tenfoot.ui.fragments.MenuFragment" + android:layout_width="380dp" + android:layout_height="match_parent" + tools:layout="@layout/action_widget_container" /> + android:id="@+id/fragmentTopMenu" + android:name="com.amazon.android.tv.tenfoot.ui.menu.TopMenuFragment" + android:layout_width="match_parent" + android:layout_height="100dp" + tools:layout="@layout/action_widget_container" /> - - + \ No newline at end of file From 5517d0ee511b24ba69f873d7022a2cb522f3de27 Mon Sep 17 00:00:00 2001 From: anurag Date: Thu, 29 Jul 2021 10:11:19 +0530 Subject: [PATCH 2/2] added the playlist fixes. --- Application/app/version.properties | 4 ++-- .../datadownloader/ZypeDataDownloader.java | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Application/app/version.properties b/Application/app/version.properties index e463ca3d..2e674cf8 100644 --- a/Application/app/version.properties +++ b/Application/app/version.properties @@ -1,3 +1,3 @@ -#Wed Jul 21 10:48:53 IST 2021 -VERSION_CODE=1313 +#Thu Jul 29 10:07:50 IST 2021 +VERSION_CODE=1323 adb=u diff --git a/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloader.java b/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloader.java index 1294d9e2..60e167eb 100644 --- a/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloader.java +++ b/DataLoader/src/main/java/com/amazon/dataloader/datadownloader/ZypeDataDownloader.java @@ -165,7 +165,7 @@ protected Data fetchData(Recipe dataLoadRecipe) throws Exception { continue; } if (playlistData.playlistItemCount > 0) { - jsonCategories.put(new JSONObject(gson.toJson(playlistData))); + //jsonCategories.put(new JSONObject(gson.toJson(playlistData))); playListVideosLoader.add(ZypeDataDownloaderHelper.loadPlayListVideos(playlistData)); } @@ -202,6 +202,16 @@ protected Data fetchData(Recipe dataLoadRecipe) throws Exception { synchronized (syncObject) { syncObject.wait(); } + + for (PlaylistData playlistData : playlists) { + String playlistId = playlistData.id; + if (playlistId.equals(ZypeConfiguration.getRootPlaylistId(mContext)) + || TextUtils.isEmpty(playlistData.parentId)) { + continue; + } + jsonCategories.put(new JSONObject(gson.toJson(playlistData))); + } + Log.d(TAG, "testData(): Videos loaded"); JSONObject jsonResult = new JSONObject();