1
0
Fork 1

Apply monocles read more read less feature

This commit is contained in:
Arne 2024-09-19 12:42:10 +02:00
parent 100db3898a
commit dcb2bb5d35
9 changed files with 305 additions and 4 deletions

View file

@ -1136,7 +1136,11 @@ public class MessageAdapter extends ArrayAdapter<Message> {
viewHolder.indicator = view.findViewById(R.id.security_indicator);
viewHolder.edit_indicator = view.findViewById(R.id.edit_indicator);
viewHolder.image = view.findViewById(R.id.message_image);
viewHolder.messageBody = view.findViewById(R.id.message_body);
if (activity.xmppConnectionService.getBooleanPreference("set_text_collapsable", R.bool.set_text_collapsable)) {
viewHolder.messageBody = view.findViewById(R.id.message_body_collapsable);
} else if (!activity.xmppConnectionService.getBooleanPreference("set_text_collapsable", R.bool.set_text_collapsable)) {
viewHolder.messageBody = view.findViewById(R.id.message_body);
}
viewHolder.time = view.findViewById(R.id.message_time);
viewHolder.subject = view.findViewById(R.id.message_subject);
viewHolder.inReplyTo = view.findViewById(R.id.in_reply_to);
@ -1160,7 +1164,11 @@ public class MessageAdapter extends ArrayAdapter<Message> {
viewHolder.indicator = view.findViewById(R.id.security_indicator);
viewHolder.edit_indicator = view.findViewById(R.id.edit_indicator);
viewHolder.image = view.findViewById(R.id.message_image);
viewHolder.messageBody = view.findViewById(R.id.message_body);
if (activity.xmppConnectionService.getBooleanPreference("set_text_collapsable", R.bool.set_text_collapsable)) {
viewHolder.messageBody = view.findViewById(R.id.message_body_collapsable);
} else if (!activity.xmppConnectionService.getBooleanPreference("set_text_collapsable", R.bool.set_text_collapsable)) {
viewHolder.messageBody = view.findViewById(R.id.message_body);
}
viewHolder.time = view.findViewById(R.id.message_time);
viewHolder.subject = view.findViewById(R.id.message_subject);
viewHolder.inReplyTo = view.findViewById(R.id.in_reply_to);

View file

@ -135,7 +135,11 @@
app:shapeAppearance="@style/ShapeAppearanceOverlay.Photo"
android:visibility="gone" />
<TextView
<de.monocles.chat.ReadMoreTextView
app:trimExpandedText="@string/show_less"
app:trimCollapsedText="@string/show_more"
app:trimMode="trimModeLength"
app:colorClickableText="?colorPrimary"
android:id="@+id/context_preview_text"
android:layout_weight="1"
android:layout_width="0dp"

View file

@ -65,7 +65,23 @@
android:paddingTop="4dp"
android:autoLink="web"
android:longClickable="false"
android:textAppearance="?textAppearanceBodyMedium" />
android:textAppearance="?textAppearanceBodyMedium"
android:visibility="gone" />
<de.monocles.chat.ReadMoreTextView
app:trimExpandedText="@string/show_less"
app:trimCollapsedText="@string/show_more"
app:trimMode="trimModeLength"
app:colorClickableText="?colorPrimary"
android:id="@+id/message_body_collapsable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:paddingTop="4dp"
android:autoLink="web"
android:longClickable="false"
android:textAppearance="?textAppearanceBodyMedium"
android:visibility="gone" />
<com.google.android.material.button.MaterialButton
android:id="@+id/download_button"

View file

@ -5,4 +5,5 @@
<bool name="show_thread_feature">false</bool>
<bool name="show_maps_inside">true</bool>
<bool name="show_own_accounts">false</bool>
<bool name="set_text_collapsable">false</bool>
</resources>

View file

@ -1114,4 +1114,8 @@
<string name="pref_show_mappreview_inside_summary">Load a preview of maps for a share location inside the chat</string>
<string name="pref_show_own_accounts">Show own account name</string>
<string name="pref_show_own_accounts_summary">Shows the used account on messages overview and details</string>
<string name="pref_set_text_collapsable_summary">Collapses text with more than 230 signs</string>
<string name="pref_set_text_collapsable">Collapse long text</string>
<string name="show_less">... show less</string>
<string name="show_more">... show more</string>
</resources>

View file

@ -117,6 +117,12 @@
android:entryValues="@array/avatars_shape_values"
android:summary="@string/pref_avatar_shape_summary"
android:title="@string/pref_avatars_shape" />
<SwitchPreferenceCompat
android:defaultValue="@bool/set_text_collapsable"
android:icon="@drawable/ic_keyboard_double_arrow_down_24dp"
android:key="set_text_collapsable"
android:summary="@string/pref_set_text_collapsable_summary"
android:title="@string/pref_set_text_collapsable" />
<SwitchPreferenceCompat
android:defaultValue="@bool/use_green_background"
android:icon="@drawable/ic_forum_24dp"

View file

@ -0,0 +1,9 @@
package de.monocles.chat;
/**
* Created by Mays Atari.
*/
public interface ReadMoreListener {
void onReadMoreClick(boolean readMore);
}

View file

@ -0,0 +1,239 @@
/*
* Copyright (C) 2016 Borja Bravo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.monocles.chat;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewTreeObserver;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.core.content.ContextCompat;
import eu.siacs.conversations.R;
public class ReadMoreTextView extends AppCompatTextView {
private static final int TRIM_MODE_LINES = 0;
private static final int TRIM_MODE_LENGTH = 1;
private static final int DEFAULT_TRIM_LENGTH = 230;
private static final int DEFAULT_TRIM_LINES = 7;
private static final int INVALID_END_INDEX = -1;
private static final boolean DEFAULT_SHOW_TRIM_EXPANDED_TEXT = true;
private static final boolean DEFAULT_READ_MORE = true;
private static final String ELLIPSIZE = "... ";
private CharSequence text;
private BufferType bufferType;
private boolean readMore;
private int trimLength;
private CharSequence trimCollapsedText;
private CharSequence trimExpandedText;
private final ReadMoreClickableSpan viewMoreSpan;
private int colorClickableText;
private final boolean showTrimExpandedText;
private ReadMoreListener readMoreListener;
private int trimMode;
private int lineEndIndex;
private int trimLines;
public ReadMoreTextView(Context context) {
this(context, null);
}
public ReadMoreTextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ReadMoreTextView);
this.trimLength = typedArray.getInt(R.styleable.ReadMoreTextView_trimLength, DEFAULT_TRIM_LENGTH);
int resourceIdTrimCollapsedText =
typedArray.getResourceId(R.styleable.ReadMoreTextView_trimCollapsedText, R.string.show_more);
int resourceIdTrimExpandedText =
typedArray.getResourceId(R.styleable.ReadMoreTextView_trimExpandedText, R.string.show_less);
this.trimCollapsedText = getResources().getString(resourceIdTrimCollapsedText);
this.trimExpandedText = getResources().getString(resourceIdTrimExpandedText);
this.trimLines = typedArray.getInt(R.styleable.ReadMoreTextView_trimLines, DEFAULT_TRIM_LINES);
this.colorClickableText = typedArray.getColor(R.styleable.ReadMoreTextView_colorClickableText,
ContextCompat.getColor(context, androidx.appcompat.R.color.abc_btn_colored_borderless_text_material));
this.showTrimExpandedText =
typedArray.getBoolean(R.styleable.ReadMoreTextView_showTrimExpandedText, DEFAULT_SHOW_TRIM_EXPANDED_TEXT);
this.readMore = typedArray.getBoolean(R.styleable.ReadMoreTextView_readMore, DEFAULT_READ_MORE);
this.trimMode = typedArray.getInt(R.styleable.ReadMoreTextView_trimMode, TRIM_MODE_LINES);
typedArray.recycle();
viewMoreSpan = new ReadMoreClickableSpan();
onGlobalLayoutLineEndIndex();
setText();
}
private void setText() {
super.setText(text, bufferType);
super.setText(getDisplayableText(), bufferType);
setMovementMethod(LinkMovementMethod.getInstance());
setHighlightColor(Color.TRANSPARENT);
}
private CharSequence getDisplayableText() {
return getTrimmedText(text);
}
@Override
public void setText(CharSequence text, BufferType type) {
this.text = text;
bufferType = type;
setText();
}
private CharSequence getTrimmedText(CharSequence text) {
if (trimMode == TRIM_MODE_LENGTH) {
if (text != null && text.length() > trimLength) {
if (readMore) {
return updateCollapsedText();
} else {
return updateExpandedText();
}
}
}
if (trimMode == TRIM_MODE_LINES) {
if (text != null && lineEndIndex > 0) {
if (readMore) {
if (getLayout().getLineCount() > trimLines) {
return updateCollapsedText();
}
} else {
return updateExpandedText();
}
}
}
return text;
}
private CharSequence updateCollapsedText() {
int trimEndIndex = text.length();
switch (trimMode) {
case TRIM_MODE_LINES:
trimEndIndex = lineEndIndex - (ELLIPSIZE.length() + trimCollapsedText.length() + 1);
if (trimEndIndex < 0) {
trimEndIndex = trimLength + 1;
}
break;
case TRIM_MODE_LENGTH:
trimEndIndex = trimLength + 1;
break;
}
SpannableStringBuilder s = new SpannableStringBuilder(text, 0, trimEndIndex)
.append(ELLIPSIZE)
.append(trimCollapsedText);
return addClickableSpan(s, trimCollapsedText);
}
private CharSequence updateExpandedText() {
if (showTrimExpandedText) {
SpannableStringBuilder s = new SpannableStringBuilder(text, 0, text.length()).append(trimExpandedText);
return addClickableSpan(s, trimExpandedText);
}
return text;
}
private CharSequence addClickableSpan(SpannableStringBuilder s, CharSequence trimText) {
s.setSpan(viewMoreSpan, s.length() - trimText.length(), s.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return s;
}
public void setTrimLength(int trimLength) {
this.trimLength = trimLength;
setText();
}
public void setColorClickableText(int colorClickableText) {
this.colorClickableText = colorClickableText;
}
public void setTrimCollapsedText(CharSequence trimCollapsedText) {
this.trimCollapsedText = trimCollapsedText;
}
public void setTrimExpandedText(CharSequence trimExpandedText) {
this.trimExpandedText = trimExpandedText;
}
public void setTrimMode(int trimMode) {
this.trimMode = trimMode;
}
public void setTrimLines(int trimLines) {
this.trimLines = trimLines;
}
public void setReadMore(boolean readMore) {
this.readMore = readMore;
}
public void setReadMoreListener(ReadMoreListener readMoreListener) {
this.readMoreListener = readMoreListener;
}
private class ReadMoreClickableSpan extends ClickableSpan {
@Override
public void onClick(View widget) {
readMore = !readMore;
setText();
if(readMoreListener != null){
readMoreListener.onReadMoreClick(readMore);
}
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(colorClickableText);
}
}
private void onGlobalLayoutLineEndIndex() {
if (trimMode == TRIM_MODE_LINES) {
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
ViewTreeObserver obs = getViewTreeObserver();
obs.removeOnGlobalLayoutListener(this);
refreshLineEndIndex();
setText();
}
});
}
}
private void refreshLineEndIndex() {
try {
if (trimLines == 0) {
lineEndIndex = getLayout().getLineEnd(0);
} else if (trimLines > 0 && getLineCount() >= trimLines) {
lineEndIndex = getLayout().getLineEnd(trimLines - 1);
} else {
lineEndIndex = INVALID_END_INDEX;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -10,4 +10,18 @@
<attr name="ic_accounts_selected" format="reference" />
<attr name="ic_group_unselected" format="reference" />
<attr name="ic_group_selected" format="reference" />
<declare-styleable name="ReadMoreTextView">
<attr name="trimExpandedText" format="string" />
<attr name="trimCollapsedText" format="string" />
<attr name="trimLength" format="integer" />
<attr name="showTrimExpandedText" format="boolean" />
<attr name="readMore" format="boolean" />
<attr name="colorClickableText" format="color" />
<attr name="trimLines" format="integer" />
<attr name="trimMode">
<enum name="trimModeLine" value="0"/>
<enum name="trimModeLength" value="1"/>
</attr>
</declare-styleable>
</resources>