session-android/src/org/thoughtcrime/securesms/stickers/StickerKeyboardPageFragment.java
2019-08-07 16:48:54 +10:00

216 lines
7.6 KiB
Java

package org.thoughtcrime.securesms.stickers;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Px;
import android.support.v4.app.Fragment;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.model.StickerRecord;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.stickers.StickerKeyboardPageAdapter.StickerKeyboardPageViewHolder;
import org.thoughtcrime.securesms.util.ViewUtil;
import network.loki.messenger.R;
/**
* An individual page of stickers in the {@link StickerKeyboardProvider}.
*/
public final class StickerKeyboardPageFragment extends Fragment implements StickerKeyboardPageAdapter.EventListener {
private static final String TAG = Log.tag(StickerKeyboardPageFragment.class);
private static final String KEY_PACK_ID = "pack_id";
public static final String RECENT_PACK_ID = StickerKeyboardPageViewModel.RECENT_PACK_ID;
private RecyclerView list;
private StickerKeyboardPageAdapter adapter;
private GridLayoutManager layoutManager;
private StickerKeyboardPageViewModel viewModel;
private EventListener eventListener;
private ListTouchListener listTouchListener;
private String packId;
public static StickerKeyboardPageFragment newInstance(@NonNull String packId) {
Bundle args = new Bundle();
args.putString(KEY_PACK_ID, packId);
StickerKeyboardPageFragment fragment = new StickerKeyboardPageFragment();
fragment.setArguments(args);
fragment.packId = packId;
return fragment;
}
@Override
public @Nullable View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.sticker_keyboard_page, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
GlideRequests glideRequests = GlideApp.with(this);
this.list = view.findViewById(R.id.sticker_keyboard_list);
this.adapter = new StickerKeyboardPageAdapter(glideRequests, this);
this.layoutManager = new GridLayoutManager(requireContext(), 2);
this.listTouchListener = new ListTouchListener(requireContext(), glideRequests);
this.packId = getArguments().getString(KEY_PACK_ID);
list.setLayoutManager(layoutManager);
list.setAdapter(adapter);
list.addOnItemTouchListener(listTouchListener);
initViewModel(packId);
onScreenWidthChanged(getScreenWidth());
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
onScreenWidthChanged(getScreenWidth());
}
@Override
public void onStickerClicked(@NonNull StickerRecord sticker) {
if (eventListener != null) {
eventListener.onStickerSelected(sticker);
}
}
@Override
public void onStickerLongClicked(@NonNull View targetView) {
if (listTouchListener != null) {
listTouchListener.enterHoverMode(list, targetView);
}
}
public void setEventListener(@NonNull EventListener eventListener) {
this.eventListener = eventListener;
}
public @NonNull String getPackId() {
return packId;
}
private void initViewModel(@NonNull String packId) {
StickerKeyboardRepository repository = new StickerKeyboardRepository(DatabaseFactory.getStickerDatabase(requireContext()));
viewModel = ViewModelProviders.of(this, new StickerKeyboardPageViewModel.Factory(requireActivity().getApplication(), repository)).get(StickerKeyboardPageViewModel.class);
viewModel.getStickers(packId).observe(getViewLifecycleOwner(), stickerRecords -> {
if (stickerRecords == null) return;
adapter.setStickers(stickerRecords, calculateStickerSize(getScreenWidth()));
});
}
private void onScreenWidthChanged(@Px int newWidth) {
if (layoutManager != null) {
layoutManager.setSpanCount(calculateColumnCount(newWidth));
adapter.setStickerSize(calculateStickerSize(newWidth));
}
}
private int getScreenWidth() {
Point size = new Point();
requireActivity().getWindowManager().getDefaultDisplay().getSize(size);
return size.x;
}
private int calculateColumnCount(@Px int screenWidth) {
float modifier = getResources().getDimensionPixelOffset(R.dimen.sticker_page_item_padding);
float divisor = getResources().getDimensionPixelOffset(R.dimen.sticker_page_item_divisor);
return (int) ((screenWidth - modifier) / divisor);
}
private int calculateStickerSize(@Px int screenWidth) {
float multiplier = getResources().getDimensionPixelOffset(R.dimen.sticker_page_item_multiplier);
int columnCount = calculateColumnCount(screenWidth);
return (int) ((screenWidth - ((columnCount + 1) * multiplier)) / columnCount);
}
private final class ListTouchListener implements RecyclerView.OnItemTouchListener {
private final StickerPreviewPopup popup;
private boolean hoverMode;
ListTouchListener(@NonNull Context context, @NonNull GlideRequests glideRequests) {
this.popup = new StickerPreviewPopup(context, glideRequests);
popup.setAnimationStyle(R.style.StickerPopupAnimation);
}
@Override
public boolean onInterceptTouchEvent(@NonNull RecyclerView recyclerView, @NonNull MotionEvent motionEvent) {
return hoverMode;
}
@Override
public void onTouchEvent(@NonNull RecyclerView recyclerView, @NonNull MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
hoverMode = false;
popup.dismiss();
eventListener.onStickerPopupEnded();
break;
default:
for (int i = 0, len = recyclerView.getChildCount(); i < len; i++) {
View child = recyclerView.getChildAt(i);
if (ViewUtil.isPointInsideView(recyclerView, motionEvent.getRawX(), motionEvent.getRawY()) &&
ViewUtil.isPointInsideView(child, motionEvent.getRawX(), motionEvent.getRawY()))
{
showStickerForView(recyclerView, child);
}
}
}
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean b) {
}
void enterHoverMode(@NonNull RecyclerView recyclerView, View targetView) {
this.hoverMode = true;
showStickerForView(recyclerView, targetView);
}
private void showStickerForView(@NonNull RecyclerView recyclerView, @NonNull View view) {
StickerKeyboardPageViewHolder holder = (StickerKeyboardPageViewHolder) recyclerView.getChildViewHolder(view);
if (holder != null && holder.getCurrentSticker() != null) {
if (!popup.isShowing()) {
popup.showAtLocation(recyclerView, Gravity.NO_GRAVITY, 0, 0);
eventListener.onStickerPopupStarted();
}
popup.presentSticker(holder.getCurrentSticker());
}
}
}
interface EventListener {
void onStickerSelected(@NonNull StickerRecord sticker);
void onStickerPopupStarted();
void onStickerPopupEnded();
}
}