277 lines
9.4 KiB
Java
277 lines
9.4 KiB
Java
package org.thoughtcrime.securesms.components.emoji;
|
|
|
|
import android.content.Context;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.viewpager.widget.PagerAdapter;
|
|
import androidx.viewpager.widget.ViewPager;
|
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
import android.util.AttributeSet;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.FrameLayout;
|
|
|
|
|
|
import org.thoughtcrime.securesms.components.InputAwareLayout.InputView;
|
|
import org.thoughtcrime.securesms.components.RepeatableImageKey;
|
|
import org.session.libsignal.utilities.Log;
|
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import network.loki.messenger.R;
|
|
|
|
public class MediaKeyboard extends FrameLayout implements InputView,
|
|
MediaKeyboardProvider.Presenter,
|
|
MediaKeyboardProvider.Controller,
|
|
MediaKeyboardBottomTabAdapter.EventListener
|
|
{
|
|
|
|
private static final String TAG = Log.tag(MediaKeyboard.class);
|
|
|
|
private RecyclerView categoryTabs;
|
|
private ViewPager categoryPager;
|
|
private ViewGroup providerTabs;
|
|
private RepeatableImageKey backspaceButton;
|
|
private RepeatableImageKey backspaceButtonBackup;
|
|
private View searchButton;
|
|
private View addButton;
|
|
private MediaKeyboardListener keyboardListener;
|
|
private MediaKeyboardProvider[] providers;
|
|
private int providerIndex;
|
|
|
|
private MediaKeyboardBottomTabAdapter categoryTabAdapter;
|
|
|
|
public MediaKeyboard(Context context) {
|
|
this(context, null);
|
|
}
|
|
|
|
public MediaKeyboard(Context context, AttributeSet attrs) {
|
|
super(context, attrs);
|
|
}
|
|
|
|
public void setProviders(int startIndex, MediaKeyboardProvider... providers) {
|
|
if (!Arrays.equals(this.providers, providers)) {
|
|
this.providers = providers;
|
|
this.providerIndex = startIndex;
|
|
|
|
requestPresent(providers, providerIndex);
|
|
}
|
|
}
|
|
|
|
public void setKeyboardListener(MediaKeyboardListener listener) {
|
|
this.keyboardListener = listener;
|
|
}
|
|
|
|
@Override
|
|
public boolean isShowing() {
|
|
return getVisibility() == VISIBLE;
|
|
}
|
|
|
|
@Override
|
|
public void show(int height, boolean immediate) {
|
|
if (this.categoryPager == null) initView();
|
|
|
|
ViewGroup.LayoutParams params = getLayoutParams();
|
|
params.height = height;
|
|
Log.i(TAG, "showing emoji drawer with height " + params.height);
|
|
setLayoutParams(params);
|
|
setVisibility(VISIBLE);
|
|
|
|
if (keyboardListener != null) keyboardListener.onShown();
|
|
|
|
requestPresent(providers, providerIndex);
|
|
}
|
|
|
|
@Override
|
|
public void hide(boolean immediate) {
|
|
setVisibility(GONE);
|
|
if (keyboardListener != null) keyboardListener.onHidden();
|
|
Log.i(TAG, "hide()");
|
|
}
|
|
|
|
@Override
|
|
public void present(@NonNull MediaKeyboardProvider provider,
|
|
@NonNull PagerAdapter pagerAdapter,
|
|
@NonNull MediaKeyboardProvider.TabIconProvider tabIconProvider,
|
|
@Nullable MediaKeyboardProvider.BackspaceObserver backspaceObserver,
|
|
@Nullable MediaKeyboardProvider.AddObserver addObserver,
|
|
@Nullable MediaKeyboardProvider.SearchObserver searchObserver,
|
|
int startingIndex)
|
|
{
|
|
if (categoryPager == null) return;
|
|
if (!provider.equals(providers[providerIndex])) return;
|
|
if (keyboardListener != null) keyboardListener.onKeyboardProviderChanged(provider);
|
|
|
|
boolean isSolo = providers.length == 1;
|
|
|
|
presentProviderStrip(isSolo);
|
|
presentCategoryPager(pagerAdapter, tabIconProvider, startingIndex);
|
|
presentProviderTabs(providers, providerIndex);
|
|
presentSearchButton(searchObserver);
|
|
presentBackspaceButton(backspaceObserver, isSolo);
|
|
presentAddButton(addObserver);
|
|
}
|
|
|
|
@Override
|
|
public int getCurrentPosition() {
|
|
return categoryPager != null ? categoryPager.getCurrentItem() : 0;
|
|
}
|
|
|
|
@Override
|
|
public void requestDismissal() {
|
|
hide(true);
|
|
providerIndex = 0;
|
|
keyboardListener.onKeyboardProviderChanged(providers[providerIndex]);
|
|
}
|
|
|
|
@Override
|
|
public boolean isVisible() {
|
|
return getVisibility() == View.VISIBLE;
|
|
}
|
|
|
|
@Override
|
|
public void onTabSelected(int index) {
|
|
if (categoryPager != null) {
|
|
categoryPager.setCurrentItem(index);
|
|
categoryTabs.smoothScrollToPosition(index);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setViewPagerEnabled(boolean enabled) {
|
|
if (categoryPager != null) {
|
|
categoryPager.setEnabled(enabled);
|
|
}
|
|
}
|
|
|
|
private void initView() {
|
|
final View view = LayoutInflater.from(getContext()).inflate(R.layout.media_keyboard, this, true);
|
|
|
|
this.categoryTabs = view.findViewById(R.id.media_keyboard_tabs);
|
|
this.categoryPager = view.findViewById(R.id.media_keyboard_pager);
|
|
this.providerTabs = view.findViewById(R.id.media_keyboard_provider_tabs);
|
|
this.backspaceButton = view.findViewById(R.id.media_keyboard_backspace);
|
|
this.backspaceButtonBackup = view.findViewById(R.id.media_keyboard_backspace_backup);
|
|
this.searchButton = view.findViewById(R.id.media_keyboard_search);
|
|
this.addButton = view.findViewById(R.id.media_keyboard_add);
|
|
|
|
this.categoryTabAdapter = new MediaKeyboardBottomTabAdapter(GlideApp.with(this), this);
|
|
|
|
categoryTabs.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
|
|
categoryTabs.setAdapter(categoryTabAdapter);
|
|
}
|
|
|
|
private void requestPresent(@NonNull MediaKeyboardProvider[] providers, int newIndex) {
|
|
providers[providerIndex].setController(null);
|
|
providerIndex = newIndex;
|
|
|
|
providers[providerIndex].setController(this);
|
|
providers[providerIndex].requestPresentation(this, providers.length == 1);
|
|
}
|
|
|
|
|
|
private void presentCategoryPager(@NonNull PagerAdapter pagerAdapter,
|
|
@NonNull MediaKeyboardProvider.TabIconProvider iconProvider,
|
|
int startingIndex) {
|
|
if (categoryPager.getAdapter() != pagerAdapter) {
|
|
categoryPager.setAdapter(pagerAdapter);
|
|
}
|
|
|
|
categoryPager.setCurrentItem(startingIndex);
|
|
|
|
categoryPager.clearOnPageChangeListeners();
|
|
categoryPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
|
@Override
|
|
public void onPageScrolled(int i, float v, int i1) {
|
|
}
|
|
|
|
@Override
|
|
public void onPageSelected(int i) {
|
|
categoryTabAdapter.setActivePosition(i);
|
|
categoryTabs.smoothScrollToPosition(i);
|
|
}
|
|
|
|
@Override
|
|
public void onPageScrollStateChanged(int i) {
|
|
}
|
|
});
|
|
|
|
categoryTabAdapter.setTabIconProvider(iconProvider, pagerAdapter.getCount());
|
|
categoryTabAdapter.setActivePosition(startingIndex);
|
|
}
|
|
|
|
private void presentProviderTabs(@NonNull MediaKeyboardProvider[] providers, int selected) {
|
|
providerTabs.removeAllViews();
|
|
|
|
LayoutInflater inflater = LayoutInflater.from(getContext());
|
|
|
|
for (int i = 0; i < providers.length; i++) {
|
|
MediaKeyboardProvider provider = providers[i];
|
|
View view = inflater.inflate(provider.getProviderIconView(i == selected), providerTabs, false);
|
|
|
|
view.setTag(provider);
|
|
|
|
final int index = i;
|
|
view.setOnClickListener(v -> {
|
|
requestPresent(providers, index);
|
|
});
|
|
|
|
providerTabs.addView(view);
|
|
}
|
|
}
|
|
|
|
private void presentBackspaceButton(@Nullable MediaKeyboardProvider.BackspaceObserver backspaceObserver,
|
|
boolean useBackupPosition)
|
|
{
|
|
if (backspaceObserver != null) {
|
|
if (useBackupPosition) {
|
|
backspaceButton.setVisibility(INVISIBLE);
|
|
backspaceButton.setOnKeyEventListener(null);
|
|
backspaceButtonBackup.setVisibility(VISIBLE);
|
|
backspaceButtonBackup.setOnKeyEventListener(backspaceObserver::onBackspaceClicked);
|
|
} else {
|
|
backspaceButton.setVisibility(VISIBLE);
|
|
backspaceButton.setOnKeyEventListener(backspaceObserver::onBackspaceClicked);
|
|
backspaceButtonBackup.setVisibility(GONE);
|
|
backspaceButtonBackup.setOnKeyEventListener(null);
|
|
}
|
|
} else {
|
|
backspaceButton.setVisibility(INVISIBLE);
|
|
backspaceButton.setOnKeyEventListener(null);
|
|
backspaceButtonBackup.setVisibility(GONE);
|
|
backspaceButton.setOnKeyEventListener(null);
|
|
}
|
|
}
|
|
|
|
private void presentAddButton(@Nullable MediaKeyboardProvider.AddObserver addObserver) {
|
|
if (addObserver != null) {
|
|
addButton.setVisibility(VISIBLE);
|
|
addButton.setOnClickListener(v -> addObserver.onAddClicked());
|
|
} else {
|
|
addButton.setVisibility(GONE);
|
|
addButton.setOnClickListener(null);
|
|
}
|
|
}
|
|
|
|
private void presentSearchButton(@Nullable MediaKeyboardProvider.SearchObserver searchObserver) {
|
|
searchButton.setVisibility(searchObserver != null ? VISIBLE : INVISIBLE);
|
|
}
|
|
|
|
private void presentProviderStrip(boolean isSolo) {
|
|
int visibility = isSolo ? View.GONE : View.VISIBLE;
|
|
|
|
searchButton.setVisibility(visibility);
|
|
backspaceButton.setVisibility(visibility);
|
|
providerTabs.setVisibility(visibility);
|
|
}
|
|
|
|
public interface MediaKeyboardListener {
|
|
void onShown();
|
|
void onHidden();
|
|
void onKeyboardProviderChanged(@NonNull MediaKeyboardProvider provider);
|
|
}
|
|
}
|