Add option to render subscriptions as normal posts(like Pleroma does) or switch back to Mastodon behavior

This commit is contained in:
Alibek Omarov 2020-12-06 02:53:38 +03:00
parent 9c11fea95d
commit 6a1c062a8d
17 changed files with 51 additions and 24 deletions

View File

@ -56,6 +56,7 @@
<string name="pref_title_enable_big_emojis">Enable bigger custom emojis</string> <string name="pref_title_enable_big_emojis">Enable bigger custom emojis</string>
<string name="pref_title_enable_experimental_stickers">Enable experimental Pleroma-FE stickers(if available)</string> <string name="pref_title_enable_experimental_stickers">Enable experimental Pleroma-FE stickers(if available)</string>
<string name="pref_title_animate_custom_emojis">Animate custom emojis</string> <string name="pref_title_animate_custom_emojis">Animate custom emojis</string>
<string name="pref_title_render_subscriptions_as_statuses">Render subscriptions as normal posts</string>
<string name="attachment_type_image">Image</string> <string name="attachment_type_image">Image</string>
<string name="attachment_type_video">Video</string> <string name="attachment_type_video">Video</string>

View File

@ -39,7 +39,7 @@ class ChatMessagesViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val mediaPreviewUnloaded = ColorDrawable(ThemeUtils.getColor(itemView.context, R.attr.colorBackgroundAccent)) private val mediaPreviewUnloaded = ColorDrawable(ThemeUtils.getColor(itemView.context, R.attr.colorBackgroundAccent))
fun setupWithChatMessage(msg: ChatMessageViewData.Concrete, chatActionListener: ChatActionListener, statusDisplayOptions: StatusDisplayOptions, payload: Any?) { fun setupWithChatMessage(msg: ChatMessageViewData.Concrete, chatActionListener: ChatActionListener, payload: Any?) {
if(payload == null) { if(payload == null) {
if(msg.content != null) { if(msg.content != null) {
val text = msg.content.emojify(msg.emojis, content) val text = msg.content.emojify(msg.emojis, content)
@ -110,15 +110,15 @@ class ChatMessagesViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private fun setAttachmentClickListener(view: View, listener: ChatActionListener, attachment: Attachment, animateTransition: Boolean) { private fun setAttachmentClickListener(view: View, listener: ChatActionListener, attachment: Attachment, animateTransition: Boolean) {
view.setOnClickListener { v: View? -> view.setOnClickListener { v: View ->
val position = adapterPosition val position = adapterPosition
if (position != RecyclerView.NO_POSITION) { if (position != RecyclerView.NO_POSITION) {
listener.onViewMedia(position, if (animateTransition) v else null) listener.onViewMedia(position, if (animateTransition) v else null)
} }
} }
view.setOnLongClickListener { v: View? -> view.setOnLongClickListener { v: View ->
val description = getAttachmentDescription(view.context, attachment) val description = getAttachmentDescription(v.context, attachment)
Toast.makeText(view.context, description, Toast.LENGTH_LONG).show() Toast.makeText(v.context, description, Toast.LENGTH_LONG).show()
true true
} }
} }
@ -162,7 +162,6 @@ class ChatMessagesViewHolder(view: View) : RecyclerView.ViewHolder(view) {
class ChatMessagesAdapter(private val dataSource : TimelineAdapter.AdapterDataSource<ChatMessageViewData>, class ChatMessagesAdapter(private val dataSource : TimelineAdapter.AdapterDataSource<ChatMessageViewData>,
private val chatActionListener: ChatActionListener, private val chatActionListener: ChatActionListener,
private val statusDisplayOptions: StatusDisplayOptions,
private val localUserId: String) private val localUserId: String)
: RecyclerView.Adapter<RecyclerView.ViewHolder>() { : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
@ -207,7 +206,7 @@ class ChatMessagesAdapter(private val dataSource : TimelineAdapter.AdapterDataSo
if(holder is PlaceholderViewHolder) { if(holder is PlaceholderViewHolder) {
holder.setup(chatActionListener, (chat as ChatMessageViewData.Placeholder).isLoading) holder.setup(chatActionListener, (chat as ChatMessageViewData.Placeholder).isLoading)
} else if(holder is ChatMessagesViewHolder) { } else if(holder is ChatMessagesViewHolder) {
holder.setupWithChatMessage(chat as ChatMessageViewData.Concrete, chatActionListener, statusDisplayOptions, holder.setupWithChatMessage(chat as ChatMessageViewData.Concrete, chatActionListener,
if (payloads != null && payloads.isNotEmpty()) payloads[0] else null) if (payloads != null && payloads.isNotEmpty()) payloads[0] else null)
} }
} }

View File

@ -280,7 +280,8 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
statusDisplayOptions.showBotOverlay(), statusDisplayOptions.showBotOverlay(),
statusDisplayOptions.useBlurhash(), statusDisplayOptions.useBlurhash(),
CardViewMode.NONE, CardViewMode.NONE,
statusDisplayOptions.confirmReblogs() statusDisplayOptions.confirmReblogs(),
statusDisplayOptions.renderStatusAsMention()
); );
} }
@ -301,6 +302,12 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
return VIEW_TYPE_STATUS; return VIEW_TYPE_STATUS;
} }
case STATUS: case STATUS:
if (statusDisplayOptions.renderStatusAsMention()) {
if (concrete.getStatusViewData() != null && concrete.getStatusViewData().isMuted())
return VIEW_TYPE_MUTED_STATUS;
return VIEW_TYPE_STATUS;
}
/* fallthrough */
case FAVOURITE: case FAVOURITE:
case REBLOG: case REBLOG:
case EMOJI_REACTION: { case EMOJI_REACTION: {

View File

@ -66,7 +66,8 @@ public final class TimelineAdapter extends RecyclerView.Adapter {
statusDisplayOptions.showBotOverlay(), statusDisplayOptions.showBotOverlay(),
statusDisplayOptions.useBlurhash(), statusDisplayOptions.useBlurhash(),
statusDisplayOptions.cardViewMode(), statusDisplayOptions.cardViewMode(),
statusDisplayOptions.confirmReblogs() statusDisplayOptions.confirmReblogs(),
statusDisplayOptions.renderStatusAsMention()
); );
} }

