From 1bd50ef7651f8455e8703e2cd08bc4a315bed28b Mon Sep 17 00:00:00 2001 From: Docile-Alligator <25734209+Docile-Alligator@users.noreply.github.com> Date: Tue, 23 Apr 2024 22:38:12 -0400 Subject: Show online themes from local server. --- .../infinityforreddit/NetworkModule.java | 9 ++ .../activities/CustomThemeListingActivity.java | 3 + .../CustomThemeListingRecyclerViewAdapter.java | 2 +- ...nlineCustomThemeListingRecyclerViewAdapter.java | 121 +++++++++++++++++++++ .../adapters/PostRecyclerViewAdapter.java | 2 +- .../apis/OnlineCustomThemeAPI.java | 12 ++ .../customtheme/CustomThemeRepository.java | 37 ------- .../customtheme/CustomThemeViewModel.java | 56 +++++++--- .../customtheme/LocalCustomThemeRepository.java | 37 +++++++ .../customtheme/OnlineCustomThemeFilter.java | 4 + .../customtheme/OnlineCustomThemePagingSource.java | 86 +++++++++++++++ .../customtheme/OnlineCustomThemeRepository.java | 40 +++++++ .../fragments/CustomThemeListingFragment.java | 38 +++++-- .../infinityforreddit/utils/JSONUtils.java | 1 + 14 files changed, 388 insertions(+), 60 deletions(-) create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/adapters/OnlineCustomThemeListingRecyclerViewAdapter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/apis/OnlineCustomThemeAPI.java delete mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/CustomThemeRepository.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/LocalCustomThemeRepository.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemeFilter.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemePagingSource.java create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemeRepository.java (limited to 'app/src/main/java/ml') diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkModule.java b/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkModule.java index 2c231682..7bbc2443 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkModule.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/NetworkModule.java @@ -191,6 +191,15 @@ abstract class NetworkModule { .build(); } + @Provides + @Named("online_custom_themes") + @Singleton + static Retrofit provideOnlineCustomThemesRetrofit(@Named("base") Retrofit retrofit) { + return retrofit.newBuilder() + .baseUrl(APIUtils.ONLINE_CUSTOM_THEMES_API_BASE_URI) + .build(); + } + @Provides @Singleton static StreamableAPI provideStreamableApi(@Named("streamable") Retrofit streamableRetrofit) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomThemeListingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomThemeListingActivity.java index f2421ac6..9ddbeffb 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomThemeListingActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomThemeListingActivity.java @@ -366,6 +366,9 @@ public class CustomThemeListingActivity extends BaseActivity implements return fragment; } CustomThemeListingFragment fragment = new CustomThemeListingFragment(); + Bundle bundle = new Bundle(); + bundle.putBoolean(CustomThemeListingFragment.EXTRA_IS_ONLINE, true); + fragment.setArguments(bundle); return fragment; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CustomThemeListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CustomThemeListingRecyclerViewAdapter.java index e0f460a3..cee53dd6 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CustomThemeListingRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/CustomThemeListingRecyclerViewAdapter.java @@ -74,7 +74,7 @@ public class CustomThemeListingRecyclerViewAdapter extends RecyclerView.Adapter< CustomTheme customTheme = predefinedCustomThemes.get(position - 1); ((PredefinedCustomThemeViewHolder) holder).colorPrimaryView.setBackgroundTintList(ColorStateList.valueOf(customTheme.colorPrimary)); ((PredefinedCustomThemeViewHolder) holder).nameTextView.setText(customTheme.name); - ((PredefinedCustomThemeViewHolder) holder).itemView.setOnClickListener(view -> { + holder.itemView.setOnClickListener(view -> { Intent intent = new Intent(activity, CustomizeThemeActivity.class); intent.putExtra(CustomizeThemeActivity.EXTRA_THEME_NAME, customTheme.name); intent.putExtra(CustomizeThemeActivity.EXTRA_IS_PREDEFIINED_THEME, true); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/OnlineCustomThemeListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/OnlineCustomThemeListingRecyclerViewAdapter.java new file mode 100644 index 00000000..038d26ca --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/OnlineCustomThemeListingRecyclerViewAdapter.java @@ -0,0 +1,121 @@ +package ml.docilealligator.infinityforreddit.adapters; + +import android.content.Intent; +import android.content.res.ColorStateList; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.paging.PagingDataAdapter; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.RecyclerView; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.activities.BaseActivity; +import ml.docilealligator.infinityforreddit.activities.CustomThemeListingActivity; +import ml.docilealligator.infinityforreddit.activities.CustomizeThemeActivity; +import ml.docilealligator.infinityforreddit.bottomsheetfragments.CustomThemeOptionsBottomSheetFragment; +import ml.docilealligator.infinityforreddit.customtheme.CustomTheme; + +public class OnlineCustomThemeListingRecyclerViewAdapter extends PagingDataAdapter { + private static final int VIEW_TYPE_USER_THEME = 1; + private static final int VIEW_TYPE_USER_THEME_DIVIDER = 2; + + private final BaseActivity activity; + + public OnlineCustomThemeListingRecyclerViewAdapter(BaseActivity activity) { + super(new DiffUtil.ItemCallback<>() { + @Override + public boolean areItemsTheSame(@NonNull CustomTheme oldItem, @NonNull CustomTheme newItem) { + return oldItem.name.equals(newItem.name); + } + + @Override + public boolean areContentsTheSame(@NonNull CustomTheme oldItem, @NonNull CustomTheme newItem) { + return false; + } + }); + this.activity = activity; + } + + @Override + public int getItemViewType(int position) { + return VIEW_TYPE_USER_THEME; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + switch (viewType) { + case VIEW_TYPE_USER_THEME_DIVIDER: + return new OnlineCustomThemeDividerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_theme_type_divider, parent, false)); + default: + return new OnlineCustomThemeViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_user_custom_theme, parent, false)); + } + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (holder instanceof OnlineCustomThemeViewHolder) { + CustomTheme customTheme = getItem(position); + ((OnlineCustomThemeViewHolder) holder).colorPrimaryView.setBackgroundTintList(ColorStateList.valueOf(customTheme.colorPrimary)); + ((OnlineCustomThemeViewHolder) holder).nameTextView.setText(customTheme.name); + ((OnlineCustomThemeViewHolder) holder).createThemeImageView.setOnClickListener(view -> { + Intent intent = new Intent(activity, CustomizeThemeActivity.class); + intent.putExtra(CustomizeThemeActivity.EXTRA_THEME_NAME, customTheme.name); + intent.putExtra(CustomizeThemeActivity.EXTRA_CREATE_THEME, true); + activity.startActivity(intent); + }); + ((OnlineCustomThemeViewHolder) holder).shareImageView.setOnClickListener(view -> { + ((CustomThemeListingActivity) activity).shareTheme(customTheme); + }); + holder.itemView.setOnClickListener(view -> { + CustomThemeOptionsBottomSheetFragment customThemeOptionsBottomSheetFragment = new CustomThemeOptionsBottomSheetFragment(); + Bundle bundle = new Bundle(); + bundle.putString(CustomThemeOptionsBottomSheetFragment.EXTRA_THEME_NAME, customTheme.name); + customThemeOptionsBottomSheetFragment.setArguments(bundle); + customThemeOptionsBottomSheetFragment.show(activity.getSupportFragmentManager(), customThemeOptionsBottomSheetFragment.getTag()); + }); + holder.itemView.setOnLongClickListener(view -> { + holder.itemView.performClick(); + return true; + }); + } + } + + class OnlineCustomThemeViewHolder extends RecyclerView.ViewHolder { + + @BindView(R.id.color_primary_item_user_custom_theme) + View colorPrimaryView; + @BindView(R.id.name_text_view_item_user_custom_theme) + TextView nameTextView; + @BindView(R.id.add_image_view_item_user_custom_theme) + ImageView createThemeImageView; + @BindView(R.id.share_image_view_item_user_custom_theme) + ImageView shareImageView; + + OnlineCustomThemeViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + if (activity.typeface != null) { + nameTextView.setTypeface(activity.typeface); + } + } + } + + class OnlineCustomThemeDividerViewHolder extends RecyclerView.ViewHolder { + + OnlineCustomThemeDividerViewHolder(@NonNull View itemView) { + super(itemView); + if (activity.typeface != null) { + ((TextView) itemView).setTypeface(activity.typeface); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostRecyclerViewAdapter.java index 14859bba..40b263da 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/PostRecyclerViewAdapter.java @@ -147,7 +147,7 @@ public class PostRecyclerViewAdapter extends PagingDataAdapter DIFF_CALLBACK = new DiffUtil.ItemCallback() { + private static final DiffUtil.ItemCallback DIFF_CALLBACK = new DiffUtil.ItemCallback<>() { @Override public boolean areItemsTheSame(@NonNull Post post, @NonNull Post t1) { return post.getId().equals(t1.getId()); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/apis/OnlineCustomThemeAPI.java b/app/src/main/java/ml/docilealligator/infinityforreddit/apis/OnlineCustomThemeAPI.java new file mode 100644 index 00000000..de2e46e2 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/apis/OnlineCustomThemeAPI.java @@ -0,0 +1,12 @@ +package ml.docilealligator.infinityforreddit.apis; + +import com.google.common.util.concurrent.ListenableFuture; + +import retrofit2.Response; +import retrofit2.http.GET; +import retrofit2.http.Query; + +public interface OnlineCustomThemeAPI { + @GET("/themes/") + ListenableFuture> getCustomThemesListenableFuture(@Query("page") String page); +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/CustomThemeRepository.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/CustomThemeRepository.java deleted file mode 100644 index 9cee3de9..00000000 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/CustomThemeRepository.java +++ /dev/null @@ -1,37 +0,0 @@ -package ml.docilealligator.infinityforreddit.customtheme; - -import androidx.lifecycle.LiveData; - -import java.util.List; - -import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; - -public class CustomThemeRepository { - private final LiveData> mAllCustomThemes; - private final LiveData mCurrentLightCustomTheme; - private final LiveData mCurrentDarkCustomTheme; - private final LiveData mCurrentAmoledCustomTheme; - - CustomThemeRepository(RedditDataRoomDatabase redditDataRoomDatabase) { - mAllCustomThemes = redditDataRoomDatabase.customThemeDao().getAllCustomThemes(); - mCurrentLightCustomTheme = redditDataRoomDatabase.customThemeDao().getLightCustomThemeLiveData(); - mCurrentDarkCustomTheme = redditDataRoomDatabase.customThemeDao().getDarkCustomThemeLiveData(); - mCurrentAmoledCustomTheme = redditDataRoomDatabase.customThemeDao().getAmoledCustomThemeLiveData(); - } - - LiveData> getAllCustomThemes() { - return mAllCustomThemes; - } - - LiveData getCurrentLightCustomTheme() { - return mCurrentLightCustomTheme; - } - - LiveData getCurrentDarkCustomTheme() { - return mCurrentDarkCustomTheme; - } - - LiveData getCurrentAmoledCustomTheme() { - return mCurrentAmoledCustomTheme; - } -} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/CustomThemeViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/CustomThemeViewModel.java index c8a6f930..b953cee2 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/CustomThemeViewModel.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/CustomThemeViewModel.java @@ -1,55 +1,83 @@ package ml.docilealligator.infinityforreddit.customtheme; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.lifecycle.LiveData; import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelKt; import androidx.lifecycle.ViewModelProvider; +import androidx.paging.PagingData; import java.util.List; +import java.util.concurrent.Executor; import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import retrofit2.Retrofit; public class CustomThemeViewModel extends ViewModel { - private final LiveData> mAllCustomThemes; - private final LiveData mCurrentLightTheme; - private final LiveData mCurrentDarkTheme; - private final LiveData mCurrentAmoledTheme; + @Nullable + private LocalCustomThemeRepository localCustomThemeRepository; + @Nullable + private OnlineCustomThemeRepository onlineCustomThemeRepository; public CustomThemeViewModel(RedditDataRoomDatabase redditDataRoomDatabase) { - CustomThemeRepository customThemeRepository = new CustomThemeRepository(redditDataRoomDatabase); - mAllCustomThemes = customThemeRepository.getAllCustomThemes(); - mCurrentLightTheme = customThemeRepository.getCurrentLightCustomTheme(); - mCurrentDarkTheme = customThemeRepository.getCurrentDarkCustomTheme(); - mCurrentAmoledTheme = customThemeRepository.getCurrentAmoledCustomTheme(); + localCustomThemeRepository = new LocalCustomThemeRepository(redditDataRoomDatabase); } + public CustomThemeViewModel(Executor executor, Retrofit retrofit, + RedditDataRoomDatabase redditDataRoomDatabase) { + onlineCustomThemeRepository = new OnlineCustomThemeRepository(executor, retrofit, redditDataRoomDatabase, + ViewModelKt.getViewModelScope(this)); + } + + @Nullable public LiveData> getAllCustomThemes() { - return mAllCustomThemes; + return localCustomThemeRepository.getAllCustomThemes(); } public LiveData getCurrentLightThemeLiveData() { - return mCurrentLightTheme; + return localCustomThemeRepository.getCurrentLightCustomTheme(); } public LiveData getCurrentDarkThemeLiveData() { - return mCurrentDarkTheme; + return localCustomThemeRepository.getCurrentDarkCustomTheme(); } + @Nullable public LiveData getCurrentAmoledThemeLiveData() { - return mCurrentAmoledTheme; + return localCustomThemeRepository.getCurrentAmoledCustomTheme(); + } + + public LiveData> getOnlineCustomThemes() { + return onlineCustomThemeRepository.getOnlineCustomThemes(); } public static class Factory extends ViewModelProvider.NewInstanceFactory { + private Executor executor; + private Retrofit retrofit; private final RedditDataRoomDatabase mRedditDataRoomDatabase; + private final boolean isOnline; public Factory(RedditDataRoomDatabase redditDataRoomDatabase) { mRedditDataRoomDatabase = redditDataRoomDatabase; + isOnline = false; + } + + public Factory(Executor executor, Retrofit retrofit, RedditDataRoomDatabase redditDataRoomDatabase) { + this.executor = executor; + this.retrofit = retrofit; + mRedditDataRoomDatabase = redditDataRoomDatabase; + isOnline = true; } @NonNull @Override public T create(@NonNull Class modelClass) { - return (T) new CustomThemeViewModel(mRedditDataRoomDatabase); + if (isOnline) { + return (T) new CustomThemeViewModel(executor, retrofit, mRedditDataRoomDatabase); + } else { + return (T) new CustomThemeViewModel(mRedditDataRoomDatabase); + } } } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/LocalCustomThemeRepository.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/LocalCustomThemeRepository.java new file mode 100644 index 00000000..3a610ec9 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/LocalCustomThemeRepository.java @@ -0,0 +1,37 @@ +package ml.docilealligator.infinityforreddit.customtheme; + +import androidx.lifecycle.LiveData; + +import java.util.List; + +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; + +public class LocalCustomThemeRepository { + private final LiveData> mAllCustomThemes; + private final LiveData mCurrentLightCustomTheme; + private final LiveData mCurrentDarkCustomTheme; + private final LiveData mCurrentAmoledCustomTheme; + + LocalCustomThemeRepository(RedditDataRoomDatabase redditDataRoomDatabase) { + mAllCustomThemes = redditDataRoomDatabase.customThemeDao().getAllCustomThemes(); + mCurrentLightCustomTheme = redditDataRoomDatabase.customThemeDao().getLightCustomThemeLiveData(); + mCurrentDarkCustomTheme = redditDataRoomDatabase.customThemeDao().getDarkCustomThemeLiveData(); + mCurrentAmoledCustomTheme = redditDataRoomDatabase.customThemeDao().getAmoledCustomThemeLiveData(); + } + + LiveData> getAllCustomThemes() { + return mAllCustomThemes; + } + + LiveData getCurrentLightCustomTheme() { + return mCurrentLightCustomTheme; + } + + LiveData getCurrentDarkCustomTheme() { + return mCurrentDarkCustomTheme; + } + + LiveData getCurrentAmoledCustomTheme() { + return mCurrentAmoledCustomTheme; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemeFilter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemeFilter.java new file mode 100644 index 00000000..f44aaf6d --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemeFilter.java @@ -0,0 +1,4 @@ +package ml.docilealligator.infinityforreddit.customtheme; + +public class OnlineCustomThemeFilter { +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemePagingSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemePagingSource.java new file mode 100644 index 00000000..5bcfd175 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemePagingSource.java @@ -0,0 +1,86 @@ +package ml.docilealligator.infinityforreddit.customtheme; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.paging.ListenableFuturePagingSource; +import androidx.paging.PagingState; + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executor; + +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.apis.OnlineCustomThemeAPI; +import ml.docilealligator.infinityforreddit.utils.JSONUtils; +import retrofit2.HttpException; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class OnlineCustomThemePagingSource extends ListenableFuturePagingSource { + private final Executor executor; + private final OnlineCustomThemeAPI api; + private final RedditDataRoomDatabase redditDataRoomDatabase; + + public OnlineCustomThemePagingSource(Executor executor, Retrofit onlineCustomThemesRetrofit, RedditDataRoomDatabase redditDataRoomDatabase) { + this.executor = executor; + this.redditDataRoomDatabase = redditDataRoomDatabase; + api = onlineCustomThemesRetrofit.create(OnlineCustomThemeAPI.class); + } + + @Nullable + @Override + public String getRefreshKey(@NonNull PagingState pagingState) { + return null; + } + + @NonNull + @Override + public ListenableFuture> loadFuture(@NonNull LoadParams loadParams) { + ListenableFuture> customThemes; + customThemes = api.getCustomThemesListenableFuture(loadParams.getKey()); + + ListenableFuture> pageFuture = Futures.transform(customThemes, this::transformData, executor); + + ListenableFuture> partialLoadResultFuture = + Futures.catching(pageFuture, HttpException.class, + LoadResult.Error::new, executor); + + return Futures.catching(partialLoadResultFuture, + IOException.class, LoadResult.Error::new, executor); + } + + public LoadResult transformData(Response response) { + if (response.isSuccessful()) { + List themes = new ArrayList<>(); + try { + String responseString = response.body(); + JSONObject data = new JSONObject(responseString); + int page = data.getInt(JSONUtils.PAGE_KEY); + JSONArray themesArray = data.getJSONArray(JSONUtils.DATA_KEY); + for (int i = 0; i < themesArray.length(); i++) { + try { + themes.add(CustomTheme.fromJson(themesArray.getJSONObject(i).getString(JSONUtils.DATA_KEY))); + } catch (JSONException ignore) {} + } + + if (themes.isEmpty()) { + return new LoadResult.Page<>(themes, null, null); + } else { + return new LoadResult.Page<>(themes, null, Integer.toString(page + 1)); + } + } catch (JSONException e) { + return new LoadResult.Error<>(new Exception("Response failed")); + } + } else { + return new LoadResult.Error<>(new Exception("Response failed")); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemeRepository.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemeRepository.java new file mode 100644 index 00000000..7a978e7a --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customtheme/OnlineCustomThemeRepository.java @@ -0,0 +1,40 @@ +package ml.docilealligator.infinityforreddit.customtheme; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Transformations; +import androidx.paging.Pager; +import androidx.paging.PagingConfig; +import androidx.paging.PagingData; +import androidx.paging.PagingLiveData; + +import java.util.concurrent.Executor; + +import kotlinx.coroutines.CoroutineScope; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import retrofit2.Retrofit; + +public class OnlineCustomThemeRepository { + private final LiveData> customThemes; + private MutableLiveData onlineCustomThemeFilterMutableLiveData; + + public OnlineCustomThemeRepository(Executor executor, Retrofit retrofit, + RedditDataRoomDatabase redditDataRoomDatabase, CoroutineScope viewModelScope) { + onlineCustomThemeFilterMutableLiveData = new MutableLiveData<>(new OnlineCustomThemeFilter()); + + Pager pager = new Pager<>(new PagingConfig(25, 4, false, 10), + () -> new OnlineCustomThemePagingSource(executor, retrofit, redditDataRoomDatabase)); + + customThemes = PagingLiveData.cachedIn(Transformations.switchMap(onlineCustomThemeFilterMutableLiveData, + customThemeFilter -> PagingLiveData.getLiveData(pager)), viewModelScope); + } + + public LiveData> getOnlineCustomThemes() { + return customThemes; + } + + public void changeOnlineCustomThemeFilter(OnlineCustomThemeFilter onlineCustomThemeFilter) { + onlineCustomThemeFilterMutableLiveData.postValue(onlineCustomThemeFilter); + } + +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/CustomThemeListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/CustomThemeListingFragment.java index c10bee15..ddb3d11d 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/CustomThemeListingFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/fragments/CustomThemeListingFragment.java @@ -22,12 +22,19 @@ import ml.docilealligator.infinityforreddit.RecyclerViewContentScrollingInterfac import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; import ml.docilealligator.infinityforreddit.activities.BaseActivity; import ml.docilealligator.infinityforreddit.adapters.CustomThemeListingRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.adapters.OnlineCustomThemeListingRecyclerViewAdapter; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeViewModel; import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper; import ml.docilealligator.infinityforreddit.databinding.FragmentCustomThemeListingBinding; +import retrofit2.Retrofit; public class CustomThemeListingFragment extends Fragment { + public static final String EXTRA_IS_ONLINE = "EIO"; + + @Inject + @Named("online_custom_themes") + Retrofit onlineCustomThemesRetrofit; @Inject @Named("default") SharedPreferences sharedPreferences; @@ -52,6 +59,7 @@ public class CustomThemeListingFragment extends Fragment { public CustomThemeViewModel customThemeViewModel; private BaseActivity activity; private FragmentCustomThemeListingBinding binding; + private boolean isOnline; public CustomThemeListingFragment() { // Required empty public constructor @@ -65,9 +73,10 @@ public class CustomThemeListingFragment extends Fragment { // Inflate the layout for this fragment binding = FragmentCustomThemeListingBinding.inflate(inflater, container, false); - CustomThemeListingRecyclerViewAdapter adapter = new CustomThemeListingRecyclerViewAdapter(activity, - CustomThemeWrapper.getPredefinedThemes(activity)); - binding.recyclerViewCustomizeThemeListingActivity.setAdapter(adapter); + if (getArguments() != null) { + isOnline = getArguments().getBoolean(EXTRA_IS_ONLINE); + } + binding.recyclerViewCustomizeThemeListingActivity.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { @@ -79,10 +88,25 @@ public class CustomThemeListingFragment extends Fragment { } }); - customThemeViewModel = new ViewModelProvider(this, - new CustomThemeViewModel.Factory(redditDataRoomDatabase)) - .get(CustomThemeViewModel.class); - customThemeViewModel.getAllCustomThemes().observe(getViewLifecycleOwner(), adapter::setUserThemes); + if (isOnline) { + OnlineCustomThemeListingRecyclerViewAdapter adapter = new OnlineCustomThemeListingRecyclerViewAdapter(activity); + binding.recyclerViewCustomizeThemeListingActivity.setAdapter(adapter); + + customThemeViewModel = new ViewModelProvider(this, + new CustomThemeViewModel.Factory(executor, onlineCustomThemesRetrofit, redditDataRoomDatabase)) + .get(CustomThemeViewModel.class); + customThemeViewModel.getOnlineCustomThemes().observe(getViewLifecycleOwner(), + customThemePagingData -> adapter.submitData(getViewLifecycleOwner().getLifecycle(), customThemePagingData)); + } else { + CustomThemeListingRecyclerViewAdapter adapter = new CustomThemeListingRecyclerViewAdapter(activity, + CustomThemeWrapper.getPredefinedThemes(activity)); + binding.recyclerViewCustomizeThemeListingActivity.setAdapter(adapter); + + customThemeViewModel = new ViewModelProvider(this, + new CustomThemeViewModel.Factory(redditDataRoomDatabase)) + .get(CustomThemeViewModel.class); + customThemeViewModel.getAllCustomThemes().observe(getViewLifecycleOwner(), adapter::setUserThemes); + } return binding.getRoot(); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/JSONUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/JSONUtils.java index 800e6d45..32b8a245 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/utils/JSONUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/utils/JSONUtils.java @@ -195,6 +195,7 @@ public class JSONUtils { public static final String SUGGESTED_SORT_KEY = "suggested_sort"; public static final String P_KEY = "p"; public static final String VARIANTS_KEY = "variants"; + public static final String PAGE_KEY = "page"; @Nullable public static Map parseMediaMetadata(JSONObject data) { -- cgit v1.2.3