From ec9d41fbbdd35e6f20bb2bf911c71d8b91f6968e Mon Sep 17 00:00:00 2001 From: sk Date: Fri, 3 Feb 2023 23:40:20 +0100 Subject: [PATCH] collapse long posts --- .../android/GlobalUserPreferences.java | 3 + .../android/fragments/SettingsFragment.java | 4 ++ .../displayitems/TextStatusDisplayItem.java | 57 ++++++++++++++++--- .../ui/views/UntouchableScrollView.java | 30 ++++++++++ .../ic_fluent_more_horizontal_24_regular.xml | 3 + .../src/main/res/layout/display_item_text.xml | 50 ++++++++++++---- mastodon/src/main/res/values/dimens.xml | 5 ++ mastodon/src/main/res/values/strings_sk.xml | 3 + 8 files changed, 136 insertions(+), 19 deletions(-) create mode 100644 mastodon/src/main/java/org/joinmastodon/android/ui/views/UntouchableScrollView.java create mode 100644 mastodon/src/main/res/drawable/ic_fluent_more_horizontal_24_regular.xml create mode 100644 mastodon/src/main/res/values/dimens.xml diff --git a/mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java b/mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java index 02ad7169f..93400787e 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java +++ b/mastodon/src/main/java/org/joinmastodon/android/GlobalUserPreferences.java @@ -41,6 +41,7 @@ public class GlobalUserPreferences{ public static boolean enablePreReleases; public static boolean prefixRepliesWithRe; public static boolean bottomEncoding; + public static boolean collapseLongPosts; public static String publishButtonText; public static ThemePreference theme; public static ColorPreference color; @@ -87,6 +88,7 @@ public class GlobalUserPreferences{ enablePreReleases=prefs.getBoolean("enablePreReleases", false); prefixRepliesWithRe=prefs.getBoolean("prefixRepliesWithRe", false); bottomEncoding=prefs.getBoolean("bottomEncoding", false); + collapseLongPosts=prefs.getBoolean("collapseLongPosts", true); publishButtonText=prefs.getString("publishButtonText", ""); theme=ThemePreference.values()[prefs.getInt("theme", 0)]; recentLanguages=fromJson(prefs.getString("recentLanguages", null), recentLanguagesType, new HashMap<>()); @@ -125,6 +127,7 @@ public class GlobalUserPreferences{ .putBoolean("showNoAltIndicator", showNoAltIndicator) .putBoolean("enablePreReleases", enablePreReleases) .putBoolean("prefixRepliesWithRe", prefixRepliesWithRe) + .putBoolean("collapseLongPosts", collapseLongPosts) .putString("publishButtonText", publishButtonText) .putBoolean("bottomEncoding", bottomEncoding) .putInt("theme", theme.ordinal()) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/SettingsFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/SettingsFragment.java index ef06d8d46..916fad32b 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/SettingsFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/SettingsFragment.java @@ -239,6 +239,10 @@ public class SettingsFragment extends MastodonToolbarFragment{ GlobalUserPreferences.showNoAltIndicator=i.checked; GlobalUserPreferences.save(); })); + items.add(new SwitchItem(R.string.sk_settings_collapse_long_posts, R.drawable.ic_fluent_more_horizontal_24_regular, GlobalUserPreferences.collapseLongPosts, i->{ + GlobalUserPreferences.collapseLongPosts=i.checked; + GlobalUserPreferences.save(); + })); items.add(new SwitchItem(R.string.sk_settings_translate_only_opened, R.drawable.ic_fluent_translate_24_regular, GlobalUserPreferences.translateButtonOpenedOnly, i->{ GlobalUserPreferences.translateButtonOpenedOnly=i.checked; GlobalUserPreferences.save(); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java index 9a75ff95f..1052cb3aa 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/TextStatusDisplayItem.java @@ -8,6 +8,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.Button; +import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; @@ -50,6 +51,7 @@ public class TextStatusDisplayItem extends StatusDisplayItem{ public boolean translated = false; public TranslatedStatus translation = null; private AccountSession session; + private boolean textIsRevealed; public static final Pattern BOTTOM_TEXT_PATTERN = Pattern.compile("(?:[\uD83E\uDEC2\uD83D\uDC96✨\uD83E\uDD7A,]+|❤️)(?:\uD83D\uDC49\uD83D\uDC48(?:[\uD83E\uDEC2\uD83D\uDC96✨\uD83E\uDD7A,]+|❤️))*\uD83D\uDC49\uD83D\uDC48"); public TextStatusDisplayItem(String parentID, CharSequence text, BaseStatusListFragment parentFragment, Status status, boolean disableTranslate){ @@ -88,10 +90,14 @@ public class TextStatusDisplayItem extends StatusDisplayItem{ public static class Holder extends StatusDisplayItem.Holder implements ImageLoaderViewHolder{ private final LinkedTextView text; private final LinearLayout spoilerHeader; - private final TextView spoilerTitle, spoilerTitleInline, translateInfo; - private final View spoilerOverlay, borderTop, borderBottom, textWrap, translateWrap, translateProgress; + private final TextView spoilerTitle, spoilerTitleInline, translateInfo, readMore; + private final View spoilerOverlay, borderTop, borderBottom, textWrap, translateWrap, translateProgress, spaceBelowText; private final int backgroundColor, borderColor; private final Button translateButton; + private final ScrollView textScrollView; + + private final float textMaxHeight, textCollapsedHeight; + private final LinearLayout.LayoutParams collapseParams, wrapParams; public Holder(Activity activity, ViewGroup parent){ super(activity, R.layout.display_item_text, parent); @@ -110,6 +116,14 @@ public class TextStatusDisplayItem extends StatusDisplayItem{ itemView.setOnClickListener(v->item.parentFragment.onRevealSpoilerClick(this)); backgroundColor=UiUtils.getThemeColor(activity, R.attr.colorBackgroundLight); borderColor=UiUtils.getThemeColor(activity, R.attr.colorPollVoted); + textScrollView=findViewById(R.id.text_scroll_view); + readMore=findViewById(R.id.read_more); + spaceBelowText=findViewById(R.id.space_below_text); + textMaxHeight=activity.getResources().getDimension(R.dimen.text_max_height); + textCollapsedHeight=activity.getResources().getDimension(R.dimen.text_collapsed_height); + collapseParams=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) textCollapsedHeight); + wrapParams=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + readMore.setOnClickListener(this::onClickReadMore); } @Override @@ -118,6 +132,9 @@ public class TextStatusDisplayItem extends StatusDisplayItem{ ? HtmlParser.parse(item.translation.content, item.status.emojis, item.status.mentions, item.status.tags, item.parentFragment.getAccountID()) : item.text); text.setTextIsSelectable(item.textSelectable); + if (item.textSelectable) { + textScrollView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); + } spoilerTitleInline.setTextIsSelectable(item.textSelectable); text.setInvalidateOnEveryFrame(false); spoilerTitleInline.setBackgroundColor(item.inset ? 0 : backgroundColor); @@ -151,14 +168,13 @@ public class TextStatusDisplayItem extends StatusDisplayItem{ instanceInfo.v2.configuration.translation.enabled; boolean isBottomText = BOTTOM_TEXT_PATTERN.matcher(item.status.getStrippedText()).find(); - translateWrap.setVisibility((isBottomText || ( + boolean translateVisible = (isBottomText || ( translateEnabled && - !item.status.visibility.isLessVisibleThan(StatusPrivacy.UNLISTED) && - item.status.language != null && - (item.session.preferences == null || !item.status.language.equalsIgnoreCase(item.session.preferences.postingDefaultLanguage)))) - && (!GlobalUserPreferences.translateButtonOpenedOnly || item.textSelectable) - ? View.VISIBLE : View.GONE - ); + !item.status.visibility.isLessVisibleThan(StatusPrivacy.UNLISTED) && + item.status.language != null && + (item.session.preferences == null || !item.status.language.equalsIgnoreCase(item.session.preferences.postingDefaultLanguage)))) + && (!GlobalUserPreferences.translateButtonOpenedOnly || item.textSelectable); + translateWrap.setVisibility(translateVisible ? View.VISIBLE : View.GONE); translateButton.setText(item.translated ? R.string.sk_translate_show_original : R.string.sk_translate_post); translateInfo.setText(item.translated ? itemView.getResources().getString(R.string.sk_translated_using, isBottomText ? "bottom-java" : item.translation.provider) : ""); translateButton.setOnClickListener(v->{ @@ -203,6 +219,29 @@ public class TextStatusDisplayItem extends StatusDisplayItem{ rebind(); } }); + + readMore.setText(item.textIsRevealed ? R.string.sk_collapse : R.string.sk_expand); + spaceBelowText.setVisibility(translateVisible ? View.VISIBLE : View.GONE); + + if (!GlobalUserPreferences.collapseLongPosts) { + textScrollView.setLayoutParams(wrapParams); + readMore.setVisibility(View.GONE); + } + + if (GlobalUserPreferences.collapseLongPosts) text.post(() -> { + boolean tooBig = text.getMeasuredHeight() > textMaxHeight; + boolean inTimeline = !item.textSelectable; + boolean hasSpoiler = !TextUtils.isEmpty(item.status.spoilerText); + boolean expandable = inTimeline && tooBig && !hasSpoiler; + readMore.setVisibility(expandable ? View.VISIBLE : View.GONE); + textScrollView.setLayoutParams(expandable && !item.textIsRevealed ? collapseParams : wrapParams); + if (expandable && !translateVisible) spaceBelowText.setVisibility(View.VISIBLE); + }); + } + + private void onClickReadMore(View v) { + item.textIsRevealed = !item.textIsRevealed; + rebind(); } @Override diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/views/UntouchableScrollView.java b/mastodon/src/main/java/org/joinmastodon/android/ui/views/UntouchableScrollView.java new file mode 100644 index 000000000..6b228cdde --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/views/UntouchableScrollView.java @@ -0,0 +1,30 @@ +package org.joinmastodon.android.ui.views; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.ScrollView; + +public class UntouchableScrollView extends ScrollView { + public UntouchableScrollView(Context context) { + super(context); + } + + public UntouchableScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public UntouchableScrollView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public UntouchableScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + super.onTouchEvent(event); + return false; + } +} diff --git a/mastodon/src/main/res/drawable/ic_fluent_more_horizontal_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_more_horizontal_24_regular.xml new file mode 100644 index 000000000..de1128305 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_more_horizontal_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/layout/display_item_text.xml b/mastodon/src/main/res/layout/display_item_text.xml index 15907788e..af3775173 100644 --- a/mastodon/src/main/res/layout/display_item_text.xml +++ b/mastodon/src/main/res/layout/display_item_text.xml @@ -44,19 +44,47 @@ android:background="?attr/colorPollVoted"/> - + android:requiresFadingEdge="vertical" + android:scrollbars="none" + android:fadingEdgeLength="36dp"> + + + + + + + +