View File

@ -259,11 +259,7 @@ class ChatActivity: BottomSheetActivity(),
} }
private fun setupChat() { private fun setupChat() {
val statusDisplayOptions = StatusDisplayOptions(false,false, adapter = ChatMessagesAdapter(dataSource, this, accountManager.activeAccount!!.accountId)
true, false, false, CardViewMode.NONE,
false)
adapter = ChatMessagesAdapter(dataSource, this, statusDisplayOptions, accountManager.activeAccount!!.accountId)
// TODO: a11y // TODO: a11y
recycler.setHasFixedSize(true) recycler.setHasFixedSize(true)

View File

@ -36,6 +36,7 @@ import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.fragment.SFragment import com.keylesspalace.tusky.fragment.SFragment
import com.keylesspalace.tusky.interfaces.ReselectableFragment import com.keylesspalace.tusky.interfaces.ReselectableFragment
import com.keylesspalace.tusky.interfaces.StatusActionListener import com.keylesspalace.tusky.interfaces.StatusActionListener
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.* import com.keylesspalace.tusky.util.*
import kotlinx.android.synthetic.main.fragment_timeline.* import kotlinx.android.synthetic.main.fragment_timeline.*
import javax.inject.Inject import javax.inject.Inject
@ -67,7 +68,8 @@ class ConversationsFragment : SFragment(), StatusActionListener, Injectable, Res
showBotOverlay = preferences.getBoolean("showBotOverlay", true), showBotOverlay = preferences.getBoolean("showBotOverlay", true),
useBlurhash = preferences.getBoolean("useBlurhash", true), useBlurhash = preferences.getBoolean("useBlurhash", true),
cardViewMode = CardViewMode.NONE, cardViewMode = CardViewMode.NONE,
confirmReblogs = preferences.getBoolean("confirmReblogs", true) confirmReblogs = preferences.getBoolean("confirmReblogs", true),
renderStatusAsMention = preferences.getBoolean(PrefKeys.RENDER_STATUS_AS_MENTION, true)
) )
adapter = ConversationAdapter(statusDisplayOptions, this, ::onTopLoaded, viewModel::retry) adapter = ConversationAdapter(statusDisplayOptions, this, ::onTopLoaded, viewModel::retry)

View File

