mirror of
https://codeberg.org/Bazsalanszky/Infinity-For-Lemmy.git
synced 2025-01-11 10:47:11 +01:00
View messages in ViewMessageActivity. Use LinkResolverActivity to handle link clicking in CustomMarkwonView. Fixed cannot load user profile image after the post is deleted.
This commit is contained in:
parent
1984332fdd
commit
ffd1d6e204
4
.idea/assetWizardSettings.xml
generated
4
.idea/assetWizardSettings.xml
generated
@ -35,9 +35,9 @@
|
||||
<map>
|
||||
<entry key="assetSourceType" value="FILE" />
|
||||
<entry key="color" value="ffffff" />
|
||||
<entry key="outputName" value="ic_outline_star_border_24px" />
|
||||
<entry key="outputName" value="ic_outline_inbox_24px" />
|
||||
<entry key="overrideSize" value="true" />
|
||||
<entry key="sourceFile" value="$USER_HOME$/Downloads/outline-star_border-24px.svg" />
|
||||
<entry key="sourceFile" value="$USER_HOME$/Downloads/outline-inbox-24px.svg" />
|
||||
</map>
|
||||
</option>
|
||||
</PersistentState>
|
||||
|
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
BIN
.idea/caches/gradle_models.ser
generated
BIN
.idea/caches/gradle_models.ser
generated
Binary file not shown.
@ -20,7 +20,13 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="true">
|
||||
<activity android:name=".AccountPostsActivity"
|
||||
<activity
|
||||
android:name=".ViewMessageActivity"
|
||||
android:label="@string/view_message_activity"
|
||||
android:parentActivityName=".MainActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
<activity
|
||||
android:name=".AccountPostsActivity"
|
||||
android:parentActivityName=".MainActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
<activity
|
||||
|
@ -6,11 +6,8 @@ import android.net.Uri;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.browser.customtabs.CustomTabsIntent;
|
||||
|
||||
import ml.docilealligator.infinityforreddit.R;
|
||||
import ml.docilealligator.infinityforreddit.ViewSubredditDetailActivity;
|
||||
import ml.docilealligator.infinityforreddit.ViewUserDetailActivity;
|
||||
import ml.docilealligator.infinityforreddit.LinkResolverActivity;
|
||||
import ru.noties.markwon.SpannableConfiguration;
|
||||
import ru.noties.markwon.view.MarkwonView;
|
||||
|
||||
@ -26,30 +23,14 @@ public class CustomMarkwonView extends MarkwonView {
|
||||
|
||||
public void setMarkdown(@Nullable String markdown, Context context) {
|
||||
SpannableConfiguration configuration = SpannableConfiguration.builder(context).linkResolver((view, link) -> {
|
||||
if(link.startsWith("/u/") || link.startsWith("u/")) {
|
||||
Intent intent = new Intent(context, ViewUserDetailActivity.class);
|
||||
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, link.substring(3));
|
||||
context.startActivity(intent);
|
||||
} else if(link.startsWith("/r/") || link.startsWith("r/")) {
|
||||
Intent intent = new Intent(context, ViewSubredditDetailActivity.class);
|
||||
intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, link.substring(3));
|
||||
context.startActivity(intent);
|
||||
Intent intent = new Intent(context, LinkResolverActivity.class);
|
||||
Uri uri = Uri.parse(link);
|
||||
if(uri.getScheme() == null && uri.getHost() == null) {
|
||||
intent.setData(LinkResolverActivity.getRedditUriByPath(link));
|
||||
} else {
|
||||
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
|
||||
// add share action to menu list
|
||||
builder.addDefaultShareMenuItem();
|
||||
builder.setToolbarColor(context.getResources().getColor(R.color.colorPrimary));
|
||||
CustomTabsIntent customTabsIntent = builder.build();
|
||||
Uri uri = Uri.parse(link);
|
||||
if(uri.getHost() != null && uri.getHost().contains("reddit.com")) {
|
||||
customTabsIntent.intent.setPackage(context.getPackageName());
|
||||
}
|
||||
String uriString = uri.toString();
|
||||
if(!uriString.startsWith("http://") && (!uriString.startsWith("https://"))) {
|
||||
uriString = "http://" + uriString;
|
||||
}
|
||||
customTabsIntent.launchUrl(context, Uri.parse(uriString));
|
||||
intent.setData(uri);
|
||||
}
|
||||
context.startActivity(intent);
|
||||
}).build();
|
||||
|
||||
super.setMarkdown(configuration, markdown);
|
||||
|
@ -35,4 +35,5 @@ interface AppComponent {
|
||||
void inject(EditCommentActivity editCommentActivity);
|
||||
void inject(AccountPostsActivity accountPostsActivity);
|
||||
void inject(PullNotificationWorker pullNotificationWorker);
|
||||
void inject(ViewMessageActivity viewMessageActivity);
|
||||
}
|
||||
|
@ -72,7 +72,6 @@ class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVie
|
||||
private String mSingleCommentId;
|
||||
private boolean mIsSingleCommentThreadMode;
|
||||
private CommentRecyclerViewAdapterCallback mCommentRecyclerViewAdapterCallback;
|
||||
private LoadSubredditIconAsyncTask mLoadSubredditIconAsyncTask;
|
||||
private boolean isInitiallyLoading;
|
||||
private boolean isInitiallyLoadingFailed;
|
||||
private boolean mHasMoreComments;
|
||||
@ -87,7 +86,6 @@ class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVie
|
||||
RedditDataRoomDatabase redditDataRoomDatabase, RequestManager glide,
|
||||
String accessToken, String accountName, Post post, Locale locale,
|
||||
String singleCommentId, boolean isSingleCommentThreadMode,
|
||||
LoadSubredditIconAsyncTask loadSubredditIconAsyncTask,
|
||||
CommentRecyclerViewAdapterCallback commentRecyclerViewAdapterCallback) {
|
||||
mActivity = activity;
|
||||
mRetrofit = retrofit;
|
||||
@ -102,7 +100,6 @@ class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVie
|
||||
mLocale = locale;
|
||||
mSingleCommentId = singleCommentId;
|
||||
mIsSingleCommentThreadMode = isSingleCommentThreadMode;
|
||||
mLoadSubredditIconAsyncTask = loadSubredditIconAsyncTask;
|
||||
mCommentRecyclerViewAdapterCallback = commentRecyclerViewAdapterCallback;
|
||||
isInitiallyLoading = true;
|
||||
isInitiallyLoadingFailed = false;
|
||||
@ -194,10 +191,10 @@ class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVie
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
if(holder.getItemViewType() == VIEW_TYPE_POST_DETAIL) {
|
||||
((PostDetailViewHolder) holder).mTitleTextView.setText(mPost.getTitle());
|
||||
|
||||
if(mPost.getSubredditNamePrefixed().equals("u/" + mPost.getAuthor())) {
|
||||
if(mPost.getSubredditNamePrefixed().startsWith("u/")) {
|
||||
if(mPost.getAuthorIconUrl() == null) {
|
||||
new LoadUserDataAsyncTask(mRedditDataRoomDatabase.userDao(), mPost.getAuthor(), mOauthRetrofit, iconImageUrl -> {
|
||||
String authorName = mPost.getAuthor().equals("[deleted]") ? mPost.getSubredditNamePrefixed().substring(2) : mPost.getAuthor();
|
||||
new LoadUserDataAsyncTask(mRedditDataRoomDatabase.userDao(), authorName, mOauthRetrofit, iconImageUrl -> {
|
||||
if(mActivity != null && getItemCount() > 0) {
|
||||
if(iconImageUrl == null || iconImageUrl.equals("")) {
|
||||
mGlide.load(R.drawable.subreddit_default_icon)
|
||||
@ -229,10 +226,7 @@ class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVie
|
||||
}
|
||||
} else {
|
||||
if(mPost.getSubredditIconUrl() == null) {
|
||||
if(mLoadSubredditIconAsyncTask != null) {
|
||||
mLoadSubredditIconAsyncTask.cancel(true);
|
||||
}
|
||||
mLoadSubredditIconAsyncTask = new LoadSubredditIconAsyncTask(
|
||||
new LoadSubredditIconAsyncTask(
|
||||
mRedditDataRoomDatabase.subredditDao(), mPost.getSubredditNamePrefixed().substring(2),
|
||||
mRetrofit, iconImageUrl -> {
|
||||
if(iconImageUrl == null || iconImageUrl.equals("")) {
|
||||
@ -248,9 +242,7 @@ class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVie
|
||||
}
|
||||
|
||||
mPost.setSubredditIconUrl(iconImageUrl);
|
||||
});
|
||||
|
||||
mLoadSubredditIconAsyncTask.execute();
|
||||
}).execute();
|
||||
} else if(!mPost.getSubredditIconUrl().equals("")) {
|
||||
mGlide.load(mPost.getSubredditIconUrl())
|
||||
.apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))
|
||||
@ -713,10 +705,6 @@ class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerVie
|
||||
}
|
||||
|
||||
void initiallyLoading() {
|
||||
if(mLoadSubredditIconAsyncTask != null) {
|
||||
mLoadSubredditIconAsyncTask.cancel(true);
|
||||
}
|
||||
|
||||
if(mVisibleComments.size() != 0) {
|
||||
int previousSize = mVisibleComments.size();
|
||||
mVisibleComments.clear();
|
||||
|
@ -87,7 +87,11 @@ public class CommentDataSource extends PageKeyedDataSource<String, CommentData>
|
||||
hasPostLiveData.postValue(true);
|
||||
}
|
||||
|
||||
callback.onResult(comments, null, after);
|
||||
if(after == null || after.equals("") || after.equals("null")) {
|
||||
callback.onResult(comments, null, null);
|
||||
} else {
|
||||
callback.onResult(comments, null, after);
|
||||
}
|
||||
initialLoadStateLiveData.postValue(NetworkState.LOADED);
|
||||
}
|
||||
|
||||
@ -147,13 +151,15 @@ public class CommentDataSource extends PageKeyedDataSource<String, CommentData>
|
||||
}
|
||||
}).execute();
|
||||
} else {
|
||||
paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data"));
|
||||
Log.i("Comments fetch error", "Error fetching data");
|
||||
paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetching data"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
|
||||
paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error parsing data"));
|
||||
Log.i("Comments fetch error", "Error fetchin data");
|
||||
paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetching data"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -57,13 +57,13 @@ class CommentsListingRecyclerViewAdapter extends PagedListAdapter<CommentData, R
|
||||
|
||||
private static final DiffUtil.ItemCallback<CommentData> DIFF_CALLBACK = new DiffUtil.ItemCallback<CommentData>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull CommentData CommentData, @NonNull CommentData t1) {
|
||||
return CommentData.getId().equals(t1.getId());
|
||||
public boolean areItemsTheSame(@NonNull CommentData commentData, @NonNull CommentData t1) {
|
||||
return commentData.getId().equals(t1.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull CommentData CommentData, @NonNull CommentData t1) {
|
||||
return CommentData.getCommentContent().equals(t1.getCommentContent());
|
||||
public boolean areContentsTheSame(@NonNull CommentData commentData, @NonNull CommentData t1) {
|
||||
return commentData.getCommentContent().equals(t1.getCommentContent());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -22,8 +22,8 @@ import retrofit2.Retrofit;
|
||||
class FetchMessages {
|
||||
|
||||
interface FetchMessagesListener {
|
||||
void fetchSuccess(@Nullable ArrayList<Message> messages);
|
||||
void fetchFailed(boolean shouldRetry);
|
||||
void fetchSuccess(ArrayList<Message> messages, @Nullable String after);
|
||||
void fetchFailed();
|
||||
}
|
||||
|
||||
static final String WHERE_INBOX = "inbox";
|
||||
@ -32,22 +32,21 @@ class FetchMessages {
|
||||
static final String WHERE_COMMENTS = "comments";
|
||||
|
||||
static void fetchMessagesAsync(Retrofit oauthRetrofit, Locale locale, String accessToken, String where,
|
||||
FetchMessagesListener fetchMessagesListener) {
|
||||
oauthRetrofit.create(RedditAPI.class).getMessages(RedditUtils.getOAuthHeader(accessToken), where)
|
||||
String after, FetchMessagesListener fetchMessagesListener) {
|
||||
oauthRetrofit.create(RedditAPI.class).getMessages(RedditUtils.getOAuthHeader(accessToken), where, after)
|
||||
.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
|
||||
if(response.isSuccessful()) {
|
||||
new ParseMessageAsnycTask(response.body(), locale,
|
||||
fetchMessagesListener::fetchSuccess).execute();
|
||||
new ParseMessageAsnycTask(response.body(), locale, fetchMessagesListener::fetchSuccess).execute();
|
||||
} else {
|
||||
fetchMessagesListener.fetchFailed(true);
|
||||
fetchMessagesListener.fetchFailed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
|
||||
fetchMessagesListener.fetchFailed(true);
|
||||
fetchMessagesListener.fetchFailed();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -104,12 +103,13 @@ class FetchMessages {
|
||||
private static class ParseMessageAsnycTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
interface ParseMessageAsyncTaskListener {
|
||||
void parseSuccess(ArrayList<Message> messages);
|
||||
void parseSuccess(ArrayList<Message> messages, @Nullable String after);
|
||||
}
|
||||
|
||||
private String response;
|
||||
private Locale locale;
|
||||
private ArrayList<Message> messages;
|
||||
private String after;
|
||||
private ParseMessageAsyncTaskListener parseMessageAsyncTaskListener;
|
||||
|
||||
ParseMessageAsnycTask(String response, Locale locale, ParseMessageAsyncTaskListener parseMessageAsnycTaskListener) {
|
||||
@ -122,13 +122,18 @@ class FetchMessages {
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
messages = parseMessage(response, locale);
|
||||
try {
|
||||
after = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.AFTER_KEY);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
super.onPostExecute(aVoid);
|
||||
parseMessageAsyncTaskListener.parseSuccess(messages);
|
||||
parseMessageAsyncTaskListener.parseSuccess(messages, after);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,11 +85,10 @@ public class LinkResolverActivity extends AppCompatActivity {
|
||||
builder.setToolbarColor(getResources().getColor(R.color.colorPrimary));
|
||||
CustomTabsIntent customTabsIntent = builder.build();
|
||||
customTabsIntent.intent.setPackage(resolveInfos.get(0).activityInfo.packageName);
|
||||
String uriString = uri.toString();
|
||||
if(!uriString.startsWith("http://") || (!uriString.startsWith("https://"))) {
|
||||
uriString = "http://" + uriString;
|
||||
if(uri.getScheme() == null) {
|
||||
uri = Uri.parse("http://" + uri.toString());
|
||||
}
|
||||
customTabsIntent.launchUrl(this, Uri.parse(uriString));
|
||||
customTabsIntent.launchUrl(this, uri);
|
||||
} else {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(uri);
|
||||
@ -133,7 +132,7 @@ public class LinkResolverActivity extends AppCompatActivity {
|
||||
return packagesSupportingCustomTabs;
|
||||
}
|
||||
|
||||
static Uri getRedditUriByPath(String path) {
|
||||
public static Uri getRedditUriByPath(String path) {
|
||||
return Uri.parse("https://www.reddit.com" + path);
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe
|
||||
@BindView(R.id.all_drawer_items_linear_layout_main_activity) LinearLayout allDrawerItemsLinearLayout;
|
||||
@BindView(R.id.profile_linear_layout_main_activity) LinearLayout profileLinearLayout;
|
||||
@BindView(R.id.subscriptions_linear_layout_main_activity) LinearLayout subscriptionLinearLayout;
|
||||
@BindView(R.id.inbox_linear_layout_main_activity) LinearLayout inboxLinearLayout;
|
||||
@BindView(R.id.upvoted_linear_layout_main_activity) LinearLayout upvotedLinearLayout;
|
||||
@BindView(R.id.downvoted_linear_layout_main_activity) LinearLayout downvotedLinearLayout;
|
||||
@BindView(R.id.hidden_linear_layout_main_activity) LinearLayout hiddenLinearLayout;
|
||||
@ -385,6 +386,12 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe
|
||||
mAccountNameTextView.setText(R.string.anonymous_account);
|
||||
profileLinearLayout.setVisibility(View.GONE);
|
||||
subscriptionLinearLayout.setVisibility(View.GONE);
|
||||
inboxLinearLayout.setVisibility(View.GONE);
|
||||
upvotedLinearLayout.setVisibility(View.GONE);
|
||||
downvotedLinearLayout.setVisibility(View.GONE);
|
||||
hiddenLinearLayout.setVisibility(View.GONE);
|
||||
savedLinearLayout.setVisibility(View.GONE);
|
||||
gildedLinearLayout.setVisibility(View.GONE);
|
||||
divider.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@ -417,6 +424,12 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe
|
||||
drawer.closeDrawers();
|
||||
});
|
||||
|
||||
inboxLinearLayout.setOnClickListener(view -> {
|
||||
Intent intent = new Intent(this, ViewMessageActivity.class);
|
||||
startActivity(intent);
|
||||
drawer.closeDrawers();
|
||||
});
|
||||
|
||||
upvotedLinearLayout.setOnClickListener(view -> {
|
||||
Intent intent = new Intent(MainActivity.this, AccountPostsActivity.class);
|
||||
intent.putExtra(AccountPostsActivity.EXTRA_USER_WHERE, PostDataSource.USER_WHERE_UPVOTED);
|
||||
|
@ -104,7 +104,7 @@ class Message {
|
||||
return formattedTime;
|
||||
}
|
||||
|
||||
public boolean isWasComment() {
|
||||
public boolean wasComment() {
|
||||
return wasComment;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,123 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.paging.PageKeyedDataSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
class MessageDataSource extends PageKeyedDataSource<String, Message> {
|
||||
private Retrofit oauthRetrofit;
|
||||
private Locale locale;
|
||||
private String accessToken;
|
||||
private String where;
|
||||
|
||||
private MutableLiveData<NetworkState> paginationNetworkStateLiveData;
|
||||
private MutableLiveData<NetworkState> initialLoadStateLiveData;
|
||||
private MutableLiveData<Boolean> hasPostLiveData;
|
||||
|
||||
private LoadInitialParams<String> initialParams;
|
||||
private LoadInitialCallback<String, Message> initialCallback;
|
||||
private LoadParams<String> params;
|
||||
private LoadCallback<String, Message> callback;
|
||||
|
||||
MessageDataSource(Retrofit oauthRetrofit, Locale locale, String accessToken, String where) {
|
||||
this.oauthRetrofit = oauthRetrofit;
|
||||
this.locale = locale;
|
||||
this.accessToken = accessToken;
|
||||
this.where = where;
|
||||
paginationNetworkStateLiveData = new MutableLiveData<>();
|
||||
initialLoadStateLiveData = new MutableLiveData<>();
|
||||
hasPostLiveData = new MutableLiveData<>();
|
||||
}
|
||||
|
||||
MutableLiveData<NetworkState> getPaginationNetworkStateLiveData() {
|
||||
return paginationNetworkStateLiveData;
|
||||
}
|
||||
|
||||
MutableLiveData<NetworkState> getInitialLoadStateLiveData() {
|
||||
return initialLoadStateLiveData;
|
||||
}
|
||||
|
||||
MutableLiveData<Boolean> hasPostLiveData() {
|
||||
return hasPostLiveData;
|
||||
}
|
||||
|
||||
void retry() {
|
||||
loadInitial(initialParams, initialCallback);
|
||||
}
|
||||
|
||||
void retryLoadingMore() {
|
||||
loadAfter(params, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadInitial(@NonNull LoadInitialParams<String> params, @NonNull LoadInitialCallback<String, Message> callback) {
|
||||
initialParams = params;
|
||||
initialCallback = callback;
|
||||
|
||||
initialLoadStateLiveData.postValue(NetworkState.LOADING);
|
||||
|
||||
FetchMessages.fetchMessagesAsync(oauthRetrofit, locale, accessToken, where, null, new FetchMessages.FetchMessagesListener() {
|
||||
@Override
|
||||
public void fetchSuccess(ArrayList<Message> messages, @Nullable String after) {
|
||||
if(messages.size() == 0) {
|
||||
hasPostLiveData.postValue(false);
|
||||
} else {
|
||||
hasPostLiveData.postValue(true);
|
||||
}
|
||||
|
||||
if(after == null || after.equals("") || after.equals("null")) {
|
||||
callback.onResult(messages, null, null);
|
||||
} else {
|
||||
callback.onResult(messages, null, after);
|
||||
}
|
||||
initialLoadStateLiveData.postValue(NetworkState.LOADED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchFailed() {
|
||||
Log.i("Messages fetch error", "Error fetch messages");
|
||||
initialLoadStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetch messages"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBefore(@NonNull LoadParams<String> params, @NonNull LoadCallback<String, Message> callback) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAfter(@NonNull LoadParams<String> params, @NonNull LoadCallback<String, Message> callback) {
|
||||
this.params = params;
|
||||
this.callback = callback;
|
||||
|
||||
paginationNetworkStateLiveData.postValue(NetworkState.LOADING);
|
||||
|
||||
FetchMessages.fetchMessagesAsync(oauthRetrofit, locale, accessToken, where, params.key, new FetchMessages.FetchMessagesListener() {
|
||||
@Override
|
||||
public void fetchSuccess(ArrayList<Message> messages, @Nullable String after) {
|
||||
if(after == null || after.equals("") || after.equals("null")) {
|
||||
callback.onResult(messages, null);
|
||||
} else {
|
||||
callback.onResult(messages, after);
|
||||
}
|
||||
|
||||
paginationNetworkStateLiveData.postValue(NetworkState.LOADED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchFailed() {
|
||||
Log.i("Comments fetch error", "Error parsing data");
|
||||
paginationNetworkStateLiveData.postValue(new NetworkState(NetworkState.Status.FAILED, "Error fetching data"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.paging.DataSource;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
class MessageDataSourceFactory extends DataSource.Factory {
|
||||
private Retrofit oauthRetrofit;
|
||||
private Locale locale;
|
||||
private String accessToken;
|
||||
private String where;
|
||||
|
||||
private MessageDataSource messageDataSource;
|
||||
private MutableLiveData<MessageDataSource> messageDataSourceLiveData;
|
||||
|
||||
MessageDataSourceFactory(Retrofit oauthRetrofit, Locale locale, String accessToken, String where) {
|
||||
this.oauthRetrofit = oauthRetrofit;
|
||||
this.locale = locale;
|
||||
this.accessToken = accessToken;
|
||||
this.where = where;
|
||||
messageDataSourceLiveData = new MutableLiveData<>();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DataSource create() {
|
||||
messageDataSource = new MessageDataSource(oauthRetrofit, locale, accessToken, where);
|
||||
messageDataSourceLiveData.postValue(messageDataSource);
|
||||
return messageDataSource;
|
||||
}
|
||||
|
||||
public MutableLiveData<MessageDataSource> getMessageDataSourceLiveData() {
|
||||
return messageDataSourceLiveData;
|
||||
}
|
||||
|
||||
MessageDataSource getMessageDataSource() {
|
||||
return messageDataSource;
|
||||
}
|
||||
|
||||
void changeWhere(String where) {
|
||||
this.where = where;
|
||||
}
|
||||
}
|
@ -0,0 +1,195 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.paging.PagedListAdapter;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import CustomView.CustomMarkwonView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
class MessageRecyclerViewAdapter extends PagedListAdapter<Message, RecyclerView.ViewHolder> {
|
||||
private static final int VIEW_TYPE_DATA = 0;
|
||||
private static final int VIEW_TYPE_ERROR = 1;
|
||||
private static final int VIEW_TYPE_LOADING = 2;
|
||||
|
||||
private Context mContext;
|
||||
private Resources resources;
|
||||
|
||||
private NetworkState networkState;
|
||||
private CommentsListingRecyclerViewAdapter.RetryLoadingMoreCallback mRetryLoadingMoreCallback;
|
||||
|
||||
interface RetryLoadingMoreCallback {
|
||||
void retryLoadingMore();
|
||||
}
|
||||
|
||||
MessageRecyclerViewAdapter(Context context) {
|
||||
super(DIFF_CALLBACK);
|
||||
mContext = context;
|
||||
resources = context.getResources();
|
||||
}
|
||||
|
||||
private static final DiffUtil.ItemCallback<Message> DIFF_CALLBACK = new DiffUtil.ItemCallback<Message>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull Message message, @NonNull Message t1) {
|
||||
return message.getId().equals(t1.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull Message message, @NonNull Message t1) {
|
||||
return message.getBody().equals(t1.getBody());
|
||||
}
|
||||
};
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if(viewType == VIEW_TYPE_DATA) {
|
||||
return new DataViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message, parent, false));
|
||||
} else if(viewType == VIEW_TYPE_ERROR) {
|
||||
return new ErrorViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_error, parent, false));
|
||||
} else {
|
||||
return new LoadingViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_loading, parent, false));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
if(holder instanceof DataViewHolder) {
|
||||
Message message = getItem(holder.getAdapterPosition());
|
||||
if(message != null) {
|
||||
if(message.isNew()) {
|
||||
((DataViewHolder) holder).itemView.setBackgroundColor(
|
||||
resources.getColor(R.color.unreadMessageBackgroundColor));
|
||||
}
|
||||
|
||||
if(message.wasComment()) {
|
||||
((DataViewHolder) holder).authorTextView.setTextColor(resources.getColor(R.color.colorPrimaryDarkDayNightTheme));
|
||||
((DataViewHolder) holder).titleTextView.setText(message.getTitle());
|
||||
} else {
|
||||
((DataViewHolder) holder).titleTextView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
((DataViewHolder) holder).authorTextView.setText(message.getAuthor());
|
||||
String subject = message.getSubject().substring(0, 1).toUpperCase() + message.getSubject().substring(1);
|
||||
((DataViewHolder) holder).subjectTextView.setText(subject);
|
||||
((DataViewHolder) holder).contentCustomMarkwonView.setMarkdown(message.getBody(), mContext);
|
||||
|
||||
((DataViewHolder) holder).itemView.setOnClickListener(view -> {
|
||||
if(message.getContext() != null && !message.getContext().equals("")) {
|
||||
Uri uri = LinkResolverActivity.getRedditUriByPath(message.getContext());
|
||||
Intent intent = new Intent(mContext, LinkResolverActivity.class);
|
||||
intent.setData(uri);
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
((DataViewHolder) holder).authorTextView.setOnClickListener(view -> {
|
||||
if(message.wasComment()) {
|
||||
Intent intent = new Intent(mContext, ViewUserDetailActivity.class);
|
||||
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, message.getAuthor());
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
((DataViewHolder) holder).contentCustomMarkwonView.setOnClickListener(view -> ((DataViewHolder) holder).itemView.performClick());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
// Reached at the end
|
||||
if (hasExtraRow() && position == getItemCount() - 1) {
|
||||
if (networkState.getStatus() == NetworkState.Status.LOADING) {
|
||||
return VIEW_TYPE_LOADING;
|
||||
} else {
|
||||
return VIEW_TYPE_ERROR;
|
||||
}
|
||||
} else {
|
||||
return VIEW_TYPE_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
if(hasExtraRow()) {
|
||||
return super.getItemCount() + 1;
|
||||
}
|
||||
return super.getItemCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
|
||||
super.onViewRecycled(holder);
|
||||
if(holder instanceof DataViewHolder) {
|
||||
((DataViewHolder) holder).itemView.setBackgroundColor(resources.getColor(android.R.color.white));
|
||||
((DataViewHolder) holder).titleTextView.setVisibility(View.VISIBLE);
|
||||
((DataViewHolder) holder).authorTextView.setTextColor(resources.getColor(R.color.primaryTextColor));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasExtraRow() {
|
||||
return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS;
|
||||
}
|
||||
|
||||
void setNetworkState(NetworkState newNetworkState) {
|
||||
NetworkState previousState = this.networkState;
|
||||
boolean previousExtraRow = hasExtraRow();
|
||||
this.networkState = newNetworkState;
|
||||
boolean newExtraRow = hasExtraRow();
|
||||
if (previousExtraRow != newExtraRow) {
|
||||
if (previousExtraRow) {
|
||||
notifyItemRemoved(super.getItemCount());
|
||||
} else {
|
||||
notifyItemInserted(super.getItemCount());
|
||||
}
|
||||
} else if (newExtraRow && !previousState.equals(newNetworkState)) {
|
||||
notifyItemChanged(getItemCount() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
class DataViewHolder extends RecyclerView.ViewHolder {
|
||||
View itemView;
|
||||
@BindView(R.id.author_text_view_item_message) TextView authorTextView;
|
||||
@BindView(R.id.subject_text_view_item_message) TextView subjectTextView;
|
||||
@BindView(R.id.title_text_view_item_message) TextView titleTextView;
|
||||
@BindView(R.id.content_custom_markwon_view_item_message) CustomMarkwonView contentCustomMarkwonView;
|
||||
|
||||
DataViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
this.itemView = itemView;
|
||||
}
|
||||
}
|
||||
|
||||
class ErrorViewHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.error_text_view_item_footer_error) TextView errorTextView;
|
||||
@BindView(R.id.retry_button_item_footer_error) Button retryButton;
|
||||
|
||||
ErrorViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
errorTextView.setText(R.string.load_comments_failed);
|
||||
retryButton.setOnClickListener(view -> mRetryLoadingMoreCallback.retryLoadingMore());
|
||||
}
|
||||
}
|
||||
|
||||
class LoadingViewHolder extends RecyclerView.ViewHolder {
|
||||
LoadingViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.Transformations;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.paging.LivePagedListBuilder;
|
||||
import androidx.paging.PagedList;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
public class MessageViewModel extends ViewModel {
|
||||
private MessageDataSourceFactory messageDataSourceFactory;
|
||||
private LiveData<NetworkState> paginationNetworkState;
|
||||
private LiveData<NetworkState> initialLoadingState;
|
||||
private LiveData<Boolean> hasMessageLiveData;
|
||||
private LiveData<PagedList<Message>> messages;
|
||||
private MutableLiveData<String> whereLiveData;
|
||||
|
||||
public MessageViewModel(Retrofit retrofit, Locale locale, String accessToken, String where) {
|
||||
messageDataSourceFactory = new MessageDataSourceFactory(retrofit, locale, accessToken, where);
|
||||
|
||||
initialLoadingState = Transformations.switchMap(messageDataSourceFactory.getMessageDataSourceLiveData(),
|
||||
MessageDataSource::getInitialLoadStateLiveData);
|
||||
paginationNetworkState = Transformations.switchMap(messageDataSourceFactory.getMessageDataSourceLiveData(),
|
||||
MessageDataSource::getPaginationNetworkStateLiveData);
|
||||
hasMessageLiveData = Transformations.switchMap(messageDataSourceFactory.getMessageDataSourceLiveData(),
|
||||
MessageDataSource::hasPostLiveData);
|
||||
|
||||
whereLiveData = new MutableLiveData<>();
|
||||
whereLiveData.postValue(where);
|
||||
|
||||
PagedList.Config pagedListConfig =
|
||||
(new PagedList.Config.Builder())
|
||||
.setEnablePlaceholders(false)
|
||||
.setPageSize(25)
|
||||
.build();
|
||||
|
||||
messages = Transformations.switchMap(whereLiveData, newWhere -> {
|
||||
messageDataSourceFactory.changeWhere(whereLiveData.getValue());
|
||||
return (new LivePagedListBuilder(messageDataSourceFactory, pagedListConfig)).build();
|
||||
});
|
||||
}
|
||||
|
||||
LiveData<PagedList<Message>> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
LiveData<NetworkState> getPaginationNetworkState() {
|
||||
return paginationNetworkState;
|
||||
}
|
||||
|
||||
LiveData<NetworkState> getInitialLoadingState() {
|
||||
return initialLoadingState;
|
||||
}
|
||||
|
||||
LiveData<Boolean> hasMessage() {
|
||||
return hasMessageLiveData;
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
messageDataSourceFactory.getMessageDataSource().invalidate();
|
||||
}
|
||||
|
||||
void retry() {
|
||||
messageDataSourceFactory.getMessageDataSource().retry();
|
||||
}
|
||||
|
||||
void retryLoadingMore() {
|
||||
messageDataSourceFactory.getMessageDataSource().retryLoadingMore();
|
||||
}
|
||||
|
||||
void changeWhere(String where) {
|
||||
whereLiveData.postValue(where);
|
||||
}
|
||||
|
||||
public static class Factory extends ViewModelProvider.NewInstanceFactory {
|
||||
private Retrofit retrofit;
|
||||
private Locale locale;
|
||||
private String accessToken;
|
||||
private String where;
|
||||
|
||||
public Factory(Retrofit retrofit, Locale locale, String accessToken, String where) {
|
||||
this.retrofit = retrofit;
|
||||
this.locale = locale;
|
||||
this.accessToken = accessToken;
|
||||
this.where = where;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
|
||||
return (T) new MessageViewModel(retrofit, locale, accessToken, where);
|
||||
}
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ class ParseSubredditData {
|
||||
jsonResponse = new JSONObject(response);
|
||||
parseFailed = false;
|
||||
} catch (JSONException e) {
|
||||
Log.i("subreddit json error", e.getMessage());
|
||||
Log.i("subreddit json error", "message: " + e.getMessage());
|
||||
parseSubredditDataListener.onParseSubredditDataFail();
|
||||
}
|
||||
}
|
||||
@ -54,38 +54,9 @@ class ParseSubredditData {
|
||||
JSONObject data = jsonResponse.getJSONObject(JSONUtils.DATA_KEY);
|
||||
mNCurrentOnlineSubscribers = data.getInt(JSONUtils.ACTIVE_USER_COUNT_KEY);
|
||||
subredditData = parseSubredditData(data);
|
||||
/*String id = data.getString(JSONUtils.EXTRA_NAME);
|
||||
String subredditFullName = data.getString(JSONUtils.DISPLAY_NAME);
|
||||
String description = data.getString(JSONUtils.PUBLIC_DESCRIPTION_KEY).trim();
|
||||
|
||||
String bannerImageUrl;
|
||||
if(data.isNull(JSONUtils.BANNER_BACKGROUND_IMAGE_KEY)) {
|
||||
bannerImageUrl = "";
|
||||
} else {
|
||||
bannerImageUrl = data.getString(JSONUtils.BANNER_BACKGROUND_IMAGE_KEY);
|
||||
}
|
||||
if(bannerImageUrl.equals("") && !data.isNull(JSONUtils.BANNER_IMG_KEY)) {
|
||||
bannerImageUrl= data.getString(JSONUtils.BANNER_IMG_KEY);
|
||||
}
|
||||
|
||||
String iconUrl;
|
||||
if(data.isNull(JSONUtils.COMMUNITY_ICON_KEY)) {
|
||||
iconUrl = "";
|
||||
} else {
|
||||
iconUrl = data.getString(JSONUtils.COMMUNITY_ICON_KEY);
|
||||
}
|
||||
if(iconUrl.equals("") && !data.isNull(JSONUtils.ICON_IMG_KEY)) {
|
||||
iconUrl = data.getString(JSONUtils.ICON_IMG_KEY);
|
||||
}
|
||||
|
||||
int nSubscribers = data.getInt(JSONUtils.SUBSCRIBERS_KEY);
|
||||
int nCurrentOnlineSubscribers = data.getInt(JSONUtils.ACTIVE_USER_COUNT_KEY);
|
||||
subredditData = new SubredditData(id, subredditFullName, iconUrl, bannerImageUrl, description, nSubscribers);
|
||||
mNCurrentOnlineSubscribers = nCurrentOnlineSubscribers;*/
|
||||
} catch (JSONException e) {
|
||||
parseFailed = true;
|
||||
Log.i("parse", "SubredditData error");
|
||||
parseSubredditDataListener.onParseSubredditDataFail();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -114,7 +85,7 @@ class ParseSubredditData {
|
||||
parseFailed = false;
|
||||
subredditListingData = new ArrayList<>();
|
||||
} catch (JSONException e) {
|
||||
Log.i("subreddit json error", e.getMessage());
|
||||
Log.i("subreddit json error", "message: " + e.getMessage());
|
||||
parseFailed = true;
|
||||
}
|
||||
}
|
||||
|
@ -248,7 +248,8 @@ class PostRecyclerViewAdapter extends PagedListAdapter<Post, RecyclerView.ViewHo
|
||||
});
|
||||
} else {
|
||||
if(post.getAuthorIconUrl() == null) {
|
||||
new LoadUserDataAsyncTask(mUserDao, post.getAuthor(), mRetrofit, iconImageUrl -> {
|
||||
String authorName = post.getAuthor().equals("[deleted]") ? post.getSubredditNamePrefixed().substring(2) : post.getAuthor();
|
||||
new LoadUserDataAsyncTask(mUserDao, authorName, mRetrofit, iconImageUrl -> {
|
||||
if(mContext != null && getItemCount() > 0) {
|
||||
if(iconImageUrl == null || iconImageUrl.equals("")) {
|
||||
mGlide.load(R.drawable.subreddit_default_icon)
|
||||
|
@ -49,13 +49,13 @@ public class PullNotificationWorker extends Worker {
|
||||
Account currentAccount = redditDataRoomDatabase.accountDao().getCurrentAccount();
|
||||
Response<String> response = mOauthRetrofit.create(RedditAPI.class).getMessages(
|
||||
RedditUtils.getOAuthHeader(currentAccount.getAccessToken()),
|
||||
FetchMessages.WHERE_COMMENTS).execute();
|
||||
FetchMessages.WHERE_UNREAD, null).execute();
|
||||
Log.i("workmanager", "has response");
|
||||
if(response.isSuccessful()) {
|
||||
String responseBody = response.body();
|
||||
ArrayList<Message> messages = FetchMessages.parseMessage(responseBody, context.getResources().getConfiguration().locale);
|
||||
|
||||
if(messages != null) {
|
||||
if(messages != null && !messages.isEmpty()) {
|
||||
NotificationManagerCompat notificationManager = NotificationUtils.getNotificationManager(context);
|
||||
|
||||
NotificationCompat.Builder summaryBuilder = NotificationUtils.buildSummaryNotification(context,
|
||||
|
@ -158,5 +158,5 @@ public interface RedditAPI {
|
||||
Call<String> selectFlair(@Path("subredditNamePrefixed") String subredditName, @HeaderMap Map<String, String> headers, @FieldMap Map<String, String> params);
|
||||
|
||||
@GET("/message/{where}.json?raw_json=1")
|
||||
Call<String> getMessages(@HeaderMap Map<String, String> headers, @Path("where") String where);
|
||||
Call<String> getMessages(@HeaderMap Map<String, String> headers, @Path("where") String where, @Query("after") String after);
|
||||
}
|
||||
|
@ -0,0 +1,230 @@
|
||||
package ml.docilealligator.infinityforreddit;
|
||||
|
||||
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 android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
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 com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||
import com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import Account.Account;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
public class ViewMessageActivity extends AppCompatActivity {
|
||||
|
||||
private static final String NULL_ACCESS_TOKEN_STATE = "NATS";
|
||||
private static final String ACCESS_TOKEN_STATE = "ATS";
|
||||
|
||||
@BindView(R.id.collapsing_toolbar_layout_view_message_activity) CollapsingToolbarLayout collapsingToolbarLayout;
|
||||
@BindView(R.id.appbar_layout_view_message_activity) AppBarLayout appBarLayout;
|
||||
@BindView(R.id.toolbar_view_message_activity) Toolbar toolbar;
|
||||
@BindView(R.id.progress_bar_view_message_activity) CircleProgressBar mProgressBar;
|
||||
@BindView(R.id.recycler_view_view_message_activity) RecyclerView recyclerView;
|
||||
@BindView(R.id.fetch_messages_info_linear_layout_view_message_activity) LinearLayout mFetchMessageInfoLinearLayout;
|
||||
@BindView(R.id.fetch_messages_info_image_view_view_message_activity) ImageView mFetchMessageInfoImageView;
|
||||
@BindView(R.id.fetch_messages_info_text_view_view_message_activity) TextView mFetchMessageInfoTextView;
|
||||
|
||||
private boolean mNullAccessToken = false;
|
||||
private String mAccessToken;
|
||||
|
||||
private MessageRecyclerViewAdapter mAdapter;
|
||||
|
||||
private RequestManager mGlide;
|
||||
|
||||
MessageViewModel mMessageViewModel;
|
||||
|
||||
@Inject
|
||||
@Named("oauth")
|
||||
Retrofit mOauthRetrofit;
|
||||
|
||||
@Inject
|
||||
RedditDataRoomDatabase mRedditDataRoomDatabase;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_view_message);
|
||||
|
||||
ButterKnife.bind(this);
|
||||
|
||||
((Infinity) getApplication()).getAppComponent().inject(this);
|
||||
|
||||
mGlide = Glide.with(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);
|
||||
}
|
||||
|
||||
int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
|
||||
if (navBarResourceId > 0) {
|
||||
recyclerView.setPadding(0, 0, 0, resources.getDimensionPixelSize(navBarResourceId));
|
||||
}
|
||||
}
|
||||
|
||||
toolbar.setTitle(R.string.inbox);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
if(savedInstanceState != null) {
|
||||
mNullAccessToken = savedInstanceState.getBoolean(NULL_ACCESS_TOKEN_STATE);
|
||||
mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE);
|
||||
|
||||
if(!mNullAccessToken && mAccessToken == null) {
|
||||
getCurrentAccountAndFetchMessage();
|
||||
} else {
|
||||
bindView();
|
||||
}
|
||||
} else {
|
||||
getCurrentAccountAndFetchMessage();
|
||||
}
|
||||
}
|
||||
|
||||
private void getCurrentAccountAndFetchMessage() {
|
||||
new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), new GetCurrentAccountAsyncTask.GetCurrentAccountAsyncTaskListener() {
|
||||
@Override
|
||||
public void success(Account account) {
|
||||
if(account == null) {
|
||||
mNullAccessToken = true;
|
||||
} else {
|
||||
mAccessToken = account.getAccessToken();
|
||||
|
||||
bindView();
|
||||
}
|
||||
}
|
||||
}).execute();
|
||||
}
|
||||
|
||||
private void bindView() {
|
||||
mAdapter = new MessageRecyclerViewAdapter(this);
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, layoutManager.getOrientation());
|
||||
recyclerView.addItemDecoration(dividerItemDecoration);
|
||||
|
||||
MessageViewModel.Factory factory = new MessageViewModel.Factory(mOauthRetrofit,
|
||||
getResources().getConfiguration().locale, mAccessToken, FetchMessages.WHERE_INBOX);
|
||||
mMessageViewModel = new ViewModelProvider(this, factory).get(MessageViewModel.class);
|
||||
mMessageViewModel.getMessages().observe(this, messages -> mAdapter.submitList(messages));
|
||||
|
||||
mMessageViewModel.getInitialLoadingState().observe(this, networkState -> {
|
||||
if(networkState.getStatus().equals(NetworkState.Status.SUCCESS)) {
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
} else if(networkState.getStatus().equals(NetworkState.Status.FAILED)) {
|
||||
mFetchMessageInfoLinearLayout.setOnClickListener(view -> mMessageViewModel.retry());
|
||||
showErrorView(R.string.load_messages_failed);
|
||||
} else {
|
||||
mFetchMessageInfoLinearLayout.setVisibility(View.GONE);
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
mMessageViewModel.hasMessage().observe(this, hasMessage -> {
|
||||
if(hasMessage) {
|
||||
mFetchMessageInfoLinearLayout.setVisibility(View.GONE);
|
||||
} else {
|
||||
mFetchMessageInfoLinearLayout.setOnClickListener(view -> {
|
||||
//Do nothing
|
||||
});
|
||||
showErrorView(R.string.no_messages);
|
||||
}
|
||||
});
|
||||
|
||||
mMessageViewModel.getPaginationNetworkState().observe(this, networkState -> {
|
||||
mAdapter.setNetworkState(networkState);
|
||||
});
|
||||
}
|
||||
|
||||
private void showErrorView(int stringResId) {
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
mFetchMessageInfoLinearLayout.setVisibility(View.VISIBLE);
|
||||
mFetchMessageInfoTextView.setText(stringResId);
|
||||
mGlide.load(R.drawable.load_post_error_indicator).into(mFetchMessageInfoImageView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.view_message_activity, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
if(item.getItemId() == R.id.action_refresh_view_message_activity) {
|
||||
mMessageViewModel.refresh();
|
||||
return true;
|
||||
} else if(item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken);
|
||||
outState.putString(ACCESS_TOKEN_STATE, mAccessToken);
|
||||
}
|
||||
}
|
@ -101,7 +101,6 @@ public class ViewPostDetailActivity extends AppCompatActivity implements FlairBo
|
||||
|
||||
private LinearLayoutManager mLinearLayoutManager;
|
||||
private CommentAndPostRecyclerViewAdapter mAdapter;
|
||||
private LoadSubredditIconAsyncTask mLoadSubredditIconAsyncTask;
|
||||
|
||||
@BindView(R.id.coordinator_layout_view_post_detail) CoordinatorLayout mCoordinatorLayout;
|
||||
@BindView(R.id.appbar_layout_view_post_detail_activity) AppBarLayout appBarLayout;
|
||||
@ -255,7 +254,7 @@ public class ViewPostDetailActivity extends AppCompatActivity implements FlairBo
|
||||
}
|
||||
mAdapter = new CommentAndPostRecyclerViewAdapter(ViewPostDetailActivity.this, mRetrofit,
|
||||
mOauthRetrofit, mRedditDataRoomDatabase, mGlide, mAccessToken, mAccountName, mPost,
|
||||
mLocale, mSingleCommentId, isSingleCommentThreadMode, mLoadSubredditIconAsyncTask,
|
||||
mLocale, mSingleCommentId, isSingleCommentThreadMode,
|
||||
new CommentAndPostRecyclerViewAdapter.CommentRecyclerViewAdapterCallback() {
|
||||
@Override
|
||||
public void updatePost(Post post) {
|
||||
@ -331,7 +330,7 @@ public class ViewPostDetailActivity extends AppCompatActivity implements FlairBo
|
||||
|
||||
mAdapter = new CommentAndPostRecyclerViewAdapter(ViewPostDetailActivity.this, mRetrofit,
|
||||
mOauthRetrofit, mRedditDataRoomDatabase, mGlide, mAccessToken, mAccountName, mPost,
|
||||
mLocale, mSingleCommentId, isSingleCommentThreadMode, mLoadSubredditIconAsyncTask,
|
||||
mLocale, mSingleCommentId, isSingleCommentThreadMode,
|
||||
new CommentAndPostRecyclerViewAdapter.CommentRecyclerViewAdapterCallback() {
|
||||
@Override
|
||||
public void updatePost(Post post) {
|
||||
@ -817,9 +816,6 @@ public class ViewPostDetailActivity extends AppCompatActivity implements FlairBo
|
||||
EventBus.getDefault().unregister(this);
|
||||
super.onDestroy();
|
||||
Bridge.clear(this);
|
||||
if(mLoadSubredditIconAsyncTask != null) {
|
||||
mLoadSubredditIconAsyncTask.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
9
app/src/main/res/drawable/ic_outline_inbox_24px.xml
Normal file
9
app/src/main/res/drawable/ic_outline_inbox_24px.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM19,19L5,19v-3h3.56c0.69,1.19 1.97,2 3.45,2s2.75,-0.81 3.45,-2L19,16v3zM19,14h-4.99c0,1.1 -0.9,2 -2,2s-2,-0.9 -2,-2L5,14L5,5h14v9z"/>
|
||||
</vector>
|
@ -90,6 +90,32 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/inbox_linear_layout_main_activity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:src="@drawable/ic_outline_inbox_24px"
|
||||
android:tint="@color/primaryTextColor"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/inbox"
|
||||
android:textColor="@color/primaryTextColor" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/upvoted_linear_layout_main_activity"
|
||||
android:layout_width="match_parent"
|
||||
|
81
app/src/main/res/layout/activity_view_message.xml
Normal file
81
app/src/main/res/layout/activity_view_message.xml
Normal file
@ -0,0 +1,81 @@
|
||||
<?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=".ViewMessageActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar_layout_view_message_activity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:id="@+id/collapsing_toolbar_layout_view_message_activity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
app:titleEnabled="false"
|
||||
app:toolbarId="@+id/toolbar_view_message_activity">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar_view_message_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>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" >
|
||||
|
||||
<com.lsjwzh.widget.materialloadingprogressbar.CircleProgressBar
|
||||
android:id="@+id/progress_bar_view_message_activity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:mlpb_progress_stoke_width="3dp"
|
||||
app:mlpb_progress_color="@color/colorAccent"
|
||||
app:mlpb_background_color="@color/circularProgressBarBackground" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view_view_message_activity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/fetch_messages_info_linear_layout_view_message_activity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/fetch_messages_info_image_view_view_message_activity"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fetch_messages_info_text_view_view_message_activity"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
34
app/src/main/res/layout/item_message.xml
Normal file
34
app/src/main/res/layout/item_message.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/author_text_view_item_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textColor="@color/primaryTextColor" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subject_text_view_item_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/primaryTextColor" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title_text_view_item_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textColor="@color/primaryTextColor" />
|
||||
|
||||
<CustomView.CustomMarkwonView
|
||||
android:id="@+id/content_custom_markwon_view_item_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
9
app/src/main/res/menu/view_message_activity.xml
Normal file
9
app/src/main/res/menu/view_message_activity.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_refresh_view_message_activity"
|
||||
android:orderInCategory="1"
|
||||
android:title="@string/action_refresh"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
@ -47,4 +47,6 @@
|
||||
<color name="cardViewBackgroundColor">#FFFFFF</color>
|
||||
|
||||
<color name="singleCommentThreadBackgroundColor">#B3E5F9</color>
|
||||
|
||||
<color name="unreadMessageBackgroundColor">#B3E5F9</color>
|
||||
</resources>
|
||||
|
@ -13,6 +13,7 @@
|
||||
<string name="search_subreddits_activity_label">Subreddits</string>
|
||||
<string name="edit_post_activity_label">Edit Post</string>
|
||||
<string name="edit_comment_activity_label">Edit Comment</string>
|
||||
<string name="view_message_activity">Inbox</string>
|
||||
|
||||
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||
@ -50,19 +51,23 @@
|
||||
<string name="no_users">No users found</string>
|
||||
<string name="no_storage_permission">No storage permission to save this file</string>
|
||||
|
||||
<string name="load_comments_failed">Error loading comments.</string>
|
||||
<string name="load_comments_failed">Error loading comments</string>
|
||||
<string name="retry">Retry</string>
|
||||
<string name="comments">Comments</string>
|
||||
<string name="no_comments_yet">No comments yet. Write a comment?</string>
|
||||
<string name="vote_failed">Vote failed</string>
|
||||
<string name="refresh_post_failed">Error refreshing the post</string>
|
||||
|
||||
<string name="load_messages_failed">Error loading messages</string>
|
||||
<string name="no_messages">Empty</string>
|
||||
|
||||
<string name="nsfw">NSFW</string>
|
||||
<string name="karma_info">Karma: %1$d</string>
|
||||
|
||||
<string name="profile">Profile</string>
|
||||
<string name="following">Following</string>
|
||||
<string name="subscriptions">Subscriptions</string>
|
||||
<string name="inbox">Inbox</string>
|
||||
<string name="upvoted">Upvoted</string>
|
||||
<string name="downvoted">Downvoted</string>
|
||||
<string name="hidden">Hidden</string>
|
||||
|
Loading…
Reference in New Issue
Block a user