diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/activities/ViewPrivateMessagesActivity.java b/app/src/main/java/eu/toldi/infinityforlemmy/activities/ViewPrivateMessagesActivity.java index 3ca525ad..0263722d 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/activities/ViewPrivateMessagesActivity.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/activities/ViewPrivateMessagesActivity.java @@ -5,6 +5,7 @@ import android.content.SharedPreferences; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.util.Log; import android.view.MenuItem; import android.view.View; import android.widget.EditText; @@ -27,6 +28,7 @@ import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import java.util.ArrayList; +import java.util.List; import java.util.concurrent.Executor; import javax.inject.Inject; @@ -46,14 +48,15 @@ import eu.toldi.infinityforlemmy.customviews.LinearLayoutManagerBugFixed; import eu.toldi.infinityforlemmy.events.PassPrivateMessageEvent; import eu.toldi.infinityforlemmy.events.PassPrivateMessageIndexEvent; import eu.toldi.infinityforlemmy.events.RepliedToPrivateMessageEvent; -import eu.toldi.infinityforlemmy.message.Message; import eu.toldi.infinityforlemmy.message.ReadMessage; -import eu.toldi.infinityforlemmy.message.ReplyMessage; +import eu.toldi.infinityforlemmy.privatemessage.LemmyPrivateMessageAPI; +import eu.toldi.infinityforlemmy.privatemessage.PrivateMessage; import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils; import retrofit2.Retrofit; public class ViewPrivateMessagesActivity extends BaseActivity implements ActivityToolbarInterface { + public static final String EXTRA_PRIVATE_MESSAGE = "EPM"; public static final String EXTRA_PRIVATE_MESSAGE_INDEX = "EPM"; public static final String EXTRA_MESSAGE_POSITION = "EMP"; private static final String USER_AVATAR_STATE = "UAS"; @@ -91,14 +94,19 @@ public class ViewPrivateMessagesActivity extends BaseActivity implements Activit CustomThemeWrapper mCustomThemeWrapper; @Inject Executor mExecutor; + + @Inject + LemmyPrivateMessageAPI mLemmyPrivateMessageAPI; private LinearLayoutManagerBugFixed mLinearLayoutManager; private PrivateMessagesDetailRecyclerViewAdapter mAdapter; @State - Message privateMessage; + PrivateMessage privateMessage; @State - Message replyTo; + PrivateMessage replyTo; private String mAccessToken; private String mAccountName; + + private String mAccountQualifiedName; private String mUserAvatar; private ArrayList mProvideUserAvatarCallbacks; private boolean isLoadingUserAvatar = false; @@ -128,6 +136,11 @@ public class ViewPrivateMessagesActivity extends BaseActivity implements Activit addOnOffsetChangedListener(mAppBarLayout); } + Intent intent = getIntent(); + privateMessage = intent.getParcelableExtra(EXTRA_PRIVATE_MESSAGE); + + Log.i("ViewPrivate", "privateMessage: " + privateMessage); + setSupportActionBar(mToolbar); setToolbarGoToTop(mToolbar); @@ -135,6 +148,7 @@ public class ViewPrivateMessagesActivity extends BaseActivity implements Activit mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null); mAccountName = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCOUNT_NAME, null); + mAccountQualifiedName = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCOUNT_QUALIFIED_NAME, null); if (savedInstanceState != null) { mUserAvatar = savedInstanceState.getString(USER_AVATAR_STATE); @@ -144,36 +158,37 @@ public class ViewPrivateMessagesActivity extends BaseActivity implements Activit bindView(); } } else { + if (privateMessage != null) { + bindView(); + } EventBus.getDefault().post(new PassPrivateMessageIndexEvent(getIntent().getIntExtra(EXTRA_PRIVATE_MESSAGE_INDEX, -1))); } } private void bindView() { if (privateMessage != null) { - if (privateMessage.getAuthor().equals(mAccountName)) { - setTitle(privateMessage.getDestination()); + if (privateMessage.getCreatorQualifiedName().equals(mAccountQualifiedName)) { + setTitle(privateMessage.getRecipientName()); mToolbar.setOnClickListener(view -> { - if (privateMessage.isDestinationDeleted()) { - return; - } + Intent intent = new Intent(this, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, privateMessage.getDestination()); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, privateMessage.getRecipientName()); + intent.putExtra(ViewUserDetailActivity.EXTRA_QUALIFIED_USER_NAME_KEY, privateMessage.getRecipientQualifiedName()); startActivity(intent); }); } else { - setTitle(privateMessage.getAuthor()); + setTitle(privateMessage.getCreatorName()); mToolbar.setOnClickListener(view -> { - if (privateMessage.isAuthorDeleted()) { - return; - } + Intent intent = new Intent(this, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, privateMessage.getAuthor()); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, privateMessage.getCreatorName()); + intent.putExtra(ViewUserDetailActivity.EXTRA_QUALIFIED_USER_NAME_KEY, privateMessage.getCreatorQualifiedName()); startActivity(intent); }); } } mAdapter = new PrivateMessagesDetailRecyclerViewAdapter(this, mSharedPreferences, - getResources().getConfiguration().locale, privateMessage, mAccountName, mCustomThemeWrapper); + getResources().getConfiguration().locale, privateMessage, mAccountQualifiedName, mCustomThemeWrapper); mLinearLayoutManager = new LinearLayoutManagerBugFixed(this); mLinearLayoutManager.setStackFromEnd(true); mRecyclerView.setLayoutManager(mLinearLayoutManager); @@ -184,45 +199,40 @@ public class ViewPrivateMessagesActivity extends BaseActivity implements Activit if (!mEditText.getText().toString().equals("")) { //Send Message if (privateMessage != null) { - ArrayList replies = privateMessage.getReplies(); + List replies = privateMessage.getReplies(); if (replyTo == null) { replyTo = privateMessage; } isSendingMessage = true; mSendImageView.setColorFilter(mSecondaryTextColor, android.graphics.PorterDuff.Mode.SRC_IN); - ReplyMessage.replyMessage(mEditText.getText().toString(), replyTo.getFullname(), - getResources().getConfiguration().locale, mOauthRetrofit, mAccessToken, - new ReplyMessage.ReplyMessageListener() { - @Override - public void replyMessageSuccess(Message message) { - if (mAdapter != null) { - mAdapter.addReply(message); - } - goToBottom(); - mEditText.setText(""); - mSendImageView.setColorFilter(mSendMessageIconColor, android.graphics.PorterDuff.Mode.SRC_IN); - isSendingMessage = false; - EventBus.getDefault().post(new RepliedToPrivateMessageEvent(message, getIntent().getIntExtra(EXTRA_MESSAGE_POSITION, -1))); - } - @Override - public void replyMessageFailed(String errorMessage) { - if (errorMessage != null && !errorMessage.equals("")) { - Snackbar.make(mCoordinatorLayout, errorMessage, Snackbar.LENGTH_LONG).show(); - } else { - Snackbar.make(mCoordinatorLayout, R.string.reply_message_failed, Snackbar.LENGTH_LONG).show(); - } - mSendImageView.setColorFilter(mSendMessageIconColor, android.graphics.PorterDuff.Mode.SRC_IN); - isSendingMessage = false; - } - }); + mLemmyPrivateMessageAPI.sendPrivateMessage(mAccessToken, replyTo.getCreatorId(), mEditText.getText().toString(), new LemmyPrivateMessageAPI.PrivateMessageSentListener() { + + @Override + public void onPrivateMessageSentSuccess(@NonNull PrivateMessage privateMessage) { + if (mAdapter != null) { + mAdapter.addReply(privateMessage); + } + goToBottom(); + mEditText.setText(""); + isSendingMessage = false; + EventBus.getDefault().post(new RepliedToPrivateMessageEvent(privateMessage, getIntent().getIntExtra(EXTRA_MESSAGE_POSITION, -1))); + } + + @Override + public void onPrivateMessageSentError() { + Snackbar.make(mCoordinatorLayout, R.string.reply_message_failed, Snackbar.LENGTH_LONG).show(); + mSendImageView.setColorFilter(mSendMessageIconColor, android.graphics.PorterDuff.Mode.SRC_IN); + isSendingMessage = false; + } + }); + + StringBuilder fullnames = new StringBuilder(); - if (privateMessage.isNew()) { - fullnames.append(privateMessage.getFullname()).append(","); - } + if (replies != null && !replies.isEmpty()) { - for (Message m : replies) { - if (m.isNew()) { + for (PrivateMessage m : replies) { + if (!m.getRead()) { fullnames.append(m).append(","); } } diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/adapters/PrivateMessageRecycleViewAdapter.java b/app/src/main/java/eu/toldi/infinityforlemmy/adapters/PrivateMessageRecycleViewAdapter.java index 3ec24f58..c833f7c3 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/adapters/PrivateMessageRecycleViewAdapter.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/adapters/PrivateMessageRecycleViewAdapter.java @@ -150,7 +150,7 @@ public class PrivateMessageRecycleViewAdapter extends PagedListAdapter { Intent intent = new Intent(mActivity, ViewPrivateMessagesActivity.class); - intent.putExtra(ViewPrivateMessagesActivity.EXTRA_PRIVATE_MESSAGE_INDEX, holder.getBindingAdapterPosition()); - intent.putExtra(ViewPrivateMessagesActivity.EXTRA_MESSAGE_POSITION, holder.getBindingAdapterPosition()); + intent.putExtra(ViewPrivateMessagesActivity.EXTRA_PRIVATE_MESSAGE, message); mActivity.startActivity(intent); diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/adapters/PrivateMessagesDetailRecyclerViewAdapter.java b/app/src/main/java/eu/toldi/infinityforlemmy/adapters/PrivateMessagesDetailRecyclerViewAdapter.java index bd031e80..cb9de220 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/adapters/PrivateMessagesDetailRecyclerViewAdapter.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/adapters/PrivateMessagesDetailRecyclerViewAdapter.java @@ -27,34 +27,35 @@ import java.util.Locale; import butterknife.BindView; import butterknife.ButterKnife; -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.inlineparser.BangInlineProcessor; -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 jp.wasabeef.glide.transformations.RoundedCornersTransformation; import eu.toldi.infinityforlemmy.R; 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.ClickableGlideImagesPlugin; 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.message.Message; +import eu.toldi.infinityforlemmy.privatemessage.PrivateMessage; import eu.toldi.infinityforlemmy.utils.SharedPreferencesUtils; import eu.toldi.infinityforlemmy.utils.Utils; +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 jp.wasabeef.glide.transformations.RoundedCornersTransformation; public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapter { private static final int VIEW_TYPE_MESSAGE_SENT = 0; private static final int VIEW_TYPE_MESSAGE_RECEIVED = 1; - private Message mMessage; + private PrivateMessage mMessage; private ViewPrivateMessagesActivity mViewPrivateMessagesActivity; private RequestManager mGlide; private Locale mLocale; @@ -70,7 +71,7 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt public PrivateMessagesDetailRecyclerViewAdapter(ViewPrivateMessagesActivity viewPrivateMessagesActivity, SharedPreferences sharedPreferences, Locale locale, - Message message, String accountName, + PrivateMessage message, String accountName, CustomThemeWrapper customThemeWrapper) { mMessage = message; mViewPrivateMessagesActivity = viewPrivateMessagesActivity; @@ -83,7 +84,6 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt mMarkwon = Markwon.builder(viewPrivateMessagesActivity) .usePlugin(MarkwonInlineParserPlugin.create(plugin -> { plugin.excludeInlineProcessor(HtmlInlineProcessor.class); - plugin.excludeInlineProcessor(BangInlineProcessor.class); })) .usePlugin(new AbstractMarkwonPlugin() { @Override @@ -108,6 +108,8 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt builder.linkColor(customThemeWrapper.getLinkColor()); } }) + .usePlugin(GlideImagesPlugin.create(viewPrivateMessagesActivity)) + .usePlugin(ClickableGlideImagesPlugin.create(viewPrivateMessagesActivity)) .usePlugin(SuperscriptPlugin.create()) .usePlugin(StrikethroughPlugin.create()) .usePlugin(SpoilerParserPlugin.create(commentColor, commentColor | 0xFF000000)) @@ -127,9 +129,9 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt @Override public int getItemViewType(int position) { if (position == 0) { - return mMessage.getAuthor().equals(mAccountName) ? VIEW_TYPE_MESSAGE_SENT : VIEW_TYPE_MESSAGE_RECEIVED; + return mMessage.getCreatorQualifiedName().equals(mAccountName) ? VIEW_TYPE_MESSAGE_SENT : VIEW_TYPE_MESSAGE_RECEIVED; } else { - return mMessage.getReplies().get(position - 1).getAuthor().equals(mAccountName) ? VIEW_TYPE_MESSAGE_SENT : VIEW_TYPE_MESSAGE_RECEIVED; + return mMessage.getReplies().get(position - 1).getCreatorQualifiedName().equals(mAccountName) ? VIEW_TYPE_MESSAGE_SENT : VIEW_TYPE_MESSAGE_RECEIVED; } } @@ -145,7 +147,7 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - Message message; + PrivateMessage message; if (holder.getBindingAdapterPosition() == 0) { message = mMessage; } else { @@ -153,12 +155,12 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt } if (message != null) { if (holder instanceof MessageViewHolder) { - mMarkwon.setMarkdown(((MessageViewHolder) holder).messageTextView, message.getBody()); + mMarkwon.setMarkdown(((MessageViewHolder) holder).messageTextView, message.getContent()); if (mShowElapsedTime) { - ((MessageViewHolder) holder).timeTextView.setText(Utils.getElapsedTime(mViewPrivateMessagesActivity, message.getTimeUTC())); + ((MessageViewHolder) holder).timeTextView.setText(Utils.getElapsedTime(mViewPrivateMessagesActivity, message.getPublished())); } else { - ((MessageViewHolder) holder).timeTextView.setText(Utils.getFormattedTime(mLocale, message.getTimeUTC(), mTimeFormatPattern)); + ((MessageViewHolder) holder).timeTextView.setText(Utils.getFormattedTime(mLocale, message.getPublished(), mTimeFormatPattern)); } } @@ -166,26 +168,33 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt ((SentMessageViewHolder) holder).messageTextView.setBackground(Utils.getTintedDrawable(mViewPrivateMessagesActivity, R.drawable.private_message_ballon, mSentMessageBackgroundColor)); } else if (holder instanceof ReceivedMessageViewHolder) { - mViewPrivateMessagesActivity.fetchUserAvatar(message.getAuthor(), userAvatarUrl -> { - if (userAvatarUrl == null || userAvatarUrl.equals("")) { - mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .into(((ReceivedMessageViewHolder) holder).userAvatarImageView); - } else { - mGlide.load(userAvatarUrl) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) - .error(mGlide.load(R.drawable.subreddit_default_icon) - .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) - .into(((ReceivedMessageViewHolder) holder).userAvatarImageView); - } - }); + if (!message.getCreatorAvatar().equals("")) { + mGlide.load(message.getCreatorAvatar()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((ReceivedMessageViewHolder) holder).userAvatarImageView); + } else { + mViewPrivateMessagesActivity.fetchUserAvatar(message.getCreatorQualifiedName(), userAvatarUrl -> { + if (userAvatarUrl == null || userAvatarUrl.equals("")) { + mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .into(((ReceivedMessageViewHolder) holder).userAvatarImageView); + } else { + mGlide.load(userAvatarUrl) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0))) + .error(mGlide.load(R.drawable.subreddit_default_icon) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(72, 0)))) + .into(((ReceivedMessageViewHolder) holder).userAvatarImageView); + } + }); + } ((ReceivedMessageViewHolder) holder).userAvatarImageView.setOnClickListener(view -> { - if (message.isAuthorDeleted()) { - return; - } + Intent intent = new Intent(mViewPrivateMessagesActivity, ViewUserDetailActivity.class); - intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, message.getAuthor()); + intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, message.getCreatorName()); + intent.putExtra(ViewUserDetailActivity.EXTRA_QUALIFIED_USER_NAME_KEY, message.getCreatorQualifiedName()); mViewPrivateMessagesActivity.startActivity(intent); }); @@ -207,12 +216,12 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt } } - public void setMessage(Message message) { + public void setMessage(PrivateMessage message) { mMessage = message; notifyDataSetChanged(); } - public void addReply(Message reply) { + public void addReply(PrivateMessage reply) { int currentSize = getItemCount(); if (mMessage != null) { @@ -273,7 +282,7 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt copyImageView.setColorFilter(mSecondaryTextColor, android.graphics.PorterDuff.Mode.SRC_IN); copyImageView.setOnClickListener(view -> { - Message message; + PrivateMessage message; if (getBindingAdapterPosition() == 0) { message = mMessage; } else { @@ -282,7 +291,7 @@ public class PrivateMessagesDetailRecyclerViewAdapter extends RecyclerView.Adapt if (message != null) { ClipboardManager clipboard = (ClipboardManager) mViewPrivateMessagesActivity.getSystemService(Context.CLIPBOARD_SERVICE); if (clipboard != null) { - ClipData clip = ClipData.newPlainText("simple text", message.getBody()); + ClipData clip = ClipData.newPlainText("simple text", message.getContent()); clipboard.setPrimaryClip(clip); if (android.os.Build.VERSION.SDK_INT < 33) { Toast.makeText(mViewPrivateMessagesActivity, R.string.copy_success, Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/events/RepliedToPrivateMessageEvent.java b/app/src/main/java/eu/toldi/infinityforlemmy/events/RepliedToPrivateMessageEvent.java index 7367d4f1..ea7ba870 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/events/RepliedToPrivateMessageEvent.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/events/RepliedToPrivateMessageEvent.java @@ -1,12 +1,12 @@ package eu.toldi.infinityforlemmy.events; -import eu.toldi.infinityforlemmy.message.Message; +import eu.toldi.infinityforlemmy.privatemessage.PrivateMessage; public class RepliedToPrivateMessageEvent { - public Message newReply; + public PrivateMessage newReply; public int messagePosition; - public RepliedToPrivateMessageEvent(Message newReply, int messagePosition) { + public RepliedToPrivateMessageEvent(PrivateMessage newReply, int messagePosition) { this.newReply = newReply; this.messagePosition = messagePosition; } diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/utils/LemmyUtils.java b/app/src/main/java/eu/toldi/infinityforlemmy/utils/LemmyUtils.java index d67cf6d1..d5e6781e 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/utils/LemmyUtils.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/utils/LemmyUtils.java @@ -1,5 +1,14 @@ package eu.toldi.infinityforlemmy.utils; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + public class LemmyUtils { public static String actorID2FullName(String url) { String[] splitURL = url.split("/"); @@ -21,4 +30,25 @@ public class LemmyUtils { String domain = splitQualifiedName[1]; return "https://" + domain + "/u/" + userName; } + + public static Long dateStringToMills(String dateStr) { + long postTimeMillis = 0; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + postTimeMillis = ZonedDateTime.parse(dateStr, + DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneId.of("Z"))).toInstant().toEpochMilli(); + } else { + dateStr = dateStr.substring(0, dateStr.lastIndexOf(".") + 4) + 'Z'; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()); + sdf.setTimeZone(TimeZone.getTimeZone("UTC")); + try { + Date date = sdf.parse(dateStr); + if (date != null) { + postTimeMillis = date.getTime(); + } + } catch (ParseException e) { + e.printStackTrace(); + } + } + return postTimeMillis; + } } diff --git a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/LemmyPrivateMessageAPI.kt b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/LemmyPrivateMessageAPI.kt index 65818c93..30edd597 100644 --- a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/LemmyPrivateMessageAPI.kt +++ b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/LemmyPrivateMessageAPI.kt @@ -2,6 +2,7 @@ package eu.toldi.infinityforlemmy.privatemessage import eu.toldi.infinityforlemmy.RetrofitHolder import eu.toldi.infinityforlemmy.apis.LemmyAPI +import eu.toldi.infinityforlemmy.dto.PrivateMessageDTO import eu.toldi.infinityforlemmy.dto.PrivateMessageReadDTO import eu.toldi.infinityforlemmy.utils.LemmyUtils import org.json.JSONObject @@ -71,6 +72,45 @@ class LemmyPrivateMessageAPI(val retrofitHolder: RetrofitHolder) { ) } + fun sendPrivateMessage( + auth: String, + recipientId: Int, + content: String, + listener: PrivateMessageSentListener + ) { + val api = retrofitHolder.retrofit.create(LemmyAPI::class.java) + + api.privateMessageSend(PrivateMessageDTO(recipientId, content, auth)).enqueue( + object : retrofit2.Callback { + override fun onResponse( + call: retrofit2.Call, + response: retrofit2.Response + ) { + if (response.isSuccessful) { + listener.onPrivateMessageSentSuccess( + parsePrivateMessage( + JSONObject(response.body()!!).getJSONObject( + "private_message_view" + ) + ) + ) + } else { + listener.onPrivateMessageSentError() + } + } + + override fun onFailure(call: retrofit2.Call, t: Throwable) { + listener.onPrivateMessageSentError() + } + } + ) + } + + interface PrivateMessageSentListener { + fun onPrivateMessageSentSuccess(privateMessage: PrivateMessage) + fun onPrivateMessageSentError() + } + interface PrivateMessageMarkedAsReadListener { fun onPrivateMessageMarkedAsReadSuccess() fun onPrivateMessageMarkedAsReadError() @@ -87,6 +127,7 @@ class LemmyPrivateMessageAPI(val retrofitHolder: RetrofitHolder) { val privateMessage = jsonObject.getJSONObject("private_message") val creator = jsonObject.getJSONObject("creator") val recipient = jsonObject.getJSONObject("recipient") + val updated = privateMessage.optString("updated", "") return PrivateMessage( id = privateMessage.getInt("id"), @@ -95,8 +136,12 @@ class LemmyPrivateMessageAPI(val retrofitHolder: RetrofitHolder) { content = privateMessage.getString("content"), deleted = privateMessage.getBoolean("deleted"), read = privateMessage.getBoolean("read"), - published = privateMessage.getString("published"), - updated = privateMessage.optString("updated", ""), + published = LemmyUtils.dateStringToMills(privateMessage.getString("published")), + updated = if (updated == "") { + null + } else { + LemmyUtils.dateStringToMills(updated) + }, creatorName = creator.getString("name"), creatorAvatar = creator.optString("avatar", ""), creatorQualifiedName = LemmyUtils.actorID2FullName(creator.getString("actor_id")), diff --git a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessage.kt b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessage.kt index 6ade6733..45497532 100644 --- a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessage.kt +++ b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessage.kt @@ -1,5 +1,8 @@ package eu.toldi.infinityforlemmy.privatemessage +import android.os.Parcel +import android.os.Parcelable + data class PrivateMessage( val id: Int, val creatorId: Int, @@ -7,12 +10,67 @@ data class PrivateMessage( val content: String, val deleted: Boolean, var read: Boolean, - val published: String, - val updated: String, + val published: Long, + val updated: Long?, val creatorName: String, val creatorAvatar: String, val creatorQualifiedName: String, val recipientName: String, val recipientAvatar: String, val recipientQualifiedName: String -) +) : Parcelable { + fun addReply(reply: PrivateMessage) { + replies.add(reply) + } + + val replies = mutableListOf() + + constructor(parcel: Parcel) : this( + parcel.readInt(), + parcel.readInt(), + parcel.readInt(), + parcel.readString()!!, + parcel.readByte() != 0.toByte(), + parcel.readByte() != 0.toByte(), + parcel.readLong(), + parcel.readValue(Long::class.java.classLoader) as? Long, + parcel.readString()!!, + parcel.readString()!!, + parcel.readString()!!, + parcel.readString()!!, + parcel.readString()!!, + parcel.readString()!! + ) { + } + + override fun writeToParcel(parcel: Parcel, flags: Int) { + parcel.writeInt(id) + parcel.writeInt(creatorId) + parcel.writeInt(recipientId) + parcel.writeString(content) + parcel.writeByte(if (deleted) 1 else 0) + parcel.writeByte(if (read) 1 else 0) + parcel.writeLong(published) + parcel.writeValue(updated) + parcel.writeString(creatorName) + parcel.writeString(creatorAvatar) + parcel.writeString(creatorQualifiedName) + parcel.writeString(recipientName) + parcel.writeString(recipientAvatar) + parcel.writeString(recipientQualifiedName) + } + + override fun describeContents(): Int { + return 0 + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): PrivateMessage { + return PrivateMessage(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } +} diff --git a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSource.kt b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSource.kt index d151bdd4..a93edba9 100644 --- a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSource.kt +++ b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSource.kt @@ -16,7 +16,7 @@ class PrivateMessageDataSource( PageKeyedDataSource() { - val paginationNetworkStateLiveData: MutableLiveData + val paginationNetworkStateLiveData: MutableLiveData = MutableLiveData() val initialLoadStateLiveData: MutableLiveData private val hasPostLiveData: MutableLiveData private var params: LoadParams? = null @@ -24,7 +24,6 @@ class PrivateMessageDataSource( private val page = 1 init { - paginationNetworkStateLiveData = MutableLiveData() initialLoadStateLiveData = MutableLiveData() hasPostLiveData = MutableLiveData() } @@ -49,7 +48,7 @@ class PrivateMessageDataSource( if (privateMessages.isEmpty()) { callback.onResult(ArrayList(), null, null) } else { - callback.onResult(privateMessages, null, page + 1) + callback.onResult(privateMessages, null, 2) } initialLoadStateLiveData.postValue(NetworkState.LOADED) }