示例#1
0
public class StickerCell extends FrameLayoutFixed {

  private KharTheme theme = ThemeCenter.get().getTheme();

  private BackupImageView imageView;

  public StickerCell(Context context) {
    super(context);

    imageView = new BackupImageView(context);
    imageView.setAspectFit(true);
    addView(imageView, LayoutHelper.createFrame(66, 66, Gravity.CENTER_HORIZONTAL, 0, 5, 0, 0));
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(
        MeasureSpec.makeMeasureSpec(
            AndroidUtilities.dp(76) + getPaddingLeft() + getPaddingRight(), MeasureSpec.EXACTLY),
        MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(78), MeasureSpec.EXACTLY));
  }

  @Override
  public void setPressed(boolean pressed) {
    if (imageView.getImageReceiver().getPressed() != pressed) {
      imageView.getImageReceiver().setPressed(pressed);
      imageView.invalidate();
    }
    super.setPressed(pressed);
  }

  public void setSticker(TLRPC.Document document, int side) {
    if (document != null && document.thumb != null) {
      imageView.setImage(document.thumb.location, null, "webp", null);
    }
    if (side == -1) {
      setBackgroundResource(theme.StickerCell_bg_1_R);
      setPadding(AndroidUtilities.dp(7), 0, 0, 0);
    } else if (side == 0) {
      setBackgroundResource(theme.StickerCell_bg_2_R);
      setPadding(0, 0, 0, 0);
    } else if (side == 1) {
      setBackgroundResource(theme.StickerCell_bg_3_R);
      setPadding(0, 0, AndroidUtilities.dp(7), 0);
    } else if (side == 2) {
      setBackgroundResource(theme.StickerCell_bg_4_R);
      setPadding(AndroidUtilities.dp(3), 0, AndroidUtilities.dp(3), 0);
    }
    if (getBackground() != null) {
      getBackground().setAlpha(230);
    }
  }
}
示例#2
0
public class ChatMusicCell extends ChatBaseCell implements SeekBar.SeekBarDelegate {

  private KharTheme theme = ThemeCenter.get().getTheme();

  public interface ChatMusicCellDelegate {
    boolean needPlayMusic(MessageObject messageObject);
  }

  private static TextPaint timePaint;
  private static TextPaint titlePaint;
  private static TextPaint authorPaint;

  private SeekBar seekBar;
  private int seekBarX;
  private int seekBarY;

  private RadialProgress radialProgress;
  private int buttonState = 0;
  private int buttonX;
  private int buttonY;
  private boolean buttonPressed = false;

  private StaticLayout timeLayout;
  private int timeX;
  private String lastTimeString = null;

  private StaticLayout titleLayout;
  private int titleX;

  private StaticLayout authorLayout;
  private int authorX;

  private ChatMusicCellDelegate musicDelegate;

  public ChatMusicCell(Context context) {
    super(context);

    seekBar = new SeekBar(context);
    seekBar.delegate = this;
    radialProgress = new RadialProgress(this);
    drawForwardedName = false;

    if (timePaint == null) {
      timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
      timePaint.setTextSize(AndroidUtilities.dp(13));

      titlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
      titlePaint.setTextSize(AndroidUtilities.dp(16));
      titlePaint.setColor(theme.ChatMusicCell_titlePaint_color);
      titlePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));

      authorPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
      authorPaint.setTextSize(AndroidUtilities.dp(15));
      authorPaint.setColor(theme.ChatMusicCell_authorPaint_color);
    }
  }

  @Override
  protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    MediaController.getInstance().removeLoadingFileObserver(this);
  }

  @Override
  protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    updateButtonState(false);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    boolean result =
        seekBar.onTouch(event.getAction(), event.getX() - seekBarX, event.getY() - seekBarY);
    if (result) {
      if (event.getAction() == MotionEvent.ACTION_DOWN) {
        getParent().requestDisallowInterceptTouchEvent(true);
      }
      invalidate();
    } else {
      int side = AndroidUtilities.dp(36);
      if (event.getAction() == MotionEvent.ACTION_DOWN) {
        if (x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side) {
          buttonPressed = true;
          invalidate();
          result = true;
        }
      } else if (buttonPressed) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
          buttonPressed = false;
          playSoundEffect(SoundEffectConstants.CLICK);
          didPressedButton();
          invalidate();
        } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
          buttonPressed = false;
          invalidate();
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
          if (!(x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side)) {
            buttonPressed = false;
            invalidate();
          }
        }
      }
      if (!result) {
        result = super.onTouchEvent(event);
      }
    }

    return result;
  }

  private void didPressedButton() {
    if (buttonState == 0) {
      if (musicDelegate != null) {
        if (musicDelegate.needPlayMusic(currentMessageObject)) {
          buttonState = 1;
          radialProgress.setBackground(getDrawableForCurrentState(), false, false);
          invalidate();
        }
      }
    } else if (buttonState == 1) {
      boolean result = MediaController.getInstance().pauseAudio(currentMessageObject);
      if (result) {
        buttonState = 0;
        radialProgress.setBackground(getDrawableForCurrentState(), false, false);
        invalidate();
      }
    } else if (buttonState == 2) {
      radialProgress.setProgress(0, false);
      FileLoader.getInstance()
          .loadFile(currentMessageObject.messageOwner.media.document, true, false);
      buttonState = 3;
      radialProgress.setBackground(getDrawableForCurrentState(), true, false);
      invalidate();
    } else if (buttonState == 3) {
      FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.document);
      buttonState = 2;
      radialProgress.setBackground(getDrawableForCurrentState(), false, false);
      invalidate();
    } else if (buttonState == 4) {
      if (currentMessageObject.isOut() && currentMessageObject.isSending()) {
        if (delegate != null) {
          delegate.didPressedCancelSendButton(this);
        }
      }
    }
  }

  public void setMusicDelegate(ChatMusicCellDelegate delegate) {
    musicDelegate = delegate;
  }

  public void updateProgress() {
    if (currentMessageObject == null) {
      return;
    }

    if (!seekBar.isDragging()) {
      seekBar.setProgress(currentMessageObject.audioProgress);
    }

    int duration = 0;
    int currentProgress = 0;
    for (TLRPC.DocumentAttribute attribute :
        currentMessageObject.messageOwner.media.document.attributes) {
      if (attribute instanceof TLRPC.TL_documentAttributeAudio) {
        duration = attribute.duration;
        break;
      }
    }
    if (MediaController.getInstance().isPlayingAudio(currentMessageObject)) {
      currentProgress = currentMessageObject.audioProgressSec;
    }
    String timeString =
        String.format(
            "%d:%02d / %d:%02d",
            currentProgress / 60, currentProgress % 60, duration / 60, duration % 60);
    if (lastTimeString == null || lastTimeString != null && !lastTimeString.equals(timeString)) {
      lastTimeString = timeString;
      int timeWidth = (int) Math.ceil(timePaint.measureText(timeString));
      timeLayout =
          new StaticLayout(
              timeString, timePaint, timeWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
    }
    invalidate();
  }

  public void downloadAudioIfNeed() {
    // if (buttonState == 2) {
    // FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.document, true,
    // false);
    //    buttonState = 3;
    //    invalidate();
    // }
  }

  public void updateButtonState(boolean animated) {
    if (currentMessageObject == null) {
      return;
    }
    if (currentMessageObject.isOut() && currentMessageObject.isSending()) {
      MediaController.getInstance()
          .addLoadingFileObserver(currentMessageObject.messageOwner.attachPath, this);
      buttonState = 4;
      radialProgress.setBackground(getDrawableForCurrentState(), true, animated);
      Float progress =
          ImageLoader.getInstance().getFileProgress(currentMessageObject.messageOwner.attachPath);
      if (progress == null
          && SendMessagesHelper.getInstance().isSendingMessage(currentMessageObject.getId())) {
        progress = 1.0f;
      }
      radialProgress.setProgress(progress != null ? progress : 0, false);
    } else {
      File cacheFile = null;
      if (currentMessageObject.messageOwner.attachPath != null
          && currentMessageObject.messageOwner.attachPath.length() > 0) {
        cacheFile = new File(currentMessageObject.messageOwner.attachPath);
        if (!cacheFile.exists()) {
          cacheFile = null;
        }
      }
      if (cacheFile == null) {
        cacheFile = FileLoader.getPathToMessage(currentMessageObject.messageOwner);
      }
      if (cacheFile.exists()) {
        MediaController.getInstance().removeLoadingFileObserver(this);
        boolean playing = MediaController.getInstance().isPlayingAudio(currentMessageObject);
        if (!playing || playing && MediaController.getInstance().isAudioPaused()) {
          buttonState = 0;
        } else {
          buttonState = 1;
        }
        radialProgress.setProgress(0, animated);
        radialProgress.setBackground(getDrawableForCurrentState(), false, animated);
      } else {
        String fileName = currentMessageObject.getFileName();
        MediaController.getInstance().addLoadingFileObserver(fileName, this);
        if (!FileLoader.getInstance().isLoadingFile(fileName)) {
          buttonState = 2;
          radialProgress.setProgress(0, animated);
          radialProgress.setBackground(getDrawableForCurrentState(), false, animated);
        } else {
          buttonState = 3;
          Float progress = ImageLoader.getInstance().getFileProgress(fileName);
          if (progress != null) {
            radialProgress.setProgress(progress, animated);
          } else {
            radialProgress.setProgress(0, animated);
          }
          radialProgress.setBackground(getDrawableForCurrentState(), true, animated);
        }
      }
    }
    updateProgress();
  }

  @Override
  public void onFailedDownload(String fileName) {
    updateButtonState(true);
  }

  @Override
  public void onSuccessDownload(String fileName) {
    updateButtonState(true);
  }

  @Override
  public void onProgressDownload(String fileName, float progress) {
    radialProgress.setProgress(progress, true);
    if (buttonState != 3) {
      updateButtonState(false);
    }
  }

  @Override
  public void onProgressUpload(String fileName, float progress, boolean isEncrypted) {
    radialProgress.setProgress(progress, true);
  }

  @Override
  public void onSeekBarDrag(float progress) {
    if (currentMessageObject == null) {
      return;
    }
    currentMessageObject.audioProgress = progress;
    MediaController.getInstance().seekToProgress(currentMessageObject, progress);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int width = MeasureSpec.getSize(widthMeasureSpec);
    setMeasuredDimension(width, AndroidUtilities.dp(78) + namesOffset);
  }

  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);

    if (currentMessageObject.isOutOwner()) {
      seekBarX = layoutWidth - backgroundWidth + AndroidUtilities.dp(52);
      buttonX = layoutWidth - backgroundWidth + AndroidUtilities.dp(13);
      timeX = layoutWidth - backgroundWidth + AndroidUtilities.dp(63);
    } else {
      if (isChat && currentMessageObject.messageOwner.from_id > 0) {
        seekBarX = AndroidUtilities.dp(113);
        buttonX = AndroidUtilities.dp(74);
        timeX = AndroidUtilities.dp(124);
      } else {
        seekBarX = AndroidUtilities.dp(61);
        buttonX = AndroidUtilities.dp(22);
        timeX = AndroidUtilities.dp(72);
      }
    }

    seekBar.width = backgroundWidth - AndroidUtilities.dp(67);
    seekBar.height = AndroidUtilities.dp(30);
    seekBarY = AndroidUtilities.dp(26) + namesOffset;
    buttonY = AndroidUtilities.dp(13) + namesOffset;
    radialProgress.setProgressRect(
        buttonX, buttonY, buttonX + AndroidUtilities.dp(40), buttonY + AndroidUtilities.dp(40));

    updateProgress();
  }

  @Override
  public void setMessageObject(MessageObject messageObject) {
    boolean dataChanged = currentMessageObject == messageObject && isUserDataChanged();
    if (currentMessageObject != messageObject || dataChanged) {
      if (AndroidUtilities.isTablet()) {
        backgroundWidth =
            Math.min(
                AndroidUtilities.getMinTabletSide()
                    - AndroidUtilities.dp(
                        isChat && messageObject.messageOwner.from_id > 0 ? 102 : 50),
                AndroidUtilities.dp(300));
      } else {
        backgroundWidth =
            Math.min(
                AndroidUtilities.displaySize.x
                    - AndroidUtilities.dp(
                        isChat && messageObject.messageOwner.from_id > 0 ? 102 : 50),
                AndroidUtilities.dp(300));
      }

      if (messageObject.isOutOwner()) {
        seekBar.type = 0;
        radialProgress.setProgressColor(theme.ChatMusicCell_radialProgress_color);
      } else {
        seekBar.type = 1;
        radialProgress.setProgressColor(theme.ChatMusicCell_radialProgress_color_2);
      }

      int maxWidth = backgroundWidth - AndroidUtilities.dp(86);

      CharSequence stringFinal =
          TextUtils.ellipsize(
              messageObject.getMusicTitle().replace("\n", " "),
              titlePaint,
              maxWidth,
              TextUtils.TruncateAt.END);
      titleLayout =
          new StaticLayout(
              stringFinal, titlePaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
      if (titleLayout.getLineCount() > 0) {
        titleX = (int) Math.ceil(titleLayout.getLineLeft(0));
      }

      stringFinal =
          TextUtils.ellipsize(
              messageObject.getMusicAuthor().replace("\n", " "),
              authorPaint,
              maxWidth,
              TextUtils.TruncateAt.END);
      authorLayout =
          new StaticLayout(
              stringFinal, authorPaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
      if (authorLayout.getLineCount() > 0) {
        authorX = (int) Math.ceil(authorLayout.getLineLeft(0));
      }

      super.setMessageObject(messageObject);
    }
    updateButtonState(dataChanged);
  }

  private Drawable getDrawableForCurrentState() {
    return ResourceLoader.audioStatesDrawable[
        currentMessageObject.isOutOwner() ? buttonState : buttonState + 5][0];
    // buttonPressed ? 1 :
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (currentMessageObject == null) {
      return;
    }

    if (currentMessageObject.isOutOwner()) {
      timePaint.setColor(theme.ChatMusicCell_timePaint_color);
    } else {
      timePaint.setColor(theme.ChatMusicCell_timePaint_color_2);
    }
    radialProgress.draw(canvas);

    canvas.save();
    canvas.translate(timeX + titleX, AndroidUtilities.dp(12) + namesOffset);
    titleLayout.draw(canvas);
    canvas.restore();

    canvas.save();
    if (MediaController.getInstance().isPlayingAudio(currentMessageObject)) {
      canvas.translate(seekBarX, seekBarY);
      seekBar.draw(canvas);
    } else {
      canvas.translate(timeX + authorX, AndroidUtilities.dp(32) + namesOffset);
      authorLayout.draw(canvas);
    }
    canvas.restore();

    canvas.save();
    canvas.translate(timeX, AndroidUtilities.dp(52) + namesOffset);
    timeLayout.draw(canvas);
    canvas.restore();
  }
}
示例#3
0
public class ChatContactCell extends ChatBaseCell {

  private KharTheme theme = ThemeCenter.get().getTheme();

  public interface ChatContactCellDelegate {
    void didClickAddButton(ChatContactCell cell, TLRPC.User user);

    void didClickPhone(ChatContactCell cell);
  }

  private static TextPaint namePaint;
  private static TextPaint phonePaint;
  private static Drawable addContactDrawableIn;
  private static Drawable addContactDrawableOut;

  private ImageReceiver avatarImage;
  private AvatarDrawable avatarDrawable;

  private StaticLayout nameLayout;
  private StaticLayout phoneLayout;

  private TLRPC.User contactUser;
  private TLRPC.FileLocation currentPhoto;

  private boolean avatarPressed = false;
  private boolean buttonPressed = false;
  private boolean drawAddButton = false;
  private int namesWidth = 0;

  private ChatContactCellDelegate contactDelegate = null;

  public ChatContactCell(Context context) {
    super(context);
    if (namePaint == null) {
      namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
      namePaint.setTextSize(AndroidUtilities.dp(15));

      phonePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
      phonePaint.setTextSize(AndroidUtilities.dp(15));
      phonePaint.setColor(theme.ChatContactCell_phonePaint_color);

      addContactDrawableIn =
          getResources().getDrawable(theme.ChatContactCell_addContactDrawableIn_R);
      addContactDrawableOut =
          getResources().getDrawable(theme.ChatContactCell_addContactDrawableOut_R);
    }
    avatarImage = new ImageReceiver(this);
    avatarImage.setRoundRadius(AndroidUtilities.dp(21));
    avatarDrawable = new AvatarDrawable();
  }

  public void setContactDelegate(ChatContactCellDelegate delegate) {
    this.contactDelegate = delegate;
  }

  @Override
  protected boolean isUserDataChanged() {
    if (currentMessageObject == null) {
      return false;
    }

    int uid = currentMessageObject.messageOwner.media.user_id;
    boolean newDrawAdd =
        contactUser != null
            && uid != UserConfig.getClientUserId()
            && ContactsController.getInstance().contactsDict.get(uid) == null;
    if (newDrawAdd != drawAddButton) {
      return true;
    }

    contactUser =
        MessagesController.getInstance().getUser(currentMessageObject.messageOwner.media.user_id);

    TLRPC.FileLocation newPhoto = null;
    if (contactUser != null && contactUser.photo != null) {
      newPhoto = contactUser.photo.photo_small;
    }

    return currentPhoto == null && newPhoto != null
        || currentPhoto != null && newPhoto == null
        || currentPhoto != null
            && newPhoto != null
            && (currentPhoto.local_id != newPhoto.local_id
                || currentPhoto.volume_id != newPhoto.volume_id)
        || super.isUserDataChanged();
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    boolean result = false;
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
      if (x >= avatarImage.getImageX()
          && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(42)
          && y >= avatarImage.getImageY()
          && y <= avatarImage.getImageY() + avatarImage.getImageHeight()) {
        avatarPressed = true;
        result = true;
      } else if (x >= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(52)
          && y >= AndroidUtilities.dp(13) + namesOffset
          && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(92)
          && y <= AndroidUtilities.dp(52) + namesOffset) {
        buttonPressed = true;
        result = true;
      }
      if (result) {
        startCheckLongPress();
      }
    } else {
      if (event.getAction() != MotionEvent.ACTION_MOVE) {
        cancelCheckLongPress();
      }
      if (avatarPressed) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
          avatarPressed = false;
          playSoundEffect(SoundEffectConstants.CLICK);
          if (contactUser != null) {
            if (delegate != null) {
              delegate.didPressedUserAvatar(this, contactUser);
            }
          } else {
            if (contactDelegate != null) {
              contactDelegate.didClickPhone(this);
            }
          }
        } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
          avatarPressed = false;
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
          if (!(x >= avatarImage.getImageX()
              && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(42)
              && y >= avatarImage.getImageY()
              && y <= avatarImage.getImageY() + avatarImage.getImageHeight())) {
            avatarPressed = false;
          }
        }
      } else if (buttonPressed) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
          buttonPressed = false;
          playSoundEffect(SoundEffectConstants.CLICK);
          if (contactUser != null && contactDelegate != null) {
            contactDelegate.didClickAddButton(this, contactUser);
          }
        } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
          buttonPressed = false;
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
          if (!(x >= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(52)
              && y >= AndroidUtilities.dp(13) + namesOffset
              && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(92)
              && y <= AndroidUtilities.dp(52) + namesOffset)) {
            buttonPressed = false;
          }
        }
      }
    }
    if (!result) {
      result = super.onTouchEvent(event);
    }

    return result;
  }

  @Override
  public void setMessageObject(MessageObject messageObject) {
    if (currentMessageObject != messageObject || isUserDataChanged()) {

      int uid = messageObject.messageOwner.media.user_id;
      contactUser = MessagesController.getInstance().getUser(uid);

      drawAddButton =
          contactUser != null
              && uid != UserConfig.getClientUserId()
              && ContactsController.getInstance().contactsDict.get(uid) == null;

      int maxWidth;
      if (AndroidUtilities.isTablet()) {
        maxWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f);
      } else {
        maxWidth =
            (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f);
      }
      maxWidth -= AndroidUtilities.dp(58 + (drawAddButton ? 42 : 0));

      if (contactUser != null) {
        if (contactUser.photo != null) {
          currentPhoto = contactUser.photo.photo_small;
        } else {
          currentPhoto = null;
        }
        avatarDrawable.setInfo(contactUser);
      } else {
        currentPhoto = null;
        avatarDrawable.setInfo(uid, null, null, false);
      }
      avatarImage.setImage(currentPhoto, "50_50", avatarDrawable, null, false);

      String currentNameString =
          ContactsController.formatName(
              messageObject.messageOwner.media.first_name,
              messageObject.messageOwner.media.last_name);
      int nameWidth = Math.min((int) Math.ceil(namePaint.measureText(currentNameString)), maxWidth);

      CharSequence stringFinal =
          TextUtils.ellipsize(
              currentNameString.replace("\n", " "), namePaint, nameWidth, TextUtils.TruncateAt.END);
      nameLayout =
          new StaticLayout(
              stringFinal, namePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
      if (nameLayout.getLineCount() > 0) {
        nameWidth = (int) Math.ceil(nameLayout.getLineWidth(0));
      } else {
        nameWidth = 0;
      }

      String phone = messageObject.messageOwner.media.phone_number;
      if (phone != null && phone.length() != 0) {
        if (!phone.startsWith("+")) {
          phone = "+" + phone;
        }
        phone = PhoneFormat.getInstance().format(phone);
      } else {
        phone = LocaleController.getString("NumberUnknown", R.string.NumberUnknown);
      }
      int phoneWidth = Math.min((int) Math.ceil(phonePaint.measureText(phone)), maxWidth);
      stringFinal =
          TextUtils.ellipsize(
              phone.replace("\n", " "), phonePaint, phoneWidth, TextUtils.TruncateAt.END);
      phoneLayout =
          new StaticLayout(
              stringFinal,
              phonePaint,
              phoneWidth,
              Layout.Alignment.ALIGN_NORMAL,
              1.0f,
              0.0f,
              false);
      if (phoneLayout.getLineCount() > 0) {
        phoneWidth = (int) Math.ceil(phoneLayout.getLineWidth(0));
      } else {
        phoneWidth = 0;
      }

      namesWidth = Math.max(nameWidth, phoneWidth);
      backgroundWidth = AndroidUtilities.dp(77 + (drawAddButton ? 42 : 0)) + namesWidth;

      super.setMessageObject(messageObject);
    }
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(
        MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(71) + namesOffset);
  }

  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);

    if (currentMessageObject == null) {
      return;
    }

    int x;

    if (currentMessageObject.isOutOwner()) {
      x = layoutWidth - backgroundWidth + AndroidUtilities.dp(8);
    } else {
      if (isChat && currentMessageObject.messageOwner.from_id > 0) {
        x = AndroidUtilities.dp(69);
      } else {
        x = AndroidUtilities.dp(16);
      }
    }
    avatarImage.setImageCoords(
        x, AndroidUtilities.dp(9) + namesOffset, AndroidUtilities.dp(42), AndroidUtilities.dp(42));
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (currentMessageObject == null) {
      return;
    }

    avatarImage.draw(canvas);

    if (nameLayout != null) {
      canvas.save();
      canvas.translate(
          avatarImage.getImageX() + avatarImage.getImageWidth() + AndroidUtilities.dp(9),
          AndroidUtilities.dp(10) + namesOffset);
      namePaint.setColor(
          AvatarDrawable.getColorForId(currentMessageObject.messageOwner.media.user_id));
      nameLayout.draw(canvas);
      canvas.restore();
    }
    if (phoneLayout != null) {
      canvas.save();
      canvas.translate(
          avatarImage.getImageX() + avatarImage.getImageWidth() + AndroidUtilities.dp(9),
          AndroidUtilities.dp(31) + namesOffset);
      phoneLayout.draw(canvas);
      canvas.restore();
    }

    if (drawAddButton) {
      Drawable addContactDrawable;
      if (currentMessageObject.isOutOwner()) {
        addContactDrawable = addContactDrawableOut;
      } else {
        addContactDrawable = addContactDrawableIn;
      }
      setDrawableBounds(
          addContactDrawable,
          avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(78),
          AndroidUtilities.dp(13) + namesOffset);
      addContactDrawable.draw(canvas);
    }
  }
}