mirror of
https://codeberg.org/Bazsalanszky/Infinity-For-Lemmy.git
synced 2024-12-29 04:17:12 +01:00
Rebase to master
This commit is contained in:
parent
81e2fdcf91
commit
92fcb811c3
@ -77,6 +77,7 @@ import eu.toldi.infinityforlemmy.fragments.InboxFragment;
|
||||
import eu.toldi.infinityforlemmy.fragments.MorePostsInfoFragment;
|
||||
import eu.toldi.infinityforlemmy.fragments.MultiRedditListingFragment;
|
||||
import eu.toldi.infinityforlemmy.fragments.PostFragment;
|
||||
import eu.toldi.infinityforlemmy.fragments.PrivateMessageFragment;
|
||||
import eu.toldi.infinityforlemmy.fragments.SidebarFragment;
|
||||
import eu.toldi.infinityforlemmy.fragments.SubredditListingFragment;
|
||||
import eu.toldi.infinityforlemmy.fragments.SubscribedSubredditsListingFragment;
|
||||
@ -319,6 +320,7 @@ public interface AppComponent {
|
||||
|
||||
void inject(CommentMoreBottomSheetFragment commentMoreBottomSheetFragment);
|
||||
|
||||
void inject(PrivateMessageFragment privateMessageFragment);
|
||||
|
||||
@Component.Factory
|
||||
interface Factory {
|
||||
|
@ -10,6 +10,7 @@ import javax.inject.Singleton;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import eu.toldi.infinityforlemmy.apis.StreamableAPI;
|
||||
import eu.toldi.infinityforlemmy.privatemessage.LemmyPrivateMessageAPI;
|
||||
import eu.toldi.infinityforlemmy.comment.LemmyCommentAPI;
|
||||
import eu.toldi.infinityforlemmy.post.LemmyPostAPI;
|
||||
import eu.toldi.infinityforlemmy.utils.APIUtils;
|
||||
@ -226,4 +227,10 @@ abstract class NetworkModule {
|
||||
static LemmyCommentAPI provideCommentAPI(@Named("no_oauth") RetrofitHolder retrofitHolder) {
|
||||
return new LemmyCommentAPI(retrofitHolder);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static LemmyPrivateMessageAPI provideLemmyPrivateMessageAPI(@Named("base") RetrofitHolder retrofit) {
|
||||
return new LemmyPrivateMessageAPI(retrofit);
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ import eu.toldi.infinityforlemmy.events.PassPrivateMessageEvent;
|
||||
import eu.toldi.infinityforlemmy.events.PassPrivateMessageIndexEvent;
|
||||
import eu.toldi.infinityforlemmy.events.SwitchAccountEvent;
|
||||
import eu.toldi.infinityforlemmy.fragments.InboxFragment;
|
||||
import eu.toldi.infinityforlemmy.fragments.PrivateMessageFragment;
|
||||
import eu.toldi.infinityforlemmy.message.CommentInteraction;
|
||||
import eu.toldi.infinityforlemmy.message.FetchMessage;
|
||||
import eu.toldi.infinityforlemmy.message.ReadMessage;
|
||||
@ -441,7 +442,7 @@ public class InboxActivity extends BaseActivity implements ActivityToolbarInterf
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment createFragment(int position) {
|
||||
InboxFragment fragment = new InboxFragment();
|
||||
Fragment fragment = new InboxFragment();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(InboxFragment.EXTRA_ACCESS_TOKEN, mAccessToken);
|
||||
switch (position) {
|
||||
@ -450,11 +451,9 @@ public class InboxActivity extends BaseActivity implements ActivityToolbarInterf
|
||||
break;
|
||||
case 1:
|
||||
bundle.putString(InboxFragment.EXTRA_MESSAGE_WHERE, FetchMessage.WHERE_MENTIONS);
|
||||
fragment.setArguments(bundle);
|
||||
break;
|
||||
case 2:
|
||||
bundle.putString(InboxFragment.EXTRA_MESSAGE_WHERE, FetchMessage.WHERE_MESSAGES);
|
||||
fragment.setArguments(bundle);
|
||||
fragment = new PrivateMessageFragment();
|
||||
break;
|
||||
}
|
||||
fragment.setArguments(bundle);
|
||||
|
@ -0,0 +1,344 @@
|
||||
package eu.toldi.infinityforlemmy.adapters;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.net.Uri;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.util.Linkify;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.paging.PagedListAdapter;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import eu.toldi.infinityforlemmy.NetworkState;
|
||||
import eu.toldi.infinityforlemmy.R;
|
||||
import eu.toldi.infinityforlemmy.activities.BaseActivity;
|
||||
import eu.toldi.infinityforlemmy.activities.LinkResolverActivity;
|
||||
import eu.toldi.infinityforlemmy.activities.ViewPrivateMessagesActivity;
|
||||
import eu.toldi.infinityforlemmy.activities.ViewUserDetailActivity;
|
||||
import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper;
|
||||
import eu.toldi.infinityforlemmy.markdown.RedditHeadingPlugin;
|
||||
import eu.toldi.infinityforlemmy.markdown.SpoilerAwareMovementMethod;
|
||||
import eu.toldi.infinityforlemmy.markdown.SpoilerParserPlugin;
|
||||
import eu.toldi.infinityforlemmy.markdown.SuperscriptPlugin;
|
||||
import eu.toldi.infinityforlemmy.privatemessage.LemmyPrivateMessageAPI;
|
||||
import eu.toldi.infinityforlemmy.privatemessage.PrivateMessage;
|
||||
import io.noties.markwon.AbstractMarkwonPlugin;
|
||||
import io.noties.markwon.Markwon;
|
||||
import io.noties.markwon.MarkwonConfiguration;
|
||||
import io.noties.markwon.core.MarkwonTheme;
|
||||
import io.noties.markwon.ext.strikethrough.StrikethroughPlugin;
|
||||
import io.noties.markwon.image.glide.GlideImagesPlugin;
|
||||
import io.noties.markwon.inlineparser.HtmlInlineProcessor;
|
||||
import io.noties.markwon.inlineparser.MarkwonInlineParserPlugin;
|
||||
import io.noties.markwon.linkify.LinkifyPlugin;
|
||||
import io.noties.markwon.movement.MovementMethodPlugin;
|
||||
import retrofit2.Retrofit;
|
||||
|
||||
public class PrivateMessageRecycleViewAdapter extends PagedListAdapter<PrivateMessage, 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 static final DiffUtil.ItemCallback<PrivateMessage> DIFF_CALLBACK = new DiffUtil.ItemCallback<>() {
|
||||
@Override
|
||||
public boolean areItemsTheSame(@NonNull PrivateMessage message, @NonNull PrivateMessage t1) {
|
||||
return message.getId() == t1.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(@NonNull PrivateMessage message, @NonNull PrivateMessage t1) {
|
||||
return message.getContent().equals(t1.getContent());
|
||||
}
|
||||
};
|
||||
private BaseActivity mActivity;
|
||||
private Retrofit retrofit;
|
||||
private Markwon mMarkwon;
|
||||
private String mAccessToken;
|
||||
|
||||
private final LemmyPrivateMessageAPI lemmyPrivateMessageAPI;
|
||||
private int mMessageType;
|
||||
private NetworkState networkState;
|
||||
private RetryLoadingMoreCallback mRetryLoadingMoreCallback;
|
||||
private int mColorAccent;
|
||||
private int mMessageBackgroundColor;
|
||||
private int mUsernameColor;
|
||||
private int mPrimaryTextColor;
|
||||
private int mSecondaryTextColor;
|
||||
private int mUnreadMessageBackgroundColor;
|
||||
private int mColorPrimaryLightTheme;
|
||||
private int mButtonTextColor;
|
||||
private boolean markAllMessagesAsRead = false;
|
||||
|
||||
public PrivateMessageRecycleViewAdapter(BaseActivity activity, Retrofit oauthRetrofit,
|
||||
CustomThemeWrapper customThemeWrapper,
|
||||
String accessToken,
|
||||
LemmyPrivateMessageAPI lemmyPrivateMessageAPI, RetryLoadingMoreCallback retryLoadingMoreCallback) {
|
||||
super(DIFF_CALLBACK);
|
||||
mActivity = activity;
|
||||
retrofit = oauthRetrofit;
|
||||
this.lemmyPrivateMessageAPI = lemmyPrivateMessageAPI;
|
||||
mRetryLoadingMoreCallback = retryLoadingMoreCallback;
|
||||
|
||||
mColorAccent = customThemeWrapper.getColorAccent();
|
||||
mMessageBackgroundColor = customThemeWrapper.getCardViewBackgroundColor();
|
||||
mUsernameColor = customThemeWrapper.getUsername();
|
||||
mPrimaryTextColor = customThemeWrapper.getPrimaryTextColor();
|
||||
mSecondaryTextColor = customThemeWrapper.getSecondaryTextColor();
|
||||
int spoilerBackgroundColor = mSecondaryTextColor | 0xFF000000;
|
||||
mUnreadMessageBackgroundColor = customThemeWrapper.getUnreadMessageBackgroundColor();
|
||||
mColorPrimaryLightTheme = customThemeWrapper.getColorPrimaryLightTheme();
|
||||
mButtonTextColor = customThemeWrapper.getButtonTextColor();
|
||||
|
||||
// todo:https://github.com/Docile-Alligator/Infinity-For-Reddit/issues/1027
|
||||
// add tables support and replace with MarkdownUtils#commonPostMarkwonBuilder
|
||||
mMarkwon = Markwon.builder(mActivity)
|
||||
.usePlugin(MarkwonInlineParserPlugin.create(plugin -> {
|
||||
plugin.excludeInlineProcessor(HtmlInlineProcessor.class);
|
||||
}))
|
||||
.usePlugin(new AbstractMarkwonPlugin() {
|
||||
@Override
|
||||
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) {
|
||||
builder.linkResolver((view, link) -> {
|
||||
Intent intent = new Intent(mActivity, LinkResolverActivity.class);
|
||||
Uri uri = Uri.parse(link);
|
||||
intent.setData(uri);
|
||||
mActivity.startActivity(intent);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureTheme(@NonNull MarkwonTheme.Builder builder) {
|
||||
builder.linkColor(customThemeWrapper.getLinkColor());
|
||||
}
|
||||
})
|
||||
.usePlugin(SuperscriptPlugin.create())
|
||||
.usePlugin(SpoilerParserPlugin.create(mSecondaryTextColor, spoilerBackgroundColor))
|
||||
.usePlugin(RedditHeadingPlugin.create())
|
||||
.usePlugin(StrikethroughPlugin.create())
|
||||
.usePlugin(MovementMethodPlugin.create(new SpoilerAwareMovementMethod()))
|
||||
.usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
|
||||
.usePlugin(GlideImagesPlugin.create(mActivity))
|
||||
.build();
|
||||
mAccessToken = accessToken;
|
||||
|
||||
}
|
||||
|
||||
@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) {
|
||||
PrivateMessage message = getItem(holder.getBindingAdapterPosition());
|
||||
if (message != null) {
|
||||
|
||||
if (message.getRead()) {
|
||||
if (markAllMessagesAsRead) {
|
||||
message.setRead(true);
|
||||
} else {
|
||||
holder.itemView.setBackgroundColor(
|
||||
mUnreadMessageBackgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
((DataViewHolder) holder).titleTextView.setVisibility(View.GONE);
|
||||
|
||||
|
||||
((DataViewHolder) holder).authorTextView.setText(message.getCreatorQualifiedName());
|
||||
String subject = message.getRecipientQualifiedName();
|
||||
((DataViewHolder) holder).subjectTextView.setText(subject);
|
||||
mMarkwon.setMarkdown(((DataViewHolder) holder).contentCustomMarkwonView, message.getContent());
|
||||
|
||||
holder.itemView.setOnClickListener(view -> {
|
||||
|
||||
Intent intent = new Intent(mActivity, ViewPrivateMessagesActivity.class);
|
||||
intent.putExtra(ViewPrivateMessagesActivity.EXTRA_PRIVATE_MESSAGE_INDEX, holder.getBindingAdapterPosition());
|
||||
intent.putExtra(ViewPrivateMessagesActivity.EXTRA_MESSAGE_POSITION, holder.getBindingAdapterPosition());
|
||||
mActivity.startActivity(intent);
|
||||
|
||||
|
||||
if (message.getRead()) {
|
||||
holder.itemView.setBackgroundColor(mMessageBackgroundColor);
|
||||
|
||||
|
||||
lemmyPrivateMessageAPI.markPrivateMessageAsRead(mAccessToken, message.getId(), new LemmyPrivateMessageAPI.PrivateMessageMarkedAsReadListener() {
|
||||
|
||||
@Override
|
||||
public void onPrivateMessageMarkedAsReadError() {
|
||||
message.setRead(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrivateMessageMarkedAsReadSuccess() {
|
||||
message.setRead(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
((DataViewHolder) holder).authorTextView.setOnClickListener(view -> {
|
||||
|
||||
Intent intent = new Intent(mActivity, ViewUserDetailActivity.class);
|
||||
intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, message.getCreatorName());
|
||||
intent.putExtra(ViewUserDetailActivity.EXTRA_QUALIFIED_USER_NAME_KEY, message.getCreatorQualifiedName());
|
||||
mActivity.startActivity(intent);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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(mMessageBackgroundColor);
|
||||
((DataViewHolder) holder).titleTextView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasExtraRow() {
|
||||
return networkState != null && networkState.getStatus() != NetworkState.Status.SUCCESS;
|
||||
}
|
||||
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateMessageReply(PrivateMessage newReply, int position) {
|
||||
if (position >= 0 && position < super.getItemCount()) {
|
||||
PrivateMessage message = getItem(position);
|
||||
if (message != null) {
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setMarkAllMessagesAsRead(boolean markAllMessagesAsRead) {
|
||||
this.markAllMessagesAsRead = markAllMessagesAsRead;
|
||||
}
|
||||
|
||||
public interface RetryLoadingMoreCallback {
|
||||
void retryLoadingMore();
|
||||
}
|
||||
|
||||
class DataViewHolder extends RecyclerView.ViewHolder {
|
||||
@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)
|
||||
TextView contentCustomMarkwonView;
|
||||
|
||||
DataViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
if (mActivity.typeface != null) {
|
||||
authorTextView.setTypeface(mActivity.typeface);
|
||||
subjectTextView.setTypeface(mActivity.typeface);
|
||||
titleTextView.setTypeface(mActivity.titleTypeface);
|
||||
contentCustomMarkwonView.setTypeface(mActivity.contentTypeface);
|
||||
}
|
||||
itemView.setBackgroundColor(mMessageBackgroundColor);
|
||||
authorTextView.setTextColor(mUsernameColor);
|
||||
subjectTextView.setTextColor(mPrimaryTextColor);
|
||||
titleTextView.setTextColor(mPrimaryTextColor);
|
||||
contentCustomMarkwonView.setTextColor(mSecondaryTextColor);
|
||||
|
||||
contentCustomMarkwonView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
contentCustomMarkwonView.setOnClickListener(view -> {
|
||||
if (contentCustomMarkwonView.getSelectionStart() == -1 && contentCustomMarkwonView.getSelectionEnd() == -1) {
|
||||
itemView.performClick();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if (mActivity.typeface != null) {
|
||||
errorTextView.setTypeface(mActivity.typeface);
|
||||
retryButton.setTypeface(mActivity.typeface);
|
||||
}
|
||||
errorTextView.setText(R.string.load_comments_failed);
|
||||
errorTextView.setTextColor(mSecondaryTextColor);
|
||||
retryButton.setOnClickListener(view -> mRetryLoadingMoreCallback.retryLoadingMore());
|
||||
retryButton.setBackgroundTintList(ColorStateList.valueOf(mColorPrimaryLightTheme));
|
||||
retryButton.setTextColor(mButtonTextColor);
|
||||
}
|
||||
}
|
||||
|
||||
class LoadingViewHolder extends RecyclerView.ViewHolder {
|
||||
@BindView(R.id.progress_bar_item_footer_loading)
|
||||
ProgressBar progressBar;
|
||||
|
||||
LoadingViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
progressBar.setIndeterminateTintList(ColorStateList.valueOf(mColorAccent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,10 @@ import eu.toldi.infinityforlemmy.dto.EditCommentDTO;
|
||||
import eu.toldi.infinityforlemmy.dto.EditPostDTO;
|
||||
import eu.toldi.infinityforlemmy.dto.FollowCommunityDTO;
|
||||
import eu.toldi.infinityforlemmy.dto.PostVoteDTO;
|
||||
import eu.toldi.infinityforlemmy.dto.PrivateMessageDTO;
|
||||
import eu.toldi.infinityforlemmy.dto.PrivateMessageReadDTO;
|
||||
import eu.toldi.infinityforlemmy.dto.PrivateMessageReportDTO;
|
||||
import eu.toldi.infinityforlemmy.dto.PrivateMessageUpdateDTO;
|
||||
import eu.toldi.infinityforlemmy.dto.ReadCommentDTO;
|
||||
import eu.toldi.infinityforlemmy.dto.ReadMessageDTO;
|
||||
import eu.toldi.infinityforlemmy.dto.ReadPostDTO;
|
||||
@ -246,4 +250,37 @@ public interface LemmyAPI {
|
||||
Call<String> getSiteInfo(
|
||||
@Query("auth") String auth
|
||||
);
|
||||
|
||||
@GET("api/v3/private_message/list")
|
||||
Call<String> privateMessagesList(
|
||||
@Query("page") Integer page,
|
||||
@Query("limit") Integer limit,
|
||||
@Query("unread_only") Boolean unread_only,
|
||||
@NonNull @Query("auth") String auth
|
||||
);
|
||||
|
||||
@POST("api/v3/private_message")
|
||||
Call<String> privateMessageSend(
|
||||
@Body PrivateMessageDTO params
|
||||
);
|
||||
|
||||
@PUT("api/v3/private_message")
|
||||
Call<String> privateMessageEdit(
|
||||
@Body PrivateMessageUpdateDTO params
|
||||
);
|
||||
|
||||
@POST("api/v3/private_message/delete")
|
||||
Call<String> privateMessageDelete(
|
||||
@Body PrivateMessageUpdateDTO params
|
||||
);
|
||||
|
||||
@POST("api/v3/private_message/mark_as_read")
|
||||
Call<String> privateMessageMarkAsRead(
|
||||
@Body PrivateMessageReadDTO params
|
||||
);
|
||||
|
||||
@POST("api/v3/private_message/report")
|
||||
Call<String> privateMessageReport(
|
||||
@Body PrivateMessageReportDTO params
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,255 @@
|
||||
package eu.toldi.infinityforlemmy.fragments;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.paging.PagedList;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.RequestManager;
|
||||
|
||||
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 eu.toldi.infinityforlemmy.FragmentCommunicator;
|
||||
import eu.toldi.infinityforlemmy.Infinity;
|
||||
import eu.toldi.infinityforlemmy.NetworkState;
|
||||
import eu.toldi.infinityforlemmy.R;
|
||||
import eu.toldi.infinityforlemmy.RecyclerViewContentScrollingInterface;
|
||||
import eu.toldi.infinityforlemmy.RedditDataRoomDatabase;
|
||||
import eu.toldi.infinityforlemmy.RetrofitHolder;
|
||||
import eu.toldi.infinityforlemmy.activities.BaseActivity;
|
||||
import eu.toldi.infinityforlemmy.adapters.PrivateMessageRecycleViewAdapter;
|
||||
import eu.toldi.infinityforlemmy.customtheme.CustomThemeWrapper;
|
||||
import eu.toldi.infinityforlemmy.customviews.LinearLayoutManagerBugFixed;
|
||||
import eu.toldi.infinityforlemmy.events.RepliedToPrivateMessageEvent;
|
||||
import eu.toldi.infinityforlemmy.privatemessage.LemmyPrivateMessageAPI;
|
||||
import eu.toldi.infinityforlemmy.privatemessage.PrivateMessage;
|
||||
import eu.toldi.infinityforlemmy.privatemessage.PrivateMessageViewModel;
|
||||
|
||||
public class PrivateMessageFragment extends Fragment implements FragmentCommunicator {
|
||||
|
||||
public static final String EXTRA_ACCESS_TOKEN = "EAT";
|
||||
public static final String EXTRA_MESSAGE_WHERE = "EMT";
|
||||
@BindView(R.id.swipe_refresh_layout_inbox_fragment)
|
||||
SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
@BindView(R.id.recycler_view_inbox_fragment)
|
||||
RecyclerView mRecyclerView;
|
||||
@BindView(R.id.fetch_messages_info_linear_layout_inbox_fragment)
|
||||
LinearLayout mFetchMessageInfoLinearLayout;
|
||||
@BindView(R.id.fetch_messages_info_image_view_inbox_fragment)
|
||||
ImageView mFetchMessageInfoImageView;
|
||||
@BindView(R.id.fetch_messages_info_text_view_inbox_fragment)
|
||||
TextView mFetchMessageInfoTextView;
|
||||
PrivateMessageViewModel mMessageViewModel;
|
||||
@Inject
|
||||
@Named("no_oauth")
|
||||
RetrofitHolder mRetrofit;
|
||||
@Inject
|
||||
RedditDataRoomDatabase mRedditDataRoomDatabase;
|
||||
@Inject
|
||||
@Named("default")
|
||||
SharedPreferences mSharedPreferences;
|
||||
@Inject
|
||||
CustomThemeWrapper mCustomThemeWrapper;
|
||||
|
||||
@Inject
|
||||
LemmyPrivateMessageAPI mLemmyPrivateMessageAPI;
|
||||
private String mAccessToken;
|
||||
private PrivateMessageRecycleViewAdapter mAdapter;
|
||||
private RequestManager mGlide;
|
||||
private LinearLayoutManagerBugFixed mLinearLayoutManager;
|
||||
private BaseActivity mActivity;
|
||||
|
||||
public PrivateMessageFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
Log.i("PrivateMessageFragment", "onCreateView");
|
||||
View rootView = inflater.inflate(R.layout.fragment_inbox, container, false);
|
||||
|
||||
((Infinity) mActivity.getApplication()).getAppComponent().inject(this);
|
||||
|
||||
ButterKnife.bind(this, rootView);
|
||||
|
||||
EventBus.getDefault().register(this);
|
||||
|
||||
applyTheme();
|
||||
|
||||
Bundle arguments = getArguments();
|
||||
if (arguments == null) {
|
||||
return rootView;
|
||||
}
|
||||
mAccessToken = getArguments().getString(EXTRA_ACCESS_TOKEN);
|
||||
mGlide = Glide.with(this);
|
||||
|
||||
if (mActivity.isImmersiveInterface()) {
|
||||
mRecyclerView.setPadding(0, 0, 0, mActivity.getNavBarHeight());
|
||||
}
|
||||
|
||||
|
||||
mAdapter = new PrivateMessageRecycleViewAdapter(mActivity, mRetrofit.getRetrofit(), mCustomThemeWrapper, mAccessToken, mLemmyPrivateMessageAPI, () -> mMessageViewModel.retryLoadingMore());
|
||||
mLinearLayoutManager = new LinearLayoutManagerBugFixed(mActivity);
|
||||
mRecyclerView.setLayoutManager(mLinearLayoutManager);
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mActivity, mLinearLayoutManager.getOrientation());
|
||||
mRecyclerView.addItemDecoration(dividerItemDecoration);
|
||||
|
||||
if (mActivity instanceof RecyclerViewContentScrollingInterface) {
|
||||
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||
if (dy > 0) {
|
||||
((RecyclerViewContentScrollingInterface) mActivity).contentScrollDown();
|
||||
} else if (dy < 0) {
|
||||
((RecyclerViewContentScrollingInterface) mActivity).contentScrollUp();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
PrivateMessageViewModel.Factory factory = new PrivateMessageViewModel.Factory(mRetrofit.getRetrofit(),
|
||||
getResources().getConfiguration().locale, mAccessToken, mLemmyPrivateMessageAPI);
|
||||
mMessageViewModel = new ViewModelProvider(this, factory).get(PrivateMessageViewModel.class);
|
||||
mMessageViewModel.getMessages().observe(getViewLifecycleOwner(), messages -> mAdapter.submitList(messages));
|
||||
|
||||
mMessageViewModel.hasMessage().observe(getViewLifecycleOwner(), hasMessage -> {
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
if (hasMessage) {
|
||||
mFetchMessageInfoLinearLayout.setVisibility(View.GONE);
|
||||
} else {
|
||||
mFetchMessageInfoLinearLayout.setOnClickListener(null);
|
||||
showErrorView(R.string.no_messages);
|
||||
}
|
||||
});
|
||||
|
||||
mMessageViewModel.getInitialLoadingState().observe(getViewLifecycleOwner(), networkState -> {
|
||||
if (networkState.getStatus().equals(NetworkState.Status.SUCCESS)) {
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
} else if (networkState.getStatus().equals(NetworkState.Status.FAILED)) {
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
mFetchMessageInfoLinearLayout.setOnClickListener(view -> {
|
||||
mFetchMessageInfoLinearLayout.setVisibility(View.GONE);
|
||||
mMessageViewModel.refresh();
|
||||
mAdapter.setNetworkState(null);
|
||||
});
|
||||
showErrorView(R.string.load_messages_failed);
|
||||
} else {
|
||||
mSwipeRefreshLayout.setRefreshing(true);
|
||||
}
|
||||
});
|
||||
|
||||
mMessageViewModel.getPaginationNetworkState().observe(getViewLifecycleOwner(), networkState -> {
|
||||
mAdapter.setNetworkState(networkState);
|
||||
});
|
||||
|
||||
mSwipeRefreshLayout.setOnRefreshListener(this::onRefresh);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
private void showErrorView(int stringResId) {
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
mFetchMessageInfoLinearLayout.setVisibility(View.VISIBLE);
|
||||
mFetchMessageInfoTextView.setText(stringResId);
|
||||
mGlide.load(R.drawable.error_image).into(mFetchMessageInfoImageView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTheme() {
|
||||
mSwipeRefreshLayout.setProgressBackgroundColorSchemeColor(mCustomThemeWrapper.getCircularProgressBarBackground());
|
||||
mSwipeRefreshLayout.setColorSchemeColors(mCustomThemeWrapper.getColorAccent());
|
||||
mFetchMessageInfoTextView.setTextColor(mCustomThemeWrapper.getSecondaryTextColor());
|
||||
if (mActivity.typeface != null) {
|
||||
mFetchMessageInfoTextView.setTypeface(mActivity.typeface);
|
||||
}
|
||||
}
|
||||
|
||||
public void goBackToTop() {
|
||||
if (mLinearLayoutManager != null) {
|
||||
mLinearLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void markAllMessagesRead() {
|
||||
if (mAdapter != null) {
|
||||
mAdapter.setMarkAllMessagesAsRead(true);
|
||||
|
||||
int previousPosition = -1;
|
||||
if (mLinearLayoutManager != null) {
|
||||
previousPosition = mLinearLayoutManager.findFirstVisibleItemPosition();
|
||||
}
|
||||
|
||||
RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
|
||||
mRecyclerView.setAdapter(null);
|
||||
mRecyclerView.setLayoutManager(null);
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
mRecyclerView.setLayoutManager(layoutManager);
|
||||
|
||||
if (previousPosition > 0) {
|
||||
mRecyclerView.scrollToPosition(previousPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onRefresh() {
|
||||
mMessageViewModel.refresh();
|
||||
mAdapter.setNetworkState(null);
|
||||
}
|
||||
|
||||
public PrivateMessage getMessageByIndex(int index) {
|
||||
if (mMessageViewModel == null || index < 0) {
|
||||
return null;
|
||||
}
|
||||
PagedList<PrivateMessage> messages = mMessageViewModel.getMessages().getValue();
|
||||
if (messages == null) {
|
||||
return null;
|
||||
}
|
||||
if (index >= messages.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return messages.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull Context context) {
|
||||
super.onAttach(context);
|
||||
mActivity = (BaseActivity) context;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onRepliedToPrivateMessageEvent(RepliedToPrivateMessageEvent repliedToPrivateMessageEvent) {
|
||||
/* if (mAdapter != null && mWhere.equals(FetchMessage.WHERE_MESSAGES)) {
|
||||
mAdapter.updateMessageReply(repliedToPrivateMessageEvent.newReply, repliedToPrivateMessageEvent.messagePosition);
|
||||
}*/
|
||||
}
|
||||
}
|
@ -220,9 +220,6 @@ public class ParsePost {
|
||||
String authorAvatar = (!data.getJSONObject("creator").isNull("avatar")) ? data.getJSONObject("creator").getString("avatar") : null;
|
||||
|
||||
Uri uri = Uri.parse(url);
|
||||
if (uri.getAuthority() == null) {
|
||||
Log.e("ParsePost", "parseData:" + uri.toString());
|
||||
}
|
||||
String path = uri.getPath();
|
||||
boolean isVideo = path.endsWith(".mp4") || path.endsWith(".webm") || path.endsWith(".gifv");
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
package eu.toldi.infinityforlemmy.dto
|
||||
|
||||
data class PrivateMessageDTO(val recipient_id: Int, val content: String, val auth: String)
|
||||
|
||||
data class PrivateMessageUpdateDTO(
|
||||
val private_message_id: Int,
|
||||
val auth: String,
|
||||
val content: String
|
||||
)
|
||||
|
||||
data class PrivateMessageDeleteDTO(
|
||||
val private_message_id: Int,
|
||||
val auth: String,
|
||||
val deleted: Boolean
|
||||
)
|
||||
|
||||
data class PrivateMessageReadDTO(val private_message_id: Int, val auth: String, val read: Boolean)
|
||||
|
||||
data class PrivateMessageReportDTO(
|
||||
val private_message_id: Int,
|
||||
val auth: String,
|
||||
val reason: String
|
||||
)
|
@ -0,0 +1,107 @@
|
||||
package eu.toldi.infinityforlemmy.privatemessage
|
||||
|
||||
import eu.toldi.infinityforlemmy.RetrofitHolder
|
||||
import eu.toldi.infinityforlemmy.apis.LemmyAPI
|
||||
import eu.toldi.infinityforlemmy.dto.PrivateMessageReadDTO
|
||||
import org.json.JSONObject
|
||||
|
||||
class LemmyPrivateMessageAPI(val retrofitHolder: RetrofitHolder) {
|
||||
|
||||
|
||||
fun fetchPrivateMessages(
|
||||
auth: String,
|
||||
page: Int,
|
||||
listener: PrivateMessageFetchedListener,
|
||||
limit: Int = 25,
|
||||
unreadOnly: Boolean = false
|
||||
) {
|
||||
val api = retrofitHolder.retrofit.create(LemmyAPI::class.java)
|
||||
api.privateMessagesList(page, limit, unreadOnly, auth).enqueue(
|
||||
object : retrofit2.Callback<String> {
|
||||
override fun onResponse(
|
||||
call: retrofit2.Call<String>,
|
||||
response: retrofit2.Response<String>
|
||||
) {
|
||||
if (response.isSuccessful) {
|
||||
val jresponse = JSONObject(response.body()!!);
|
||||
val privateMessages = jresponse.getJSONArray("private_messages")
|
||||
val privateMessageList = mutableListOf<PrivateMessage>()
|
||||
for (i in 0 until privateMessages.length()) {
|
||||
val privateMessage =
|
||||
parsePrivateMessage(privateMessages.getJSONObject(i))
|
||||
privateMessageList.add(privateMessage)
|
||||
}
|
||||
listener.onPrivateMessageFetchedSuccess(privateMessageList)
|
||||
} else {
|
||||
listener.onPrivateMessageFetchedError()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: retrofit2.Call<String>, t: Throwable) {
|
||||
listener.onPrivateMessageFetchedError()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun markPrivateMessageAsRead(
|
||||
auth: String,
|
||||
privateMessageId: Int,
|
||||
listener: PrivateMessageMarkedAsReadListener
|
||||
) {
|
||||
val api = retrofitHolder.retrofit.create(LemmyAPI::class.java)
|
||||
api.privateMessageMarkAsRead(PrivateMessageReadDTO(privateMessageId, auth, true)).enqueue(
|
||||
object : retrofit2.Callback<String> {
|
||||
override fun onResponse(
|
||||
call: retrofit2.Call<String>,
|
||||
response: retrofit2.Response<String>
|
||||
) {
|
||||
if (response.isSuccessful) {
|
||||
listener.onPrivateMessageMarkedAsReadSuccess()
|
||||
} else {
|
||||
listener.onPrivateMessageMarkedAsReadError()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(call: retrofit2.Call<String>, t: Throwable) {
|
||||
listener.onPrivateMessageMarkedAsReadError()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
interface PrivateMessageMarkedAsReadListener {
|
||||
fun onPrivateMessageMarkedAsReadSuccess()
|
||||
fun onPrivateMessageMarkedAsReadError()
|
||||
}
|
||||
|
||||
|
||||
interface PrivateMessageFetchedListener {
|
||||
fun onPrivateMessageFetchedSuccess(privateMessage: List<PrivateMessage>)
|
||||
fun onPrivateMessageFetchedError()
|
||||
}
|
||||
|
||||
private fun parsePrivateMessage(jsonObject: JSONObject): PrivateMessage {
|
||||
|
||||
val privateMessage = jsonObject.getJSONObject("private_message")
|
||||
val creator = jsonObject.getJSONObject("creator")
|
||||
val recipient = jsonObject.getJSONObject("recipient")
|
||||
|
||||
return PrivateMessage(
|
||||
id = privateMessage.getInt("id"),
|
||||
creatorId = privateMessage.getInt("creator_id"),
|
||||
recipientId = privateMessage.getInt("recipient_id"),
|
||||
content = privateMessage.getString("content"),
|
||||
deleted = privateMessage.getBoolean("deleted"),
|
||||
read = privateMessage.getBoolean("read"),
|
||||
published = privateMessage.getString("published"),
|
||||
updated = privateMessage.optString("updated", ""),
|
||||
creatorName = creator.getString("name"),
|
||||
creatorAvatar = creator.optString("avatar", ""),
|
||||
creatorQualifiedName = creator.getString("actor_id"),
|
||||
recipientName = recipient.getString("name"),
|
||||
recipientAvatar = recipient.optString("avatar", ""),
|
||||
recipientQualifiedName = recipient.getString("actor_id")
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package eu.toldi.infinityforlemmy.privatemessage
|
||||
|
||||
data class PrivateMessage(
|
||||
val id: Int,
|
||||
val creatorId: Int,
|
||||
val recipientId: Int,
|
||||
val content: String,
|
||||
val deleted: Boolean,
|
||||
var read: Boolean,
|
||||
val published: String,
|
||||
val updated: String,
|
||||
val creatorName: String,
|
||||
val creatorAvatar: String,
|
||||
val creatorQualifiedName: String,
|
||||
val recipientName: String,
|
||||
val recipientAvatar: String,
|
||||
val recipientQualifiedName: String
|
||||
)
|
@ -0,0 +1,103 @@
|
||||
package eu.toldi.infinityforlemmy.privatemessage
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.paging.PageKeyedDataSource
|
||||
import eu.toldi.infinityforlemmy.NetworkState
|
||||
import retrofit2.Retrofit
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
class PrivateMessageDataSource(
|
||||
private val retrofit: Retrofit,
|
||||
private val locale: Locale,
|
||||
private val accessToken: String,
|
||||
private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI
|
||||
) :
|
||||
PageKeyedDataSource<Int, PrivateMessage>() {
|
||||
|
||||
|
||||
val paginationNetworkStateLiveData: MutableLiveData<NetworkState>
|
||||
val initialLoadStateLiveData: MutableLiveData<NetworkState>
|
||||
private val hasPostLiveData: MutableLiveData<Boolean>
|
||||
private var params: LoadParams<Int>? = null
|
||||
private var callback: LoadCallback<Int, PrivateMessage>? = null
|
||||
private val page = 1
|
||||
|
||||
init {
|
||||
paginationNetworkStateLiveData = MutableLiveData()
|
||||
initialLoadStateLiveData = MutableLiveData()
|
||||
hasPostLiveData = MutableLiveData()
|
||||
}
|
||||
|
||||
fun hasPostLiveData(): MutableLiveData<Boolean> {
|
||||
return hasPostLiveData
|
||||
}
|
||||
|
||||
fun retryLoadingMore() {
|
||||
loadAfter(params!!, callback!!)
|
||||
}
|
||||
|
||||
override fun loadInitial(
|
||||
params: LoadInitialParams<Int>,
|
||||
callback: LoadInitialCallback<Int, PrivateMessage>
|
||||
) {
|
||||
initialLoadStateLiveData.postValue(NetworkState.LOADING)
|
||||
mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, page, object :
|
||||
LemmyPrivateMessageAPI.PrivateMessageFetchedListener {
|
||||
override fun onPrivateMessageFetchedSuccess(privateMessages: List<PrivateMessage>) {
|
||||
hasPostLiveData.postValue(true)
|
||||
if (privateMessages.isEmpty()) {
|
||||
callback.onResult(ArrayList(), null, null)
|
||||
} else {
|
||||
callback.onResult(privateMessages, null, page + 1)
|
||||
}
|
||||
initialLoadStateLiveData.postValue(NetworkState.LOADED)
|
||||
}
|
||||
|
||||
override fun onPrivateMessageFetchedError() {
|
||||
initialLoadStateLiveData.postValue(
|
||||
NetworkState(
|
||||
NetworkState.Status.FAILED,
|
||||
"Error fetch messages"
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun loadBefore(
|
||||
params: LoadParams<Int>,
|
||||
callback: LoadCallback<Int, PrivateMessage>
|
||||
) {
|
||||
}
|
||||
|
||||
override fun loadAfter(
|
||||
params: LoadParams<Int>,
|
||||
callback: LoadCallback<Int, PrivateMessage>
|
||||
) {
|
||||
this.params = params
|
||||
this.callback = callback
|
||||
paginationNetworkStateLiveData.postValue(NetworkState.LOADING)
|
||||
mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, params.key, object :
|
||||
LemmyPrivateMessageAPI.PrivateMessageFetchedListener {
|
||||
override fun onPrivateMessageFetchedSuccess(privateMessages: List<PrivateMessage>) {
|
||||
hasPostLiveData.postValue(true)
|
||||
if (privateMessages.isEmpty()) {
|
||||
callback.onResult(ArrayList(), null)
|
||||
} else {
|
||||
callback.onResult(privateMessages, params.key + 1)
|
||||
}
|
||||
paginationNetworkStateLiveData.postValue(NetworkState.LOADED)
|
||||
}
|
||||
|
||||
override fun onPrivateMessageFetchedError() {
|
||||
paginationNetworkStateLiveData.postValue(
|
||||
NetworkState(
|
||||
NetworkState.Status.FAILED,
|
||||
"Error fetch messages"
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package eu.toldi.infinityforlemmy.privatemessage
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.paging.DataSource
|
||||
import retrofit2.Retrofit
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
internal class PrivateMessageDataSourceFactory(
|
||||
retrofit: Retrofit,
|
||||
locale: Locale,
|
||||
accessToken: String,
|
||||
private var mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI
|
||||
) : DataSource.Factory<Int, PrivateMessage>() {
|
||||
private val mPrivateMessageDataSource: PrivateMessageDataSource =
|
||||
PrivateMessageDataSource(retrofit, locale, accessToken, mLemmyPrivateMessageAPI)
|
||||
private val messageDataSourceLiveData: MutableLiveData<PrivateMessageDataSource> =
|
||||
MutableLiveData<PrivateMessageDataSource>()
|
||||
|
||||
override fun create(): DataSource<Int, PrivateMessage> {
|
||||
messageDataSourceLiveData.postValue(mPrivateMessageDataSource)
|
||||
return mPrivateMessageDataSource
|
||||
}
|
||||
|
||||
fun getMessageDataSourceLiveData(): MutableLiveData<PrivateMessageDataSource> {
|
||||
return messageDataSourceLiveData
|
||||
}
|
||||
|
||||
fun getMessageDataSource(): PrivateMessageDataSource {
|
||||
return mPrivateMessageDataSource
|
||||
}
|
||||
|
||||
fun changeLemmPrivateMessageAPI(lemmyPrivateMessageAPI: LemmyPrivateMessageAPI) {
|
||||
this.mLemmyPrivateMessageAPI = lemmyPrivateMessageAPI
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package eu.toldi.infinityforlemmy.privatemessage
|
||||
|
||||
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 eu.toldi.infinityforlemmy.NetworkState
|
||||
import retrofit2.Retrofit
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
class PrivateMessageViewModel(
|
||||
retrofit: Retrofit,
|
||||
locale: Locale,
|
||||
accessToken: String,
|
||||
lemmyPrivateMessageAPI: LemmyPrivateMessageAPI
|
||||
) :
|
||||
ViewModel() {
|
||||
private val messageDataSourceFactory: PrivateMessageDataSourceFactory
|
||||
val paginationNetworkState: LiveData<NetworkState>
|
||||
val initialLoadingState: LiveData<NetworkState>
|
||||
private val hasMessageLiveData: LiveData<Boolean>
|
||||
val messages: LiveData<PagedList<PrivateMessage>>
|
||||
private val whereLiveData: MutableLiveData<LemmyPrivateMessageAPI> = MutableLiveData()
|
||||
|
||||
init {
|
||||
messageDataSourceFactory =
|
||||
PrivateMessageDataSourceFactory(retrofit, locale, accessToken, lemmyPrivateMessageAPI)
|
||||
initialLoadingState = Transformations.switchMap(
|
||||
messageDataSourceFactory.getMessageDataSourceLiveData(),
|
||||
PrivateMessageDataSource::initialLoadStateLiveData
|
||||
)
|
||||
paginationNetworkState = Transformations.switchMap(
|
||||
messageDataSourceFactory.getMessageDataSourceLiveData(),
|
||||
PrivateMessageDataSource::paginationNetworkStateLiveData
|
||||
)
|
||||
hasMessageLiveData = Transformations.switchMap(
|
||||
messageDataSourceFactory.getMessageDataSourceLiveData(),
|
||||
PrivateMessageDataSource::hasPostLiveData
|
||||
)
|
||||
|
||||
whereLiveData.postValue(lemmyPrivateMessageAPI)
|
||||
|
||||
val pagedListConfig: PagedList.Config = PagedList.Config.Builder()
|
||||
.setEnablePlaceholders(false)
|
||||
.setPageSize(25)
|
||||
.build()
|
||||
messages = Transformations.switchMap<LemmyPrivateMessageAPI, PagedList<PrivateMessage>>(
|
||||
whereLiveData
|
||||
) { newWhere: LemmyPrivateMessageAPI? ->
|
||||
messageDataSourceFactory.changeLemmPrivateMessageAPI(whereLiveData.value!!)
|
||||
LivePagedListBuilder(
|
||||
messageDataSourceFactory,
|
||||
pagedListConfig
|
||||
).build()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun hasMessage(): LiveData<Boolean> {
|
||||
return hasMessageLiveData
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
messageDataSourceFactory.getMessageDataSource().invalidate()
|
||||
}
|
||||
|
||||
fun retryLoadingMore() {
|
||||
messageDataSourceFactory.getMessageDataSource().retryLoadingMore()
|
||||
}
|
||||
|
||||
class Factory(
|
||||
private val retrofit: Retrofit,
|
||||
private val locale: Locale,
|
||||
private val accessToken: String,
|
||||
private val lemmyPrivateMessageAPI: LemmyPrivateMessageAPI
|
||||
) :
|
||||
ViewModelProvider.NewInstanceFactory() {
|
||||
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return PrivateMessageViewModel(
|
||||
retrofit,
|
||||
locale,
|
||||
accessToken,
|
||||
lemmyPrivateMessageAPI
|
||||
) as T
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user