mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
improve screen reader support in conversations
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
android:src="@drawable/msg_encr_out"
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:contentDescription="@string/chat_input_placeholder"
|
||||
android:importantForAccessibility="no"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<TextView
|
||||
|
||||
@@ -164,6 +164,7 @@
|
||||
android:paddingTop="@dimen/message_bubble_top_padding"
|
||||
android:textColor="?conversation_item_incoming_text_primary_color"
|
||||
android:textColorLink="?conversation_item_incoming_text_primary_color"
|
||||
android:importantForAccessibility="no"
|
||||
app:scaleEmojis="true"
|
||||
tools:text="Mango pickle lorem ipsum"/>
|
||||
|
||||
|
||||
@@ -142,6 +142,7 @@
|
||||
android:paddingTop="@dimen/message_bubble_top_padding"
|
||||
android:textColor="?conversation_item_outgoing_text_primary_color"
|
||||
android:textColorLink="?conversation_item_outgoing_text_primary_color"
|
||||
android:importantForAccessibility="no"
|
||||
app:scaleEmojis="true"
|
||||
tools:text="Mango pickle lorem ipsum"/>
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -77,6 +78,8 @@ public abstract class BaseConversationItem extends LinearLayout
|
||||
return batchSelected.isEmpty() && (messageRecord.isFailed());
|
||||
}
|
||||
|
||||
protected void onAccessibilityClick() {}
|
||||
|
||||
protected class PassthroughClickListener implements View.OnLongClickListener, View.OnClickListener {
|
||||
|
||||
@Override
|
||||
@@ -103,6 +106,9 @@ public abstract class BaseConversationItem extends LinearLayout
|
||||
|
||||
public void onClick(View v) {
|
||||
if (!shouldInterceptClicks(messageRecord) && parent != null) {
|
||||
if (batchSelected.isEmpty() && ((AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE)).isTouchExplorationEnabled()) {
|
||||
BaseConversationItem.this.onAccessibilityClick();
|
||||
}
|
||||
parent.onClick(v);
|
||||
} else if (messageRecord.isFailed()) {
|
||||
View view = View.inflate(context, R.layout.message_details_view, null);
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
@@ -193,6 +194,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
setReactions(messageRecord);
|
||||
setFooter(messageRecord, locale);
|
||||
setQuote(messageRecord);
|
||||
setContentDescription(messageRecord);
|
||||
}
|
||||
|
||||
|
||||
@@ -305,6 +307,36 @@ public class ConversationItem extends BaseConversationItem
|
||||
}
|
||||
}
|
||||
|
||||
private void setContentDescription(DcMsg messageRecord) {
|
||||
String desc = "";
|
||||
if (groupSenderHolder.getVisibility() == View.VISIBLE) {
|
||||
desc = groupSender.getText() + "\n";
|
||||
}
|
||||
if (audioViewStub.resolved() && audioViewStub.get().getVisibility() == View.VISIBLE) {
|
||||
desc += audioViewStub.get().getDescription() + "\n";
|
||||
} else if (documentViewStub.resolved() && documentViewStub.get().getVisibility() == View.VISIBLE) {
|
||||
desc += documentViewStub.get().getDescription() + "\n";
|
||||
} else if (webxdcViewStub.resolved() && webxdcViewStub.get().getVisibility() == View.VISIBLE) {
|
||||
desc += webxdcViewStub.get().getDescription() + "\n";
|
||||
} else if (mediaThumbnailStub.resolved() && mediaThumbnailStub.get().getVisibility() == View.VISIBLE) {
|
||||
desc += mediaThumbnailStub.get().getDescription() + "\n";
|
||||
} else if (stickerStub.resolved() && stickerStub.get().getVisibility() == View.VISIBLE) {
|
||||
desc += context.getString(R.string.sticker) + "\n";
|
||||
}
|
||||
|
||||
if (bodyText.getVisibility() == View.VISIBLE) {
|
||||
desc += bodyText.getText() + "\n";
|
||||
}
|
||||
|
||||
if (footer.getVisibility() == View.VISIBLE) {
|
||||
desc += footer.getDescription() + "\n";
|
||||
} else if (stickerFooter.getVisibility() == View.VISIBLE) {
|
||||
desc += stickerFooter.getDescription() + "\n";
|
||||
}
|
||||
|
||||
this.setContentDescription(desc);
|
||||
}
|
||||
|
||||
private boolean hasAudio(DcMsg messageRecord) {
|
||||
int type = messageRecord.getType();
|
||||
return type==DcMsg.DC_MSG_AUDIO || type==DcMsg.DC_MSG_VOICE;
|
||||
@@ -447,6 +479,9 @@ public class ConversationItem extends BaseConversationItem
|
||||
|
||||
audioViewStub.get().setAudio(new AudioSlide(context, messageRecord), duration);
|
||||
audioViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
audioViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -463,6 +498,9 @@ public class ConversationItem extends BaseConversationItem
|
||||
documentViewStub.get().setDocument(new DocumentSlide(context, messageRecord));
|
||||
documentViewStub.get().setDocumentClickListener(new ThumbnailClickListener());
|
||||
documentViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
documentViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -478,6 +516,9 @@ public class ConversationItem extends BaseConversationItem
|
||||
webxdcViewStub.get().setWebxdc(messageRecord, context.getString(R.string.webxdc_app));
|
||||
webxdcViewStub.get().setWebxdcClickListener(new ThumbnailClickListener());
|
||||
webxdcViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
webxdcViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -512,6 +553,9 @@ public class ConversationItem extends BaseConversationItem
|
||||
mediaThumbnailStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
mediaThumbnailStub.get().setOnClickListener(passthroughClickListener);
|
||||
mediaThumbnailStub.get().showShade(TextUtils.isEmpty(messageRecord.getText()));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
mediaThumbnailStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
|
||||
setThumbnailOutlineCorners(messageRecord, showSender);
|
||||
|
||||
@@ -531,9 +575,11 @@ public class ConversationItem extends BaseConversationItem
|
||||
|
||||
stickerStub.get().setSlide(glideRequests, new StickerSlide(context, messageRecord));
|
||||
stickerStub.get().setThumbnailClickListener(new StickerClickListener());
|
||||
|
||||
stickerStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
stickerStub.get().setOnClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
stickerStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -792,6 +838,14 @@ public class ConversationItem extends BaseConversationItem
|
||||
return availableWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccessibilityClick() {
|
||||
if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().performClick();
|
||||
else if (audioViewStub.resolved()) audioViewStub.get().performClick();
|
||||
else if (documentViewStub.resolved()) documentViewStub.get().performClick();
|
||||
else if (webxdcViewStub.resolved()) webxdcViewStub.get().performClick();
|
||||
}
|
||||
|
||||
/// Event handlers
|
||||
|
||||
private class ThumbnailClickListener implements SlideClickListener {
|
||||
|
||||
@@ -93,6 +93,30 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performClick() {
|
||||
if (this.playButton.getVisibility() == View.VISIBLE) {
|
||||
playButton.performClick();
|
||||
} else {
|
||||
pauseButton.performClick();
|
||||
}
|
||||
return super.performClick();
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
String desc;
|
||||
if (this.title.getVisibility() == View.VISIBLE) {
|
||||
desc = getContext().getString(R.string.audio);
|
||||
} else {
|
||||
desc = getContext().getString(R.string.voice_message);
|
||||
}
|
||||
desc += "\n" + this.timestamp.getText();
|
||||
if (title.getVisibility() == View.VISIBLE) {
|
||||
desc += "\n" + this.title.getText();
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDuration(int duration) {
|
||||
if (getProgress()==0)
|
||||
this.timestamp.setText(DateUtils.getFormatedDuration(duration));
|
||||
|
||||
@@ -100,4 +100,13 @@ public class ConversationItemFooter extends LinearLayout {
|
||||
deliveryStatusView.setTint(textColor); // Reset the color to the standard color (because the footer is re-used in a RecyclerView)
|
||||
}
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
String desc = dateView.getText().toString();
|
||||
String deliveryDesc = deliveryStatusView.getDescription();
|
||||
if (!"".equals(deliveryDesc)) {
|
||||
desc += "\n" + deliveryDesc;
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,10 @@ public class ConversationItemThumbnail extends FrameLayout {
|
||||
setTouchDelegate(thumbnail.getTouchDelegate());
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return thumbnail.getDescription() + "\n" + footer.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int originalWidthMeasureSpec, int originalHeightMeasureSpec) {
|
||||
int width = MeasureSpec.getSize(originalWidthMeasureSpec);
|
||||
@@ -185,6 +189,11 @@ public class ConversationItemThumbnail extends FrameLayout {
|
||||
thumbnail.setThumbnailClickListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performClick() {
|
||||
return thumbnail.performClick();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void setImageResource(@NonNull GlideRequests glideRequests, @NonNull Slide slide,
|
||||
int naturalWidth, int naturalHeight)
|
||||
|
||||
@@ -123,4 +123,11 @@ public class DeliveryStatusView {
|
||||
public void resetTint() {
|
||||
deliveryIndicator.setColorFilter(null);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
if (deliveryIndicator.getVisibility() == View.VISIBLE) {
|
||||
return deliveryIndicator.getContentDescription().toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,13 @@ public class DocumentView extends FrameLayout {
|
||||
this.setOnClickListener(new OpenClickedListener(documentSlide));
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
String desc = getContext().getString(R.string.file);
|
||||
desc += "\n" + fileName.getText();
|
||||
desc += "\n" + fileSize.getText();
|
||||
return desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocusable(boolean focusable) {
|
||||
super.setFocusable(focusable);
|
||||
|
||||
@@ -82,6 +82,14 @@ public class ThumbnailView extends FrameLayout {
|
||||
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
if (slide != null && slide.hasPlayOverlay()) {
|
||||
return getContext().getString(R.string.video);
|
||||
} else {
|
||||
return getContext().getString(R.string.image);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int originalWidthMeasureSpec, int originalHeightMeasureSpec) {
|
||||
fillTargetDimensions(measureDimens, dimens, bounds);
|
||||
|
||||
@@ -89,6 +89,15 @@ public class WebxdcView extends FrameLayout {
|
||||
appSubtitle.setText(summary);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
String desc = getContext().getString(R.string.webxdc_app);
|
||||
desc += "\n" + appName.getText();
|
||||
if (appSubtitle.getText() != null && !appSubtitle.getText().toString().equals("") && !appSubtitle.getText().toString().equals(getContext().getString(R.string.webxdc_app))) {
|
||||
desc += "\n" + appSubtitle.getText();
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
private class OpenClickedListener implements View.OnClickListener {
|
||||
private final @NonNull DocumentSlide slide;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user