Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 147 additions & 17 deletions TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,8 @@ public float getLastTouchY() {
CharSequence accessibilityText;
private boolean accessibilityTextUnread, accessibilityTextContentUnread;
private long accessibilityTextFileSize;
private int accessibilityTextButtonState = Integer.MIN_VALUE, accessibilityTextMiniButtonState = Integer.MIN_VALUE;
private int accessibilityTextTransferIndex = -1;
private boolean wasTranscriptionOpen;
private Path instantLinkArrowPath;
private Paint instantLinkArrowPaint;
Expand Down Expand Up @@ -6342,6 +6344,11 @@ public TLRPC.Chat getCurrentChat() {
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();

accessibilityFocused = false;
announcedTransferOnce = false;
accessibilityHovered = false;
announcedTransferOnce = false;

NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.startSpoilers);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.stopSpoilers);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded);
Expand Down Expand Up @@ -6993,6 +7000,15 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe
captionAbove = currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.invert_media || groupedMessages != null && groupedMessages.captionAbove;
isSmallImage = false;
lastLoadingSizeTotal = 0;
lastAnnouncedTransferStep = -1;
lastAnnouncedTransferPercent = -1;
lastAnnouncedTransferSize = -1;
announcedTransferOnce = false;
lastAnnouncedTransferTime = 0;
accessibilityFocused = false;
announcedTransferOnce = false;
accessibilityHovered = false;
announcedTransferOnce = false;
if (scheduledInvalidate) {
AndroidUtilities.cancelRunOnUIThread(invalidateRunnable);
scheduledInvalidate = false;
Expand Down Expand Up @@ -11224,6 +11240,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe
loadingProgressLayout = null;
animatingLoadingProgressProgress = 0;
lastLoadingSizeTotal = 0;
lastAnnouncedTransferStep = -1;
selectedBackgroundProgress = 0f;
if (statusDrawableAnimator != null) {
statusDrawableAnimator.removeAllListeners();
Expand Down Expand Up @@ -18185,11 +18202,108 @@ public void onAnimationReady(ImageReceiver imageReceiver) {
}
}

private int lastAnnouncedTransferStep = -1;
private int lastAnnouncedTransferPercent = -1;
private long lastAnnouncedTransferSize = -1;
private boolean announcedTransferOnce;
private long lastAnnouncedTransferTime;
private boolean accessibilityFocused;
private boolean accessibilityHovered;

private static final int TRANSFER_ANNOUNCE_STEP_PERCENT = 10;
private static final long TRANSFER_ANNOUNCE_INTERVAL = 2500;

private boolean hasTransferSizeInfo() {
return documentAttach != null && (documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO);
}

private CharSequence formatTransferProgress(boolean sending, int percent, long loadedSize, long totalSize) {
final StringBuilder sb = new StringBuilder();
sb.append(getString(sending ? R.string.AccDescrMsgSending : R.string.Downloading));
sb.append(" ").append(percent).append("%");
if (totalSize > 0) {
sb.append(", ").append(formatString(R.string.AccDescrPlayerDuration, AndroidUtilities.formatFileSize(loadedSize), AndroidUtilities.formatFileSize(totalSize)));
}
return sb;
}

private int getTransferPercent() {
if (currentMessageObject == null) {
return -1;
}
if (getIconForCurrentState() != MediaActionDrawable.ICON_CANCEL && getMiniIconForCurrentState() != MediaActionDrawable.ICON_CANCEL) {
return -1;
}
final float progress;
if (hasTransferSizeInfo() && loadingProgressLayout != null && lastLoadingSizeTotal > 0) {
progress = Math.min(1f, currentMessageObject.loadedFileSize / (float) lastLoadingSizeTotal);
} else {
progress = drawVideoImageButton ? videoRadialProgress.getProgress() : radialProgress.getProgress();
}
return Math.round(progress * 100);
}

private CharSequence getTransferProgressText() {
final int percent = getTransferPercent();
if (percent < 0) {
return null;
}
final boolean hasSize = hasTransferSizeInfo() && loadingProgressLayout != null && lastLoadingSizeTotal > 0;
return formatTransferProgress(currentMessageObject.isSending(), percent, currentMessageObject.loadedFileSize, hasSize ? lastLoadingSizeTotal : 0);
}

private boolean isExploredByAccessibility() {
if (!accessibilityHovered && !accessibilityFocused && !isAccessibilityFocused()) {
return false;
}
final AccessibilityManager am = (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
return am != null && am.isEnabled() && am.isTouchExplorationEnabled();
}

private void announceTransferProgress(boolean sending, long loadedSize, long totalSize) {
if (currentMessageObject == null || totalSize <= 0) {
return;
}
final boolean hovered = accessibilityHovered;
if (!isExploredByAccessibility()) {
return;
}
final int percent = (int) Math.min(100, Math.round(loadedSize / (float) totalSize * 100));
final int step = percent / TRANSFER_ANNOUNCE_STEP_PERCENT;
final long now = SystemClock.elapsedRealtime();
if (hovered) {
// while the finger explores the message, follow every step of the progress
if (step == lastAnnouncedTransferStep) {
return;
}
} else if (now - lastAnnouncedTransferTime < TRANSFER_ANNOUNCE_INTERVAL) {
// the message only holds accessibility focus, so keep the updates rare
return;
} else if (percent == lastAnnouncedTransferPercent && loadedSize == lastAnnouncedTransferSize) {
// nothing moved since the last update: there is nothing to say
return;
}
lastAnnouncedTransferStep = step;
lastAnnouncedTransferTime = now;
lastAnnouncedTransferPercent = percent;
lastAnnouncedTransferSize = loadedSize;
// the first update after reaching the message tells the whole of it, as reaching it does,
// and the ones after that only tell what has changed since
if (announcedTransferOnce) {
announceForAccessibility(hasTransferSizeInfo() ? percent + "%, " + AndroidUtilities.formatFileSize(loadedSize) : percent + "%");
} else {
announcedTransferOnce = true;
announceForAccessibility(formatTransferProgress(sending, percent, loadedSize, hasTransferSizeInfo() ? totalSize : 0));
}
}


@Override
public void onProgressDownload(String fileName, long downloadedSize, long totalSize) {
float progress = totalSize == 0 ? 0 : Math.min(1f, downloadedSize / (float) totalSize);
currentMessageObject.loadedFileSize = downloadedSize;
createLoadingProgressLayout(downloadedSize, totalSize);
announceTransferProgress(false, downloadedSize, totalSize);
if (drawVideoImageButton) {
videoRadialProgress.setProgress(progress, true);
} else {
Expand Down Expand Up @@ -18236,6 +18350,7 @@ public void onProgressUpload(String fileName, long uploadedSize, long totalSize,
lastLoadingSizeTotal = totalSize;
}
createLoadingProgressLayout(uploadedSize, totalSize);
announceTransferProgress(true, uploadedSize, totalSize);
}

private void createLoadingProgressLayout(TLRPC.Document document) {
Expand Down Expand Up @@ -26347,6 +26462,12 @@ public int getLayoutHeight() {

@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) {
accessibilityFocused = true;
} else if (action == AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS) {
accessibilityFocused = false;
announcedTransferOnce = false;
}
if (delegate != null && delegate.onAccessibilityAction(action, arguments)) {
return false;
}
Expand Down Expand Up @@ -26424,6 +26545,7 @@ public boolean onHoverEvent(MotionEvent event) {
int x = (int) getEventX(event);
int y = (int) getEventY(event);
if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER || event.getAction() == MotionEvent.ACTION_HOVER_MOVE) {
accessibilityHovered = true;
for (int i = 0; i < accessibilityVirtualViewBounds.size(); i++) {
Rect rect = accessibilityVirtualViewBounds.valueAt(i);
if (rect.contains(x, y)) {
Expand All @@ -26437,6 +26559,8 @@ public boolean onHoverEvent(MotionEvent event) {
}
} else if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
currentFocusedVirtualView = 0;
accessibilityHovered = false;
announcedTransferOnce = false;
}
return super.onHoverEvent(event);
}
Expand Down Expand Up @@ -26851,7 +26975,7 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
final boolean unread = currentMessageObject != null && currentMessageObject.isOut() && !currentMessageObject.scheduled && currentMessageObject.isUnread();
final boolean contentUnread = currentMessageObject != null && currentMessageObject.isContentUnread();
final long fileSize = currentMessageObject != null ? currentMessageObject.loadedFileSize : 0;
if (accessibilityText == null || accessibilityTextUnread != unread || accessibilityTextContentUnread != contentUnread || accessibilityTextFileSize != fileSize) {
if (accessibilityText == null || accessibilityTextUnread != unread || accessibilityTextContentUnread != contentUnread || accessibilityTextFileSize != fileSize || accessibilityTextButtonState != buttonState || accessibilityTextMiniButtonState != miniButtonState) {
SpannableStringBuilder sb = new SpannableStringBuilder();
if (isChat && currentUser != null && !currentMessageObject.isOut()) {
sb.append(UserObject.getUserName(currentUser));
Expand Down Expand Up @@ -26930,15 +27054,7 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
}
sb.append(messageText);
}
if (documentAttach != null && (documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO)) {
if (buttonState == 1 && loadingProgressLayout != null) {
sb.append("\n");
final boolean sending = currentMessageObject.isSending();
final String key = sending ? "AccDescrUploadProgress" : "AccDescrDownloadProgress";
final int resId = sending ? R.string.AccDescrUploadProgress : R.string.AccDescrDownloadProgress;
sb.append(formatString(key, resId, AndroidUtilities.formatFileSize(currentMessageObject.loadedFileSize), AndroidUtilities.formatFileSize(lastLoadingSizeTotal)));
}
}
accessibilityTextTransferIndex = sb.length();
if (currentMessageObject.isMusic()) {
sb.append("\n");
sb.append(formatString("AccDescrMusicInfo", R.string.AccDescrMusicInfo, currentMessageObject.getMusicAuthor(), currentMessageObject.getMusicTitle()));
Expand Down Expand Up @@ -27006,11 +27122,13 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
sb.append(currentMessageObject.isUnread() ? getString("AccDescrMsgUnread", R.string.AccDescrMsgUnread) : getString("AccDescrMsgRead", R.string.AccDescrMsgRead));
}
} else if (currentMessageObject.isSending()) {
sb.append("\n");
sb.append(getString("AccDescrMsgSending", R.string.AccDescrMsgSending));
final float sendingProgress = radialProgress.getProgress();
if (sendingProgress > 0f) {
sb.append(Integer.toString(Math.round(sendingProgress * 100))).append("%");
if (getTransferPercent() < 0) {
sb.append("\n");
sb.append(getString("AccDescrMsgSending", R.string.AccDescrMsgSending));
final float sendingProgress = radialProgress.getProgress();
if (sendingProgress > 0f) {
sb.append(" ").append(Integer.toString(Math.round(sendingProgress * 100))).append("%");
}
}
} else if (currentMessageObject.isSendError()) {
sb.append("\n");
Expand Down Expand Up @@ -27096,12 +27214,24 @@ public void onClick(View view) {
accessibilityTextUnread = unread;
accessibilityTextContentUnread = contentUnread;
accessibilityTextFileSize = fileSize;
accessibilityTextButtonState = buttonState;
accessibilityTextMiniButtonState = miniButtonState;
}

// the progress moves while the message stays as it is, so it cannot live in the
// text that is kept: it goes in where it belongs every time the message is read
CharSequence spokenText = accessibilityText;
final CharSequence transferProgress = getTransferProgressText();
if (transferProgress != null && accessibilityTextTransferIndex >= 0 && accessibilityTextTransferIndex <= accessibilityText.length()) {
final SpannableStringBuilder withProgress = new SpannableStringBuilder(accessibilityText);
withProgress.insert(accessibilityTextTransferIndex, "\n" + transferProgress);
spokenText = withProgress;
}

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
info.setContentDescription(accessibilityText.toString());
info.setContentDescription(spokenText.toString());
} else {
info.setText(accessibilityText);
info.setText(spokenText);
}

info.setEnabled(true);
Expand Down