diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index b153b848..c6198f2d 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/caches/gradle_models.ser b/.idea/caches/gradle_models.ser index aff67652..c31c3375 100644 Binary files a/.idea/caches/gradle_models.ser and b/.idea/caches/gradle_models.ser differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 81a9c8f3..e31b13d7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,20 +11,31 @@ android:supportsRtl="true" android:theme="@style/AppTheme" android:usesCleartextTraffic="true"> + + + + + + + @@ -54,12 +65,10 @@ android:parentActivityName=".MainActivity" android:theme="@style/AppTheme.NoActionBar" android:windowSoftInputMode="adjustResize" /> - - - @@ -225,6 +233,7 @@ android:name=".ViewUserDetailActivity" android:parentActivityName=".MainActivity" android:theme="@style/AppTheme.NoActionBarWithTranslucentWindow" /> + + + - - - \ No newline at end of file diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AccountPostsActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AccountPostsActivity.java index 9d3dab85..d7ee9918 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AccountPostsActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AccountPostsActivity.java @@ -58,8 +58,6 @@ public class AccountPostsActivity extends AppCompatActivity implements UserThing private Menu mMenu; private AppBarLayout.LayoutParams params; - private UserThingSortTypeBottomSheetFragment userThingSortTypeBottomSheetFragment; - @Inject RedditDataRoomDatabase mRedditDataRoomDatabase; @@ -146,9 +144,6 @@ public class AccountPostsActivity extends AppCompatActivity implements UserThing } else if(mUserWhere.equals(PostDataSource.USER_WHERE_HIDDEN)) { toolbar.setTitle(R.string.hidden); } else if(mUserWhere.equals(PostDataSource.USER_WHERE_GILDED)){ - if(mMenu != null) { - mMenu.findItem(R.id.action_sort_account_posts_activity).setVisible(true); - } toolbar.setTitle(R.string.gilded); } @@ -171,8 +166,6 @@ public class AccountPostsActivity extends AppCompatActivity implements UserThing } else { getCurrentAccountAndInitializeFragment(); } - - userThingSortTypeBottomSheetFragment = new UserThingSortTypeBottomSheetFragment(); } private void getCurrentAccountAndInitializeFragment() { @@ -204,9 +197,6 @@ public class AccountPostsActivity extends AppCompatActivity implements UserThing public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.account_posts_activity, menu); mMenu = menu; - if(mUserWhere != null && mUserWhere.equals(PostDataSource.USER_WHERE_GILDED)) { - menu.findItem(R.id.action_sort_account_posts_activity).setVisible(true); - } MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_account_posts_activity); if(isInLazyMode) { lazyModeItem.setTitle(R.string.action_stop_lazy_mode); @@ -223,9 +213,6 @@ public class AccountPostsActivity extends AppCompatActivity implements UserThing @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { - case R.id.action_sort_account_posts_activity: - userThingSortTypeBottomSheetFragment.show(getSupportFragmentManager(), userThingSortTypeBottomSheetFragment.getTag()); - return true; case R.id.action_refresh_account_posts_activity: if(mMenu != null) { mMenu.findItem(R.id.action_lazy_mode_account_posts_activity).setTitle(R.string.action_start_lazy_mode); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AccountSavedThingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AccountSavedThingActivity.java new file mode 100644 index 00000000..2b8206e4 --- /dev/null +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AccountSavedThingActivity.java @@ -0,0 +1,394 @@ +package ml.docilealligator.infinityforreddit; + +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.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.appbar.AppBarLayout; +import com.google.android.material.appbar.CollapsingToolbarLayout; +import com.google.android.material.tabs.TabLayout; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import javax.inject.Inject; +import javax.inject.Named; + +import butterknife.BindView; +import butterknife.ButterKnife; +import retrofit2.Retrofit; + +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO; +import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES; + +public class AccountSavedThingActivity extends AppCompatActivity { + + 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"; + private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; + + @BindView(R.id.collapsing_toolbar_layout_account_saved_thing_activity) CollapsingToolbarLayout collapsingToolbarLayout; + @BindView(R.id.appbar_layout_account_saved_thing_activity) AppBarLayout appBarLayout; + @BindView(R.id.toolbar_account_saved_thing_activity) Toolbar toolbar; + @BindView(R.id.tab_layout_tab_layout_account_saved_thing_activity_activity) TabLayout tabLayout; + @BindView(R.id.view_pager_account_saved_thing_activity) ViewPager viewPager; + + private SectionsPagerAdapter sectionsPagerAdapter; + private Menu mMenu; + private AppBarLayout.LayoutParams params; + + private boolean mNullAccessToken = false; + private String mAccessToken; + private String mAccountName; + private boolean isInLazyMode = false; + + @Inject + @Named("oauth") + Retrofit mOauthRetrofit; + + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + + @Inject + SharedPreferences mSharedPreferences; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_account_saved_thing); + + ButterKnife.bind(this); + + ((Infinity) getApplication()).getAppComponent().inject(this); + + EventBus.getDefault().register(this); + + Resources resources = getResources(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 + && (resources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT + || resources.getBoolean(R.bool.isTablet))) { + 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); + } + appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() { + @Override + void onStateChanged(AppBarLayout appBarLayout, 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) toolbar.getLayoutParams(); + params.topMargin = getResources().getDimensionPixelSize(statusBarResourceId); + toolbar.setLayoutParams(params); + } + } + + boolean systemDefault = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q; + int themeType = Integer.parseInt(mSharedPreferences.getString(SharedPreferencesUtils.THEME_KEY, "2")); + switch (themeType) { + case 0: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO); + break; + case 1: + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_YES); + break; + case 2: + if(systemDefault) { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_FOLLOW_SYSTEM); + } else { + AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_AUTO_BATTERY); + } + + } + + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + + params = (AppBarLayout.LayoutParams) collapsingToolbarLayout.getLayoutParams(); + + if(savedInstanceState != null) { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); + isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); + if(!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndInitializeViewPager(); + } else { + initializeViewPager(); + } + } else { + getCurrentAccountAndInitializeViewPager(); + } + } + + private void getCurrentAccountAndInitializeViewPager() { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + initializeViewPager(); + }).execute(); + } + + private void initializeViewPager() { + sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); + viewPager.setAdapter(sectionsPagerAdapter); + viewPager.setOffscreenPageLimit(2); + tabLayout.setupWithViewPager(viewPager); + + viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + if(isInLazyMode) { + if(viewPager.getCurrentItem() == 0) { + sectionsPagerAdapter.resumeLazyMode(); + } else { + sectionsPagerAdapter.pauseLazyMode(); + } + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.account_saved_thing_activity, menu); + mMenu = menu; + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_account_saved_thing_activity); + if (isInLazyMode) { + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } else { + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | + AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } + + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + case R.id.action_refresh_account_saved_thing_activity: + if(mMenu != null) { + mMenu.findItem(R.id.action_lazy_mode_account_saved_thing_activity).setTitle(R.string.action_start_lazy_mode); + } + sectionsPagerAdapter.refresh(); + return true; + case R.id.action_lazy_mode_account_saved_thing_activity: + MenuItem lazyModeItem = mMenu.findItem(R.id.action_lazy_mode_account_saved_thing_activity); + if(isInLazyMode) { + isInLazyMode = false; + sectionsPagerAdapter.stopLazyMode(); + lazyModeItem.setTitle(R.string.action_start_lazy_mode); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | + AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } else { + isInLazyMode = true; + if(sectionsPagerAdapter.startLazyMode()) { + lazyModeItem.setTitle(R.string.action_stop_lazy_mode); + appBarLayout.setExpanded(false); + params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED); + collapsingToolbarLayout.setLayoutParams(params); + } else { + isInLazyMode = false; + } + } + return true; + } + return false; + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(IS_IN_LAZY_MODE_STATE, isInLazyMode); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putString(ACCOUNT_NAME_STATE, mAccountName); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Subscribe + public void onAccountSwitchEvent(SwitchAccountEvent event) { + finish(); + } + + @Subscribe + public void onChangeNSFWEvent(ChangeNSFWEvent changeNSFWEvent) { + sectionsPagerAdapter.changeNSFW(changeNSFWEvent.nsfw); + } + + private class SectionsPagerAdapter extends FragmentPagerAdapter { + private PostFragment postFragment; + private CommentsListingFragment commentsListingFragment; + + SectionsPagerAdapter(FragmentManager fm) { + super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); + } + + @NonNull + @Override + public Fragment getItem(int position) { + if (position == 0) { + PostFragment fragment = new PostFragment(); + Bundle bundle = new Bundle(); + bundle.putInt(PostFragment.EXTRA_POST_TYPE, PostDataSource.TYPE_USER); + bundle.putString(PostFragment.EXTRA_USER_NAME, mAccountName); + bundle.putString(PostFragment.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_SAVED); + bundle.putString(PostFragment.EXTRA_SORT_TYPE, PostDataSource.SORT_TYPE_NEW); + bundle.putInt(PostFragment.EXTRA_FILTER, PostFragment.EXTRA_NO_FILTER); + bundle.putString(PostFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + fragment.setArguments(bundle); + return fragment; + } + CommentsListingFragment fragment = new CommentsListingFragment(); + Bundle bundle = new Bundle(); + bundle.putString(CommentsListingFragment.EXTRA_USERNAME, mAccountName); + bundle.putString(CommentsListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); + bundle.putString(CommentsListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); + bundle.putBoolean(CommentsListingFragment.EXTRA_ARE_SAVED_COMMENTS, true); + fragment.setArguments(bundle); + return fragment; + } + + @Override + public int getCount() { + return 2; + } + + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return "Posts"; + case 1: + return "Comments"; + } + return null; + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + Fragment fragment = (Fragment) super.instantiateItem(container, position); + switch (position) { + case 0: + postFragment = (PostFragment) fragment; + break; + case 1: + commentsListingFragment = (CommentsListingFragment) fragment; + } + return fragment; + } + + public void refresh() { + if (viewPager.getCurrentItem() == 0) { + if(postFragment != null) { + postFragment.refresh(); + } + } else { + if(commentsListingFragment != null) { + commentsListingFragment.refresh(); + } + } + } + + boolean startLazyMode() { + if(postFragment != null) { + return ((FragmentCommunicator) postFragment).startLazyMode(); + } + return false; + } + + void stopLazyMode() { + if(postFragment != null) { + ((FragmentCommunicator) postFragment).stopLazyMode(); + } + } + + void resumeLazyMode() { + if(postFragment != null) { + ((FragmentCommunicator) postFragment).resumeLazyMode(false); + } + } + + void pauseLazyMode() { + if(postFragment != null) { + ((FragmentCommunicator) postFragment).pauseLazyMode(false); + } + } + + public void changeNSFW(boolean nsfw) { + if(postFragment != null) { + postFragment.changeNSFW(nsfw); + } + } + } +} diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java index 2e6617f8..4cbc8e2f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppComponent.java @@ -43,4 +43,5 @@ public interface AppComponent { void inject(SearchActivity searchActivity); void inject(SettingsActivity settingsActivity); void inject(MainPreferenceFragment mainPreferenceFragment); + void inject(AccountSavedThingActivity accountSavedThingActivity); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSource.java index 04c95734..ad77ba21 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSource.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSource.java @@ -1,9 +1,9 @@ package ml.docilealligator.infinityforreddit; import android.os.AsyncTask; -import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.lifecycle.MutableLiveData; import androidx.paging.PageKeyedDataSource; @@ -23,8 +23,11 @@ public class CommentDataSource extends PageKeyedDataSource private Retrofit retrofit; private Locale locale; + @Nullable + private String accessToken; private String username; private String sortType; + private boolean areSavedComments; private MutableLiveData paginationNetworkStateLiveData; private MutableLiveData initialLoadStateLiveData; @@ -33,11 +36,14 @@ public class CommentDataSource extends PageKeyedDataSource private LoadParams params; private LoadCallback callback; - CommentDataSource(Retrofit retrofit, Locale locale, String username, String sortType) { + CommentDataSource(Retrofit retrofit, Locale locale, @Nullable String accessToken, String username, String sortType, + boolean areSavedComments) { this.retrofit = retrofit; this.locale = locale; + this.accessToken = accessToken; this.username = username; this.sortType = sortType; + this.areSavedComments = areSavedComments; paginationNetworkStateLiveData = new MutableLiveData<>(); initialLoadStateLiveData = new MutableLiveData<>(); hasPostLiveData = new MutableLiveData<>(); @@ -64,7 +70,18 @@ public class CommentDataSource extends PageKeyedDataSource initialLoadStateLiveData.postValue(NetworkState.LOADING); RedditAPI api = retrofit.create(RedditAPI.class); - Call commentsCall = api.getUserComments(username, null, sortType); + Call commentsCall; + if(areSavedComments) { + commentsCall = api.getUserSavedCommentsOauth(username, PostDataSource.USER_WHERE_SAVED, + null, sortType, RedditUtils.getOAuthHeader(accessToken)); + } else { + if(accessToken == null) { + commentsCall = api.getUserComments(username, null, sortType); + } else { + commentsCall = api.getUserCommentsOauth(RedditUtils.getOAuthHeader(accessToken), username, + null, sortType); + } + } commentsCall.enqueue(new Callback() { @Override public void onResponse(@NonNull Call call, @NonNull Response response) { @@ -116,8 +133,19 @@ public class CommentDataSource extends PageKeyedDataSource paginationNetworkStateLiveData.postValue(NetworkState.LOADING); RedditAPI api = retrofit.create(RedditAPI.class); - Call bestPost = api.getUserComments(username, params.key, sortType); - bestPost.enqueue(new Callback() { + Call commentsCall; + if(areSavedComments) { + commentsCall = api.getUserSavedCommentsOauth(username, PostDataSource.USER_WHERE_SAVED, params.key, + sortType, RedditUtils.getOAuthHeader(accessToken)); + } else { + if(accessToken == null) { + commentsCall = api.getUserComments(username, params.key, sortType); + } else { + commentsCall = api.getUserCommentsOauth(RedditUtils.getOAuthHeader(accessToken), + username, params.key, sortType); + } + } + commentsCall.enqueue(new Callback() { @Override public void onResponse(@NonNull Call call, @NonNull Response response) { if(response.isSuccessful()) { @@ -150,9 +178,10 @@ public class CommentDataSource extends PageKeyedDataSource } private static class ParseCommentAsyncTask extends AsyncTask, ArrayList> { - private String response; private String after; private Locale locale; + private JSONArray commentsJSONArray; + private boolean parseFailed; private ParseCommentAsyncTaskListener parseCommentAsyncTaskListener; interface ParseCommentAsyncTaskListener { @@ -161,27 +190,33 @@ public class CommentDataSource extends PageKeyedDataSource } ParseCommentAsyncTask(String response, Locale locale, ParseCommentAsyncTaskListener parseCommentAsyncTaskListener) { - this.response = response; this.locale = locale; this.parseCommentAsyncTaskListener = parseCommentAsyncTaskListener; + try { + JSONObject data = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY); + commentsJSONArray = data.getJSONArray(JSONUtils.CHILDREN_KEY); + after = data.getString(JSONUtils.AFTER_KEY); + parseFailed = false; + } catch (JSONException e) { + parseFailed = true; + e.printStackTrace(); + } } @Override protected ArrayList doInBackground(Void... voids) { - try { - JSONObject data = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY); - JSONArray commentsJSONArray = data.getJSONArray(JSONUtils.CHILDREN_KEY); - ArrayList comments = new ArrayList<>(); - for(int i = 0; i < commentsJSONArray.length(); i++) { + if(parseFailed) { + return null; + } + + ArrayList comments = new ArrayList<>(); + for(int i = 0; i < commentsJSONArray.length(); i++) { + try { JSONObject commentJSON = commentsJSONArray.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); comments.add(ParseComment.parseSingleComment(commentJSON, 0, locale)); - } - after = data.getString(JSONUtils.AFTER_KEY); - return comments; - } catch (JSONException e) { - e.printStackTrace(); + } catch (JSONException ignored) {} } - return null; + return comments; } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSourceFactory.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSourceFactory.java index bfe83a82..2a586d2f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSourceFactory.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentDataSourceFactory.java @@ -1,6 +1,7 @@ package ml.docilealligator.infinityforreddit; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.lifecycle.MutableLiveData; import androidx.paging.DataSource; @@ -11,24 +12,31 @@ import retrofit2.Retrofit; class CommentDataSourceFactory extends DataSource.Factory { private Retrofit retrofit; private Locale locale; + private String accessToken; private String username; private String sortType; + private boolean areSavedComments; private CommentDataSource commentDataSource; private MutableLiveData commentDataSourceLiveData; - CommentDataSourceFactory(Retrofit retrofit, Locale locale, String username, String sortType) { + CommentDataSourceFactory(Retrofit retrofit, Locale locale, @Nullable String accessToken, + String username, String sortType, + boolean areSavedComments) { this.retrofit = retrofit; this.locale = locale; + this.accessToken = accessToken; this.username = username; this.sortType = sortType; + this.areSavedComments = areSavedComments; commentDataSourceLiveData = new MutableLiveData<>(); } @NonNull @Override public DataSource create() { - commentDataSource = new CommentDataSource(retrofit, locale, username, sortType); + commentDataSource = new CommentDataSource(retrofit, locale, accessToken, username, sortType, + areSavedComments); commentDataSourceLiveData.postValue(commentDataSource); return commentDataSource; } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java index 4f5c1e92..e5c4519d 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentViewModel.java @@ -21,8 +21,10 @@ public class CommentViewModel extends ViewModel { private LiveData> comments; private MutableLiveData sortTypeLiveData; - public CommentViewModel(Retrofit retrofit, Locale locale, String username, String sortType) { - commentDataSourceFactory = new CommentDataSourceFactory(retrofit, locale, username, sortType); + public CommentViewModel(Retrofit retrofit, Locale locale, String accessToken, String username, String sortType, + boolean areSavedComments) { + commentDataSourceFactory = new CommentDataSourceFactory(retrofit, locale, accessToken, username, sortType, + areSavedComments); initialLoadingState = Transformations.switchMap(commentDataSourceFactory.getCommentDataSourceLiveData(), CommentDataSource::getInitialLoadStateLiveData); @@ -77,20 +79,25 @@ public class CommentViewModel extends ViewModel { public static class Factory extends ViewModelProvider.NewInstanceFactory { private Retrofit retrofit; private Locale locale; + private String accessToken; private String username; private String sortType; + private boolean areSavedComments; - public Factory(Retrofit retrofit, Locale locale, String username, String sortType) { + public Factory(Retrofit retrofit, Locale locale, String accessToken, String username, + String sortType, boolean areSavedComments) { this.retrofit = retrofit; this.locale = locale; + this.accessToken = accessToken; this.username = username; this.sortType = sortType; + this.areSavedComments = areSavedComments; } @NonNull @Override public T create(@NonNull Class modelClass) { - return (T) new CommentViewModel(retrofit, locale, username, sortType); + return (T) new CommentViewModel(retrofit, locale, accessToken, username, sortType, areSavedComments); } } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingFragment.java index b2dafa7f..e90e032d 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/CommentsListingFragment.java @@ -38,9 +38,13 @@ import retrofit2.Retrofit; */ public class CommentsListingFragment extends Fragment implements FragmentCommunicator { - static final String EXTRA_USERNAME_KEY = "ENK"; + static final String EXTRA_USERNAME = "EN"; static final String EXTRA_ACCESS_TOKEN = "EAT"; static final String EXTRA_ACCOUNT_NAME = "EAN"; + static final String EXTRA_ARE_SAVED_COMMENTS = "EISC"; + + private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; + private static final String ACCESS_TOKEN_STATE = "ATS"; @BindView(R.id.coordinator_layout_comments_listing_fragment) CoordinatorLayout mCoordinatorLayout; @BindView(R.id.recycler_view_comments_listing_fragment) RecyclerView mCommentRecyclerView; @@ -49,6 +53,9 @@ public class CommentsListingFragment extends Fragment implements FragmentCommuni @BindView(R.id.fetch_comments_info_image_view_comments_listing_fragment) ImageView mFetchCommentInfoImageView; @BindView(R.id.fetch_comments_info_text_view_comments_listing_fragment) TextView mFetchCommentInfoTextView; + private boolean mNullAccessToken = false; + private String mAccessToken; + private RequestManager mGlide; private Activity activity; @@ -64,6 +71,9 @@ public class CommentsListingFragment extends Fragment implements FragmentCommuni @Inject @Named("oauth") Retrofit mOauthRetrofit; + @Inject + RedditDataRoomDatabase mRedditDataRoomDatabase; + public CommentsListingFragment() { // Required empty public constructor } @@ -91,18 +101,56 @@ public class CommentsListingFragment extends Fragment implements FragmentCommuni } } + if (savedInstanceState == null) { + getCurrentAccountAndBindView(resources); + } else { + mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE); + mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); + + if (!mNullAccessToken && mAccessToken == null) { + getCurrentAccountAndBindView(resources); + } else { + bindView(resources); + } + } + + return rootView; + } + + private void getCurrentAccountAndBindView(Resources resources) { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + } + bindView(resources); + }).execute(); + } + + private void bindView(Resources resources) { mCommentRecyclerView.setLayoutManager(new LinearLayoutManager(activity)); mAdapter = new CommentsListingRecyclerViewAdapter(activity, mOauthRetrofit, getArguments().getString(EXTRA_ACCESS_TOKEN), getArguments().getString(EXTRA_ACCOUNT_NAME), () -> mCommentViewModel.retryLoadingMore()); - String username = getArguments().getString(EXTRA_USERNAME_KEY); + String username = getArguments().getString(EXTRA_USERNAME); mCommentRecyclerView.setAdapter(mAdapter); - CommentViewModel.Factory factory = new CommentViewModel.Factory(mRetrofit, - resources.getConfiguration().locale, username, PostDataSource.SORT_TYPE_NEW); + CommentViewModel.Factory factory; + + if(mAccessToken == null) { + factory = new CommentViewModel.Factory(mRetrofit, + resources.getConfiguration().locale, mAccessToken, username, PostDataSource.SORT_TYPE_NEW, + getArguments().getBoolean(EXTRA_ARE_SAVED_COMMENTS)); + } else { + factory = new CommentViewModel.Factory(mOauthRetrofit, + resources.getConfiguration().locale, mAccessToken, username, PostDataSource.SORT_TYPE_NEW, + getArguments().getBoolean(EXTRA_ARE_SAVED_COMMENTS)); + } + mCommentViewModel = new ViewModelProvider(this, factory).get(CommentViewModel.class); mCommentViewModel.getComments().observe(this, comments -> mAdapter.submitList(comments)); @@ -130,11 +178,7 @@ public class CommentsListingFragment extends Fragment implements FragmentCommuni } }); - mCommentViewModel.getPaginationNetworkState().observe(this, networkState -> { - mAdapter.setNetworkState(networkState); - }); - - return rootView; + mCommentViewModel.getPaginationNetworkState().observe(this, networkState -> mAdapter.setNetworkState(networkState)); } void changeSortType(String sortType) { @@ -147,6 +191,13 @@ public class CommentsListingFragment extends Fragment implements FragmentCommuni this.activity = (Activity) context; } + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString(ACCESS_TOKEN_STATE, mAccessToken); + outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); + } + @Override public void refresh() { mFetchCommentInfoLinearLayout.setVisibility(View.GONE); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java index f07c0f39..d4365b0a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java @@ -625,8 +625,7 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe }); savedLinearLayout.setOnClickListener(view -> { - Intent intent = new Intent(MainActivity.this, AccountPostsActivity.class); - intent.putExtra(AccountPostsActivity.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_SAVED); + Intent intent = new Intent(MainActivity.this, AccountSavedThingActivity.class); startActivity(intent); drawer.closeDrawers(); }); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java index bf8334d6..0f34840a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ParsePost.java @@ -113,17 +113,19 @@ class ParsePost { for (int i = 0; i < size; i++) { try { - JSONObject data = allData.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); - Post post = parseBasicData(data, locale); - if(!(!nsfw && post.isNSFW())) { - if (filter == PostFragment.EXTRA_NO_FILTER) { - newPosts.add(post); - } else if (filter == post.getPostType()) { - newPosts.add(post); - } else if (filter == Post.LINK_TYPE && post.getPostType() == Post.NO_PREVIEW_LINK_TYPE) { - newPosts.add(post); - } else if(filter == Post.NSFW_TYPE && post.isNSFW()) { - newPosts.add(post); + if(allData.getJSONObject(i).getString(JSONUtils.KIND_KEY).equals("t3")) { + JSONObject data = allData.getJSONObject(i).getJSONObject(JSONUtils.DATA_KEY); + Post post = parseBasicData(data, locale); + if(post != null && !(!nsfw && post.isNSFW())) { + if (filter == PostFragment.EXTRA_NO_FILTER) { + newPosts.add(post); + } else if (filter == post.getPostType()) { + newPosts.add(post); + } else if (filter == Post.LINK_TYPE && post.getPostType() == Post.NO_PREVIEW_LINK_TYPE) { + newPosts.add(post); + } else if(filter == Post.NSFW_TYPE && post.isNSFW()) { + newPosts.add(post); + } } } } catch (JSONException e) { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java index 970e902a..c1030f3a 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PostDataSource.java @@ -1,7 +1,5 @@ package ml.docilealligator.infinityforreddit; -import android.util.Log; - import androidx.annotation.NonNull; import androidx.lifecycle.MutableLiveData; import androidx.paging.PageKeyedDataSource; @@ -412,9 +410,9 @@ class PostDataSource extends PageKeyedDataSource { Call getPost; if(accessToken == null) { - getPost = api.getUserBestPosts(subredditOrUserName, lastItem, sortType); + getPost = api.getUserPosts(subredditOrUserName, lastItem, sortType); } else { - getPost = api.getUserBestPostsOauth(subredditOrUserName, userWhere, lastItem, sortType, + getPost = api.getUserPostsOauth(subredditOrUserName, userWhere, lastItem, sortType, RedditUtils.getOAuthHeader(accessToken)); } getPost.enqueue(new Callback() { @@ -470,9 +468,9 @@ class PostDataSource extends PageKeyedDataSource { Call getPost; if(accessToken == null) { - getPost = api.getUserBestPosts(subredditOrUserName, after, sortType); + getPost = api.getUserPosts(subredditOrUserName, after, sortType); } else { - getPost = api.getUserBestPostsOauth(subredditOrUserName, userWhere, after, sortType, + getPost = api.getUserPostsOauth(subredditOrUserName, userWhere, after, sortType, RedditUtils.getOAuthHeader(accessToken)); } getPost.enqueue(new Callback() { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java index 8a9b8a9e..b7189918 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/RedditAPI.java @@ -51,13 +51,13 @@ public interface RedditAPI { Call getSubredditBestPosts(@Path("subredditName") String subredditName, @Path("sortType") String sortType, @Query("after") String lastItem); - @GET("user/{username}/{where}.json?&raw_json=1&limit=25") - Call getUserBestPostsOauth(@Path("username") String username, @Path("where") String where, - @Query("after") String lastItem, @Query("sort") String sortType, @HeaderMap Map headers); + @GET("user/{username}/{where}.json?&type=links&raw_json=1&limit=25") + Call getUserPostsOauth(@Path("username") String username, @Path("where") String where, + @Query("after") String lastItem, @Query("sort") String sortType, @HeaderMap Map headers); @GET("user/{username}/submitted.json?raw_json=1&limit=25") - Call getUserBestPosts(@Path("username") String username, @Query("after") String lastItem, - @Query("sort") String sortType); + Call getUserPosts(@Path("username") String username, @Query("after") String lastItem, + @Query("sort") String sortType); @GET("user/{username}/about.json?raw_json=1") Call getUserData(@Path("username") String username); @@ -66,6 +66,14 @@ public interface RedditAPI { Call getUserComments(@Path("username") String username, @Query("after") String after, @Query("sort") String sortType); + @GET("user/{username}/comments.json?raw_json=1") + Call getUserCommentsOauth(@HeaderMap Map headers, @Path("username") String username, + @Query("after") String after, @Query("sort") String sortType); + + @GET("user/{username}/{where}.json?&type=comments&raw_json=1&limit=25") + Call getUserSavedCommentsOauth(@Path("username") String username, @Path("where") String where, + @Query("after") String lastItem, @Query("sort") String sortType, @HeaderMap Map headers); + @FormUrlEncoded @POST("api/subscribe") Call subredditSubscription(@HeaderMap Map headers, @FieldMap Map params); @@ -76,29 +84,29 @@ public interface RedditAPI { @GET("/api/info.json?raw_json=1") Call getInfoOauth(@Query("id") String id, @HeaderMap Map headers); - @GET("subreddits/search.json?raw_json=1") + @GET("subreddits/search.json?include_over_18=1&raw_json=1") Call searchSubreddits(@Query("q") String subredditName, @Query("after") String after, @Query("sort") String sort); - @GET("search.json?raw_json=1&type=user") + @GET("search.json?include_over_18=1&raw_json=1&type=user") Call searchUsers(@Query("q") String profileName, @Query("after") String after, @Query("sort") String sort); - @GET("search.json?raw_json=1&type=link") + @GET("search.json?include_over_18=1&raw_json=1&type=link") Call searchPostsOauth(@Query("q") String query, @Query("after") String after, @Query("sort") String sort, @HeaderMap Map headers); - @GET("search.json?raw_json=1&type=link") + @GET("search.json?include_over_18=1&raw_json=1&type=link") Call searchPosts(@Query("q") String query, @Query("after") String after, @Query("sort") String sort); - @GET("r/{subredditName}/search.json?raw_json=1&type=link&restrict_sr=true") + @GET("r/{subredditName}/search.json?include_over_18=1&raw_json=1&type=link&restrict_sr=true") Call searchPostsInSpecificSubredditOauth(@Path("subredditName") String subredditName, @Query("q") String query, @Query("after") String after, @HeaderMap Map headers); - @GET("r/{subredditName}/search.json?raw_json=1&type=link&restrict_sr=true") + @GET("r/{subredditName}/search.json?include_over_18=1&raw_json=1&type=link&restrict_sr=true") Call searchPostsInSpecificSubreddit(@Path("subredditName") String subredditName, @Query("q") String query, @Query("after") String after); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java index 9dbe7d9a..91525a3e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java @@ -667,9 +667,10 @@ public class ViewUserDetailActivity extends AppCompatActivity implements UserThi } CommentsListingFragment fragment = new CommentsListingFragment(); Bundle bundle = new Bundle(); - bundle.putString(CommentsListingFragment.EXTRA_USERNAME_KEY, username); + bundle.putString(CommentsListingFragment.EXTRA_USERNAME, username); bundle.putString(CommentsListingFragment.EXTRA_ACCESS_TOKEN, mAccessToken); bundle.putString(CommentsListingFragment.EXTRA_ACCOUNT_NAME, mAccountName); + bundle.putBoolean(CommentsListingFragment.EXTRA_ARE_SAVED_COMMENTS, false); fragment.setArguments(bundle); return fragment; } diff --git a/app/src/main/res/layout/activity_account_saved_thing.xml b/app/src/main/res/layout/activity_account_saved_thing.xml new file mode 100644 index 00000000..868f3b37 --- /dev/null +++ b/app/src/main/res/layout/activity_account_saved_thing.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/account_posts_activity.xml b/app/src/main/res/menu/account_posts_activity.xml index cf39a53d..18781e33 100644 --- a/app/src/main/res/menu/account_posts_activity.xml +++ b/app/src/main/res/menu/account_posts_activity.xml @@ -1,23 +1,16 @@ - \ No newline at end of file diff --git a/app/src/main/res/menu/account_saved_thing_activity.xml b/app/src/main/res/menu/account_saved_thing_activity.xml new file mode 100644 index 00000000..1e7717fc --- /dev/null +++ b/app/src/main/res/menu/account_saved_thing_activity.xml @@ -0,0 +1,17 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 774871ce..51149699 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,6 +15,7 @@ Edit Comment Inbox Settings + Saved Open navigation drawer Close navigation drawer