Remove dead keyboard code after refresh.

This commit is contained in:
Cody Henthorne
2021-06-29 12:34:49 -04:00
committed by Greyson Parrelli
parent 7419570f94
commit c54c6018b2
45 changed files with 97 additions and 1545 deletions

View File

@@ -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();
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}
}