@ -133,7 +133,8 @@ class PreferencesActivity : BaseActivity(), SharedPreferences.OnSharedPreference
} }
"statusTextSize", "absoluteTimeView", "showBotOverlay", "animateGifAvatars", "statusTextSize", "absoluteTimeView", "showBotOverlay", "animateGifAvatars",
"useBlurhash", "showCardsInTimelines", "confirmReblogs", "useBlurhash", "showCardsInTimelines", "confirmReblogs",
"enableSwipeForTabs", "bigEmojis", "mainNavPosition", PrefKeys.HIDE_TOP_TOOLBAR -> { "enableSwipeForTabs", "bigEmojis", "mainNavPosition", PrefKeys.HIDE_TOP_TOOLBAR,
PrefKeys.RENDER_STATUS_AS_MENTION -> {
restartActivitiesOnExit = true restartActivitiesOnExit = true
} }
"language" -> { "language" -> {

View File

@ -199,6 +199,13 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable {
setTitle(R.string.pref_title_animate_custom_emojis) setTitle(R.string.pref_title_animate_custom_emojis)
isSingleLineTitle = false isSingleLineTitle = false
} }
switchPreference {
setDefaultValue(true)
key = PrefKeys.RENDER_STATUS_AS_MENTION
setTitle(R.string.pref_title_render_subscriptions_as_statuses)
isSingleLineTitle = true
}
} }
preferenceCategory(R.string.pref_title_privacy) { preferenceCategory(R.string.pref_title_privacy) {

View File

@ -43,6 +43,7 @@ import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.Attachment import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.* import com.keylesspalace.tusky.util.*
import com.keylesspalace.tusky.viewdata.AttachmentViewData import com.keylesspalace.tusky.viewdata.AttachmentViewData
import kotlinx.android.synthetic.main.fragment_report_statuses.* import kotlinx.android.synthetic.main.fragment_report_statuses.*
@ -117,7 +118,8 @@ class ReportStatusesFragment : Fragment(), Injectable, AdapterHandler {
showBotOverlay = false, showBotOverlay = false,
useBlurhash = preferences.getBoolean("useBlurhash", true), useBlurhash = preferences.getBoolean("useBlurhash", true),
cardViewMode = CardViewMode.NONE, cardViewMode = CardViewMode.NONE,
confirmReblogs = preferences.getBoolean("confirmReblogs", true) confirmReblogs = preferences.getBoolean("confirmReblogs", true),
renderStatusAsMention = preferences.getBoolean(PrefKeys.RENDER_STATUS_AS_MENTION, true)
) )
adapter = StatusesAdapter(statusDisplayOptions, adapter = StatusesAdapter(statusDisplayOptions,

View File

@ -54,6 +54,7 @@ import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.entity.Status.Mention import com.keylesspalace.tusky.entity.Status.Mention
import com.keylesspalace.tusky.interfaces.AccountSelectionListener import com.keylesspalace.tusky.interfaces.AccountSelectionListener
import com.keylesspalace.tusky.interfaces.StatusActionListener import com.keylesspalace.tusky.interfaces.StatusActionListener
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.CardViewMode import com.keylesspalace.tusky.util.CardViewMode
import com.keylesspalace.tusky.util.LinkHelper import com.keylesspalace.tusky.util.LinkHelper
import com.keylesspalace.tusky.util.NetworkState import com.keylesspalace.tusky.util.NetworkState
@ -87,7 +88,8 @@ class SearchStatusesFragment : SearchFragment<Pair<Status, StatusViewData.Concre
showBotOverlay = preferences.getBoolean("showBotOverlay", true), showBotOverlay = preferences.getBoolean("showBotOverlay", true),
useBlurhash = preferences.getBoolean("useBlurhash", true), useBlurhash = preferences.getBoolean("useBlurhash", true),
cardViewMode = CardViewMode.NONE, cardViewMode = CardViewMode.NONE,
confirmReblogs = preferences.getBoolean("confirmReblogs", true) confirmReblogs = preferences.getBoolean("confirmReblogs", true),
renderStatusAsMention = preferences.getBoolean(PrefKeys.RENDER_STATUS_AS_MENTION, true)
) )
searchRecyclerView.addItemDecoration(DividerItemDecoration(searchRecyclerView.context, DividerItemDecoration.VERTICAL)) searchRecyclerView.addItemDecoration(DividerItemDecoration(searchRecyclerView.context, DividerItemDecoration.VERTICAL))

View File

@ -165,7 +165,7 @@ class ChatsFragment : BaseFragment(), Injectable, RefreshableFragment, Reselecta
accountManager.activeAccount!!.mediaPreviewEnabled, accountManager.activeAccount!!.mediaPreviewEnabled,
preferences.getBoolean("absoluteTimeView", false), preferences.getBoolean("absoluteTimeView", false),
preferences.getBoolean("showBotOverlay", true), preferences.getBoolean("showBotOverlay", true),
false, CardViewMode.NONE,false false, CardViewMode.NONE,false, false
) )
adapter = ChatsAdapter(dataSource, statusDisplayOptions, this, accountManager.activeAccount!!.accountId) adapter = ChatsAdapter(dataSource, statusDisplayOptions, this, accountManager.activeAccount!!.accountId)

View File

@ -250,7 +250,8 @@ public class NotificationsFragment extends SFragment implements
preferences.getBoolean("showBotOverlay", true), preferences.getBoolean("showBotOverlay", true),
preferences.getBoolean("useBlurhash", true), preferences.getBoolean("useBlurhash", true),
CardViewMode.NONE, CardViewMode.NONE,
preferences.getBoolean("confirmReblogs", true) preferences.getBoolean("confirmReblogs", true),
preferences.getBoolean(PrefKeys.RENDER_STATUS_AS_MENTION, true)
); );
withMuted = !preferences.getBoolean(PrefKeys.HIDE_MUTED_USERS, false); withMuted = !preferences.getBoolean(PrefKeys.HIDE_MUTED_USERS, false);

