/**
* Wire
* Copyright (C) 2016 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.waz.zclient.pages.extendedcursor.emoji;
import android.app.Instrumentation;
import android.content.Context;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.LinearLayout;
import com.waz.threading.Threading;
import com.waz.zclient.R;
import com.waz.zclient.ui.colorpicker.EmojiAdapter;
import com.waz.zclient.ui.colorpicker.EmojiSize;
import com.waz.zclient.ui.views.tab.TabIndicatorLayout;
import com.waz.zclient.utils.Emojis;
import com.waz.zclient.utils.ViewUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class EmojiKeyboardLayout extends LinearLayout {
private static final int SPAN_COUNT = 4;
private static final int CATEGORY_COUNT = 9;
private static final int TAB_COUNT = 10;
private Callback callback;
private EmojiAdapter emojiAdapter;
private RecyclerView recyclerView;
private GridLayoutManager layoutManager;
private TabIndicatorLayout tapIndicatorLayout;
private EmojiSize currentEmojiSize;
private int[] categoryPositions;
private List<String> emojis;
private List<Integer> spaces;
public EmojiKeyboardLayout(Context context) {
this(context, null);
}
public EmojiKeyboardLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public EmojiKeyboardLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
tapIndicatorLayout = ViewUtils.getView(this, R.id.til__emoji_keyboard);
recyclerView = ViewUtils.getView(this, R.id.rv__emoji_keyboard);
init();
}
public void setCallback(Callback callback) {
this.callback = callback;
}
public void setEmojis(List<String> recent, Set<String> unsupported) {
populateEmojis(recent, unsupported);
emojiAdapter.setEmojis(emojis, currentEmojiSize);
updateCategoryPositions(unsupported);
if (recent != null && recent.size() > 0) {
tapIndicatorLayout.setSelected(0);
} else {
tapIndicatorLayout.setSelected(1);
}
}
private void init() {
currentEmojiSize = EmojiSize.MEDIUM;
categoryPositions = new int[CATEGORY_COUNT];
emojiAdapter = new EmojiAdapter(getContext());
layoutManager = new GridLayoutManager(getContext(),
SPAN_COUNT,
LinearLayoutManager.HORIZONTAL,
false);
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return spaces.contains(position) ? SPAN_COUNT : 1;
}
});
layoutManager.setSpanCount(SPAN_COUNT);
recyclerView.addOnScrollListener(new EmojiScrollListener());
tapIndicatorLayout.setShowDivider(false);
tapIndicatorLayout.setGlyphLabels(Emojis.EMOJI_KEYBOARD_TAB_LABELS);
tapIndicatorLayout.setTextColor(ContextCompat.getColorStateList(getContext(), com.waz.zclient.ui.R.color.wire__text_color_dark_selector));
tapIndicatorLayout.setPrimaryColor(ContextCompat.getColor(getContext(), com.waz.zclient.ui.R.color.text__primary_dark));
tapIndicatorLayout.setLabelHeight(getContext().getResources().getDimensionPixelSize(com.waz.zclient.ui.R.dimen.sketch__emoji__keyboard__tab_label_size));
tapIndicatorLayout.setCallback(new TabIndicatorLayout.Callback() {
@Override
public void onItemSelected(int pos) {
if (ViewCompat.getLayoutDirection(EmojiKeyboardLayout.this) == ViewCompat.LAYOUT_DIRECTION_RTL) {
// Revert tab position for RTL layout
pos = (TAB_COUNT - 1) - pos;
}
if (pos == TAB_COUNT - 1) {
Threading.Background().execute(new Runnable() {
@Override
public void run() {
Instrumentation inst = new Instrumentation();
inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DEL);
}
});
} else {
tapIndicatorLayout.setSelected(pos);
layoutManager.scrollToPositionWithOffset(getCategoryByTabPosition(pos), 0);
}
}
});
recyclerView.setAdapter(emojiAdapter);
recyclerView.setLayoutManager(layoutManager);
setRecyclerViewPadding(recyclerView);
emojiAdapter.setOnEmojiClickListener(new EmojiAdapter.OnEmojiClickListener() {
@Override
public void onEmojiClick(String emoji, EmojiSize emojiSize) {
if (callback != null) {
callback.onEmojiSelected(emoji);
}
}
});
}
private List<String> getFilteredList(String[] strings, Set<String> unsupported) {
List<String> list = Arrays.asList(strings);
if (unsupported == null || unsupported.size() == 0) {
return list;
}
LinkedList<String> filteredList = new LinkedList<>(list);
filteredList.removeAll(unsupported);
return filteredList;
}
private void populateEmojis(List<String> recent, Set<String> unsupported) {
spaces = new ArrayList<>();
emojis = new ArrayList<>();
if (recent != null && recent.size() > 0) {
emojis.addAll(recent);
spaces.add(emojis.size());
emojis.add(EmojiAdapter.SPACE);
}
for (String[] emojiArray : Emojis.getAllEmojisSortedByCategory()) {
emojis.addAll(getFilteredList(emojiArray, unsupported));
spaces.add(emojis.size());
emojis.add(EmojiAdapter.SPACE);
}
}
private void setRecyclerViewPadding(RecyclerView recyclerView) {
int padding;
switch (currentEmojiSize) {
case SMALL:
padding = getContext().getResources().getDimensionPixelOffset(com.waz.zclient.ui.R.dimen.sketch__emoji__keyboard__item_padding__small);
break;
case MEDIUM:
padding = getContext().getResources().getDimensionPixelOffset(com.waz.zclient.ui.R.dimen.sketch__emoji__keyboard__item_padding__medium);
break;
case LARGE:
padding = getContext().getResources().getDimensionPixelOffset(com.waz.zclient.ui.R.dimen.sketch__emoji__keyboard__item_padding__large);
break;
default:
padding = getContext().getResources().getDimensionPixelOffset(com.waz.zclient.ui.R.dimen.sketch__emoji__keyboard__item_padding__small);
break;
}
int sidePadding = getContext().getResources().getDimensionPixelSize(com.waz.zclient.ui.R.dimen.sketch__emoji__keyboard__side_padding);
recyclerView.setClipToPadding(false);
recyclerView.setPadding(sidePadding, padding, sidePadding, padding);
}
private int getCategoryByTabPosition(int tabPos) {
if (tabPos >= categoryPositions.length) {
return 0;
}
return categoryPositions[tabPos];
}
private int getTabByItemPosition(int itemPos) {
for (int i = 0; i < categoryPositions.length - 1; i++) {
if (itemPos >= categoryPositions[categoryPositions.length - 1]) {
return categoryPositions.length - 1;
}
int categoryFirstItem = categoryPositions[i];
int nextCategoryFirstItem = categoryPositions[i + 1];
if (itemPos >= categoryFirstItem &&
itemPos < nextCategoryFirstItem) {
return i;
}
}
return 0;
}
private void updateCategoryPositions(Set<String> unsupported) {
for (int i = 0; i < CATEGORY_COUNT; i++) {
int pos = 0;
List<String> filteredList = null;
switch (i) {
case 1:
filteredList = getFilteredList(Emojis.PEOPLE, unsupported);
break;
case 2:
filteredList = getFilteredList(Emojis.NATURE, unsupported);
break;
case 3:
filteredList = getFilteredList(Emojis.FOOD_AND_DRINK, unsupported);
break;
case 4:
filteredList = getFilteredList(Emojis.ACTIVITY, unsupported);
break;
case 5:
filteredList = getFilteredList(Emojis.TRAVEL_AND_PLACES, unsupported);
break;
case 6:
filteredList = getFilteredList(Emojis.OBJECTS, unsupported);
break;
case 7:
filteredList = getFilteredList(Emojis.SYMBOLS, unsupported);
break;
case 8:
filteredList = getFilteredList(Emojis.FLAGS, unsupported);
break;
default:
pos = 0;
break;
}
if (filteredList != null && filteredList.size() > 1) {
pos = emojis.indexOf(filteredList.get(0));
if (pos < 0) {
pos = 0;
}
}
categoryPositions[i] = pos;
}
}
private class EmojiScrollListener extends RecyclerView.OnScrollListener {
private EmojiScrollListener() {
super();
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int itemPos = layoutManager.findFirstCompletelyVisibleItemPosition();
tapIndicatorLayout.setSelected(getTabByItemPosition(itemPos));
}
}
public interface Callback {
void onEmojiSelected(String emoji);
}
}