org.telegram.ui.Components.AudioPlayerAlert.java Source code

Java tutorial

Introduction

Here is the source code for org.telegram.ui.Components.AudioPlayerAlert.java

Source

/*
 * This is the source code of Telegram for Android v. 5.x.x.
 * It is licensed under GNU GPL v. 2 or later.
 * You should have received a copy of the license in this archive (see LICENSE).
 *
 * Copyright Nikolai Kudashov, 2013-2018.
 */

package org.telegram.ui.Components;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Keep;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BuildConfig;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.DownloadController;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLoader;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SendMessagesHelper;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.UserObject;
import org.telegram.messenger.Utilities;
import org.telegram.messenger.audioinfo.AudioInfo;
import org.telegram.messenger.support.widget.LinearLayoutManager;
import org.telegram.messenger.support.widget.RecyclerView;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.ActionBarMenu;
import org.telegram.ui.ActionBar.ActionBarMenuItem;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.AudioPlayerCell;
import org.telegram.ui.Cells.CheckBoxCell;
import org.telegram.ui.ChatActivity;
import org.telegram.ui.DialogsActivity;
import org.telegram.ui.LaunchActivity;

import java.io.File;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

public class AudioPlayerAlert extends BottomSheet
        implements NotificationCenter.NotificationCenterDelegate, DownloadController.FileDownloadProgressListener {

    private ActionBar actionBar;
    private View shadow;
    private View shadow2;
    private ChatAvatarContainer avatarContainer;
    private ActionBarMenuItem searchItem;
    private ActionBarMenuItem menuItem;
    private boolean searchWas;
    private boolean searching;

    private RecyclerListView listView;
    private LinearLayoutManager layoutManager;
    private ListAdapter listAdapter;

    private FrameLayout playerLayout;
    private BackupImageView placeholderImageView;
    private TextView titleTextView;
    private TextView authorTextView;
    private ActionBarMenuItem optionsButton;
    private LineProgressView progressView;
    private SeekBarView seekBarView;
    private SimpleTextView timeTextView;
    private TextView durationTextView;
    private ActionBarMenuItem shuffleButton;
    private ImageView playButton;
    private ImageView repeatButton;
    private View[] buttons = new View[5];
    private Drawable[] playOrderButtons = new Drawable[2];
    private boolean hasOptions = true;

    private boolean scrollToSong = true;

    private boolean isInFullMode;
    private AnimatorSet animatorSet;
    private float fullAnimationProgress;
    private float startTranslation;
    private float endTranslation;
    private float panelStartTranslation;
    private float panelEndTranslation;

    private int searchOpenPosition = -1;
    private int searchOpenOffset;

    private int hasNoCover;
    private Drawable noCoverDrawable;
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    private float thumbMaxScale;
    private int thumbMaxX;
    private int thumbMaxY;

    private ArrayList<MessageObject> playlist;

    private int scrollOffsetY = Integer.MAX_VALUE;
    private int topBeforeSwitch;
    private Drawable shadowDrawable;

    private boolean inFullSize;

    private AnimatorSet actionBarAnimation;

    private int lastTime;
    private int TAG;

    private LaunchActivity parentActivity;

    public AudioPlayerAlert(final Context context) {
        super(context, true);

        MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
        if (messageObject != null) {
            currentAccount = messageObject.currentAccount;
        } else {
            currentAccount = UserConfig.selectedAccount;
        }

        parentActivity = (LaunchActivity) context;
        noCoverDrawable = context.getResources().getDrawable(R.drawable.nocover).mutate();
        noCoverDrawable.setColorFilter(
                new PorterDuffColorFilter(Theme.getColor(Theme.key_player_placeholder), PorterDuff.Mode.MULTIPLY));

        TAG = DownloadController.getInstance(currentAccount).generateObserverTag();
        NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidReset);
        NotificationCenter.getInstance(currentAccount).addObserver(this,
                NotificationCenter.messagePlayingPlayStateChanged);
        NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagePlayingDidStart);
        NotificationCenter.getInstance(currentAccount).addObserver(this,
                NotificationCenter.messagePlayingProgressDidChanged);
        NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.musicDidLoad);

        shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow).mutate();
        shadowDrawable.setColorFilter(
                new PorterDuffColorFilter(Theme.getColor(Theme.key_player_background), PorterDuff.Mode.MULTIPLY));
        paint.setColor(Theme.getColor(Theme.key_player_placeholderBackground));

        containerView = new FrameLayout(context) {

            private boolean ignoreLayout = false;

            @Override
            public boolean onInterceptTouchEvent(MotionEvent ev) {
                if (ev.getAction() == MotionEvent.ACTION_DOWN && scrollOffsetY != 0 && ev.getY() < scrollOffsetY
                        && placeholderImageView.getTranslationX() == 0) {
                    dismiss();
                    return true;
                }
                return super.onInterceptTouchEvent(ev);
            }

            @Override
            public boolean onTouchEvent(MotionEvent e) {
                return !isDismissed() && super.onTouchEvent(e);
            }

            @Override
            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                int height = MeasureSpec.getSize(heightMeasureSpec);
                int contentSize = AndroidUtilities.dp(178) + playlist.size() * AndroidUtilities.dp(56)
                        + backgroundPaddingTop + ActionBar.getCurrentActionBarHeight()
                        + AndroidUtilities.statusBarHeight;
                int padding;
                heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
                if (searching) {
                    padding = AndroidUtilities.dp(178) + ActionBar.getCurrentActionBarHeight()
                            + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0);
                } else {
                    if (contentSize < height) {
                        padding = height - contentSize;
                    } else {
                        padding = (contentSize < height ? 0 : height - (height / 5 * 3));
                    }
                    padding += ActionBar.getCurrentActionBarHeight()
                            + (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0);
                }
                if (listView.getPaddingTop() != padding) {
                    ignoreLayout = true;
                    listView.setPadding(0, padding, 0, AndroidUtilities.dp(8));
                    ignoreLayout = false;
                }
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                inFullSize = getMeasuredHeight() >= height;
                int availableHeight = height - ActionBar.getCurrentActionBarHeight()
                        - (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0)
                        - AndroidUtilities.dp(120);
                int maxSize = Math.max(availableHeight, getMeasuredWidth());
                thumbMaxX = (getMeasuredWidth() - maxSize) / 2 - AndroidUtilities.dp(17);
                thumbMaxY = AndroidUtilities.dp(19);
                panelEndTranslation = getMeasuredHeight() - playerLayout.getMeasuredHeight();
                thumbMaxScale = maxSize / (float) placeholderImageView.getMeasuredWidth() - 1.0f;

                endTranslation = ActionBar.getCurrentActionBarHeight() + AndroidUtilities.dp(5);
                int scaledHeight = (int) Math
                        .ceil(placeholderImageView.getMeasuredHeight() * (1.0f + thumbMaxScale));
                if (scaledHeight > availableHeight) {
                    endTranslation -= (scaledHeight - availableHeight);
                }
            }

            @Override
            protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
                super.onLayout(changed, left, top, right, bottom);
                int y = actionBar.getMeasuredHeight();
                shadow.layout(shadow.getLeft(), y, shadow.getRight(), y + shadow.getMeasuredHeight());
                updateLayout();

                setFullAnimationProgress(fullAnimationProgress);
            }

            @Override
            public void requestLayout() {
                if (ignoreLayout) {
                    return;
                }
                super.requestLayout();
            }

            @Override
            protected void onDraw(Canvas canvas) {
                shadowDrawable.setBounds(0,
                        Math.max(actionBar.getMeasuredHeight(), scrollOffsetY) - backgroundPaddingTop,
                        getMeasuredWidth(), getMeasuredHeight());
                shadowDrawable.draw(canvas);
            }
        };
        containerView.setWillNotDraw(false);
        containerView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0);

        actionBar = new ActionBar(context);
        actionBar.setBackgroundColor(Theme.getColor(Theme.key_player_actionBar));
        actionBar.setBackButtonImage(R.drawable.ic_ab_back);
        actionBar.setItemsColor(Theme.getColor(Theme.key_player_actionBarItems), false);
        actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_player_actionBarSelector), false);
        actionBar.setTitleColor(Theme.getColor(Theme.key_player_actionBarTitle));
        actionBar.setSubtitleColor(Theme.getColor(Theme.key_player_actionBarSubtitle));
        actionBar.setAlpha(0.0f);
        actionBar.setTitle("1");
        actionBar.setSubtitle("1");
        actionBar.getTitleTextView().setAlpha(0.0f);
        actionBar.getSubtitleTextView().setAlpha(0.0f);
        avatarContainer = new ChatAvatarContainer(context, null, false);
        avatarContainer.setEnabled(false);
        avatarContainer.setTitleColors(Theme.getColor(Theme.key_player_actionBarTitle),
                Theme.getColor(Theme.key_player_actionBarSubtitle));
        if (messageObject != null) {
            long did = messageObject.getDialogId();
            int lower_id = (int) did;
            int high_id = (int) (did >> 32);
            if (lower_id != 0) {
                if (lower_id > 0) {
                    TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(lower_id);
                    if (user != null) {
                        avatarContainer.setTitle(ContactsController.formatName(user.first_name, user.last_name));
                        avatarContainer.setUserAvatar(user);
                    }
                } else {
                    TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_id);
                    if (chat != null) {
                        avatarContainer.setTitle(chat.title);
                        avatarContainer.setChatAvatar(chat);
                    }
                }
            } else {
                TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance(currentAccount)
                        .getEncryptedChat(high_id);
                if (encryptedChat != null) {
                    TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(encryptedChat.user_id);
                    if (user != null) {
                        avatarContainer.setTitle(ContactsController.formatName(user.first_name, user.last_name));
                        avatarContainer.setUserAvatar(user);
                    }
                }
            }
        }
        avatarContainer.setSubtitle(LocaleController.getString("AudioTitle", R.string.AudioTitle));
        actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT,
                LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 56, 0, 40, 0));

        ActionBarMenu menu = actionBar.createMenu();
        menuItem = menu.addItem(0, R.drawable.ic_ab_other);
        menuItem.addSubItem(1, LocaleController.getString("Forward", R.string.Forward));
        menuItem.addSubItem(2, LocaleController.getString("ShareFile", R.string.ShareFile));
        //menuItem.addSubItem(3, LocaleController.getString("Delete", R.string.Delete));
        menuItem.addSubItem(4, LocaleController.getString("ShowInChat", R.string.ShowInChat));
        menuItem.setTranslationX(AndroidUtilities.dp(48));
        menuItem.setAlpha(0.0f);

        searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true)
                .setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() {
                    @Override
                    public void onSearchCollapse() {
                        avatarContainer.setVisibility(View.VISIBLE);
                        if (hasOptions) {
                            menuItem.setVisibility(View.INVISIBLE);
                        }
                        if (searching) {
                            searchWas = false;
                            searching = false;
                            setAllowNestedScroll(true);
                            listAdapter.search(null);
                        }
                    }

                    @Override
                    public void onSearchExpand() {
                        searchOpenPosition = layoutManager.findLastVisibleItemPosition();
                        View firstVisView = layoutManager.findViewByPosition(searchOpenPosition);
                        searchOpenOffset = ((firstVisView == null) ? 0 : firstVisView.getTop())
                                - listView.getPaddingTop();

                        avatarContainer.setVisibility(View.GONE);
                        if (hasOptions) {
                            menuItem.setVisibility(View.GONE);
                        }
                        searching = true;
                        setAllowNestedScroll(false);
                        listAdapter.notifyDataSetChanged();
                    }

                    @Override
                    public void onTextChanged(EditText editText) {
                        if (editText.length() > 0) {
                            listAdapter.search(editText.getText().toString());
                        } else {
                            searchWas = false;
                            listAdapter.search(null);
                        }
                    }
                });
        EditTextBoldCursor editText = searchItem.getSearchField();
        editText.setHint(LocaleController.getString("Search", R.string.Search));
        editText.setTextColor(Theme.getColor(Theme.key_player_actionBarTitle));
        editText.setHintTextColor(Theme.getColor(Theme.key_player_time));
        editText.setCursorColor(Theme.getColor(Theme.key_player_actionBarTitle));

        if (!AndroidUtilities.isTablet()) {
            actionBar.showActionModeTop();
            actionBar.setActionModeTopColor(Theme.getColor(Theme.key_player_actionBarTop));
        }
        actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
            @Override
            public void onItemClick(int id) {
                if (id == -1) {
                    dismiss();
                } else {
                    onSubItemClick(id);
                }
            }
        });

        shadow = new View(context);
        shadow.setAlpha(0.0f);
        shadow.setBackgroundResource(R.drawable.header_shadow);

        shadow2 = new View(context);
        shadow2.setAlpha(0.0f);
        shadow2.setBackgroundResource(R.drawable.header_shadow);

        playerLayout = new FrameLayout(context);
        playerLayout.setBackgroundColor(Theme.getColor(Theme.key_player_background));

        placeholderImageView = new BackupImageView(context) {

            private RectF rect = new RectF();

            @Override
            protected void onDraw(Canvas canvas) {
                if (hasNoCover == 1 || hasNoCover == 2
                        && (!getImageReceiver().hasBitmapImage() || getImageReceiver().getCurrentAlpha() != 1.0f)) {
                    rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
                    canvas.drawRoundRect(rect, getRoundRadius(), getRoundRadius(), paint);
                    float plusScale = thumbMaxScale / getScaleX() / 3;
                    int s = (int) (AndroidUtilities.dp(63)
                            * Math.max(plusScale / thumbMaxScale, 1.0f / thumbMaxScale));
                    int x = (int) (rect.centerX() - s / 2);
                    int y = (int) (rect.centerY() - s / 2);
                    noCoverDrawable.setBounds(x, y, x + s, y + s);
                    noCoverDrawable.draw(canvas);
                }
                if (hasNoCover != 1) {
                    super.onDraw(canvas);
                }
            }
        };
        placeholderImageView.setRoundRadius(AndroidUtilities.dp(20));
        placeholderImageView.setPivotX(0);
        placeholderImageView.setPivotY(0);
        placeholderImageView.setOnClickListener(view -> {
            if (animatorSet != null) {
                animatorSet.cancel();
                animatorSet = null;
            }
            animatorSet = new AnimatorSet();
            if (scrollOffsetY <= actionBar.getMeasuredHeight()) {
                animatorSet.playTogether(ObjectAnimator.ofFloat(AudioPlayerAlert.this, "fullAnimationProgress",
                        isInFullMode ? 0.0f : 1.0f));
            } else {
                animatorSet.playTogether(
                        ObjectAnimator.ofFloat(AudioPlayerAlert.this, "fullAnimationProgress",
                                isInFullMode ? 0.0f : 1.0f),
                        ObjectAnimator.ofFloat(actionBar, "alpha", isInFullMode ? 0.0f : 1.0f),
                        ObjectAnimator.ofFloat(shadow, "alpha", isInFullMode ? 0.0f : 1.0f),
                        ObjectAnimator.ofFloat(shadow2, "alpha", isInFullMode ? 0.0f : 1.0f));
            }

            animatorSet.setInterpolator(new DecelerateInterpolator());
            animatorSet.setDuration(250);
            animatorSet.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    if (animation.equals(animatorSet)) {
                        if (!isInFullMode) {
                            listView.setScrollEnabled(true);
                            if (hasOptions) {
                                menuItem.setVisibility(View.INVISIBLE);
                            }
                            searchItem.setVisibility(View.VISIBLE);
                        } else {
                            if (hasOptions) {
                                menuItem.setVisibility(View.VISIBLE);
                            }
                            searchItem.setVisibility(View.INVISIBLE);
                        }
                        animatorSet = null;
                    }
                }
            });
            animatorSet.start();
            if (hasOptions) {
                menuItem.setVisibility(View.VISIBLE);
            }
            searchItem.setVisibility(View.VISIBLE);
            isInFullMode = !isInFullMode;
            listView.setScrollEnabled(false);
            if (isInFullMode) {
                shuffleButton.setAdditionalOffset(-AndroidUtilities.dp(20 + 48));
            } else {
                shuffleButton.setAdditionalOffset(-AndroidUtilities.dp(10));
            }
        });

        titleTextView = new TextView(context);
        titleTextView.setTextColor(Theme.getColor(Theme.key_player_actionBarTitle));
        titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
        titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
        titleTextView.setEllipsize(TextUtils.TruncateAt.END);
        titleTextView.setSingleLine(true);
        playerLayout.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT,
                LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 72, 18, 60, 0));

        authorTextView = new TextView(context);
        authorTextView.setTextColor(Theme.getColor(Theme.key_player_time));
        authorTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
        authorTextView.setEllipsize(TextUtils.TruncateAt.END);
        authorTextView.setSingleLine(true);
        playerLayout.addView(authorTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT,
                LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 72, 40, 60, 0));

        optionsButton = new ActionBarMenuItem(context, null, 0, Theme.getColor(Theme.key_player_actionBarItems));
        optionsButton.setLongClickEnabled(false);
        optionsButton.setIcon(R.drawable.ic_ab_other);
        optionsButton.setAdditionalOffset(-AndroidUtilities.dp(120));
        playerLayout.addView(optionsButton,
                LayoutHelper.createFrame(40, 40, Gravity.TOP | Gravity.RIGHT, 0, 19, 10, 0));
        optionsButton.addSubItem(1, LocaleController.getString("Forward", R.string.Forward));
        optionsButton.addSubItem(2, LocaleController.getString("ShareFile", R.string.ShareFile));
        //optionsButton.addSubItem(3, LocaleController.getString("Delete", R.string.Delete));
        optionsButton.addSubItem(4, LocaleController.getString("ShowInChat", R.string.ShowInChat));
        optionsButton.setOnClickListener(v -> optionsButton.toggleSubMenu());
        optionsButton.setDelegate(this::onSubItemClick);

        seekBarView = new SeekBarView(context);
        seekBarView.setDelegate(progress -> MediaController.getInstance()
                .seekToProgress(MediaController.getInstance().getPlayingMessageObject(), progress));
        playerLayout.addView(seekBarView,
                LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 30, Gravity.TOP | Gravity.LEFT, 8, 62, 8, 0));

        progressView = new LineProgressView(context);
        progressView.setVisibility(View.INVISIBLE);
        progressView.setBackgroundColor(Theme.getColor(Theme.key_player_progressBackground));
        progressView.setProgressColor(Theme.getColor(Theme.key_player_progress));
        playerLayout.addView(progressView,
                LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, Gravity.TOP | Gravity.LEFT, 20, 78, 20, 0));

        timeTextView = new SimpleTextView(context);
        timeTextView.setTextSize(12);
        timeTextView.setText("0:00");
        timeTextView.setTextColor(Theme.getColor(Theme.key_player_time));
        playerLayout.addView(timeTextView,
                LayoutHelper.createFrame(100, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 20, 92, 0, 0));

        durationTextView = new TextView(context);
        durationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
        durationTextView.setTextColor(Theme.getColor(Theme.key_player_time));
        durationTextView.setGravity(Gravity.CENTER);
        playerLayout.addView(durationTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT,
                LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.RIGHT, 0, 90, 20, 0));

        FrameLayout bottomView = new FrameLayout(context) {
            @Override
            protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
                int dist = ((right - left) - AndroidUtilities.dp(8 + 48 * 5)) / 4;
                for (int a = 0; a < 5; a++) {
                    int l = AndroidUtilities.dp(4 + 48 * a) + dist * a;
                    int t = AndroidUtilities.dp(9);
                    buttons[a].layout(l, t, l + buttons[a].getMeasuredWidth(), t + buttons[a].getMeasuredHeight());
                }
            }
        };
        playerLayout.addView(bottomView,
                LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 66, Gravity.TOP | Gravity.LEFT, 0, 106, 0, 0));

        buttons[0] = shuffleButton = new ActionBarMenuItem(context, null, 0, 0);
        shuffleButton.setLongClickEnabled(false);
        shuffleButton.setAdditionalOffset(-AndroidUtilities.dp(10));
        bottomView.addView(shuffleButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
        shuffleButton.setOnClickListener(v -> shuffleButton.toggleSubMenu());

        TextView textView = shuffleButton.addSubItem(1,
                LocaleController.getString("ReverseOrder", R.string.ReverseOrder));
        textView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(16), 0);
        playOrderButtons[0] = context.getResources().getDrawable(R.drawable.music_reverse).mutate();
        textView.setCompoundDrawablePadding(AndroidUtilities.dp(8));
        textView.setCompoundDrawablesWithIntrinsicBounds(playOrderButtons[0], null, null, null);

        textView = shuffleButton.addSubItem(2, LocaleController.getString("Shuffle", R.string.Shuffle));
        textView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(16), 0);
        playOrderButtons[1] = context.getResources().getDrawable(R.drawable.pl_shuffle).mutate();
        textView.setCompoundDrawablePadding(AndroidUtilities.dp(8));
        textView.setCompoundDrawablesWithIntrinsicBounds(playOrderButtons[1], null, null, null);

        shuffleButton.setDelegate(id -> {
            MediaController.getInstance().toggleShuffleMusic(id);
            updateShuffleButton();
            listAdapter.notifyDataSetChanged();
        });

        ImageView prevButton;
        buttons[1] = prevButton = new ImageView(context);
        prevButton.setScaleType(ImageView.ScaleType.CENTER);
        prevButton.setImageDrawable(Theme.createSimpleSelectorDrawable(context, R.drawable.pl_previous,
                Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive)));
        bottomView.addView(prevButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
        prevButton.setOnClickListener(v -> MediaController.getInstance().playPreviousMessage());

        buttons[2] = playButton = new ImageView(context);
        playButton.setScaleType(ImageView.ScaleType.CENTER);
        playButton.setImageDrawable(Theme.createSimpleSelectorDrawable(context, R.drawable.pl_play,
                Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive)));
        bottomView.addView(playButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
        playButton.setOnClickListener(v -> {
            if (MediaController.getInstance().isDownloadingCurrentMessage()) {
                return;
            }
            if (MediaController.getInstance().isMessagePaused()) {
                MediaController.getInstance().playMessage(MediaController.getInstance().getPlayingMessageObject());
            } else {
                MediaController.getInstance().pauseMessage(MediaController.getInstance().getPlayingMessageObject());
            }
        });

        ImageView nextButton;
        buttons[3] = nextButton = new ImageView(context);
        nextButton.setScaleType(ImageView.ScaleType.CENTER);
        nextButton.setImageDrawable(Theme.createSimpleSelectorDrawable(context, R.drawable.pl_next,
                Theme.getColor(Theme.key_player_button), Theme.getColor(Theme.key_player_buttonActive)));
        bottomView.addView(nextButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
        nextButton.setOnClickListener(v -> MediaController.getInstance().playNextMessage());

        buttons[4] = repeatButton = new ImageView(context);
        repeatButton.setScaleType(ImageView.ScaleType.CENTER);
        repeatButton.setPadding(0, 0, AndroidUtilities.dp(8), 0);
        bottomView.addView(repeatButton, LayoutHelper.createFrame(50, 48, Gravity.LEFT | Gravity.TOP));
        repeatButton.setOnClickListener(v -> {
            SharedConfig.toggleRepeatMode();
            updateRepeatButton();
        });

        listView = new RecyclerListView(context) {

            boolean ignoreLayout;

            @Override
            protected void onLayout(boolean changed, int l, int t, int r, int b) {
                super.onLayout(changed, l, t, r, b);

                if (searchOpenPosition != -1 && !actionBar.isSearchFieldVisible()) {
                    ignoreLayout = true;
                    layoutManager.scrollToPositionWithOffset(searchOpenPosition, searchOpenOffset);
                    super.onLayout(false, l, t, r, b);
                    ignoreLayout = false;
                    searchOpenPosition = -1;
                } else if (scrollToSong) {
                    scrollToSong = false;
                    boolean found = false;
                    MessageObject playingMessageObject = MediaController.getInstance().getPlayingMessageObject();
                    if (playingMessageObject != null) {
                        int count = listView.getChildCount();
                        for (int a = 0; a < count; a++) {
                            View child = listView.getChildAt(a);
                            if (child instanceof AudioPlayerCell) {
                                if (((AudioPlayerCell) child).getMessageObject() == playingMessageObject) {
                                    if (child.getBottom() <= getMeasuredHeight()) {
                                        found = true;
                                    }
                                    break;
                                }
                            }
                        }
                        if (!found) {
                            int idx = playlist.indexOf(playingMessageObject);
                            if (idx >= 0) {
                                ignoreLayout = true;
                                if (SharedConfig.playOrderReversed) {
                                    layoutManager.scrollToPosition(idx);
                                } else {
                                    layoutManager.scrollToPosition(playlist.size() - idx);
                                }
                                super.onLayout(false, l, t, r, b);
                                ignoreLayout = false;
                            }
                        }
                    }
                }
            }

            @Override
            public void requestLayout() {
                if (ignoreLayout) {
                    return;
                }
                super.requestLayout();
            }

            @Override
            protected boolean allowSelectChildAtPosition(float x, float y) {
                float p = playerLayout.getY() + playerLayout.getMeasuredHeight();
                return playerLayout == null || y > playerLayout.getY() + playerLayout.getMeasuredHeight();
            }

            @Override
            public boolean drawChild(Canvas canvas, View child, long drawingTime) {
                canvas.save();
                canvas.clipRect(0,
                        (actionBar != null ? actionBar.getMeasuredHeight() : 0) + AndroidUtilities.dp(50),
                        getMeasuredWidth(), getMeasuredHeight());
                boolean result = super.drawChild(canvas, child, drawingTime);
                canvas.restore();
                return result;
            }
        };
        listView.setPadding(0, 0, 0, AndroidUtilities.dp(8));
        listView.setClipToPadding(false);
        listView.setLayoutManager(
                layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
        listView.setHorizontalScrollBarEnabled(false);
        listView.setVerticalScrollBarEnabled(false);
        containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT,
                LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT));
        listView.setAdapter(listAdapter = new ListAdapter(context));
        listView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow));
        listView.setOnItemClickListener((view, position) -> {
            if (view instanceof AudioPlayerCell) {
                ((AudioPlayerCell) view).didPressedButton();
            }
        });
        listView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                if (newState == RecyclerView.SCROLL_STATE_DRAGGING && searching && searchWas) {
                    AndroidUtilities.hideKeyboard(getCurrentFocus());
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                updateLayout();
            }
        });

        playlist = MediaController.getInstance().getPlaylist();
        listAdapter.notifyDataSetChanged();

        containerView.addView(playerLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 178));
        containerView.addView(shadow2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3));
        containerView.addView(placeholderImageView,
                LayoutHelper.createFrame(40, 40, Gravity.TOP | Gravity.LEFT, 17, 19, 0, 0));
        containerView.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3));
        containerView.addView(actionBar);

        updateTitle(false);
        updateRepeatButton();
        updateShuffleButton();
    }

    @Keep
    public void setFullAnimationProgress(float value) {
        fullAnimationProgress = value;
        placeholderImageView.setRoundRadius(AndroidUtilities.dp(20 * (1.0f - fullAnimationProgress)));
        float scale = 1.0f + thumbMaxScale * fullAnimationProgress;
        placeholderImageView.setScaleX(scale);
        placeholderImageView.setScaleY(scale);
        float translationY = placeholderImageView.getTranslationY();
        placeholderImageView.setTranslationX(thumbMaxX * fullAnimationProgress);
        placeholderImageView
                .setTranslationY(startTranslation + (endTranslation - startTranslation) * fullAnimationProgress);
        playerLayout.setTranslationY(
                panelStartTranslation + (panelEndTranslation - panelStartTranslation) * fullAnimationProgress);
        shadow2.setTranslationY(
                panelStartTranslation + (panelEndTranslation - panelStartTranslation) * fullAnimationProgress
                        + playerLayout.getMeasuredHeight());
        menuItem.setAlpha(fullAnimationProgress);
        searchItem.setAlpha(1.0f - fullAnimationProgress);
        avatarContainer.setAlpha(1.0f - fullAnimationProgress);
        actionBar.getTitleTextView().setAlpha(fullAnimationProgress);
        actionBar.getSubtitleTextView().setAlpha(fullAnimationProgress);
    }

    @Keep
    public float getFullAnimationProgress() {
        return fullAnimationProgress;
    }

    private void onSubItemClick(int id) {
        final MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
        if (messageObject == null || parentActivity == null) {
            return;
        }
        if (id == 1) {
            if (UserConfig.selectedAccount != currentAccount) {
                parentActivity.switchToAccount(currentAccount, true);
            }
            Bundle args = new Bundle();
            args.putBoolean("onlySelect", true);
            args.putInt("dialogsType", 3);
            DialogsActivity fragment = new DialogsActivity(args);
            final ArrayList<MessageObject> fmessages = new ArrayList<>();
            fmessages.add(messageObject);
            fragment.setDelegate((fragment1, dids, message, param) -> {
                if (dids.size() > 1 || dids.get(0) == UserConfig.getInstance(currentAccount).getClientUserId()
                        || message != null) {
                    for (int a = 0; a < dids.size(); a++) {
                        long did = dids.get(a);
                        if (message != null) {
                            SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did,
                                    null, null, true, null, null, null);
                        }
                        SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessages, did);
                    }
                    fragment1.finishFragment();
                } else {
                    long did = dids.get(0);
                    int lower_part = (int) did;
                    int high_part = (int) (did >> 32);
                    Bundle args1 = new Bundle();
                    args1.putBoolean("scrollToTopOnResume", true);
                    if (lower_part != 0) {
                        if (lower_part > 0) {
                            args1.putInt("user_id", lower_part);
                        } else if (lower_part < 0) {
                            args1.putInt("chat_id", -lower_part);
                        }
                    } else {
                        args1.putInt("enc_id", high_part);
                    }
                    NotificationCenter.getInstance(currentAccount)
                            .postNotificationName(NotificationCenter.closeChats);
                    ChatActivity chatActivity = new ChatActivity(args1);
                    if (parentActivity.presentFragment(chatActivity, true, false)) {
                        chatActivity.showFieldPanelForForward(true, fmessages);
                    } else {
                        fragment1.finishFragment();
                    }
                }
            });
            parentActivity.presentFragment(fragment);
            dismiss();
        } else if (id == 2) {
            try {
                File f = null;
                boolean isVideo = false;

                if (!TextUtils.isEmpty(messageObject.messageOwner.attachPath)) {
                    f = new File(messageObject.messageOwner.attachPath);
                    if (!f.exists()) {
                        f = null;
                    }
                }
                if (f == null) {
                    f = FileLoader.getPathToMessage(messageObject.messageOwner);
                }

                if (f.exists()) {
                    Intent intent = new Intent(Intent.ACTION_SEND);
                    if (messageObject != null) {
                        intent.setType(messageObject.getMimeType());
                    } else {
                        intent.setType("audio/mp3");
                    }
                    if (Build.VERSION.SDK_INT >= 24) {
                        try {
                            intent.putExtra(Intent.EXTRA_STREAM,
                                    FileProvider.getUriForFile(ApplicationLoader.applicationContext,
                                            BuildConfig.APPLICATION_ID + ".provider", f));
                            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        } catch (Exception ignore) {
                            intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
                        }
                    } else {
                        intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(f));
                    }

                    parentActivity.startActivityForResult(Intent.createChooser(intent,
                            LocaleController.getString("ShareFile", R.string.ShareFile)), 500);
                } else {
                    AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity);
                    builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
                    builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
                    builder.setMessage(LocaleController.getString("PleaseDownload", R.string.PleaseDownload));
                    builder.show();
                }
            } catch (Exception e) {
                FileLog.e(e);
            }
        } else if (id == 3) {
            AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity);
            //builder.setMessage(LocaleController.formatString("AreYouSureDeleteAudio", R.string.AreYouSureDeleteAudio));
            builder.setTitle(LocaleController.getString("AppName", R.string.AppName));

            final boolean deleteForAll[] = new boolean[1];
            int lower_id = (int) messageObject.getDialogId();
            if (lower_id != 0) {
                TLRPC.Chat currentChat;
                TLRPC.User currentUser;
                if (lower_id > 0) {
                    currentUser = MessagesController.getInstance(currentAccount).getUser(lower_id);
                    currentChat = null;
                } else {
                    currentUser = null;
                    currentChat = MessagesController.getInstance(currentAccount).getChat(-lower_id);
                }
                if (currentUser != null || !ChatObject.isChannel(currentChat)) {
                    boolean hasOutgoing = false;
                    int currentDate = ConnectionsManager.getInstance(currentAccount).getCurrentTime();
                    if (currentUser != null
                            && currentUser.id != UserConfig.getInstance(currentAccount).getClientUserId()
                            || currentChat != null) {
                        if ((messageObject.messageOwner.action == null
                                || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty)
                                && messageObject.isOut()
                                && (currentDate - messageObject.messageOwner.date) <= 2 * 24 * 60 * 60) {
                            FrameLayout frameLayout = new FrameLayout(parentActivity);
                            CheckBoxCell cell = new CheckBoxCell(parentActivity, 1);
                            cell.setBackgroundDrawable(Theme.getSelectorDrawable(false));
                            if (currentChat != null) {
                                cell.setText(LocaleController.getString("DeleteForAll", R.string.DeleteForAll), "",
                                        false, false);
                            } else {
                                cell.setText(LocaleController.formatString("DeleteForUser", R.string.DeleteForUser,
                                        UserObject.getFirstName(currentUser)), "", false, false);
                            }
                            cell.setPadding(
                                    LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0,
                                    LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0);
                            frameLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48,
                                    Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0));
                            cell.setOnClickListener(v -> {
                                CheckBoxCell cell1 = (CheckBoxCell) v;
                                deleteForAll[0] = !deleteForAll[0];
                                cell1.setChecked(deleteForAll[0], true);
                            });
                            builder.setView(frameLayout);
                        }
                    }
                }
            }
            builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> {
                dismiss();
                ArrayList<Integer> arr = new ArrayList<>();
                arr.add(messageObject.getId());
                ArrayList<Long> random_ids = null;
                TLRPC.EncryptedChat encryptedChat = null;
                if ((int) messageObject.getDialogId() == 0 && messageObject.messageOwner.random_id != 0) {
                    random_ids = new ArrayList<>();
                    random_ids.add(messageObject.messageOwner.random_id);
                    encryptedChat = MessagesController.getInstance(currentAccount)
                            .getEncryptedChat((int) (messageObject.getDialogId() >> 32));
                }
                MessagesController.getInstance(currentAccount).deleteMessages(arr, random_ids, encryptedChat,
                        messageObject.messageOwner.to_id.channel_id, deleteForAll[0]);
            });
            builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
            builder.show();
        } else if (id == 4) {
            if (UserConfig.selectedAccount != currentAccount) {
                parentActivity.switchToAccount(currentAccount, true);
            }

            Bundle args = new Bundle();
            long did = messageObject.getDialogId();
            int lower_part = (int) did;
            int high_id = (int) (did >> 32);
            if (lower_part != 0) {
                if (high_id == 1) {
                    args.putInt("chat_id", lower_part);
                } else {
                    if (lower_part > 0) {
                        args.putInt("user_id", lower_part);
                    } else if (lower_part < 0) {
                        TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-lower_part);
                        if (chat != null && chat.migrated_to != null) {
                            args.putInt("migrated_to", lower_part);
                            lower_part = -chat.migrated_to.channel_id;
                        }
                        args.putInt("chat_id", -lower_part);
                    }
                }
            } else {
                args.putInt("enc_id", high_id);
            }
            args.putInt("message_id", messageObject.getId());
            NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats);
            parentActivity.presentFragment(new ChatActivity(args), false, false);
            dismiss();
        }
    }

    private int getCurrentTop() {
        if (listView.getChildCount() != 0) {
            View child = listView.getChildAt(0);
            RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findContainingViewHolder(child);
            if (holder != null) {
                return listView.getPaddingTop()
                        - (holder.getAdapterPosition() == 0 && child.getTop() >= 0 ? child.getTop() : 0);
            }
        }
        return -1000;
    }

    @Override
    public void didReceivedNotification(int id, int account, Object... args) {
        if (id == NotificationCenter.messagePlayingDidStart
                || id == NotificationCenter.messagePlayingPlayStateChanged
                || id == NotificationCenter.messagePlayingDidReset) {
            updateTitle(id == NotificationCenter.messagePlayingDidReset && (Boolean) args[1]);
            if (id == NotificationCenter.messagePlayingDidReset
                    || id == NotificationCenter.messagePlayingPlayStateChanged) {
                int count = listView.getChildCount();
                for (int a = 0; a < count; a++) {
                    View view = listView.getChildAt(a);
                    if (view instanceof AudioPlayerCell) {
                        AudioPlayerCell cell = (AudioPlayerCell) view;
                        MessageObject messageObject = cell.getMessageObject();
                        if (messageObject != null && (messageObject.isVoice() || messageObject.isMusic())) {
                            cell.updateButtonState(false, true);
                        }
                    }
                }
            } else if (id == NotificationCenter.messagePlayingDidStart) {
                MessageObject messageObject = (MessageObject) args[0];
                if (messageObject.eventId != 0) {
                    return;
                }
                int count = listView.getChildCount();
                for (int a = 0; a < count; a++) {
                    View view = listView.getChildAt(a);
                    if (view instanceof AudioPlayerCell) {
                        AudioPlayerCell cell = (AudioPlayerCell) view;
                        MessageObject messageObject1 = cell.getMessageObject();
                        if (messageObject1 != null && (messageObject1.isVoice() || messageObject1.isMusic())) {
                            cell.updateButtonState(false, true);
                        }
                    }
                }
            }
        } else if (id == NotificationCenter.messagePlayingProgressDidChanged) {
            MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
            if (messageObject != null && messageObject.isMusic()) {
                updateProgress(messageObject);
            }
        } else if (id == NotificationCenter.musicDidLoad) {
            playlist = MediaController.getInstance().getPlaylist();
            listAdapter.notifyDataSetChanged();
        }
    }

    @Override
    protected boolean canDismissWithSwipe() {
        return false;
    }

    private void updateLayout() {
        if (listView.getChildCount() <= 0) {
            return;
        }
        View child = listView.getChildAt(0);
        RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findContainingViewHolder(child);
        int top = child.getTop();
        int newOffset = top > 0 && holder != null && holder.getAdapterPosition() == 0 ? top : 0;
        if (searchWas || searching) {
            newOffset = 0;
        }
        if (scrollOffsetY != newOffset) {
            listView.setTopGlowOffset(scrollOffsetY = newOffset);
            playerLayout.setTranslationY(Math.max(actionBar.getMeasuredHeight(), scrollOffsetY));
            placeholderImageView.setTranslationY(Math.max(actionBar.getMeasuredHeight(), scrollOffsetY));
            shadow2.setTranslationY(
                    Math.max(actionBar.getMeasuredHeight(), scrollOffsetY) + playerLayout.getMeasuredHeight());
            containerView.invalidate();

            if (inFullSize && scrollOffsetY <= actionBar.getMeasuredHeight() || searchWas) {
                if (actionBar.getTag() == null) {
                    if (actionBarAnimation != null) {
                        actionBarAnimation.cancel();
                    }
                    actionBar.setTag(1);
                    actionBarAnimation = new AnimatorSet();
                    actionBarAnimation.playTogether(ObjectAnimator.ofFloat(actionBar, "alpha", 1.0f),
                            ObjectAnimator.ofFloat(shadow, "alpha", 1.0f),
                            ObjectAnimator.ofFloat(shadow2, "alpha", 1.0f));
                    actionBarAnimation.setDuration(180);
                    actionBarAnimation.start();
                }
            } else {
                if (actionBar.getTag() != null) {
                    if (actionBarAnimation != null) {
                        actionBarAnimation.cancel();
                    }
                    actionBar.setTag(null);
                    actionBarAnimation = new AnimatorSet();
                    actionBarAnimation.playTogether(ObjectAnimator.ofFloat(actionBar, "alpha", 0.0f),
                            ObjectAnimator.ofFloat(shadow, "alpha", 0.0f),
                            ObjectAnimator.ofFloat(shadow2, "alpha", 0.0f));
                    actionBarAnimation.setDuration(180);
                    actionBarAnimation.start();
                }
            }
        }

        startTranslation = Math.max(actionBar.getMeasuredHeight(), scrollOffsetY);
        panelStartTranslation = Math.max(actionBar.getMeasuredHeight(), scrollOffsetY);
    }

    @Override
    public void dismiss() {
        super.dismiss();
        NotificationCenter.getInstance(currentAccount).removeObserver(this,
                NotificationCenter.messagePlayingDidReset);
        NotificationCenter.getInstance(currentAccount).removeObserver(this,
                NotificationCenter.messagePlayingPlayStateChanged);
        NotificationCenter.getInstance(currentAccount).removeObserver(this,
                NotificationCenter.messagePlayingDidStart);
        NotificationCenter.getInstance(currentAccount).removeObserver(this,
                NotificationCenter.messagePlayingProgressDidChanged);
        NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.musicDidLoad);
        DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this);
    }

    @Override
    public void onBackPressed() {
        if (actionBar != null && actionBar.isSearchFieldVisible()) {
            actionBar.closeSearchField();
            return;
        }
        super.onBackPressed();
    }

    @Override
    public void onFailedDownload(String fileName, boolean canceled) {

    }

    @Override
    public void onSuccessDownload(String fileName) {

    }

    @Override
    public void onProgressDownload(String fileName, float progress) {
        progressView.setProgress(progress, true);
    }

    @Override
    public void onProgressUpload(String fileName, float progress, boolean isEncrypted) {

    }

    @Override
    public int getObserverTag() {
        return TAG;
    }

    private void updateShuffleButton() {
        if (SharedConfig.shuffleMusic) {
            Drawable drawable = getContext().getResources().getDrawable(R.drawable.pl_shuffle).mutate();
            drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_buttonActive),
                    PorterDuff.Mode.MULTIPLY));
            shuffleButton.setIcon(drawable);
        } else {
            Drawable drawable = getContext().getResources().getDrawable(R.drawable.music_reverse).mutate();
            if (SharedConfig.playOrderReversed) {
                drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_buttonActive),
                        PorterDuff.Mode.MULTIPLY));
            } else {
                drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_button),
                        PorterDuff.Mode.MULTIPLY));
            }
            shuffleButton.setIcon(drawable);
        }

        playOrderButtons[0].setColorFilter(new PorterDuffColorFilter(
                Theme.getColor(
                        SharedConfig.playOrderReversed ? Theme.key_player_buttonActive : Theme.key_player_button),
                PorterDuff.Mode.MULTIPLY));
        playOrderButtons[1].setColorFilter(new PorterDuffColorFilter(
                Theme.getColor(SharedConfig.shuffleMusic ? Theme.key_player_buttonActive : Theme.key_player_button),
                PorterDuff.Mode.MULTIPLY));
    }

    private void updateRepeatButton() {
        int mode = SharedConfig.repeatMode;
        if (mode == 0) {
            repeatButton.setImageResource(R.drawable.pl_repeat);
            repeatButton.setTag(Theme.key_player_button);
            repeatButton.setColorFilter(
                    new PorterDuffColorFilter(Theme.getColor(Theme.key_player_button), PorterDuff.Mode.MULTIPLY));
        } else if (mode == 1) {
            repeatButton.setImageResource(R.drawable.pl_repeat);
            repeatButton.setTag(Theme.key_player_buttonActive);
            repeatButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_buttonActive),
                    PorterDuff.Mode.MULTIPLY));
        } else if (mode == 2) {
            repeatButton.setImageResource(R.drawable.pl_repeat1);
            repeatButton.setTag(Theme.key_player_buttonActive);
            repeatButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_buttonActive),
                    PorterDuff.Mode.MULTIPLY));
        }
    }

    private void updateProgress(MessageObject messageObject) {
        if (seekBarView != null) {
            if (!seekBarView.isDragging()) {
                seekBarView.setProgress(messageObject.audioProgress);
                seekBarView.setBufferedProgress(messageObject.bufferedProgress);
            }
            if (lastTime != messageObject.audioProgressSec) {
                lastTime = messageObject.audioProgressSec;
                timeTextView.setText(String.format("%d:%02d", messageObject.audioProgressSec / 60,
                        messageObject.audioProgressSec % 60));
            }
        }
    }

    private void checkIfMusicDownloaded(MessageObject messageObject) {
        File cacheFile = null;
        if (messageObject.messageOwner.attachPath != null && messageObject.messageOwner.attachPath.length() > 0) {
            cacheFile = new File(messageObject.messageOwner.attachPath);
            if (!cacheFile.exists()) {
                cacheFile = null;
            }
        }
        if (cacheFile == null) {
            cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner);
        }
        boolean canStream = SharedConfig.streamMedia && (int) messageObject.getDialogId() != 0
                && messageObject.isMusic();
        if (!cacheFile.exists() && !canStream) {
            String fileName = messageObject.getFileName();
            DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, this);
            Float progress = ImageLoader.getInstance().getFileProgress(fileName);
            progressView.setProgress(progress != null ? progress : 0, false);
            progressView.setVisibility(View.VISIBLE);
            seekBarView.setVisibility(View.INVISIBLE);
            playButton.setEnabled(false);
        } else {
            DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this);
            progressView.setVisibility(View.INVISIBLE);
            seekBarView.setVisibility(View.VISIBLE);
            playButton.setEnabled(true);
        }
    }

    private void updateTitle(boolean shutdown) {
        MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
        if (messageObject == null && shutdown || messageObject != null && !messageObject.isMusic()) {
            dismiss();
        } else {
            if (messageObject == null) {
                return;
            }
            if (messageObject.eventId != 0 || messageObject.getId() <= -2000000000) {
                hasOptions = false;
                menuItem.setVisibility(View.INVISIBLE);
                optionsButton.setVisibility(View.INVISIBLE);
            } else {
                hasOptions = true;
                if (!actionBar.isSearchFieldVisible()) {
                    menuItem.setVisibility(View.VISIBLE);
                }
                optionsButton.setVisibility(View.VISIBLE);
            }
            checkIfMusicDownloaded(messageObject);
            updateProgress(messageObject);

            if (MediaController.getInstance().isMessagePaused()) {
                playButton.setImageDrawable(Theme.createSimpleSelectorDrawable(playButton.getContext(),
                        R.drawable.pl_play, Theme.getColor(Theme.key_player_button),
                        Theme.getColor(Theme.key_player_buttonActive)));
            } else {
                playButton.setImageDrawable(Theme.createSimpleSelectorDrawable(playButton.getContext(),
                        R.drawable.pl_pause, Theme.getColor(Theme.key_player_button),
                        Theme.getColor(Theme.key_player_buttonActive)));
            }
            String title = messageObject.getMusicTitle();
            String author = messageObject.getMusicAuthor();
            titleTextView.setText(title);
            authorTextView.setText(author);
            actionBar.setTitle(title);
            actionBar.setSubtitle(author);

            String loadTitle = author + " " + title;
            AudioInfo audioInfo = MediaController.getInstance().getAudioInfo();
            if (audioInfo != null && audioInfo.getCover() != null) {
                hasNoCover = 0;
                placeholderImageView.setImageBitmap(audioInfo.getCover());
            } else {
                String artworkUrl = messageObject.getArtworkUrl(false);
                if (!TextUtils.isEmpty(artworkUrl)) {
                    placeholderImageView.setImage(artworkUrl, null, null);
                    hasNoCover = 2;
                } else {
                    placeholderImageView.setImageDrawable(null);
                    hasNoCover = 1;
                }
                placeholderImageView.invalidate();
            }

            if (durationTextView != null) {
                int duration = messageObject.getDuration();
                durationTextView
                        .setText(duration != 0 ? String.format("%d:%02d", duration / 60, duration % 60) : "-:--");
            }
        }
    }

    private class ListAdapter extends RecyclerListView.SelectionAdapter {

        private Context context;
        private ArrayList<MessageObject> searchResult = new ArrayList<>();
        private Timer searchTimer;

        public ListAdapter(Context context) {
            this.context = context;
        }

        @Override
        public int getItemCount() {
            if (searchWas) {
                return searchResult.size();
            } else if (searching) {
                return playlist.size();
            }
            return 1 + playlist.size();
        }

        @Override
        public boolean isEnabled(RecyclerView.ViewHolder holder) {
            return searchWas || holder.getAdapterPosition() > 0;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view;
            switch (viewType) {
            case 0:
                view = new View(context);
                view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                        AndroidUtilities.dp(178)));
                break;
            case 1:
            default:
                view = new AudioPlayerCell(context);
                break;
            }
            return new RecyclerListView.Holder(view);
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            if (holder.getItemViewType() == 1) {
                AudioPlayerCell cell = (AudioPlayerCell) holder.itemView;
                if (searchWas) {
                    cell.setMessageObject(searchResult.get(position));
                } else if (searching) {
                    if (SharedConfig.playOrderReversed) {
                        cell.setMessageObject(playlist.get(position));
                    } else {
                        cell.setMessageObject(playlist.get(playlist.size() - position - 1));
                    }
                } else if (position > 0) {
                    if (SharedConfig.playOrderReversed) {
                        cell.setMessageObject(playlist.get(position - 1));
                    } else {
                        cell.setMessageObject(playlist.get(playlist.size() - position));
                    }
                }
            }
        }

        @Override
        public int getItemViewType(int i) {
            if (searchWas || searching) {
                return 1;
            }
            if (i == 0) {
                return 0;
            }
            return 1;
        }

        public void search(final String query) {
            try {
                if (searchTimer != null) {
                    searchTimer.cancel();
                }
            } catch (Exception e) {
                FileLog.e(e);
            }
            if (query == null) {
                searchResult.clear();
                notifyDataSetChanged();
            } else {
                searchTimer = new Timer();
                searchTimer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        try {
                            searchTimer.cancel();
                            searchTimer = null;
                        } catch (Exception e) {
                            FileLog.e(e);
                        }
                        processSearch(query);
                    }
                }, 200, 300);
            }
        }

        private void processSearch(final String query) {
            AndroidUtilities.runOnUIThread(() -> {
                final ArrayList<MessageObject> copy = new ArrayList<>(playlist);
                Utilities.searchQueue.postRunnable(() -> {
                    String search1 = query.trim().toLowerCase();
                    if (search1.length() == 0) {
                        updateSearchResults(new ArrayList<>());
                        return;
                    }
                    String search2 = LocaleController.getInstance().getTranslitString(search1);
                    if (search1.equals(search2) || search2.length() == 0) {
                        search2 = null;
                    }
                    String search[] = new String[1 + (search2 != null ? 1 : 0)];
                    search[0] = search1;
                    if (search2 != null) {
                        search[1] = search2;
                    }

                    ArrayList<MessageObject> resultArray = new ArrayList<>();

                    for (int a = 0; a < copy.size(); a++) {
                        MessageObject messageObject = copy.get(a);
                        for (int b = 0; b < search.length; b++) {
                            String q = search[b];
                            String name = messageObject.getDocumentName();
                            if (name == null || name.length() == 0) {
                                continue;
                            }
                            name = name.toLowerCase();
                            if (name.contains(q)) {
                                resultArray.add(messageObject);
                                break;
                            }
                            TLRPC.Document document;
                            if (messageObject.type == 0) {
                                document = messageObject.messageOwner.media.webpage.document;
                            } else {
                                document = messageObject.messageOwner.media.document;
                            }
                            boolean ok = false;
                            for (int c = 0; c < document.attributes.size(); c++) {
                                TLRPC.DocumentAttribute attribute = document.attributes.get(c);
                                if (attribute instanceof TLRPC.TL_documentAttributeAudio) {
                                    if (attribute.performer != null) {
                                        ok = attribute.performer.toLowerCase().contains(q);
                                    }
                                    if (!ok && attribute.title != null) {
                                        ok = attribute.title.toLowerCase().contains(q);
                                    }
                                    break;
                                }
                            }
                            if (ok) {
                                resultArray.add(messageObject);
                                break;
                            }
                        }
                    }

                    updateSearchResults(resultArray);
                });
            });
        }

        private void updateSearchResults(final ArrayList<MessageObject> documents) {
            AndroidUtilities.runOnUIThread(() -> {
                searchWas = true;
                searchResult = documents;
                notifyDataSetChanged();
                layoutManager.scrollToPosition(0);
            });
        }
    }
}