mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 17:29:32 +01:00
Remove dead keyboard code after refresh.
This commit is contained in:
committed by
Greyson Parrelli
parent
7419570f94
commit
c54c6018b2
@@ -0,0 +1,11 @@
|
||||
package org.thoughtcrime.securesms.stickers;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
|
||||
public interface StickerEventListener {
|
||||
void onStickerSelected(@NonNull StickerRecord sticker);
|
||||
|
||||
void onStickerManagementClicked();
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
package org.thoughtcrime.securesms.stickers;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Px;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
import org.thoughtcrime.securesms.glide.cache.ApngOptions;
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Adapter for a specific page in the sticker keyboard. Shows the stickers in a grid.
|
||||
* @see StickerKeyboardPageFragment
|
||||
*/
|
||||
public final class StickerKeyboardPageAdapter extends RecyclerView.Adapter<StickerKeyboardPageAdapter.StickerKeyboardPageViewHolder> {
|
||||
|
||||
private final GlideRequests glideRequests;
|
||||
private final EventListener eventListener;
|
||||
private final List<StickerRecord> stickers;
|
||||
private final boolean allowApngAnimation;
|
||||
|
||||
private int stickerSize;
|
||||
|
||||
public StickerKeyboardPageAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener, boolean allowApngAnimation) {
|
||||
this.glideRequests = glideRequests;
|
||||
this.eventListener = eventListener;
|
||||
this.allowApngAnimation = allowApngAnimation;
|
||||
this.stickers = new ArrayList<>();
|
||||
|
||||
setHasStableIds(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return stickers.get(position).getRowId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull StickerKeyboardPageViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
|
||||
return new StickerKeyboardPageViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.sticker_keyboard_page_list_item, viewGroup, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull StickerKeyboardPageViewHolder viewHolder, int i) {
|
||||
viewHolder.bind(glideRequests, eventListener, stickers.get(i), stickerSize, allowApngAnimation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewRecycled(@NonNull StickerKeyboardPageViewHolder holder) {
|
||||
holder.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return stickers.size();
|
||||
}
|
||||
|
||||
public void setStickers(@NonNull List<StickerRecord> stickers, @Px int stickerSize) {
|
||||
this.stickers.clear();
|
||||
this.stickers.addAll(stickers);
|
||||
|
||||
this.stickerSize = stickerSize;
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setStickerSize(@Px int stickerSize) {
|
||||
this.stickerSize = stickerSize;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
static class StickerKeyboardPageViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private final ImageView image;
|
||||
|
||||
private StickerRecord currentSticker;
|
||||
|
||||
public StickerKeyboardPageViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
image = itemView.findViewById(R.id.sticker_keyboard_page_image);
|
||||
}
|
||||
|
||||
public void bind(@NonNull GlideRequests glideRequests,
|
||||
@Nullable EventListener eventListener,
|
||||
@NonNull StickerRecord sticker,
|
||||
@Px int size,
|
||||
boolean allowApngAnimation)
|
||||
{
|
||||
currentSticker = sticker;
|
||||
|
||||
itemView.getLayoutParams().height = size;
|
||||
itemView.getLayoutParams().width = size;
|
||||
itemView.requestLayout();
|
||||
|
||||
glideRequests.load(new DecryptableUri(sticker.getUri()))
|
||||
.set(ApngOptions.ANIMATE, allowApngAnimation)
|
||||
.transition(DrawableTransitionOptions.withCrossFade())
|
||||
.into(image);
|
||||
|
||||
if (eventListener != null) {
|
||||
image.setOnClickListener(v -> eventListener.onStickerClicked(sticker));
|
||||
image.setOnLongClickListener(v -> {
|
||||
eventListener.onStickerLongClicked(v);
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
image.setOnClickListener(null);
|
||||
image.setOnLongClickListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
void recycle() {
|
||||
image.setOnClickListener(null);
|
||||
}
|
||||
|
||||
@Nullable StickerRecord getCurrentSticker() {
|
||||
return currentSticker;
|
||||
}
|
||||
}
|
||||
|
||||
public interface EventListener {
|
||||
void onStickerClicked(@NonNull StickerRecord sticker);
|
||||
void onStickerLongClicked(@NonNull View targetView);
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
package org.thoughtcrime.securesms.stickers;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Px;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.stickers.StickerKeyboardPageAdapter.StickerKeyboardPageViewHolder;
|
||||
import org.thoughtcrime.securesms.util.DeviceProperties;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
|
||||
/**
|
||||
* An individual page of stickers in the {@link StickerKeyboardProvider}.
|
||||
*/
|
||||
public final class StickerKeyboardPageFragment extends Fragment implements StickerKeyboardPageAdapter.EventListener,
|
||||
StickerRolloverTouchListener.RolloverStickerRetriever
|
||||
{
|
||||
|
||||
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 StickerRolloverTouchListener 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, DeviceProperties.shouldAllowApngStickerAnimation(requireContext()));
|
||||
this.layoutManager = new GridLayoutManager(requireContext(), 2);
|
||||
this.listTouchListener = new StickerRolloverTouchListener(requireContext(), glideRequests, eventListener, this);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Pair<Object, String> getStickerDataFromView(@NonNull View view) {
|
||||
if (list != null) {
|
||||
StickerKeyboardPageViewHolder holder = (StickerKeyboardPageViewHolder) list.getChildViewHolder(view);
|
||||
if (holder != null && holder.getCurrentSticker() != null) {
|
||||
return new Pair<>(new DecryptableStreamUriLoader.DecryptableUri(holder.getCurrentSticker().getUri()),
|
||||
holder.getCurrentSticker().getEmoji());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
interface EventListener extends StickerRolloverTouchListener.RolloverEventListener {
|
||||
void onStickerSelected(@NonNull StickerRecord sticker);
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package org.thoughtcrime.securesms.stickers;
|
||||
|
||||
import android.app.Application;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseContentProviders;
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
import org.thoughtcrime.securesms.util.Throttler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
final class StickerKeyboardPageViewModel extends ViewModel {
|
||||
|
||||
static final String RECENT_PACK_ID = "RECENT";
|
||||
|
||||
private final Application application;
|
||||
private final StickerKeyboardRepository repository;
|
||||
private final MutableLiveData<List<StickerRecord>> stickers;
|
||||
private final Throttler observerThrottler;
|
||||
private final ContentObserver observer;
|
||||
|
||||
private String packId;
|
||||
|
||||
private StickerKeyboardPageViewModel(@NonNull Application application, @NonNull StickerKeyboardRepository repository) {
|
||||
this.application = application;
|
||||
this.repository = repository;
|
||||
this.stickers = new MutableLiveData<>();
|
||||
this.observerThrottler = new Throttler(500);
|
||||
this.observer = new ContentObserver(new Handler(Looper.getMainLooper())) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
observerThrottler.publish(() -> getStickers(packId));
|
||||
}
|
||||
};
|
||||
|
||||
application.getContentResolver().registerContentObserver(DatabaseContentProviders.Sticker.CONTENT_URI, true, observer);
|
||||
}
|
||||
|
||||
LiveData<List<StickerRecord>> getStickers(@NonNull String packId) {
|
||||
this.packId = packId;
|
||||
|
||||
if (RECENT_PACK_ID.equals(packId)) {
|
||||
repository.getRecentStickers(stickers::postValue);
|
||||
} else {
|
||||
repository.getStickersForPack(packId, stickers::postValue);
|
||||
}
|
||||
|
||||
return stickers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCleared() {
|
||||
application.getContentResolver().unregisterContentObserver(observer);
|
||||
}
|
||||
|
||||
static class Factory extends ViewModelProvider.NewInstanceFactory {
|
||||
private final Application application;
|
||||
private final StickerKeyboardRepository repository;
|
||||
|
||||
Factory(@NonNull Application application, @NonNull StickerKeyboardRepository repository) {
|
||||
this.application = application;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull<T extends ViewModel> T create(@NonNull Class<T> modelClass) {
|
||||
//noinspection ConstantConditions
|
||||
return modelClass.cast(new StickerKeyboardPageViewModel(application, repository));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,270 +0,0 @@
|
||||
package org.thoughtcrime.securesms.stickers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.model.StickerPackRecord;
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
import org.thoughtcrime.securesms.glide.cache.ApngOptions;
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.stickers.StickerKeyboardPageFragment.EventListener;
|
||||
import org.thoughtcrime.securesms.stickers.StickerKeyboardRepository.PackListResult;
|
||||
import org.thoughtcrime.securesms.util.DeviceProperties;
|
||||
import org.thoughtcrime.securesms.util.Throttler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A provider to select stickers in the {@link org.thoughtcrime.securesms.components.emoji.MediaKeyboard}.
|
||||
*/
|
||||
public final class StickerKeyboardProvider implements MediaKeyboardProvider,
|
||||
MediaKeyboardProvider.AddObserver,
|
||||
StickerKeyboardPageFragment.EventListener
|
||||
{
|
||||
private static final int UNSET = -1;
|
||||
|
||||
private final Context context;
|
||||
private final StickerEventListener eventListener;
|
||||
private final StickerPagerAdapter pagerAdapter;
|
||||
private final Throttler stickerThrottler;
|
||||
|
||||
private Controller controller;
|
||||
private Presenter presenter;
|
||||
private boolean isSoloProvider;
|
||||
private StickerKeyboardViewModel viewModel;
|
||||
private int currentPosition;
|
||||
|
||||
public StickerKeyboardProvider(@NonNull FragmentActivity activity,
|
||||
@NonNull StickerEventListener eventListener)
|
||||
{
|
||||
this.context = activity;
|
||||
this.eventListener = eventListener;
|
||||
this.pagerAdapter = new StickerPagerAdapter(activity.getSupportFragmentManager(), this);
|
||||
this.stickerThrottler = new Throttler(100);
|
||||
this.currentPosition = UNSET;
|
||||
|
||||
initViewModel(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProviderIconView(boolean selected) {
|
||||
if (selected) {
|
||||
return R.layout.sticker_keyboard_icon_selected;
|
||||
} else {
|
||||
return R.layout.sticker_keyboard_icon;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPresentation(@NonNull Presenter presenter, boolean isSoloProvider) {
|
||||
this.presenter = presenter;
|
||||
this.isSoloProvider = isSoloProvider;
|
||||
|
||||
PackListResult result = viewModel.getPacks().getValue();
|
||||
|
||||
if (result != null) {
|
||||
present(presenter, result, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setController(@Nullable Controller controller) {
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAddClicked() {
|
||||
eventListener.onStickerManagementClicked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStickerSelected(@NonNull StickerRecord sticker) {
|
||||
stickerThrottler.publish(() -> eventListener.onStickerSelected(sticker));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStickerPopupStarted() {
|
||||
if (controller != null) {
|
||||
controller.setViewPagerEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStickerPopupEnded() {
|
||||
if (controller != null) {
|
||||
controller.setViewPagerEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentPosition(int currentPosition) {
|
||||
this.currentPosition = currentPosition;
|
||||
}
|
||||
|
||||
private void initViewModel(@NonNull FragmentActivity activity) {
|
||||
StickerKeyboardRepository repository = new StickerKeyboardRepository(DatabaseFactory.getStickerDatabase(activity));
|
||||
viewModel = ViewModelProviders.of(activity, new StickerKeyboardViewModel.Factory(activity.getApplication(), repository)).get(StickerKeyboardViewModel.class);
|
||||
|
||||
viewModel.getPacks().observe(activity, result -> {
|
||||
if (result == null) return;
|
||||
|
||||
int previousCount = pagerAdapter.getCount();
|
||||
|
||||
pagerAdapter.setPacks(result.getPacks());
|
||||
|
||||
if (presenter != null) {
|
||||
present(presenter, result, previousCount != pagerAdapter.getCount());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void present(@NonNull Presenter presenter, @NonNull PackListResult result, boolean calculateStartingIndex) {
|
||||
if (result.getPacks().isEmpty() && presenter.isVisible()) {
|
||||
context.startActivity(StickerManagementActivity.getIntent(context));
|
||||
presenter.requestDismissal();
|
||||
return;
|
||||
}
|
||||
|
||||
int startingIndex = currentPosition;
|
||||
|
||||
if (calculateStartingIndex || startingIndex == UNSET) {
|
||||
startingIndex = !result.hasRecents() && result.getPacks().size() > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
presenter.present(this, pagerAdapter, new IconProvider(context, result.getPacks(), DeviceProperties.shouldAllowApngStickerAnimation(context)), null, this, null, startingIndex);
|
||||
|
||||
if (isSoloProvider && result.getPacks().isEmpty()) {
|
||||
context.startActivity(StickerManagementActivity.getIntent(context));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return obj instanceof StickerKeyboardProvider;
|
||||
}
|
||||
|
||||
private static class StickerPagerAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
private final List<StickerPackRecord> packs;
|
||||
private final Map<String, Integer> itemPositions;
|
||||
private final EventListener eventListener;
|
||||
|
||||
public StickerPagerAdapter(@NonNull FragmentManager fm, @NonNull EventListener eventListener) {
|
||||
super(fm);
|
||||
this.eventListener = eventListener;
|
||||
this.packs = new ArrayList<>();
|
||||
this.itemPositions = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemPosition(@NonNull Object object) {
|
||||
String packId = ((StickerKeyboardPageFragment) object).getPackId();
|
||||
|
||||
if (itemPositions.containsKey(packId)) {
|
||||
//noinspection ConstantConditions
|
||||
return itemPositions.get(packId);
|
||||
}
|
||||
|
||||
return POSITION_NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int i) {
|
||||
StickerKeyboardPageFragment fragment;
|
||||
|
||||
if (i == 0) {
|
||||
fragment = StickerKeyboardPageFragment.newInstance(StickerKeyboardPageFragment.RECENT_PACK_ID);
|
||||
} else {
|
||||
StickerPackRecord pack = packs.get(i - 1);
|
||||
fragment = StickerKeyboardPageFragment.newInstance(pack.getPackId());
|
||||
}
|
||||
|
||||
fragment.setEventListener(eventListener);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return packs.isEmpty() ? 0 : packs.size() + 1;
|
||||
}
|
||||
|
||||
void setPacks(@NonNull List<StickerPackRecord> packs) {
|
||||
itemPositions.clear();
|
||||
|
||||
if (areListsEqual(this.packs, packs)) {
|
||||
itemPositions.put(StickerKeyboardPageFragment.RECENT_PACK_ID, 0);
|
||||
for (int i = 0; i < packs.size(); i++) {
|
||||
itemPositions.put(packs.get(i).getPackId(), i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
this.packs.clear();
|
||||
this.packs.addAll(packs);
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
boolean areListsEqual(@NonNull List<StickerPackRecord> a, @NonNull List<StickerPackRecord> b) {
|
||||
if (a.size() != b.size()) return false;
|
||||
|
||||
for (int i = 0; i < a.size(); i++) {
|
||||
if (!a.get(i).equals(b.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static class IconProvider implements TabIconProvider {
|
||||
|
||||
private final Context context;
|
||||
private final List<StickerPackRecord> packs;
|
||||
private final boolean allowApngAnimation;
|
||||
|
||||
private IconProvider(@NonNull Context context, List<StickerPackRecord> packs, boolean allowApngAnimation) {
|
||||
this.context = context;
|
||||
this.packs = packs;
|
||||
this.allowApngAnimation = allowApngAnimation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCategoryTabIcon(@NonNull GlideRequests glideRequests, @NonNull ImageView imageView, int index) {
|
||||
if (index == 0) {
|
||||
Drawable icon = ContextCompat.getDrawable(context, R.drawable.ic_recent_20);
|
||||
imageView.setImageDrawable(icon);
|
||||
} else {
|
||||
Uri uri = packs.get(index - 1).getCover().getUri();
|
||||
|
||||
glideRequests.load(new DecryptableStreamUriLoader.DecryptableUri(uri))
|
||||
.set(ApngOptions.ANIMATE, allowApngAnimation)
|
||||
.into(imageView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface StickerEventListener {
|
||||
void onStickerSelected(@NonNull StickerRecord sticker);
|
||||
void onStickerManagementClicked();
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
package org.thoughtcrime.securesms.stickers;
|
||||
|
||||
import android.database.Cursor;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.thoughtcrime.securesms.database.StickerDatabase;
|
||||
import org.thoughtcrime.securesms.database.StickerDatabase.StickerPackRecordReader;
|
||||
import org.thoughtcrime.securesms.database.StickerDatabase.StickerRecordReader;
|
||||
import org.thoughtcrime.securesms.database.model.StickerPackRecord;
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
final class StickerKeyboardRepository {
|
||||
|
||||
private static final int RECENT_LIMIT = 24;
|
||||
|
||||
private final StickerDatabase stickerDatabase;
|
||||
|
||||
StickerKeyboardRepository(@NonNull StickerDatabase stickerDatabase) {
|
||||
this.stickerDatabase = stickerDatabase;
|
||||
}
|
||||
|
||||
void getPackList(@NonNull Callback<PackListResult> callback) {
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
List<StickerPackRecord> packs = new ArrayList<>();
|
||||
|
||||
try (StickerPackRecordReader reader = new StickerPackRecordReader(stickerDatabase.getInstalledStickerPacks())) {
|
||||
StickerPackRecord pack;
|
||||
while ((pack = reader.getNext()) != null) {
|
||||
packs.add(pack);
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasRecents;
|
||||
|
||||
try (Cursor recentsCursor = stickerDatabase.getRecentlyUsedStickers(1)) {
|
||||
hasRecents = recentsCursor != null && recentsCursor.moveToFirst();
|
||||
}
|
||||
|
||||
callback.onComplete(new PackListResult(packs, hasRecents));
|
||||
});
|
||||
}
|
||||
|
||||
void getStickersForPack(@NonNull String packId, @NonNull Callback<List<StickerRecord>> callback) {
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
List<StickerRecord> stickers = new ArrayList<>();
|
||||
|
||||
try (StickerRecordReader reader = new StickerRecordReader(stickerDatabase.getStickersForPack(packId))) {
|
||||
StickerRecord sticker;
|
||||
while ((sticker = reader.getNext()) != null) {
|
||||
stickers.add(sticker);
|
||||
}
|
||||
}
|
||||
|
||||
callback.onComplete(stickers);
|
||||
});
|
||||
}
|
||||
|
||||
void getRecentStickers(@NonNull Callback<List<StickerRecord>> callback) {
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
List<StickerRecord> stickers = new ArrayList<>();
|
||||
|
||||
try (StickerRecordReader reader = new StickerRecordReader(stickerDatabase.getRecentlyUsedStickers(RECENT_LIMIT))) {
|
||||
StickerRecord sticker;
|
||||
while ((sticker = reader.getNext()) != null) {
|
||||
stickers.add(sticker);
|
||||
}
|
||||
}
|
||||
|
||||
callback.onComplete(stickers);
|
||||
});
|
||||
}
|
||||
|
||||
static class PackListResult {
|
||||
|
||||
private final List<StickerPackRecord> packs;
|
||||
private final boolean hasRecents;
|
||||
|
||||
PackListResult(List<StickerPackRecord> packs, boolean hasRecents) {
|
||||
this.packs = packs;
|
||||
this.hasRecents = hasRecents;
|
||||
}
|
||||
|
||||
List<StickerPackRecord> getPacks() {
|
||||
return packs;
|
||||
}
|
||||
|
||||
boolean hasRecents() {
|
||||
return hasRecents;
|
||||
}
|
||||
}
|
||||
|
||||
interface Callback<T> {
|
||||
void onComplete(T result);
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package org.thoughtcrime.securesms.stickers;
|
||||
|
||||
import android.app.Application;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseContentProviders;
|
||||
import org.thoughtcrime.securesms.stickers.StickerKeyboardRepository.PackListResult;
|
||||
import org.thoughtcrime.securesms.util.Throttler;
|
||||
|
||||
final class StickerKeyboardViewModel extends ViewModel {
|
||||
|
||||
private final Application application;
|
||||
private final MutableLiveData<PackListResult> packs;
|
||||
private final Throttler observerThrottler;
|
||||
private final ContentObserver observer;
|
||||
|
||||
private StickerKeyboardViewModel(@NonNull Application application, @NonNull StickerKeyboardRepository repository) {
|
||||
this.application = application;
|
||||
this.packs = new MutableLiveData<>();
|
||||
this.observerThrottler = new Throttler(500);
|
||||
this.observer = new ContentObserver(new Handler(Looper.getMainLooper())) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
observerThrottler.publish(() -> repository.getPackList(packs::postValue));
|
||||
}
|
||||
};
|
||||
|
||||
repository.getPackList(packs::postValue);
|
||||
application.getContentResolver().registerContentObserver(DatabaseContentProviders.StickerPack.CONTENT_URI, true, observer);
|
||||
}
|
||||
|
||||
@NonNull LiveData<PackListResult> getPacks() {
|
||||
return packs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCleared() {
|
||||
application.getContentResolver().unregisterContentObserver(observer);
|
||||
}
|
||||
|
||||
public static final class Factory extends ViewModelProvider.NewInstanceFactory {
|
||||
private final Application application;
|
||||
private final StickerKeyboardRepository repository;
|
||||
|
||||
public Factory(@NonNull Application application, @NonNull StickerKeyboardRepository repository) {
|
||||
this.application = application;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull<T extends ViewModel> T create(@NonNull Class<T> modelClass) {
|
||||
//noinspection ConstantConditions
|
||||
return modelClass.cast(new StickerKeyboardViewModel(application, repository));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user