[WIP] Show quotes replies
This commit is contained in:
parent
c107aa78ef
commit
9d1159969f
|
@ -66,6 +66,7 @@ import com.keylesspalace.tusky.util.TimestampUtils;
|
|||
import com.keylesspalace.tusky.util.TouchDelegateHelper;
|
||||
import com.keylesspalace.tusky.view.MediaPreviewImageView;
|
||||
import com.keylesspalace.tusky.view.MediaPreviewLayout;
|
||||
import com.keylesspalace.tusky.view.StatusQuoteView;
|
||||
import com.keylesspalace.tusky.viewdata.PollOptionViewData;
|
||||
import com.keylesspalace.tusky.viewdata.PollViewData;
|
||||
import com.keylesspalace.tusky.viewdata.PollViewDataKt;
|
||||
|
@ -135,6 +136,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
|||
private final Drawable mediaPreviewUnloaded;
|
||||
|
||||
private ChipGroup emojiReactionsView;
|
||||
private StatusQuoteView quoteView;
|
||||
|
||||
protected StatusBaseViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
|
@ -151,6 +153,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
|||
bookmarkButton = itemView.findViewById(R.id.status_bookmark);
|
||||
moreButton = itemView.findViewById(R.id.status_more);
|
||||
emojiReactionsView = itemView.findViewById(R.id.status_emoji_reactions);
|
||||
quoteView = itemView.findViewById(R.id.status_quote_view);
|
||||
|
||||
mediaContainer = itemView.findViewById(R.id.status_media_preview_container);
|
||||
mediaContainer.setClipToOutline(true);
|
||||
|
@ -475,6 +478,18 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
|||
bookmarkButton.setChecked(bookmarked);
|
||||
}
|
||||
|
||||
protected void setQuote(StatusViewData.Concrete status, final StatusActionListener listener) {
|
||||
Status quotedStatus = status.getActionable().getQuote();
|
||||
if (quotedStatus == null) {
|
||||
quoteView.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
|
||||
StatusViewData.Concrete statusViewData = status.copyWithStatus(quotedStatus);
|
||||
quoteView.setupWithStatus(statusViewData, listener, getBindingAdapterPosition());
|
||||
quoteView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private BitmapDrawable decodeBlurHash(String blurhash) {
|
||||
return ImageLoadingHelper.decodeBlurHash(this.avatar.getContext(), blurhash);
|
||||
}
|
||||
|
@ -820,6 +835,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
|||
setReblogged(actionable.getReblogged());
|
||||
setFavourited(actionable.getFavourited());
|
||||
setBookmarked(actionable.getBookmarked());
|
||||
setQuote(status, listener);
|
||||
List<Attachment> attachments = actionable.getAttachments();
|
||||
boolean sensitive = actionable.getSensitive();
|
||||
if (statusDisplayOptions.mediaPreviewEnabled() && hasPreviewableAttachment(attachments)) {
|
||||
|
@ -1277,10 +1293,18 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
|
|||
pollOptions.setVisibility(visibility);
|
||||
pollButton.setVisibility(visibility);
|
||||
pollDescription.setVisibility(visibility);
|
||||
showStatusButtons(show);
|
||||
}
|
||||
|
||||
public void showStatusButtons(boolean show) {
|
||||
int visibility = show ? View.VISIBLE : View.GONE;
|
||||
emojiReactionsView.setVisibility(visibility);
|
||||
replyButton.setVisibility(visibility);
|
||||
replyCountLabel.setVisibility(visibility);
|
||||
reblogButton.setVisibility(visibility);
|
||||
favouriteButton.setVisibility(visibility);
|
||||
bookmarkButton.setVisibility(visibility);
|
||||
reactButton.setVisibility(visibility);
|
||||
moreButton.setVisibility(visibility);
|
||||
}
|
||||
|
||||
|
|
|
@ -133,6 +133,7 @@ data class ConversationStatusEntity(
|
|||
language = language,
|
||||
filtered = null,
|
||||
pleroma = null, // FIXME
|
||||
quote = null, // FIXME??
|
||||
),
|
||||
isExpanded = expanded,
|
||||
isShowingContent = showingHiddenContent,
|
||||
|
|
|
@ -497,6 +497,11 @@ class TimelineFragment :
|
|||
super.viewReplyTo(status.actionable.inReplyToId);
|
||||
}
|
||||
|
||||
override fun onViewQuote(position: Int) {
|
||||
val status = adapter.peek(position)?.asStatusOrNull()?.actionable?.quote ?: return
|
||||
super.viewThread(status.id, status.url)
|
||||
}
|
||||
|
||||
override fun onViewTag(tag: String) {
|
||||
if (viewModel.kind == TimelineViewModel.Kind.TAG && viewModel.tags.size == 1 &&
|
||||
viewModel.tags.contains(tag)
|
||||
|
|
|
@ -204,6 +204,7 @@ fun TimelineStatusWithAccount.toViewData(gson: Gson, isDetailed: Boolean = false
|
|||
language = status.language,
|
||||
filtered = status.filtered,
|
||||
pleroma = pleroma,
|
||||
quote = null, // FIXME: cache this
|
||||
)
|
||||
}
|
||||
val status = if (reblog != null) {
|
||||
|
@ -238,6 +239,7 @@ fun TimelineStatusWithAccount.toViewData(gson: Gson, isDetailed: Boolean = false
|
|||
language = status.language,
|
||||
filtered = status.filtered,
|
||||
pleroma = pleroma,
|
||||
quote = null, // FIXME: cache this
|
||||
)
|
||||
} else {
|
||||
Status(
|
||||
|
@ -271,6 +273,7 @@ fun TimelineStatusWithAccount.toViewData(gson: Gson, isDetailed: Boolean = false
|
|||
language = status.language,
|
||||
filtered = status.filtered,
|
||||
pleroma = pleroma,
|
||||
quote = null, // FIXME: cache this
|
||||
)
|
||||
}
|
||||
return StatusViewData.Concrete(
|
||||
|
|
|
@ -366,6 +366,15 @@ class ViewThreadFragment :
|
|||
super.viewReplyTo(id)
|
||||
}
|
||||
|
||||
override fun onViewQuote(position: Int) {
|
||||
val status = adapter.currentList[position].actionable.quote ?: return
|
||||
if (thisThreadsStatusId == status.id) {
|
||||
// If already viewing this thread, don't reopen it.
|
||||
return
|
||||
}
|
||||
super.viewThread(status.id, status.url)
|
||||
}
|
||||
|
||||
override fun onViewUrl(url: String) {
|
||||
val status: StatusViewData.Concrete? = viewModel.detailedStatus()
|
||||
if (status != null && status.status.url == url) {
|
||||
|
|
|
@ -52,6 +52,7 @@ data class Status(
|
|||
val language: String?,
|
||||
val filtered: List<FilterResult>?,
|
||||
val pleroma: PleromaStatus?,
|
||||
val quote: Status?,
|
||||
) {
|
||||
|
||||
val actionableId: String
|
||||
|
|
|
@ -33,6 +33,7 @@ public interface StatusActionListener extends LinkListener {
|
|||
void onViewMedia(int position, int attachmentIndex, @Nullable View view);
|
||||
void onViewThread(int position);
|
||||
void onViewReplyTo(int position);
|
||||
default void onViewQuote(int position) {}
|
||||
|
||||
/**
|
||||
* Open reblog author for the status.
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
package com.keylesspalace.tusky.view
|
||||
|
||||
import android.content.*
|
||||
import android.util.*
|
||||
import android.view.*
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.adapter.StatusViewHolder
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener
|
||||
import com.keylesspalace.tusky.settings.PrefKeys
|
||||
import com.keylesspalace.tusky.util.CardViewMode
|
||||
import com.keylesspalace.tusky.util.StatusDisplayOptions
|
||||
import com.keylesspalace.tusky.viewdata.StatusViewData
|
||||
|
||||
class StatusQuoteView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0)
|
||||
: ConstraintLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private lateinit var viewHolder : StatusViewHolder
|
||||
private var statusDisplayOptions : StatusDisplayOptions
|
||||
init {
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
statusDisplayOptions = StatusDisplayOptions(
|
||||
animateAvatars = preferences.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false),
|
||||
mediaPreviewEnabled = true, // FIXME: get value from AccountManager
|
||||
useAbsoluteTime = preferences.getBoolean(PrefKeys.ABSOLUTE_TIME_VIEW, false),
|
||||
showBotOverlay = preferences.getBoolean(PrefKeys.SHOW_BOT_OVERLAY, true),
|
||||
useBlurhash = preferences.getBoolean(PrefKeys.USE_BLURHASH, true),
|
||||
cardViewMode = CardViewMode.NONE,
|
||||
confirmReblogs = false,
|
||||
confirmFavourites = false,
|
||||
hideStats = false,
|
||||
animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false),
|
||||
showStatsInline = false,
|
||||
showSensitiveMedia = false, // FIXME: get value from AccountManager
|
||||
openSpoiler = false, // FIXME: get value from AccountManager
|
||||
bigEmojis = preferences.getBoolean(PrefKeys.BIG_EMOJIS, true),
|
||||
)
|
||||
}
|
||||
|
||||
fun setupWithStatus(status: StatusViewData.Concrete, statusActionListener: StatusActionListener, position: Int) {
|
||||
removeAllViews()
|
||||
View.inflate(context, R.layout.item_status, this)
|
||||
viewHolder = StatusViewHolder(this)
|
||||
viewHolder.showStatusButtons(false)
|
||||
viewHolder.setupWithStatus(status, ProxyQuoteStatusActionListener(statusActionListener, position), statusDisplayOptions)
|
||||
}
|
||||
|
||||
class ProxyQuoteStatusActionListener constructor(
|
||||
private val higherLevelStatusListener: StatusActionListener,
|
||||
val position: Int
|
||||
): StatusActionListener {
|
||||
|
||||
override fun onReply(position: Int) { }
|
||||
override fun onReblog(reblog: Boolean, position: Int) { }
|
||||
override fun onFavourite(favourite: Boolean, position: Int) { }
|
||||
override fun onBookmark(bookmark: Boolean, position: Int) { }
|
||||
override fun onMore(view: View, position: Int) { }
|
||||
override fun onViewMedia(position: Int, attachmentIndex: Int, view: View?) { }
|
||||
|
||||
override fun onViewThread(position: Int) {
|
||||
higherLevelStatusListener.onViewQuote(this.position)
|
||||
}
|
||||
|
||||
override fun onViewReplyTo(position: Int) { }
|
||||
override fun onOpenReblog(position: Int) { }
|
||||
override fun onExpandedChange(expanded: Boolean, position: Int) { }
|
||||
override fun onContentHiddenChange(isShowing: Boolean, position: Int) { }
|
||||
override fun onLoadMore(position: Int) { }
|
||||
override fun onContentCollapsedChange(isCollapsed: Boolean, position: Int) { }
|
||||
override fun onVoteInPoll(position: Int, choices: MutableList<Int>) { }
|
||||
|
||||
override fun onViewAccount(id: String) {
|
||||
higherLevelStatusListener.onViewAccount(id)
|
||||
}
|
||||
|
||||
override fun onViewTag(id: String) {
|
||||
higherLevelStatusListener.onViewTag(id)
|
||||
}
|
||||
|
||||
override fun onViewUrl(id: String) {
|
||||
higherLevelStatusListener.onViewUrl(id)
|
||||
}
|
||||
|
||||
override fun clearWarningAction(position: Int) { }
|
||||
}
|
||||
}
|
|
@ -103,6 +103,11 @@ sealed class StatusViewData {
|
|||
this.isCollapsible = shouldTrimStatus(this.content)
|
||||
}
|
||||
|
||||
/** Helper for Java */
|
||||
fun copyWithStatus(status: Status): Concrete {
|
||||
return copy(status = status)
|
||||
}
|
||||
|
||||
/** Helper for Java */
|
||||
fun copyWithCollapsed(isCollapsed: Boolean): Concrete {
|
||||
return copy(isCollapsed = isCollapsed)
|
||||
|
|
|
@ -326,6 +326,18 @@
|
|||
app:layout_constraintTop_toBottomOf="@id/status_poll_button"
|
||||
tools:text="7 votes • 7 hours remaining" />
|
||||
|
||||
<com.keylesspalace.tusky.view.StatusQuoteView
|
||||
android:id="@+id/status_quote_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/status_media_preview_margin_top"
|
||||
android:layout_marginEnd="14dp"
|
||||
android:background="@drawable/card_frame"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_description" />
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/status_emoji_reactions"
|
||||
android:layout_width="0dp"
|
||||
|
@ -333,7 +345,7 @@
|
|||
android:layout_marginTop="4dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="@id/status_display_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_description"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_quote_view"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
|
|
|
@ -281,6 +281,19 @@
|
|||
app:layout_constraintTop_toBottomOf="@id/status_poll_button"
|
||||
tools:text="7 votes • 7 hours remaining" />
|
||||
|
||||
<com.keylesspalace.tusky.view.StatusQuoteView
|
||||
android:id="@+id/status_quote_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="14dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="14dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="@drawable/card_frame"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_description" />
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/status_emoji_reactions"
|
||||
android:layout_width="0dp"
|
||||
|
@ -289,7 +302,7 @@
|
|||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_poll_description" />
|
||||
app:layout_constraintTop_toBottomOf="@id/status_quote_view" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/status_meta_info"
|
||||
|
|
Loading…
Reference in New Issue