Perform bidirectionality isolation manually instead of relying on BidiFormatter (#1976)

* Perform manual isolation of display names etc. instead of relying on BidiFormatter.
Fixes #1921

* Make follow request notification header formatting more like other notifications
This commit is contained in:
Levi Bard 2020-11-04 18:21:41 +01:00 committed by GitHub
commit 2170e6b0fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 49 additions and 34 deletions

View file

@ -1,13 +1,19 @@
package com.keylesspalace.tusky.adapter
import android.graphics.Typeface
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.StyleSpan
import android.view.View
import androidx.core.text.BidiFormatter
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.RecyclerView
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.interfaces.AccountActionListener
import com.keylesspalace.tusky.util.*
import com.keylesspalace.tusky.util.emojify
import com.keylesspalace.tusky.util.loadAvatar
import com.keylesspalace.tusky.util.unicodeWrap
import com.keylesspalace.tusky.util.visible
import kotlinx.android.synthetic.main.item_follow_request_notification.view.*
internal class FollowRequestViewHolder(itemView: View, private val showHeader: Boolean) : RecyclerView.ViewHolder(itemView) {
@ -15,13 +21,16 @@ internal class FollowRequestViewHolder(itemView: View, private val showHeader: B
private val animateAvatar: Boolean = PreferenceManager.getDefaultSharedPreferences(itemView.context)
.getBoolean("animateGifAvatars", false)
fun setupWithAccount(account: Account, formatter: BidiFormatter?) {
fun setupWithAccount(account: Account) {
id = account.id
val wrappedName = formatter?.unicodeWrap(account.name) ?: account.name
val wrappedName = account.name.unicodeWrap()
val emojifiedName: CharSequence = wrappedName.emojify(account.emojis, itemView)
itemView.displayNameTextView.text = emojifiedName
if (showHeader) {
itemView.notificationTextView?.text = itemView.context.getString(R.string.notification_follow_request_format, emojifiedName)
val wholeMessage: String = itemView.context.getString(R.string.notification_follow_request_format, wrappedName)
itemView.notificationTextView?.text = SpannableStringBuilder(wholeMessage).apply {
setSpan(StyleSpan(Typeface.BOLD), 0, wrappedName.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}.emojify(account.emojis, itemView)
}
itemView.notificationTextView?.visible(showHeader)
val format = itemView.context.getString(R.string.status_username_format)

View file

@ -53,7 +53,7 @@ public class FollowRequestsAdapter extends AccountAdapter {
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
if (getItemViewType(position) == VIEW_TYPE_ACCOUNT) {
FollowRequestViewHolder holder = (FollowRequestViewHolder) viewHolder;
holder.setupWithAccount(accountList.get(position), null);
holder.setupWithAccount(accountList.get(position));
holder.setupActionListener(accountActionListener);
}
}

View file

@ -35,7 +35,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.core.text.BidiFormatter;
import androidx.recyclerview.widget.RecyclerView;
import com.keylesspalace.tusky.R;
@ -51,6 +50,7 @@ import com.keylesspalace.tusky.util.ImageLoadingHelper;
import com.keylesspalace.tusky.util.LinkHelper;
import com.keylesspalace.tusky.util.SmartLengthInputFilter;
import com.keylesspalace.tusky.util.StatusDisplayOptions;
import com.keylesspalace.tusky.util.StringUtils;
import com.keylesspalace.tusky.util.TimestampUtils;
import com.keylesspalace.tusky.viewdata.NotificationViewData;
import com.keylesspalace.tusky.viewdata.StatusViewData;
@ -86,7 +86,6 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
private StatusActionListener statusListener;
private NotificationActionListener notificationActionListener;
private AccountActionListener accountActionListener;
private BidiFormatter bidiFormatter;
private AdapterDataSource<NotificationViewData> dataSource;
public NotificationsAdapter(String accountId,
@ -102,7 +101,6 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
this.statusListener = statusListener;
this.notificationActionListener = notificationActionListener;
this.accountActionListener = accountActionListener;
bidiFormatter = BidiFormatter.getInstance();
}
@NonNull
@ -204,7 +202,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
concreteNotificaton.getAccount().getAvatar());
}
holder.setMessage(concreteNotificaton, statusListener, bidiFormatter);
holder.setMessage(concreteNotificaton, statusListener);
holder.setupButtons(notificationActionListener,
concreteNotificaton.getAccount().getId(),
concreteNotificaton.getId());
@ -221,7 +219,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
case VIEW_TYPE_FOLLOW: {
if (payloadForHolder == null) {
FollowViewHolder holder = (FollowViewHolder) viewHolder;
holder.setMessage(concreteNotificaton.getAccount(), bidiFormatter);
holder.setMessage(concreteNotificaton.getAccount());
holder.setupButtons(notificationActionListener, concreteNotificaton.getAccount().getId());
}
break;
@ -229,7 +227,7 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
case VIEW_TYPE_FOLLOW_REQUEST: {
if (payloadForHolder == null) {
FollowRequestViewHolder holder = (FollowRequestViewHolder) viewHolder;
holder.setupWithAccount(concreteNotificaton.getAccount(), bidiFormatter);
holder.setupWithAccount(concreteNotificaton.getAccount());
holder.setupActionListener(accountActionListener);
}
}
@ -325,11 +323,11 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
this.statusDisplayOptions = statusDisplayOptions;
}
void setMessage(Account account, BidiFormatter bidiFormatter) {
void setMessage(Account account) {
Context context = message.getContext();
String format = context.getString(R.string.notification_follow_format);
String wrappedDisplayName = bidiFormatter.unicodeWrap(account.getName());
String wrappedDisplayName = StringUtils.unicodeWrap(account.getName());
String wholeMessage = String.format(format, wrappedDisplayName);
CharSequence emojifiedMessage = CustomEmojiHelper.emojify(wholeMessage, account.getEmojis(), message);
message.setText(emojifiedMessage);
@ -459,10 +457,10 @@ public class NotificationsAdapter extends RecyclerView.Adapter {
}
}
void setMessage(NotificationViewData.Concrete notificationViewData, LinkListener listener, BidiFormatter bidiFormatter) {
void setMessage(NotificationViewData.Concrete notificationViewData, LinkListener listener) {
this.statusViewData = notificationViewData.getStatusViewData();
String displayName = bidiFormatter.unicodeWrap(notificationViewData.getAccount().getName());
String displayName = StringUtils.unicodeWrap(notificationViewData.getAccount().getName());
Notification.Type type = notificationViewData.getType();
Context context = message.getContext();