View File

@ -241,7 +241,8 @@ public class TimelineFragment extends SFragment implements
preferences.getBoolean("showCardsInTimelines", false) ? preferences.getBoolean("showCardsInTimelines", false) ?
CardViewMode.INDENTED : CardViewMode.INDENTED :
CardViewMode.NONE, CardViewMode.NONE,
preferences.getBoolean("confirmReblogs", true) preferences.getBoolean("confirmReblogs", true),
preferences.getBoolean(PrefKeys.RENDER_STATUS_AS_MENTION, true)
); );
adapter = new TimelineAdapter(dataSource, statusDisplayOptions, this); adapter = new TimelineAdapter(dataSource, statusDisplayOptions, this);

View File

@ -49,6 +49,7 @@ import com.keylesspalace.tusky.di.Injectable;
import com.keylesspalace.tusky.entity.*; import com.keylesspalace.tusky.entity.*;
import com.keylesspalace.tusky.interfaces.StatusActionListener; import com.keylesspalace.tusky.interfaces.StatusActionListener;
import com.keylesspalace.tusky.network.MastodonApi; import com.keylesspalace.tusky.network.MastodonApi;
import com.keylesspalace.tusky.settings.PrefKeys;
import com.keylesspalace.tusky.util.CardViewMode; import com.keylesspalace.tusky.util.CardViewMode;
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate; import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate;
import com.keylesspalace.tusky.util.PairedList; import com.keylesspalace.tusky.util.PairedList;
@ -126,7 +127,8 @@ public final class ViewThreadFragment extends SFragment implements
preferences.getBoolean("showCardsInTimelines", false) ? preferences.getBoolean("showCardsInTimelines", false) ?
CardViewMode.INDENTED : CardViewMode.INDENTED :
CardViewMode.NONE, CardViewMode.NONE,
preferences.getBoolean("confirmReblogs", true) preferences.getBoolean("confirmReblogs", true),
preferences.getBoolean(PrefKeys.RENDER_STATUS_AS_MENTION, true)
); );
adapter = new ThreadAdapter(statusDisplayOptions, this); adapter = new ThreadAdapter(statusDisplayOptions, this);
} }

View File

@ -36,6 +36,7 @@ object PrefKeys {
const val ANONYMIZE_FILENAMES = "anonymizeFilenames" const val ANONYMIZE_FILENAMES = "anonymizeFilenames"
const val HIDE_MUTED_USERS = "hideMutedUsers" const val HIDE_MUTED_USERS = "hideMutedUsers"
const val ANIMATE_CUSTOM_EMOJIS = "animateCustomEmojis" const val ANIMATE_CUSTOM_EMOJIS = "animateCustomEmojis"
const val RENDER_STATUS_AS_MENTION = "renderStatusAsMention"
const val CUSTOM_TABS = "customTabs" const val CUSTOM_TABS = "customTabs"

View File

@ -14,5 +14,7 @@ data class StatusDisplayOptions(
@get:JvmName("cardViewMode") @get:JvmName("cardViewMode")
val cardViewMode: CardViewMode, val cardViewMode: CardViewMode,
@get:JvmName("confirmReblogs") @get:JvmName("confirmReblogs")
val confirmReblogs: Boolean val confirmReblogs: Boolean,
@get:JvmName("renderStatusAsMention")
val renderStatusAsMention: Boolean,
) )

View File

@ -19,6 +19,7 @@ import com.keylesspalace.tusky.util.CardViewMode
import com.keylesspalace.tusky.util.ViewDataUtils import com.keylesspalace.tusky.util.ViewDataUtils
import com.keylesspalace.tusky.util.StatusDisplayOptions import com.keylesspalace.tusky.util.StatusDisplayOptions
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.settings.PrefKeys
import java.util.*; import java.util.*;
@ -40,7 +41,8 @@ class StatusView @JvmOverloads constructor(
showBotOverlay = false, showBotOverlay = false,
useBlurhash = preferences.getBoolean("useBlurhash", true), useBlurhash = preferences.getBoolean("useBlurhash", true),
cardViewMode = CardViewMode.NONE, cardViewMode = CardViewMode.NONE,
confirmReblogs = preferences.getBoolean("confirmReblogs", true) confirmReblogs = preferences.getBoolean("confirmReblogs", true),
renderStatusAsMention = preferences.getBoolean(PrefKeys.RENDER_STATUS_AS_MENTION, true)
) )
viewHolder = StatusViewHolder(this) viewHolder = StatusViewHolder(this)
} }