diff options
23 files changed, 1300 insertions, 14 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0104eb95..90dfd84b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -21,7 +21,10 @@ android:theme="@style/AppTheme" android:usesCleartextTraffic="true" tools:replace="android:label"> - + <activity android:name=".Activity.MultiRedditListingActivity" + android:label="@string/multi_reddit_listing_activity" + android:parentActivityName=".Activity.MainActivity" + android:theme="@style/AppTheme.NoActionBar" /> <activity android:name=".Activity.ViewGIFActivity" android:parentActivityName=".Activity.MainActivity" diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java index 136f697c..11e1480f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MainActivity.java @@ -808,8 +808,10 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.action_subscriptions_main_activity: - Intent subscriptionsIntent = new Intent(this, SubscribedThingListingActivity.class); - startActivity(subscriptionsIntent); + /*Intent subscriptionsIntent = new Intent(this, SubscribedThingListingActivity.class); + startActivity(subscriptionsIntent);*/ + Intent multiIntent = new Intent(this, MultiRedditListingActivity.class); + startActivity(multiIntent); return true; case R.id.action_sort_main_activity: if (viewPager.getCurrentItem() == 1 || viewPager.getCurrentItem() == 2) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MultiRedditListingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MultiRedditListingActivity.java new file mode 100644 index 00000000..63aaffdb --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/MultiRedditListingActivity.java @@ -0,0 +1,241 @@ +package ml.docilealligator.infinityforreddit.Activity; + +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.appcompat.widget.Toolbar; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.google.android.material.appbar.AppBarLayout; + +import java.util.ArrayList; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import ml.docilealligator.infinityforreddit.Adapter.MultiRedditListingRecyclerViewAdapter; +import ml.docilealligator.infinityforreddit.AppBarStateChangeListener; +import ml.docilealligator.infinityforreddit.AsyncTask.GetCurrentAccountAsyncTask; +import ml.docilealligator.infinityforreddit.AsyncTask.InsertMultiRedditAsyncTask; +import ml.docilealligator.infinityforreddit.Infinity; +import ml.docilealligator.infinityforreddit.MultiReddit.GetMultiReddit; +import ml.docilealligator.infinityforreddit.MultiReddit.MultiReddit; +import ml.docilealligator.infinityforreddit.MultiReddit.MultiRedditViewModel; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils; +import retrofit2.Retrofit; + +public class MultiRedditListingActivity extends BaseActivity { + + private static final String INSERT_MULTI_REDDIT_STATE = "ISSS"; + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; + private static final String ACCOUNT_NAME_STATE = "ANS"; + + @BindView(R.id.appbar_layout_multi_reddit_listing_activity) + AppBarLayout mAppBarLayout; + @BindView(R.id.toolbar_multi_reddit_listing_activity) + Toolbar mToolbar; + @BindView(R.id.recycler_view_multi_reddit_listing_activity) + RecyclerView mRecyclerView; + @BindView(R.id.fetch_multi_reddit_listing_info_linear_layout_multi_reddit_listing_activity) + LinearLayout mErrorLinearLayout; + @BindView(R.id.fetch_multi_reddit_listing_info_image_view_multi_reddit_listing_activity) + ImageView mErrorImageView; + @BindView(R.id.fetch_multi_reddit_listing_info_text_view_multi_reddit_listing_activity) + TextView mErrorTextView; + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + @Inject + SharedPreferences mSharedPreferences; + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + MultiRedditViewModel mMultiRedditViewModel; + private RequestManager mGlide; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private boolean mInsertSuccess = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + ((Infinity) getApplication()).getAppComponent().inject(this); + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_multi_reddit_listing); + + ButterKnife.bind(this); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + Resources resources = getResources(); + + if ((resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT || resources.getBoolean(R.bool.isTablet)) + && mSharedPreferences.getBoolean(SharedPreferencesUtils.IMMERSIVE_INTERFACE_KEY, true)) { + Window window = getWindow(); + window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + + boolean lightNavBar = false; + if ((resources.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) != Configuration.UI_MODE_NIGHT_YES) { + lightNavBar = true; + } + boolean finalLightNavBar = lightNavBar; + + View decorView = window.getDecorView(); + if (finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + mAppBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + public void onStateChanged(AppBarLayout appBarLayout, AppBarStateChangeListener.State state) { + if (state == State.COLLAPSED) { + if (finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } else if (state == State.EXPANDED) { + if (finalLightNavBar) { + decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR); + } + } + } + }); + + int statusBarResourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (statusBarResourceId > 0) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mToolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + mToolbar.setLayoutParams(params); + } + + int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); + if (navBarResourceId > 0) { + mRecyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId)); + } + } + } + + setSupportActionBar(mToolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + if (savedInstanceState != null) { + mInsertSuccess = savedInstanceState.getBoolean(INSERT_MULTI_REDDIT_STATE); + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + if (!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndBindView(); + } else { + bindView(); + } + } else { + getCurrentAccountAndBindView(); + } + } + + private void getCurrentAccountAndBindView() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if (account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + bindView(); + }).execute(); + } + + private void bindView() { + loadMultiReddits(); + + mGlide = Glide.with(this); + + mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); + MultiRedditListingRecyclerViewAdapter adapter = new MultiRedditListingRecyclerViewAdapter(this, + mOauthRetrofit, mRedditDataRoomDatabase, mAccessToken); + mRecyclerView.setAdapter(adapter); + + mMultiRedditViewModel = new ViewModelProvider(this, + new MultiRedditViewModel.Factory(getApplication(), mRedditDataRoomDatabase, mAccountName)) + .get(MultiRedditViewModel.class); + + mMultiRedditViewModel.getAllMultiReddits().observe(this, subscribedUserData -> { + if (subscribedUserData == null || subscribedUserData.size() == 0) { + mRecyclerView.setVisibility(View.GONE); + mErrorLinearLayout.setVisibility(View.VISIBLE); + mGlide.load(R.drawable.error_image).into(mErrorImageView); + } else { + mErrorLinearLayout.setVisibility(View.GONE); + mRecyclerView.setVisibility(View.VISIBLE); + mGlide.clear(mErrorImageView); + } + adapter.setMultiReddits(subscribedUserData); + }); + + mMultiRedditViewModel.getAllFavoriteMultiReddits().observe(this, favoriteSubscribedUserData -> { + if (favoriteSubscribedUserData != null && favoriteSubscribedUserData.size() > 0) { + mErrorLinearLayout.setVisibility(View.GONE); + mRecyclerView.setVisibility(View.VISIBLE); + mGlide.clear(mErrorImageView); + } + adapter.setFavoriteMultiReddits(favoriteSubscribedUserData); + }); + } + + private void loadMultiReddits() { + GetMultiReddit.getMyMultiReddits(mOauthRetrofit, mAccessToken, new GetMultiReddit.GetMultiRedditListener() { + @Override + public void success(ArrayList<MultiReddit> multiReddits) { + new InsertMultiRedditAsyncTask(mRedditDataRoomDatabase, multiReddits, () -> mInsertSuccess = true).execute(); + } + + @Override + public void failed() { + mInsertSuccess = false; + } + }); + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } + + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(INSERT_MULTI_REDDIT_STATE, mInsertSuccess); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + } + + @Override + public SharedPreferences getSharedPreferences() { + return mSharedPreferences; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/MultiRedditListingRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/MultiRedditListingRecyclerViewAdapter.java new file mode 100644 index 00000000..7503cfa7 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/MultiRedditListingRecyclerViewAdapter.java @@ -0,0 +1,349 @@ +package ml.docilealligator.infinityforreddit.Adapter; + +import android.content.Context; +import android.content.Intent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.RequestManager; +import com.bumptech.glide.request.RequestOptions; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; +import ml.docilealligator.infinityforreddit.Activity.ViewSubredditDetailActivity; +import ml.docilealligator.infinityforreddit.MultiReddit.FavoriteMultiReddit; +import ml.docilealligator.infinityforreddit.MultiReddit.MultiReddit; +import ml.docilealligator.infinityforreddit.R; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import pl.droidsonroids.gif.GifImageView; +import retrofit2.Retrofit; + +public class MultiRedditListingRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { + + private static final int VIEW_TYPE_FAVORITE_MULTI_REDDIT_DIVIDER = 0; + private static final int VIEW_TYPE_FAVORITE_MULTI_REDDIT = 1; + private static final int VIEW_TYPE_MULTI_REDDIT_DIVIDER = 2; + private static final int VIEW_TYPE_MULTI_REDDIT = 3; + + private Context mContext; + private Retrofit mOauthRetrofit; + private RedditDataRoomDatabase mRedditDataRoomDatabase; + private RequestManager mGlide; + + private String mAccessToken; + private List<MultiReddit> mMultiReddits; + private List<MultiReddit> mFavoriteMultiReddits; + + public MultiRedditListingRecyclerViewAdapter(Context context, Retrofit oauthRetrofit, + RedditDataRoomDatabase redditDataRoomDatabase, + String accessToken) { + mContext = context; + mGlide = Glide.with(context.getApplicationContext()); + mOauthRetrofit = oauthRetrofit; + mRedditDataRoomDatabase = redditDataRoomDatabase; + mAccessToken = accessToken; + + } + + @Override + public int getItemViewType(int position) { + if (mFavoriteMultiReddits != null && mFavoriteMultiReddits.size() > 0) { + if (position == 0) { + return VIEW_TYPE_FAVORITE_MULTI_REDDIT_DIVIDER; + } else if (position == mFavoriteMultiReddits.size() + 1) { + return VIEW_TYPE_MULTI_REDDIT_DIVIDER; + } else if (position <= mFavoriteMultiReddits.size()) { + return VIEW_TYPE_FAVORITE_MULTI_REDDIT; + } else { + return VIEW_TYPE_MULTI_REDDIT; + } + } else { + return VIEW_TYPE_MULTI_REDDIT; + } + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + switch (viewType) { + case VIEW_TYPE_FAVORITE_MULTI_REDDIT_DIVIDER: + return new FavoriteMultiRedditsDividerViewHolder(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_favorite_thing_divider, parent, false)); + case VIEW_TYPE_FAVORITE_MULTI_REDDIT: + return new FavoriteMultiRedditViewHolder(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_multi_reddit, parent, false)); + case VIEW_TYPE_MULTI_REDDIT_DIVIDER: + return new AllMultiRedditsDividerViewHolder(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_favorite_thing_divider, parent, false)); + default: + return new MultiRedditViewHolder(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_multi_reddit, parent, false)); + } + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (holder instanceof MultiRedditViewHolder) { + String name; + String iconUrl; + + int offset = (mFavoriteMultiReddits != null && mFavoriteMultiReddits.size() > 0) ? + mFavoriteMultiReddits.size() + 2 : 0; + + name = mMultiReddits.get(holder.getAdapterPosition() - offset).getName(); + iconUrl = mMultiReddits.get(holder.getAdapterPosition() - offset).getIconUrl(); + if(mMultiReddits.get(holder.getAdapterPosition() - offset).isFavorite()) { + ((MultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_24dp); + } else { + ((MultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_border_24dp); + } + + ((MultiRedditViewHolder) holder).favoriteImageView.setOnClickListener(view -> { + if(mMultiReddits.get(holder.getAdapterPosition() - offset).isFavorite()) { + ((MultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_border_24dp); + mMultiReddits.get(holder.getAdapterPosition() - offset).setFavorite(false); + FavoriteMultiReddit.favoriteMultiReddit(mOauthRetrofit, mRedditDataRoomDatabase, mAccessToken, + false, mMultiReddits.get(holder.getAdapterPosition() - offset), + new FavoriteMultiReddit.FavoriteMultiRedditListener() { + @Override + public void success() { + int position = holder.getAdapterPosition() - offset; + if(position >= 0 && mMultiReddits.size() > position) { + mMultiReddits.get(position).setFavorite(false); + } + ((MultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_border_24dp); + } + + @Override + public void failed() { + Toast.makeText(mContext, R.string.thing_unfavorite_failed, Toast.LENGTH_SHORT).show(); + int position = holder.getAdapterPosition() - offset; + if(position >= 0 && mMultiReddits.size() > position) { + mMultiReddits.get(position).setFavorite(true); + } + ((MultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_24dp); + } + } + ); + } else { + ((MultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_24dp); + mMultiReddits.get(holder.getAdapterPosition() - offset).setFavorite(true); + FavoriteMultiReddit.favoriteMultiReddit(mOauthRetrofit, mRedditDataRoomDatabase, mAccessToken, + true, mMultiReddits.get(holder.getAdapterPosition() - offset), + new FavoriteMultiReddit.FavoriteMultiRedditListener() { + @Override + public void success() { + int position = holder.getAdapterPosition() - offset; + if(position >= 0 && mMultiReddits.size() > position) { + mMultiReddits.get(position).setFavorite(true); + } + ((MultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_24dp); + } + + @Override + public void failed() { + Toast.makeText(mContext, R.string.thing_favorite_failed, Toast.LENGTH_SHORT).show(); + int position = holder.getAdapterPosition() - offset; + if(position >= 0 && mMultiReddits.size() > position) { + mMultiReddits.get(position).setFavorite(false); + } + ((MultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_border_24dp); + } + } + ); + } + }); + holder.itemView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, ViewSubredditDetailActivity.class); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, name); + mContext.startActivity(intent); + }); + + if (iconUrl != null && !iconUrl.equals("")) { + mGlide.load(iconUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((MultiRedditViewHolder) holder).iconImageView); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((MultiRedditViewHolder) holder).iconImageView); + } + ((MultiRedditViewHolder) holder).multiRedditNameTextView.setText(name); + } else if (holder instanceof FavoriteMultiRedditViewHolder) { + String name = mFavoriteMultiReddits.get(holder.getAdapterPosition() - 1).getName(); + String iconUrl = mFavoriteMultiReddits.get(holder.getAdapterPosition() - 1).getIconUrl(); + if(mFavoriteMultiReddits.get(holder.getAdapterPosition() - 1).isFavorite()) { + ((FavoriteMultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_24dp); + } else { + ((FavoriteMultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_border_24dp); + } + + ((FavoriteMultiRedditViewHolder) holder).favoriteImageView.setOnClickListener(view -> { + if(mFavoriteMultiReddits.get(holder.getAdapterPosition() - 1).isFavorite()) { + ((FavoriteMultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_border_24dp); + mFavoriteMultiReddits.get(holder.getAdapterPosition() - 1).setFavorite(false); + FavoriteMultiReddit.favoriteMultiReddit(mOauthRetrofit, mRedditDataRoomDatabase, mAccessToken, + false, mFavoriteMultiReddits.get(holder.getAdapterPosition() - 1), + new FavoriteMultiReddit.FavoriteMultiRedditListener() { + @Override + public void success() { + int position = holder.getAdapterPosition() - 1; + if(position >= 0 && mFavoriteMultiReddits.size() > position) { + mFavoriteMultiReddits.get(position).setFavorite(false); + } + ((FavoriteMultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_border_24dp); + } + + @Override + public void failed() { + Toast.makeText(mContext, R.string.thing_unfavorite_failed, Toast.LENGTH_SHORT).show(); + int position = holder.getAdapterPosition() - 1; + if(position >= 0 && mFavoriteMultiReddits.size() > position) { + mFavoriteMultiReddits.get(position).setFavorite(true); + } + ((FavoriteMultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_24dp); + } + } + ); + } else { + ((FavoriteMultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_24dp); + mFavoriteMultiReddits.get(holder.getAdapterPosition() - 1).setFavorite(true); + FavoriteMultiReddit.favoriteMultiReddit(mOauthRetrofit, mRedditDataRoomDatabase, mAccessToken, + true, mFavoriteMultiReddits.get(holder.getAdapterPosition() - 1), + new FavoriteMultiReddit.FavoriteMultiRedditListener() { + @Override + public void success() { + int position = holder.getAdapterPosition() - 1; + if(position >= 0 && mFavoriteMultiReddits.size() > position) { + mFavoriteMultiReddits.get(position).setFavorite(true); + } + ((FavoriteMultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_24dp); + } + + @Override + public void failed() { + Toast.makeText(mContext, R.string.thing_favorite_failed, Toast.LENGTH_SHORT).show(); + int position = holder.getAdapterPosition() - 1; + if(position >= 0 && mFavoriteMultiReddits.size() > position) { + mFavoriteMultiReddits.get(position).setFavorite(false); + } + ((FavoriteMultiRedditViewHolder) holder).favoriteImageView.setImageResource(R.drawable.ic_favorite_border_24dp); + } + } + ); + } + }); + holder.itemView.setOnClickListener(view -> { + Intent intent = new Intent(mContext, ViewSubredditDetailActivity.class); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, name); + mContext.startActivity(intent); + }); + + if (iconUrl != null && !iconUrl.equals("")) { + mGlide.load(iconUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((FavoriteMultiRedditViewHolder) holder).iconImageView); + } else { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((FavoriteMultiRedditViewHolder) holder).iconImageView); + } + ((FavoriteMultiRedditViewHolder) holder).multiRedditNameTextView.setText(name); + } + } + + @Override + public int getItemCount() { + if (mMultiReddits != null) { + if(mFavoriteMultiReddits != null && mFavoriteMultiReddits.size() > 0) { + return mMultiReddits.size() > 0 ? + mFavoriteMultiReddits.size() + mMultiReddits.size() + 2 : 0; + } + + return mMultiReddits.size(); + } + return 0; + } + + @Override + public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { + if(holder instanceof MultiRedditViewHolder) { + mGlide.clear(((MultiRedditViewHolder) holder).iconImageView); + } else if (holder instanceof FavoriteMultiRedditViewHolder) { + mGlide.clear(((FavoriteMultiRedditViewHolder) holder).iconImageView); + } + } + + public void setMultiReddits(List<MultiReddit> multiReddits) { + mMultiReddits = multiReddits; + notifyDataSetChanged(); + } + + public void setFavoriteMultiReddits(List<MultiReddit> favoriteMultiReddits) { + mFavoriteMultiReddits = favoriteMultiReddits; + notifyDataSetChanged(); + } + + class MultiRedditViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.multi_reddit_icon_gif_image_view_item_multi_reddit) + GifImageView iconImageView; + @BindView(R.id.multi_reddit_name_text_view_item_multi_reddit) + TextView multiRedditNameTextView; + @BindView(R.id.favorite_image_view_item_multi_reddit) + ImageView favoriteImageView; + + MultiRedditViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } + + class FavoriteMultiRedditViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.multi_reddit_icon_gif_image_view_item_multi_reddit) + GifImageView iconImageView; + @BindView(R.id.multi_reddit_name_text_view_item_multi_reddit) + TextView multiRedditNameTextView; + @BindView(R.id.favorite_image_view_item_multi_reddit) + ImageView favoriteImageView; + + FavoriteMultiRedditViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + } + + class FavoriteMultiRedditsDividerViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.divider_text_view_item_favorite_thing_divider) TextView dividerTextView; + + FavoriteMultiRedditsDividerViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + dividerTextView.setText(R.string.favorites); + } + } + + class AllMultiRedditsDividerViewHolder extends RecyclerView.ViewHolder { + @BindView(R.id.divider_text_view_item_favorite_thing_divider) TextView dividerTextView; + + AllMultiRedditsDividerViewHolder(@NonNull View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + dividerTextView.setText(R.string.all); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java index 4ca67f58..33dd286e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java @@ -12,6 +12,7 @@ import ml.docilealligator.infinityforreddit.Activity.FilteredThingActivity; import ml.docilealligator.infinityforreddit.Activity.LinkResolverActivity; import ml.docilealligator.infinityforreddit.Activity.LoginActivity; import ml.docilealligator.infinityforreddit.Activity.MainActivity; +import ml.docilealligator.infinityforreddit.Activity.MultiRedditListingActivity; import ml.docilealligator.infinityforreddit.Activity.PostImageActivity; import ml.docilealligator.infinityforreddit.Activity.PostLinkActivity; import ml.docilealligator.infinityforreddit.Activity.PostTextActivity; @@ -116,4 +117,6 @@ public interface AppComponent { void inject(ViewImageActivity viewImageActivity); void inject(ViewGIFActivity viewGIFActivity); + + void inject(MultiRedditListingActivity multiRedditListingActivity); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/GetCurrentAccountAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/GetCurrentAccountAsyncTask.java index 2d9253b8..38d67e02 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/GetCurrentAccountAsyncTask.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/GetCurrentAccountAsyncTask.java @@ -7,9 +7,10 @@ import ml.docilealligator.infinityforreddit.Account.AccountDao; public class GetCurrentAccountAsyncTask extends AsyncTask<Void, Void, Void> { - Account account; - AccountDao accountDao; - GetCurrentAccountAsyncTaskListener getCurrentAccountAsyncTaskListener; + private Account account; + private AccountDao accountDao; + private GetCurrentAccountAsyncTaskListener getCurrentAccountAsyncTaskListener; + public GetCurrentAccountAsyncTask(AccountDao accountDao, GetCurrentAccountAsyncTaskListener getCurrentAccountAsyncTaskListener) { this.accountDao = accountDao; this.getCurrentAccountAsyncTaskListener = getCurrentAccountAsyncTaskListener; diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/InsertMultiRedditAsyncTask.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/InsertMultiRedditAsyncTask.java new file mode 100644 index 00000000..22613362 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AsyncTask/InsertMultiRedditAsyncTask.java @@ -0,0 +1,41 @@ +package ml.docilealligator.infinityforreddit.AsyncTask; + +import android.os.AsyncTask; + +import java.util.ArrayList; + +import ml.docilealligator.infinityforreddit.MultiReddit.MultiReddit; +import ml.docilealligator.infinityforreddit.MultiReddit.MultiRedditDao; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; + +public class InsertMultiRedditAsyncTask extends AsyncTask<Void, Void, Void> { + private MultiRedditDao multiRedditDao; + private ArrayList<MultiReddit> multiReddits; + private InsertMultiRedditAsyncTaskListener insertMultiRedditAsyncTaskListener; + + public InsertMultiRedditAsyncTask(RedditDataRoomDatabase redditDataRoomDatabase, + ArrayList<MultiReddit> multiReddits, + InsertMultiRedditAsyncTaskListener insertMultiRedditAsyncTaskListener) { + multiRedditDao = redditDataRoomDatabase.multiRedditDao(); + this.multiReddits = multiReddits; + this.insertMultiRedditAsyncTaskListener = insertMultiRedditAsyncTaskListener; + } + + @Override + protected Void doInBackground(Void... voids) { + for (MultiReddit multiReddit : multiReddits) { + multiRedditDao.insert(multiReddit); + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + insertMultiRedditAsyncTaskListener.success(); + } + + public interface InsertMultiRedditAsyncTaskListener { + void success(); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FollowedUsersListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FollowedUsersListingFragment.java index 539aed91..43603177 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FollowedUsersListingFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/FollowedUsersListingFragment.java @@ -52,9 +52,9 @@ public class FollowedUsersListingFragment extends Fragment { Retrofit mOauthRetrofit; @Inject RedditDataRoomDatabase mRedditDataRoomDatabase; + SubscribedUserViewModel mSubscribedUserViewModel; private Activity mActivity; private RequestManager mGlide; - private SubscribedUserViewModel mSubscribedUserViewModel; public FollowedUsersListingFragment() { // Required empty public constructor diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/FavoriteMultiReddit.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/FavoriteMultiReddit.java new file mode 100644 index 00000000..d05e917b --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/FavoriteMultiReddit.java @@ -0,0 +1,52 @@ +package ml.docilealligator.infinityforreddit.MultiReddit; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import ml.docilealligator.infinityforreddit.AsyncTask.InsertMultiRedditAsyncTask; +import ml.docilealligator.infinityforreddit.RedditAPI; +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; +import ml.docilealligator.infinityforreddit.Utils.RedditUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class FavoriteMultiReddit { + public interface FavoriteMultiRedditListener { + void success(); + void failed(); + } + + public static void favoriteMultiReddit(Retrofit oauthRetrofit, RedditDataRoomDatabase redditDataRoomDatabase, + String accessToken, boolean makeFavorite, MultiReddit multiReddit, + FavoriteMultiRedditListener favoriteMultiRedditListener) { + Map<String, String> params = new HashMap<>(); + params.put(RedditUtils.MULTIPATH_KEY, multiReddit.getPath()); + params.put(RedditUtils.MAKE_FAVORITE_KEY, String.valueOf(makeFavorite)); + params.put(RedditUtils.API_TYPE_KEY, RedditUtils.API_TYPE_JSON); + oauthRetrofit.create(RedditAPI.class).favoriteMultiReddit(RedditUtils.getOAuthHeader(accessToken), + params).enqueue(new Callback<String>() { + @Override + public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) { + if (response.isSuccessful()) { + multiReddit.setFavorite(true); + ArrayList<MultiReddit> singleMultiRedditList = new ArrayList<>(); + singleMultiRedditList.add(multiReddit); + new InsertMultiRedditAsyncTask(redditDataRoomDatabase, singleMultiRedditList, + favoriteMultiRedditListener::success).execute(); + } else { + favoriteMultiRedditListener.failed(); + } + } + + @Override + public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { + favoriteMultiRedditListener.failed(); + } + }); + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/GetMultiReddit.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/GetMultiReddit.java new file mode 100644 index 00000000..bf90d4ab --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/GetMultiReddit.java @@ -0,0 +1,128 @@ +package ml.docilealligator.infinityforreddit.MultiReddit; + +import android.os.AsyncTask; + +import androidx.annotation.NonNull; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; + +import ml.docilealligator.infinityforreddit.RedditAPI; +import ml.docilealligator.infinityforreddit.Utils.JSONUtils; +import ml.docilealligator.infinityforreddit.Utils.RedditUtils; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; + +public class GetMultiReddit { + public interface GetMultiRedditListener { + void success(ArrayList<MultiReddit> multiReddits); + void failed(); + } + + public static void getMyMultiReddits(Retrofit oauthRetrofit, String accessToken, GetMultiRedditListener getMultiRedditListener) { + oauthRetrofit.create(RedditAPI.class) + .getMyMultiReddits(RedditUtils.getOAuthHeader(accessToken)).enqueue(new Callback<String>() { + @Override + public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) { + if (response.isSuccessful()) { + new ParseMultiRedditsListAsyncTask(response.body(), new ParseMultiRedditsListAsyncTask.ParseMultiRedditsListAsyncTaskListener() { + @Override + public void success(ArrayList<MultiReddit> multiReddits) { + getMultiRedditListener.success(multiReddits); + } + + @Override + public void failed() { + getMultiRedditListener.failed(); + } + }).execute(); + } else { + getMultiRedditListener.failed(); + } + } + + @Override + public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) { + getMultiRedditListener.failed(); + } + }); + } + + private static class ParseMultiRedditsListAsyncTask extends AsyncTask<Void, Void, Void> { + private JSONArray arrayResponse; + private boolean parseFailed; + private ArrayList<MultiReddit> multiReddits; + private ParseMultiRedditsListAsyncTaskListener parseMultiRedditsListAsyncTaskListener; + + interface ParseMultiRedditsListAsyncTaskListener { + void success(ArrayList<MultiReddit> multiReddits); + void failed(); + } + + ParseMultiRedditsListAsyncTask(String response, + ParseMultiRedditsListAsyncTaskListener parseMultiRedditsListAsyncTaskListener) { + this.parseMultiRedditsListAsyncTaskListener = parseMultiRedditsListAsyncTaskListener; + try { + arrayResponse = new JSONArray(response); + multiReddits = new ArrayList<>(); + parseFailed = false; + } catch (JSONException e) { + e.printStackTrace(); + parseFailed = true; + } + } + + @Override + protected Void doInBackground(Void... voids) { + if (!parseFailed) { + for (int i = 0; i < arrayResponse.length(); i++) { + try { + JSONObject singleMultiReddit = arrayResponse.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); + String displayName = singleMultiReddit.getString(JSONUtils.DISPLAY_NAME); + String name = singleMultiReddit.getString(JSONUtils.NAME_KEY); + String description = singleMultiReddit.getString(JSONUtils.DESCRIPTION_HTML_KEY); + int nSubscribers = singleMultiReddit.getInt(JSONUtils.NUM_SUBSCRIBERS_KEY); + String copiedFrom = singleMultiReddit.getString(JSONUtils.COPIED_FROM_KEY); + String iconUrl = singleMultiReddit.getString(JSONUtils.ICON_URL_KEY); + long createdUTC = singleMultiReddit.getLong(JSONUtils.CREATED_UTC_KEY); + String visibility = singleMultiReddit.getString(JSONUtils.VISIBILITY_KEY); + boolean over18 = singleMultiReddit.getBoolean(JSONUtils.OVER_18_KEY); + String path = singleMultiReddit.getString(JSONUtils.PATH_KEY); + String owner = singleMultiReddit.getString(JSONUtils.OWNER_KEY); + boolean isSubscriber = singleMultiReddit.getBoolean(JSONUtils.IS_SUBSCRIBER_KEY); + boolean isFavorited = singleMultiReddit.getBoolean(JSONUtils.IS_FAVORITED_KEY); + + JSONArray subredditsArray = singleMultiReddit.getJSONArray(JSONUtils.SUBREDDITS_KEY); + ArrayList<String> subreddits = new ArrayList<>(); + for (int j = 0; j < subredditsArray.length(); j++) { + subreddits.add(subredditsArray.getJSONObject(j).getString(JSONUtils.NAME_KEY)); + } + + MultiReddit multiReddit = new MultiReddit(path, displayName, name, description, copiedFrom, + iconUrl, visibility, owner, nSubscribers, createdUTC, over18, isSubscriber, + isFavorited, subreddits); + multiReddits.add(multiReddit); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if (!parseFailed) { + parseMultiRedditsListAsyncTaskListener.success(multiReddits); + } else { + parseMultiRedditsListAsyncTaskListener.failed(); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiReddit.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiReddit.java new file mode 100644 index 00000000..4692c8d4 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiReddit.java @@ -0,0 +1,201 @@ +package ml.docilealligator.infinityforreddit.MultiReddit; + +import androidx.annotation.NonNull; +import androidx.room.ColumnInfo; +import androidx.room.Entity; +import androidx.room.ForeignKey; +import androidx.room.Ignore; + +import java.util.ArrayList; + +import ml.docilealligator.infinityforreddit.Account.Account; + +@Entity(tableName = "multi_reddits", primaryKeys = {"path", "username"}, + foreignKeys = @ForeignKey(entity = Account.class, parentColumns = "username", + childColumns = "username", onDelete = ForeignKey.CASCADE)) +public class MultiReddit { + @NonNull + @ColumnInfo(name = "path") + private String path; + @NonNull + @ColumnInfo(name = "display_name") + private String displayName; + @NonNull + @ColumnInfo(name = "name") + private String name; + @ColumnInfo(name = "description") + private String description; + @ColumnInfo(name = "copied_from") + private String copiedFrom; + @ColumnInfo(name = "icon_url") + private String iconUrl; + @ColumnInfo(name = "visibility") + private String visibility; + @NonNull + @ColumnInfo(name = "username") + private String owner; + @ColumnInfo(name = "n_subscribers") + private int nSubscribers; + @ColumnInfo(name = "created_UTC") + private long createdUTC; + @ColumnInfo(name = "over_18") + private boolean over18; + @ColumnInfo(name = "is_subscriber") + private boolean isSubscriber; + @ColumnInfo(name = "is_favorite") + private boolean isFavorite; + @Ignore + private ArrayList<String> subreddits; + + public MultiReddit(@NonNull String path, @NonNull String displayName, @NonNull String name, + String description, String copiedFrom, String iconUrl, String visibility, + @NonNull String owner, int nSubscribers, long createdUTC, boolean over18, + boolean isSubscriber, boolean isFavorite) { + this.displayName = displayName; + this.name = name; + this.description = description; + this.copiedFrom = copiedFrom; + this.iconUrl = iconUrl; + this.visibility = visibility; + this.path = path; + this.owner = owner; + this.nSubscribers = nSubscribers; + this.createdUTC = createdUTC; + this.over18 = over18; + this.isSubscriber = isSubscriber; + this.isFavorite = isFavorite; + } + + public MultiReddit(@NonNull String path, String displayName, String name, String description, String copiedFrom, + String iconUrl, String visibility, @NonNull String owner, + int nSubscribers, long createdUTC, boolean over18, boolean isSubscriber, + boolean isFavorite, ArrayList<String> subreddits) { + this.displayName = displayName; + this.name = name; + this.description = description; + this.copiedFrom = copiedFrom; + this.iconUrl = iconUrl; + this.visibility = visibility; + this.path = path; + this.owner = owner; + this.nSubscribers = nSubscribers; + this.createdUTC = createdUTC; + this.over18 = over18; + this.isSubscriber = isSubscriber; + this.isFavorite = isFavorite; + this.subreddits = subreddits; + } + + @NonNull + public String getPath() { + return path; + } + + public void setPath(@NonNull String path) { + this.path = path; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getCopiedFrom() { + return copiedFrom; + } + + public void setCopiedFrom(String copiedFrom) { + this.copiedFrom = copiedFrom; + } + + public String getIconUrl() { + return iconUrl; + } + + public void setIconUrl(String iconUrl) { + this.iconUrl = iconUrl; + } + + public String getVisibility() { + return visibility; + } + + public void setVisibility(String visibility) { + this.visibility = visibility; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public int getNSubscribers() { + return nSubscribers; + } + + public void setNSubscribers(int nSubscribers) { + this.nSubscribers = nSubscribers; + } + + public long getCreatedUTC() { + return createdUTC; + } + + public void setCreatedUTC(long createdUTC) { + this.createdUTC = createdUTC; + } + + public boolean isOver18() { + return over18; + } + + public void setOver18(boolean over18) { + this.over18 = over18; + } + + public boolean isSubscriber() { + return isSubscriber; + } + + public void setSubscriber(boolean subscriber) { + isSubscriber = subscriber; + } + + public boolean isFavorite() { + return isFavorite; + } + + public void setFavorite(boolean favorite) { + isFavorite = favorite; + } + + public ArrayList<String> getSubreddits() { + return subreddits; + } + + public void setSubreddits(ArrayList<String> subreddits) { + this.subreddits = subreddits; + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiRedditDao.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiRedditDao.java new file mode 100644 index 00000000..1e72966d --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiRedditDao.java @@ -0,0 +1,27 @@ +package ml.docilealligator.infinityforreddit.MultiReddit; + +import androidx.lifecycle.LiveData; +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.OnConflictStrategy; +import androidx.room.Query; + +import java.util.List; + +@Dao +public interface MultiRedditDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(MultiReddit MultiReddit); + + @Query("SELECT * FROM multi_reddits WHERE username = :username ORDER BY name COLLATE NOCASE ASC") + LiveData<List<MultiReddit>> getAllMultiReddits(String username); + + @Query("SELECT * FROM multi_reddits WHERE username = :username AND is_favorite ORDER BY name COLLATE NOCASE ASC") + LiveData<List<MultiReddit>> getAllFavoriteMultiReddits(String username); + + @Query("SELECT * FROM multi_reddits WHERE name = :name AND username = :username COLLATE NOCASE LIMIT 1") + MultiReddit getMultiReddit(String name, String username); + + @Query("DELETE FROM multi_reddits WHERE name = :name AND username = :username") + void deleteMultiReddit(String name, String username); +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiRedditRepository.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiRedditRepository.java new file mode 100644 index 00000000..b725caa2 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiRedditRepository.java @@ -0,0 +1,48 @@ +package ml.docilealligator.infinityforreddit.MultiReddit; + +import android.os.AsyncTask; + +import androidx.lifecycle.LiveData; + +import java.util.List; + +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; + +public class MultiRedditRepository { + private MultiRedditDao mMultiRedditDao; + private LiveData<List<MultiReddit>> mAllMultiReddits; + private LiveData<List<MultiReddit>> mAllFavoriteMultiReddits; + + MultiRedditRepository(RedditDataRoomDatabase redditDataRoomDatabase, String accountName) { + mMultiRedditDao = redditDataRoomDatabase.multiRedditDao(); + mAllMultiReddits = mMultiRedditDao.getAllMultiReddits(accountName); + mAllFavoriteMultiReddits = mMultiRedditDao.getAllFavoriteMultiReddits(accountName); + } + + LiveData<List<MultiReddit>> getAllMultiReddits() { + return mAllMultiReddits; + } + + LiveData<List<MultiReddit>> getAllFavoriteMultiReddits() { + return mAllFavoriteMultiReddits; + } + + public void insert(MultiReddit MultiReddit) { + new MultiRedditRepository.insertAsyncTask(mMultiRedditDao).execute(); + } + + private static class insertAsyncTask extends AsyncTask<MultiReddit, Void, Void> { + + private MultiRedditDao mAsyncTaskDao; + + insertAsyncTask(MultiRedditDao dao) { + mAsyncTaskDao = dao; + } + + @Override + protected Void doInBackground(final MultiReddit... params) { + mAsyncTaskDao.insert(params[0]); + return null; + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiRedditViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiRedditViewModel.java new file mode 100644 index 00000000..bb9dcf76 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MultiReddit/MultiRedditViewModel.java @@ -0,0 +1,56 @@ +package ml.docilealligator.infinityforreddit.MultiReddit; + +import android.app.Application; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; + +import java.util.List; + +import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase; + +public class MultiRedditViewModel extends AndroidViewModel { + private MultiRedditRepository mMultiRedditRepository; + private LiveData<List<MultiReddit>> mAllMultiReddits; + private LiveData<List<MultiReddit>> mAllFavoriteMultiReddits; + + public MultiRedditViewModel(Application application, RedditDataRoomDatabase redditDataRoomDatabase, String accountName) { + super(application); + mMultiRedditRepository = new MultiRedditRepository(redditDataRoomDatabase, accountName); + mAllMultiReddits = mMultiRedditRepository.getAllMultiReddits(); + mAllFavoriteMultiReddits = mMultiRedditRepository.getAllFavoriteMultiReddits(); + } + + public LiveData<List<MultiReddit>> getAllMultiReddits() { + return mAllMultiReddits; + } + + public LiveData<List<MultiReddit>> getAllFavoriteMultiReddits() { + return mAllFavoriteMultiReddits; + } + + public void insert(MultiReddit MultiReddit) { + mMultiRedditRepository.insert(MultiReddit); + } + + public static class Factory extends ViewModelProvider.NewInstanceFactory { + private Application mApplication; + private RedditDataRoomDatabase mRedditDataRoomDatabase; + private String mAccountName; + + public Factory(Application application, RedditDataRoomDatabase redditDataRoomDatabase, String accountName) { + mApplication = application; + mRedditDataRoomDatabase = redditDataRoomDatabase; + mAccountName = accountName; + } + + @NonNull + @Override + public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { + return (T) new MultiRedditViewModel(mApplication, mRedditDataRoomDatabase, mAccountName); + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java index 52fdb0ed..9097b026 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java @@ -261,4 +261,11 @@ public interface RedditAPI { @FormUrlEncoded @POST("/api/favorite") Call<String> favoriteThing(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params); + + @GET("/api/multi/mine") + Call<String> getMyMultiReddits(@HeaderMap Map<String, String> headers); + + @FormUrlEncoded + @POST("/api/multi/favorite?raw_json=1&gilding_detail=1") + Call<String> favoriteMultiReddit(@HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java index 7953ae75..df94d020 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditDataRoomDatabase.java @@ -11,6 +11,8 @@ import androidx.sqlite.db.SupportSQLiteDatabase; import ml.docilealligator.infinityforreddit.Account.Account; import ml.docilealligator.infinityforreddit.Account.AccountDao; +import ml.docilealligator.infinityforreddit.MultiReddit.MultiReddit; +import ml.docilealligator.infinityforreddit.MultiReddit.MultiRedditDao; import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditDao; import ml.docilealligator.infinityforreddit.SubredditDatabase.SubredditData; import ml.docilealligator.infinityforreddit.SubscribedSubredditDatabase.SubscribedSubredditDao; @@ -20,7 +22,8 @@ import ml.docilealligator.infinityforreddit.SubscribedUserDatabase.SubscribedUse import ml.docilealligator.infinityforreddit.User.UserDao; import ml.docilealligator.infinityforreddit.User.UserData; -@Database(entities = {Account.class, SubredditData.class, SubscribedSubredditData.class, UserData.class, SubscribedUserData.class}, version = 3) +@Database(entities = {Account.class, SubredditData.class, SubscribedSubredditData.class, UserData.class, + SubscribedUserData.class, MultiReddit.class}, version = 4) public abstract class RedditDataRoomDatabase extends RoomDatabase { private static RedditDataRoomDatabase INSTANCE; @@ -30,7 +33,7 @@ public abstract class RedditDataRoomDatabase extends RoomDatabase { if (INSTANCE == null) { INSTANCE = Room.databaseBuilder(context.getApplicationContext(), RedditDataRoomDatabase.class, "reddit_data") - .addMigrations(MIGRATION_1_2, MIGRATION_2_3) + .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4) .build(); } } @@ -48,6 +51,8 @@ public abstract class RedditDataRoomDatabase extends RoomDatabase { public abstract SubscribedUserDao subscribedUserDao(); + public abstract MultiRedditDao multiRedditDao(); + private static final Migration MIGRATION_1_2 = new Migration(1, 2) { @Override public void migrate(SupportSQLiteDatabase database) { @@ -80,4 +85,17 @@ public abstract class RedditDataRoomDatabase extends RoomDatabase { database.execSQL("ALTER TABLE subscribed_users_temp RENAME TO subscribed_users"); } }; + + private static final Migration MIGRATION_3_4 = new Migration(3, 4) { + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + database.execSQL("CREATE TABLE multi_reddits" + + "(path TEXT NOT NULL, username TEXT NOT NULL, name TEXT NOT NULL, " + + "display_name TEXT NOT NULL, description TEXT, copied_from TEXT, " + + "n_subscribers INTEGER NOT NULL, icon_url TEXT, created_UTC INTEGER NOT NULL, " + + "visibility TEXT, over_18 INTEGER NOT NULL, is_subscriber INTEGER NOT NULL, " + + "is_favorite INTEGER NOT NULL, PRIMARY KEY(path, username), " + + "FOREIGN KEY(username) REFERENCES accounts(username) ON DELETE CASCADE)"); + } + }; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedUserDatabase/SubscribedUserDao.java b/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedUserDatabase/SubscribedUserDao.java index 33ecac48..c085f298 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedUserDatabase/SubscribedUserDao.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/SubscribedUserDatabase/SubscribedUserDao.java @@ -13,9 +13,6 @@ public interface SubscribedUserDao { @Insert(onConflict = OnConflictStrategy.REPLACE) void insert(SubscribedUserData subscribedUserData); - @Query("DELETE FROM subscribed_users") - void deleteAllSubscribedUsers(); - @Query("SELECT * FROM subscribed_users WHERE username = :accountName ORDER BY name COLLATE NOCASE ASC") LiveData<List<SubscribedUserData>> getAllSubscribedUsers(String accountName); 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 d0979f5e..91babc40 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/JSONUtils.java @@ -53,6 +53,7 @@ public class JSONUtils { public static final String BANNER_IMG_KEY = "banner_img"; public static final String BANNER_BACKGROUND_IMAGE_KEY = "banner_background_image"; public static final String ICON_IMG_KEY = "icon_img"; + public static final String ICON_URL_KEY = "icon_url"; public static final String COMMUNITY_ICON_KEY = "community_icon"; public static final String LINK_KARMA_KEY = "link_karma"; public static final String COMMENT_KARMA_KEY = "comment_karma"; @@ -77,6 +78,7 @@ public class JSONUtils { public static final String RULES_KEY = "rules"; public static final String SHORT_NAME_KEY = "short_name"; public static final String DESCRIPTION_KEY = "description"; + public static final String DESCRIPTION_HTML_KEY = "description_html"; public static final String ARCHIVED_KEY = "archived"; public static final String LOCKEC_KEY = "locked"; public static final String SAVED_KEY = "saved"; @@ -90,4 +92,13 @@ public class JSONUtils { public static final String HIDDEN_KEY = "hidden"; public static final String USER_HAS_FAVORITED_KEY = "user_has_favorited"; public static final String RESOLUTIONS_KEY = "resolutions"; + public static final String NUM_SUBSCRIBERS_KEY = "num_subscribers"; + public static final String COPIED_FROM_KEY = "copied_from"; + public static final String VISIBILITY_KEY = "visibility"; + public static final String OVER_18_KEY = "over_18"; + public static final String OWNER_KEY = "owner"; + public static final String IS_SUBSCRIBER_KEY = "is_subscriber"; + public static final String IS_FAVORITED_KEY = "is_favorited"; + public static final String SUBREDDITS_KEY = "subreddits"; + public static final String PATH_KEY = "path"; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/RedditUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/RedditUtils.java index 000178e4..28faaf6d 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/RedditUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Utils/RedditUtils.java @@ -81,6 +81,8 @@ public class RedditUtils { public static final String MAKE_FAVORITE_KEY = "make_favorite"; + public static final String MULTIPATH_KEY = "multipath"; + public static Map<String, String> getHttpBasicAuthHeader() { Map<String, String> params = new HashMap<>(); String credentials = String.format("%s:%s", RedditUtils.CLIENT_ID, ""); diff --git a/app/src/main/res/layout/activity_multi_reddit_listing.xml b/app/src/main/res/layout/activity_multi_reddit_listing.xml new file mode 100644 index 00000000..73bf93ad --- /dev/null +++ b/app/src/main/res/layout/activity_multi_reddit_listing.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" + 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" + tools:context=".Activity.MultiRedditListingActivity"> + + <com.google.android.material.appbar.AppBarLayout + android:id="@+id/appbar_layout_multi_reddit_listing_activity" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/toolbarAndTabBackgroundColor" + android:theme="@style/AppTheme.AppBarOverlay"> + + <com.google.android.material.appbar.CollapsingToolbarLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_scrollFlags="scroll|enterAlways" + app:titleEnabled="false" + app:toolbarId="@+id/toolbar_multi_reddit_listing_activity"> + + <androidx.appcompat.widget.Toolbar + android:id="@+id/toolbar_multi_reddit_listing_activity" + android:layout_width="match_parent" + android:layout_height="?attr/actionBarSize" + app:popupTheme="@style/AppTheme.PopupOverlay" + app:navigationIcon="?attr/homeAsUpIndicator" /> + + </com.google.android.material.appbar.CollapsingToolbarLayout> + + </com.google.android.material.appbar.AppBarLayout> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/recycler_view_multi_reddit_listing_activity" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> + + <LinearLayout + android:id="@+id/fetch_multi_reddit_listing_info_linear_layout_multi_reddit_listing_activity" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginBottom="48dp" + android:gravity="center" + android:orientation="vertical" + android:visibility="gone" + app:layout_behavior="@string/appbar_scrolling_view_behavior"> + + <ImageView + android:id="@+id/fetch_multi_reddit_listing_info_image_view_multi_reddit_listing_activity" + android:layout_width="150dp" + android:layout_height="wrap_content" /> + + <TextView + android:id="@+id/fetch_multi_reddit_listing_info_text_view_multi_reddit_listing_activity" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:gravity="center" + android:textSize="?attr/font_default" /> + + </LinearLayout> + +</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/item_multi_reddit.xml b/app/src/main/res/layout/item_multi_reddit.xml new file mode 100644 index 00000000..6a8723d2 --- /dev/null +++ b/app/src/main/res/layout/item_multi_reddit.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="16dp" + android:clickable="true" + android:focusable="true" + android:background="?attr/selectableItemBackground"> + + <pl.droidsonroids.gif.GifImageView + android:id="@+id/multi_reddit_icon_gif_image_view_item_multi_reddit" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="center_vertical" + android:layout_marginEnd="32dp" /> + + <TextView + android:id="@+id/multi_reddit_name_text_view_item_multi_reddit" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="@color/primaryTextColor" + android:textSize="?attr/font_default" + android:layout_gravity="center_vertical" /> + + <ImageView + android:id="@+id/favorite_image_view_item_multi_reddit" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="end|center_vertical" + android:layout_marginStart="32dp" /> + +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8f1aa5ca..1a610b48 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,6 +16,7 @@ <string name="view_message_activity_label">Inbox</string> <string name="settings_activity_label">Settings</string> <string name="account_saved_thing_activity">Saved</string> + <string name="multi_reddit_listing_activity">MultiReddit</string> <string name="navigation_drawer_open">Open navigation drawer</string> <string name="navigation_drawer_close">Close navigation drawer</string> @@ -359,7 +360,7 @@ <string name="post_layout_card">Card Layout</string> <string name="post_layout_compact">Compact Layout</string> - + <string name="elapsed_time_just_now">Just Now</string> <string name="elapsed_time_a_minute_ago">1 Minute</string> <string name="elapsed_time_minutes_ago">%1$d Minutes</string> diff --git a/build.gradle b/build.gradle index ca512c89..ac5dccfc 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.2' + classpath 'com.android.tools.build:gradle:3.5.3' // NOTE: Do not place your application dependencies here; they belong |