mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-22 10:46:50 +00:00
Remove dead keyboard code after refresh.
This commit is contained in:
committed by
Greyson Parrelli
parent
7419570f94
commit
c54c6018b2
@@ -31,11 +31,10 @@ import org.signal.core.util.ThreadUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiEventListener;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiToggle;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationStickerSuggestionAdapter;
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardPage;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
@@ -59,7 +58,7 @@ import java.util.concurrent.TimeUnit;
|
||||
public class InputPanel extends LinearLayout
|
||||
implements MicrophoneRecorderView.Listener,
|
||||
KeyboardAwareLinearLayout.OnKeyboardShownListener,
|
||||
EmojiKeyboardProvider.EmojiEventListener,
|
||||
EmojiEventListener,
|
||||
ConversationStickerSuggestionAdapter.EventListener
|
||||
{
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
public interface EmojiEventListener {
|
||||
void onEmojiSelected(String emoji);
|
||||
|
||||
void onKeyEvent(KeyEvent keyEvent);
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.VariationSelectorListener;
|
||||
import org.thoughtcrime.securesms.emoji.EmojiSource;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A provider to select emoji in the {@link org.thoughtcrime.securesms.components.emoji.MediaKeyboard}.
|
||||
*
|
||||
* TODO [alex] -- Are we still using any of this?
|
||||
*/
|
||||
public class EmojiKeyboardProvider implements MediaKeyboardProvider,
|
||||
MediaKeyboardProvider.TabIconProvider,
|
||||
MediaKeyboardProvider.BackspaceObserver,
|
||||
VariationSelectorListener
|
||||
{
|
||||
private static final KeyEvent DELETE_KEY_EVENT = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL);
|
||||
|
||||
// TODO [alex] -- We are using this.
|
||||
public static final String RECENT_STORAGE_KEY = "pref_recent_emoji2";
|
||||
|
||||
private final Context context;
|
||||
private final List<EmojiPageModel> models;
|
||||
private final RecentEmojiPageModel recentModel;
|
||||
private final EmojiPagerAdapter emojiPagerAdapter;
|
||||
private final EmojiEventListener emojiEventListener;
|
||||
|
||||
private Controller controller;
|
||||
private int currentPosition;
|
||||
|
||||
public EmojiKeyboardProvider(@NonNull Context context, @Nullable EmojiEventListener emojiEventListener) {
|
||||
this.context = context;
|
||||
this.emojiEventListener = emojiEventListener;
|
||||
this.models = new LinkedList<>();
|
||||
this.recentModel = new RecentEmojiPageModel(context, RECENT_STORAGE_KEY);
|
||||
this.emojiPagerAdapter = new EmojiPagerAdapter(context, models, new EmojiEventListener() {
|
||||
@Override
|
||||
public void onEmojiSelected(String emoji) {
|
||||
recentModel.onCodePointSelected(emoji);
|
||||
SignalStore.emojiValues().setPreferredVariation(emoji);
|
||||
|
||||
if (emojiEventListener != null) {
|
||||
emojiEventListener.onEmojiSelected(emoji);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyEvent(KeyEvent keyEvent) {
|
||||
if (emojiEventListener != null) {
|
||||
emojiEventListener.onKeyEvent(keyEvent);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
models.add(recentModel);
|
||||
models.addAll(EmojiSource.getLatest().getDisplayPages());
|
||||
|
||||
currentPosition = recentModel.getEmoji().size() > 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPresentation(@NonNull Presenter presenter, boolean isSoloProvider) {
|
||||
presenter.present(this, emojiPagerAdapter, this, this, null, null, currentPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentPosition(int currentPosition) {
|
||||
this.currentPosition = currentPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setController(@Nullable Controller controller) {
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProviderIconView(boolean selected) {
|
||||
if (selected) {
|
||||
return R.layout.emoji_keyboard_icon_selected;
|
||||
} else {
|
||||
return R.layout.emoji_keyboard_icon;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadCategoryTabIcon(@NonNull GlideRequests glideRequests, @NonNull ImageView imageView, int index) {
|
||||
Drawable drawable = ResUtil.getDrawable(context, models.get(index).getIconAttr());
|
||||
imageView.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackspaceClicked() {
|
||||
if (emojiEventListener != null) {
|
||||
emojiEventListener.onKeyEvent(DELETE_KEY_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVariationSelectorStateChanged(boolean open) {
|
||||
if (controller != null) {
|
||||
controller.setViewPagerEnabled(!open);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return obj instanceof EmojiKeyboardProvider;
|
||||
}
|
||||
|
||||
private static class EmojiPagerAdapter extends PagerAdapter {
|
||||
private Context context;
|
||||
private List<EmojiPageModel> pages;
|
||||
private EmojiEventListener emojiSelectionListener;
|
||||
private VariationSelectorListener variationSelectorListener;
|
||||
|
||||
public EmojiPagerAdapter(@NonNull Context context,
|
||||
@NonNull List<EmojiPageModel> pages,
|
||||
@NonNull EmojiEventListener emojiSelectionListener,
|
||||
@NonNull VariationSelectorListener variationSelectorListener)
|
||||
{
|
||||
super();
|
||||
this.context = context;
|
||||
this.pages = pages;
|
||||
this.emojiSelectionListener = emojiSelectionListener;
|
||||
this.variationSelectorListener = variationSelectorListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return pages.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Object instantiateItem(@NonNull ViewGroup container, int position) {
|
||||
EmojiPageView page = new EmojiPageView(context, emojiSelectionListener, variationSelectorListener, true);
|
||||
page.setModel(pages.get(position));
|
||||
container.addView(page);
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(ViewGroup container, int position, Object object) {
|
||||
container.removeView((View)object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimaryItem(ViewGroup container, int position, Object object) {
|
||||
EmojiPageView current = (EmojiPageView) object;
|
||||
current.onSelected();
|
||||
super.setPrimaryItem(container, position, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(View view, Object object) {
|
||||
return view == object;
|
||||
}
|
||||
}
|
||||
|
||||
public interface EmojiEventListener {
|
||||
void onEmojiSelected(String emoji);
|
||||
void onKeyEvent(KeyEvent keyEvent);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ import androidx.recyclerview.widget.LinearSmoothScroller;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider.EmojiEventListener;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.EmojiHeader;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.EmojiNoResultsModel;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.VariationSelectorListener;
|
||||
|
||||
@@ -10,7 +10,6 @@ import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider.EmojiEventListener;
|
||||
import org.thoughtcrime.securesms.util.MappingAdapter;
|
||||
import org.thoughtcrime.securesms.util.MappingModel;
|
||||
import org.thoughtcrime.securesms.util.MappingViewHolder;
|
||||
|
||||
@@ -6,11 +6,9 @@ import android.util.AttributeSet;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.AppCompatImageButton;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardPage;
|
||||
import org.thoughtcrime.securesms.stickers.StickerKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.util.ContextUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider.EmojiEventListener;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.components.emoji;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
@@ -13,7 +12,6 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
@@ -22,13 +20,7 @@ import org.thoughtcrime.securesms.keyboard.KeyboardPage;
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardPagerFragment;
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.search.EmojiSearchFragment;
|
||||
|
||||
import java.security.Key;
|
||||
|
||||
public class MediaKeyboard extends FrameLayout implements InputView,
|
||||
MediaKeyboardProvider.Presenter,
|
||||
MediaKeyboardProvider.Controller,
|
||||
MediaKeyboardBottomTabAdapter.EventListener
|
||||
{
|
||||
public class MediaKeyboard extends FrameLayout implements InputView {
|
||||
|
||||
private static final String TAG = Log.tag(MediaKeyboard.class);
|
||||
private static final String EMOJI_SEARCH = "emoji_search_fragment";
|
||||
@@ -88,60 +80,6 @@ public class MediaKeyboard extends FrameLayout implements InputView,
|
||||
keyboardPagerFragment.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.onKeyboardChanged(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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestDismissal() {
|
||||
hide(true);
|
||||
}
|
||||
|
||||
@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);
|
||||
// }
|
||||
}
|
||||
|
||||
public void onCloseEmojiSearch() {
|
||||
onCloseEmojiSearchInternal(true);
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboardProvider.TabIconProvider;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
|
||||
public class MediaKeyboardBottomTabAdapter extends RecyclerView.Adapter<MediaKeyboardBottomTabAdapter.MediaKeyboardBottomTabViewHolder> {
|
||||
|
||||
private final GlideRequests glideRequests;
|
||||
private final EventListener eventListener;
|
||||
|
||||
private TabIconProvider tabIconProvider;
|
||||
private int activePosition;
|
||||
private int count;
|
||||
|
||||
public MediaKeyboardBottomTabAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) {
|
||||
this.glideRequests = glideRequests;
|
||||
this.eventListener = eventListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull MediaKeyboardBottomTabViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
|
||||
return new MediaKeyboardBottomTabViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.media_keyboard_bottom_tab_item, viewGroup, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull MediaKeyboardBottomTabViewHolder viewHolder, int i) {
|
||||
viewHolder.bind(glideRequests, eventListener, tabIconProvider, i, i == activePosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewRecycled(@NonNull MediaKeyboardBottomTabViewHolder holder) {
|
||||
holder.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setTabIconProvider(@NonNull TabIconProvider iconProvider, int count) {
|
||||
this.tabIconProvider = iconProvider;
|
||||
this.count = count;
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setActivePosition(int position) {
|
||||
this.activePosition = position;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
static class MediaKeyboardBottomTabViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private final ImageView image;
|
||||
private final View imageSelected;
|
||||
|
||||
public MediaKeyboardBottomTabViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
this.image = itemView.findViewById(R.id.category_icon);
|
||||
this.imageSelected = itemView.findViewById(R.id.category_icon_selected);
|
||||
}
|
||||
|
||||
void bind(@NonNull GlideRequests glideRequests,
|
||||
@NonNull EventListener eventListener,
|
||||
@NonNull TabIconProvider tabIconProvider,
|
||||
int index,
|
||||
boolean selected)
|
||||
{
|
||||
tabIconProvider.loadCategoryTabIcon(glideRequests, image, index);
|
||||
image.setAlpha(selected ? 1 : 0.5f);
|
||||
imageSelected.setSelected(selected);
|
||||
|
||||
itemView.setOnClickListener(v -> eventListener.onTabSelected(index));
|
||||
}
|
||||
|
||||
void recycle() {
|
||||
itemView.setOnClickListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
public interface EventListener {
|
||||
void onTabSelected(int index);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package org.thoughtcrime.securesms.components.emoji;
|
||||
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
|
||||
public interface MediaKeyboardProvider {
|
||||
@LayoutRes int getProviderIconView(boolean selected);
|
||||
/** @return True if the click was handled with provider-specific logic, otherwise false */
|
||||
void requestPresentation(@NonNull Presenter presenter, boolean isSoloProvider);
|
||||
void setController(@Nullable Controller controller);
|
||||
void setCurrentPosition(int currentPosition);
|
||||
|
||||
interface BackspaceObserver {
|
||||
void onBackspaceClicked();
|
||||
}
|
||||
|
||||
interface AddObserver {
|
||||
void onAddClicked();
|
||||
}
|
||||
|
||||
interface SearchObserver {
|
||||
void onSearchOpened();
|
||||
void onSearchClosed();
|
||||
void onSearchChanged(@NonNull String query);
|
||||
}
|
||||
|
||||
interface Controller {
|
||||
void setViewPagerEnabled(boolean enabled);
|
||||
}
|
||||
|
||||
interface Presenter {
|
||||
void present(@NonNull MediaKeyboardProvider provider,
|
||||
@NonNull PagerAdapter pagerAdapter,
|
||||
@NonNull TabIconProvider iconProvider,
|
||||
@Nullable BackspaceObserver backspaceObserver,
|
||||
@Nullable AddObserver addObserver,
|
||||
@Nullable SearchObserver searchObserver,
|
||||
int startingIndex);
|
||||
int getCurrentPosition();
|
||||
void requestDismissal();
|
||||
boolean isVisible();
|
||||
}
|
||||
|
||||
interface TabIconProvider {
|
||||
void loadCategoryTabIcon(@NonNull GlideRequests glideRequests, @NonNull ImageView imageView, int index);
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ import org.thoughtcrime.securesms.components.MaskView;
|
||||
import org.thoughtcrime.securesms.components.SendButton;
|
||||
import org.thoughtcrime.securesms.components.TooltipPopup;
|
||||
import org.thoughtcrime.securesms.components.TypingStatusSender;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiEventListener;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiStrings;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard;
|
||||
import org.thoughtcrime.securesms.components.identity.UnverifiedBannerView;
|
||||
@@ -244,7 +244,7 @@ import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingEndSessionMessage;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
import org.thoughtcrime.securesms.stickers.StickerKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.stickers.StickerEventListener;
|
||||
import org.thoughtcrime.securesms.stickers.StickerLocator;
|
||||
import org.thoughtcrime.securesms.stickers.StickerManagementActivity;
|
||||
import org.thoughtcrime.securesms.stickers.StickerPackInstallEvent;
|
||||
@@ -318,14 +318,14 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
||||
InputPanel.MediaListener,
|
||||
ComposeText.CursorPositionChangedListener,
|
||||
ConversationSearchBottomBar.EventListener,
|
||||
StickerKeyboardProvider.StickerEventListener,
|
||||
StickerEventListener,
|
||||
AttachmentKeyboard.Callback,
|
||||
ConversationReactionOverlay.OnReactionSelectedListener,
|
||||
ReactWithAnyEmojiBottomSheetDialogFragment.Callback,
|
||||
SafetyNumberChangeDialog.Callback,
|
||||
ReactionsBottomSheetDialogFragment.Callback,
|
||||
MediaKeyboard.MediaKeyboardListener,
|
||||
EmojiKeyboardProvider.EmojiEventListener,
|
||||
EmojiEventListener,
|
||||
GifKeyboardPageFragment.Host,
|
||||
EmojiKeyboardPageFragment.Callback,
|
||||
EmojiSearchFragment.Callback
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
package org.thoughtcrime.securesms.giph.mp4;
|
||||
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
|
||||
/**
|
||||
* MediaKeyboardProvider for MP4 Gifs
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public final class GiphyMp4MediaKeyboardProvider implements MediaKeyboardProvider {
|
||||
|
||||
private final GiphyMp4MediaKeyboardPagerAdapter pagerAdapter;
|
||||
|
||||
private Controller controller;
|
||||
|
||||
public GiphyMp4MediaKeyboardProvider(@NonNull FragmentActivity fragmentActivity, boolean isForMms) {
|
||||
pagerAdapter = new GiphyMp4MediaKeyboardPagerAdapter(fragmentActivity.getSupportFragmentManager(), isForMms);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getProviderIconView(boolean selected) {
|
||||
if (selected) {
|
||||
return R.layout.giphy_mp4_keyboard_icon_selected;
|
||||
} else {
|
||||
return R.layout.giphy_mp4_keyboard_icon;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPresentation(@NonNull Presenter presenter, boolean isSoloProvider) {
|
||||
presenter.present(this, pagerAdapter, new GiphyMp4MediaKeyboardTabIconProvider(), null, null, null, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setController(@Nullable Controller controller) {
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentPosition(int currentPosition) {
|
||||
// ignored.
|
||||
}
|
||||
|
||||
private static final class GiphyMp4MediaKeyboardPagerAdapter extends FragmentStatePagerAdapter {
|
||||
|
||||
private final boolean isForMms;
|
||||
|
||||
public GiphyMp4MediaKeyboardPagerAdapter(@NonNull FragmentManager fm, boolean isForMms) {
|
||||
super(fm, FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
||||
this.isForMms = isForMms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Fragment getItem(int position) {
|
||||
return GiphyMp4Fragment.create(isForMms);
|
||||
}
|
||||
|
||||
@Override public int getCount() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class GiphyMp4MediaKeyboardTabIconProvider implements TabIconProvider {
|
||||
@Override public void loadCategoryTabIcon(@NonNull GlideRequests glideRequests, @NonNull ImageView imageView, int index) { }
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE
|
||||
import com.google.android.material.appbar.AppBarLayout
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiEventListener
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageView
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.EmojiHeader
|
||||
@@ -22,14 +22,14 @@ import java.util.Optional
|
||||
|
||||
private val DELETE_KEY_EVENT: KeyEvent = KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)
|
||||
|
||||
class EmojiKeyboardPageFragment : Fragment(R.layout.keyboard_pager_emoji_page_fragment), EmojiKeyboardProvider.EmojiEventListener, EmojiPageViewGridAdapter.VariationSelectorListener {
|
||||
class EmojiKeyboardPageFragment : Fragment(R.layout.keyboard_pager_emoji_page_fragment), EmojiEventListener, EmojiPageViewGridAdapter.VariationSelectorListener {
|
||||
|
||||
private lateinit var viewModel: EmojiKeyboardPageViewModel
|
||||
private lateinit var emojiPageView: EmojiPageView
|
||||
private lateinit var searchView: View
|
||||
private lateinit var emojiCategoriesRecycler: RecyclerView
|
||||
private lateinit var backspaceView: View
|
||||
private lateinit var eventListener: EmojiKeyboardProvider.EmojiEventListener
|
||||
private lateinit var eventListener: EmojiEventListener
|
||||
private lateinit var callback: Callback
|
||||
private lateinit var categoriesAdapter: EmojiKeyboardPageCategoriesAdapter
|
||||
private lateinit var searchBar: KeyboardPageSearchView
|
||||
|
||||
@@ -2,15 +2,15 @@ package org.thoughtcrime.securesms.keyboard.emoji
|
||||
|
||||
import android.content.Context
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageModel
|
||||
import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel
|
||||
import org.thoughtcrime.securesms.emoji.EmojiSource.Companion.latest
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import java.util.function.Consumer
|
||||
|
||||
class EmojiKeyboardPageRepository(context: Context) {
|
||||
|
||||
private val recentEmojiPageModel: RecentEmojiPageModel = RecentEmojiPageModel(context, EmojiKeyboardProvider.RECENT_STORAGE_KEY)
|
||||
private val recentEmojiPageModel: RecentEmojiPageModel = RecentEmojiPageModel(context, TextSecurePreferences.RECENT_STORAGE_KEY)
|
||||
|
||||
fun getEmoji(consumer: Consumer<List<EmojiPageModel>>) {
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
|
||||
@@ -6,7 +6,6 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageModel
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.EmojiHeader
|
||||
@@ -19,6 +18,7 @@ import org.thoughtcrime.securesms.keyboard.emoji.EmojiKeyboardPageCategoryMappin
|
||||
import org.thoughtcrime.securesms.util.DefaultValueLiveData
|
||||
import org.thoughtcrime.securesms.util.MappingModel
|
||||
import org.thoughtcrime.securesms.util.MappingModelList
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil
|
||||
|
||||
class EmojiKeyboardPageViewModel(repository: EmojiKeyboardPageRepository) : ViewModel() {
|
||||
@@ -70,12 +70,12 @@ class EmojiKeyboardPageViewModel(repository: EmojiKeyboardPageRepository) : View
|
||||
}
|
||||
|
||||
fun addToRecents(emoji: String) {
|
||||
RecentEmojiPageModel(ApplicationDependencies.getApplication(), EmojiKeyboardProvider.RECENT_STORAGE_KEY).onCodePointSelected(emoji)
|
||||
RecentEmojiPageModel(ApplicationDependencies.getApplication(), TextSecurePreferences.RECENT_STORAGE_KEY).onCodePointSelected(emoji)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getStartingTab(): String {
|
||||
return if (RecentEmojiPageModel.hasRecents(ApplicationDependencies.getApplication(), EmojiKeyboardProvider.RECENT_STORAGE_KEY)) {
|
||||
return if (RecentEmojiPageModel.hasRecents(ApplicationDependencies.getApplication(), TextSecurePreferences.RECENT_STORAGE_KEY)) {
|
||||
RecentEmojiPageModel.KEY
|
||||
} else {
|
||||
EmojiCategory.PEOPLE.key
|
||||
|
||||
@@ -11,7 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiEventListener
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageView
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView
|
||||
@@ -36,7 +36,7 @@ class EmojiSearchFragment : Fragment(R.layout.emoji_search_fragment), EmojiPageV
|
||||
viewModel = ViewModelProviders.of(this, factory)[EmojiSearchViewModel::class.java]
|
||||
|
||||
val keyboardAwareLinearLayout: KeyboardAwareLinearLayout = view.findViewById(R.id.kb_aware_layout)
|
||||
val eventListener: EmojiKeyboardProvider.EmojiEventListener = requireNotNull(findListener())
|
||||
val eventListener: EmojiEventListener = requireNotNull(findListener())
|
||||
val searchBar: KeyboardPageSearchView = view.findViewById(R.id.emoji_search_view)
|
||||
val resultsContainer: FrameLayout = view.findViewById(R.id.emoji_search_results_container)
|
||||
val noResults: TextView = view.findViewById(R.id.emoji_search_empty)
|
||||
|
||||
@@ -4,12 +4,12 @@ import android.content.Context
|
||||
import android.net.Uri
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.thoughtcrime.securesms.components.emoji.Emoji
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageModel
|
||||
import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.database.EmojiSearchDatabase
|
||||
import org.thoughtcrime.securesms.emoji.EmojiSource
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import java.util.function.Consumer
|
||||
|
||||
private const val MINIMUM_QUERY_THRESHOLD = 1
|
||||
@@ -21,7 +21,7 @@ class EmojiSearchRepository(private val context: Context) {
|
||||
|
||||
fun submitQuery(query: String, includeRecents: Boolean, limit: Int = EMOJI_SEARCH_LIMIT, consumer: Consumer<EmojiPageModel>) {
|
||||
if (query.length < MINIMUM_QUERY_THRESHOLD && includeRecents) {
|
||||
consumer.accept(RecentEmojiPageModel(context, EmojiKeyboardProvider.RECENT_STORAGE_KEY))
|
||||
consumer.accept(RecentEmojiPageModel(context, TextSecurePreferences.RECENT_STORAGE_KEY))
|
||||
} else {
|
||||
SignalExecutors.SERIAL.execute {
|
||||
val emoji: List<String> = emojiSearchDatabase.query(query, limit)
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.thoughtcrime.securesms.util.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.MappingModel
|
||||
import org.thoughtcrime.securesms.util.MappingViewHolder
|
||||
|
||||
class StickerPackListAdapter(private val glideRequests: GlideRequests, private val allowApngAnimation: Boolean, private val onTabSelected: (StickerPack) -> Unit) : MappingAdapter() {
|
||||
class KeyboardStickerPackListAdapter(private val glideRequests: GlideRequests, private val allowApngAnimation: Boolean, private val onTabSelected: (StickerPack) -> Unit) : MappingAdapter() {
|
||||
|
||||
init {
|
||||
registerFactory(StickerPack::class.java, LayoutFactory(::StickerPackViewHolder, R.layout.keyboard_pager_category_icon))
|
||||
@@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView
|
||||
import org.thoughtcrime.securesms.keyboard.findListener
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.stickers.StickerKeyboardProvider.StickerEventListener
|
||||
import org.thoughtcrime.securesms.stickers.StickerEventListener
|
||||
import org.thoughtcrime.securesms.stickers.StickerRolloverTouchListener
|
||||
import org.thoughtcrime.securesms.stickers.StickerRolloverTouchListener.RolloverStickerRetriever
|
||||
import org.thoughtcrime.securesms.util.DeviceProperties
|
||||
@@ -36,12 +36,12 @@ class StickerKeyboardPageFragment :
|
||||
View.OnLayoutChangeListener {
|
||||
|
||||
private lateinit var stickerList: RecyclerView
|
||||
private lateinit var keyboardStickerListAdapter: KeyboardStickerListAdapter
|
||||
private lateinit var stickerListAdapter: KeyboardStickerListAdapter
|
||||
private lateinit var layoutManager: GridLayoutManager
|
||||
private lateinit var listTouchListener: StickerRolloverTouchListener
|
||||
private lateinit var stickerPacksRecycler: RecyclerView
|
||||
private lateinit var appBarLayout: AppBarLayout
|
||||
private lateinit var stickerPacksAdapter: StickerPackListAdapter
|
||||
private lateinit var stickerPacksAdapter: KeyboardStickerPackListAdapter
|
||||
|
||||
private lateinit var viewModel: StickerKeyboardPageViewModel
|
||||
|
||||
@@ -53,11 +53,11 @@ class StickerKeyboardPageFragment :
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val glideRequests = GlideApp.with(this)
|
||||
keyboardStickerListAdapter = KeyboardStickerListAdapter(glideRequests, this, DeviceProperties.shouldAllowApngStickerAnimation(requireContext()))
|
||||
stickerListAdapter = KeyboardStickerListAdapter(glideRequests, this, DeviceProperties.shouldAllowApngStickerAnimation(requireContext()))
|
||||
layoutManager = GridLayoutManager(requireContext(), 2).apply {
|
||||
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
val model: Optional<MappingModel<*>> = keyboardStickerListAdapter.getModel(position)
|
||||
val model: Optional<MappingModel<*>> = stickerListAdapter.getModel(position)
|
||||
if (model.isPresent && model.get() is KeyboardStickerListAdapter.StickerHeader) {
|
||||
return spanCount
|
||||
}
|
||||
@@ -69,13 +69,13 @@ class StickerKeyboardPageFragment :
|
||||
|
||||
stickerList = view.findViewById(R.id.sticker_keyboard_list)
|
||||
stickerList.layoutManager = layoutManager
|
||||
stickerList.adapter = keyboardStickerListAdapter
|
||||
stickerList.adapter = stickerListAdapter
|
||||
stickerList.addOnItemTouchListener(listTouchListener)
|
||||
stickerList.addOnScrollListener(packIdSelectionOnScroll)
|
||||
|
||||
stickerPacksRecycler = view.findViewById(R.id.sticker_packs_recycler)
|
||||
|
||||
stickerPacksAdapter = StickerPackListAdapter(glideRequests, DeviceProperties.shouldAllowApngStickerAnimation(requireContext()), this::onTabSelected)
|
||||
stickerPacksAdapter = KeyboardStickerPackListAdapter(glideRequests, DeviceProperties.shouldAllowApngStickerAnimation(requireContext()), this::onTabSelected)
|
||||
stickerPacksRecycler.adapter = stickerPacksAdapter
|
||||
|
||||
appBarLayout = view.findViewById(R.id.sticker_keyboard_search_appbar)
|
||||
@@ -106,21 +106,21 @@ class StickerKeyboardPageFragment :
|
||||
viewModel = ViewModelProviders.of(requireActivity(), StickerKeyboardPageViewModel.Factory(requireContext()))
|
||||
.get(StickerKeyboardPageViewModel::class.java)
|
||||
|
||||
viewModel.stickers.observe(viewLifecycleOwner, keyboardStickerListAdapter::submitList)
|
||||
viewModel.stickers.observe(viewLifecycleOwner, stickerListAdapter::submitList)
|
||||
viewModel.packs.observe(viewLifecycleOwner, stickerPacksAdapter::submitList)
|
||||
viewModel.getSelectedPack().observe(viewLifecycleOwner, this::updateCategoryTab)
|
||||
|
||||
viewModel.refreshStickers()
|
||||
}
|
||||
|
||||
private fun onTabSelected(stickerPack: StickerPackListAdapter.StickerPack) {
|
||||
private fun onTabSelected(stickerPack: KeyboardStickerPackListAdapter.StickerPack) {
|
||||
scrollTo(stickerPack.packRecord.packId)
|
||||
viewModel.selectPack(stickerPack.packRecord.packId)
|
||||
}
|
||||
|
||||
private fun updateCategoryTab(packId: String) {
|
||||
stickerPacksRecycler.post {
|
||||
val index: Int = stickerPacksAdapter.indexOfFirst(StickerPackListAdapter.StickerPack::class.java) { it.packRecord.packId == packId }
|
||||
val index: Int = stickerPacksAdapter.indexOfFirst(KeyboardStickerPackListAdapter.StickerPack::class.java) { it.packRecord.packId == packId }
|
||||
|
||||
if (index != -1) {
|
||||
stickerPacksRecycler.smoothScrollToPosition(index)
|
||||
@@ -129,7 +129,7 @@ class StickerKeyboardPageFragment :
|
||||
}
|
||||
|
||||
private fun scrollTo(packId: String) {
|
||||
val index = keyboardStickerListAdapter.indexOfFirst(KeyboardStickerListAdapter.StickerHeader::class.java) { it.packId == packId }
|
||||
val index = stickerListAdapter.indexOfFirst(KeyboardStickerListAdapter.StickerHeader::class.java) { it.packId == packId }
|
||||
if (index != -1) {
|
||||
appBarLayout.setExpanded(false, true)
|
||||
packIdSelectionOnScroll.startAutoScrolling()
|
||||
@@ -163,7 +163,7 @@ class StickerKeyboardPageFragment :
|
||||
|
||||
override fun getStickerDataFromView(view: View): Pair<Any, String>? {
|
||||
val position: Int = stickerList.getChildAdapterPosition(view)
|
||||
val model: Optional<MappingModel<*>> = keyboardStickerListAdapter.getModel(position)
|
||||
val model: Optional<MappingModel<*>> = stickerListAdapter.getModel(position)
|
||||
if (model.isPresent && model.get() is KeyboardStickerListAdapter.Sticker) {
|
||||
val sticker = model.get() as KeyboardStickerListAdapter.Sticker
|
||||
return Pair(sticker.uri, sticker.stickerRecord.emoji)
|
||||
@@ -216,7 +216,7 @@ class StickerKeyboardPageFragment :
|
||||
|
||||
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
||||
val index = layoutManager.findFirstCompletelyVisibleItemPosition()
|
||||
val item: Optional<MappingModel<*>> = keyboardStickerListAdapter.getModel(index)
|
||||
val item: Optional<MappingModel<*>> = stickerListAdapter.getModel(index)
|
||||
if (item.isPresent && item.get() is KeyboardStickerListAdapter.HasPackId) {
|
||||
viewModel.selectPack((item.get() as KeyboardStickerListAdapter.HasPackId).packId)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.keyboard.sticker.StickerPackListAdapter.StickerPack
|
||||
import org.thoughtcrime.securesms.keyboard.sticker.KeyboardStickerPackListAdapter.StickerPack
|
||||
import org.thoughtcrime.securesms.util.MappingModelList
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.thoughtcrime.securesms.keyboard.sticker
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Point
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@@ -13,25 +11,23 @@ import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord
|
||||
import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView
|
||||
import org.thoughtcrime.securesms.keyboard.findListener
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.stickers.StickerKeyboardPageAdapter
|
||||
import org.thoughtcrime.securesms.stickers.StickerKeyboardProvider
|
||||
import org.thoughtcrime.securesms.stickers.StickerEventListener
|
||||
import org.thoughtcrime.securesms.util.DeviceProperties
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
|
||||
/**
|
||||
* Search dialog for finding stickers.
|
||||
*/
|
||||
class StickerSearchDialogFragment : DialogFragment(), StickerKeyboardPageAdapter.EventListener {
|
||||
class StickerSearchDialogFragment : DialogFragment(), KeyboardStickerListAdapter.EventListener, View.OnLayoutChangeListener {
|
||||
|
||||
private lateinit var search: KeyboardPageSearchView
|
||||
private lateinit var list: RecyclerView
|
||||
private lateinit var noResults: View
|
||||
|
||||
private lateinit var adapter: StickerKeyboardPageAdapter
|
||||
private lateinit var adapter: KeyboardStickerListAdapter
|
||||
private lateinit var layoutManager: GridLayoutManager
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -49,19 +45,17 @@ class StickerSearchDialogFragment : DialogFragment(), StickerKeyboardPageAdapter
|
||||
list = view.findViewById(R.id.sticker_search_list)
|
||||
noResults = view.findViewById(R.id.sticker_search_no_results)
|
||||
|
||||
adapter = StickerKeyboardPageAdapter(GlideApp.with(this), this, DeviceProperties.shouldAllowApngStickerAnimation(requireContext()))
|
||||
adapter = KeyboardStickerListAdapter(GlideApp.with(this), this, DeviceProperties.shouldAllowApngStickerAnimation(requireContext()))
|
||||
layoutManager = GridLayoutManager(requireContext(), 2)
|
||||
|
||||
list.layoutManager = layoutManager
|
||||
list.adapter = adapter
|
||||
|
||||
onScreenWidthChanged(getScreenWidth())
|
||||
|
||||
val viewModel: StickerSearchViewModel = ViewModelProviders.of(this, StickerSearchViewModel.Factory(requireContext())).get(StickerSearchViewModel::class.java)
|
||||
|
||||
viewModel.searchResults.observe(viewLifecycleOwner) { stickerRecords ->
|
||||
adapter.setStickers(stickerRecords, calculateStickerSize(getScreenWidth()))
|
||||
noResults.visibility = if (stickerRecords.isEmpty()) View.VISIBLE else View.GONE
|
||||
viewModel.searchResults.observe(viewLifecycleOwner) { stickers ->
|
||||
adapter.submitList(stickers)
|
||||
noResults.visibility = if (stickers.isEmpty()) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
search.enableBackNavigation()
|
||||
@@ -77,22 +71,12 @@ class StickerSearchDialogFragment : DialogFragment(), StickerKeyboardPageAdapter
|
||||
}
|
||||
|
||||
search.requestFocus()
|
||||
|
||||
view.addOnLayoutChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
onScreenWidthChanged(getScreenWidth())
|
||||
}
|
||||
|
||||
private fun onScreenWidthChanged(@Px newWidth: Int) {
|
||||
layoutManager.spanCount = calculateColumnCount(newWidth)
|
||||
adapter.setStickerSize(calculateStickerSize(newWidth))
|
||||
}
|
||||
|
||||
private fun getScreenWidth(): Int {
|
||||
val size = Point()
|
||||
requireActivity().windowManager.defaultDisplay.getSize(size)
|
||||
return size.x
|
||||
override fun onLayoutChange(v: View?, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {
|
||||
layoutManager.spanCount = calculateColumnCount(view?.width ?: 0)
|
||||
}
|
||||
|
||||
private fun calculateColumnCount(@Px screenWidth: Int): Int {
|
||||
@@ -101,23 +85,17 @@ class StickerSearchDialogFragment : DialogFragment(), StickerKeyboardPageAdapter
|
||||
return ((screenWidth - modifier) / divisor).toInt()
|
||||
}
|
||||
|
||||
private fun calculateStickerSize(@Px screenWidth: Int): Int {
|
||||
val multiplier = resources.getDimensionPixelOffset(R.dimen.sticker_page_item_multiplier).toFloat()
|
||||
val columnCount = calculateColumnCount(screenWidth)
|
||||
return ((screenWidth - (columnCount + 1) * multiplier) / columnCount).toInt()
|
||||
override fun onStickerClicked(sticker: KeyboardStickerListAdapter.Sticker) {
|
||||
ViewUtil.hideKeyboard(requireContext(), requireView())
|
||||
findListener<StickerEventListener>()?.onStickerSelected(sticker.stickerRecord)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
override fun onStickerLongClicked(sticker: KeyboardStickerListAdapter.Sticker) = Unit
|
||||
|
||||
companion object {
|
||||
fun show(fragmentManager: FragmentManager) {
|
||||
StickerSearchDialogFragment().show(fragmentManager, "TAG")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStickerClicked(sticker: StickerRecord) {
|
||||
ViewUtil.hideKeyboard(requireContext(), requireView())
|
||||
findListener<StickerKeyboardProvider.StickerEventListener>()?.onStickerSelected(sticker)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
override fun onStickerLongClicked(targetView: View) = Unit
|
||||
}
|
||||
|
||||
@@ -5,14 +5,16 @@ import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil
|
||||
|
||||
class StickerSearchViewModel(private val searchRepository: StickerSearchRepository) : ViewModel() {
|
||||
|
||||
private val searchQuery: MutableLiveData<String> = MutableLiveData("")
|
||||
|
||||
val searchResults: LiveData<List<StickerRecord>> = LiveDataUtil.mapAsync(searchQuery) { q -> searchRepository.search(q) }
|
||||
val searchResults: LiveData<List<KeyboardStickerListAdapter.Sticker>> = LiveDataUtil.mapAsync(searchQuery) { q ->
|
||||
searchRepository.search(q)
|
||||
.map { KeyboardStickerListAdapter.Sticker(it.packId, it) }
|
||||
}
|
||||
|
||||
fun query(query: String) {
|
||||
searchQuery.postValue(query)
|
||||
|
||||
@@ -46,7 +46,7 @@ import org.thoughtcrime.securesms.components.InputAwareLayout;
|
||||
import org.thoughtcrime.securesms.components.SendButton;
|
||||
import org.thoughtcrime.securesms.components.TooltipPopup;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiEventListener;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiToggle;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard;
|
||||
import org.thoughtcrime.securesms.components.mention.MentionAnnotation;
|
||||
@@ -104,18 +104,18 @@ import java.util.Set;
|
||||
* It will return the {@link Media} that the user decided to send.
|
||||
*/
|
||||
public class MediaSendActivity extends PassphraseRequiredActivity implements MediaPickerFolderFragment.Controller,
|
||||
MediaPickerItemFragment.Controller,
|
||||
ImageEditorFragment.Controller,
|
||||
MediaSendVideoFragment.Controller,
|
||||
CameraFragment.Controller,
|
||||
CameraContactSelectionFragment.Controller,
|
||||
ViewTreeObserver.OnGlobalLayoutListener,
|
||||
MediaRailAdapter.RailItemListener,
|
||||
InputAwareLayout.OnKeyboardShownListener,
|
||||
InputAwareLayout.OnKeyboardHiddenListener,
|
||||
EmojiKeyboardProvider.EmojiEventListener,
|
||||
EmojiKeyboardPageFragment.Callback,
|
||||
EmojiSearchFragment.Callback
|
||||
MediaPickerItemFragment.Controller,
|
||||
ImageEditorFragment.Controller,
|
||||
MediaSendVideoFragment.Controller,
|
||||
CameraFragment.Controller,
|
||||
CameraContactSelectionFragment.Controller,
|
||||
ViewTreeObserver.OnGlobalLayoutListener,
|
||||
MediaRailAdapter.RailItemListener,
|
||||
InputAwareLayout.OnKeyboardShownListener,
|
||||
InputAwareLayout.OnKeyboardHiddenListener,
|
||||
EmojiEventListener,
|
||||
EmojiKeyboardPageFragment.Callback,
|
||||
EmojiSearchFragment.Callback
|
||||
{
|
||||
private static final String TAG = Log.tag(MediaSendActivity.class);
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import com.google.android.material.shape.MaterialShapeDrawable;
|
||||
import com.google.android.material.shape.ShapeAppearanceModel;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiEventListener;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageView;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
@@ -42,18 +42,19 @@ import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView;
|
||||
import org.thoughtcrime.securesms.reactions.ReactionsLoader;
|
||||
import org.thoughtcrime.securesms.reactions.edit.EditReactionsActivity;
|
||||
import org.thoughtcrime.securesms.util.MappingModel;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
|
||||
|
||||
public final class ReactWithAnyEmojiBottomSheetDialogFragment extends BottomSheetDialogFragment implements EmojiKeyboardProvider.EmojiEventListener,
|
||||
public final class ReactWithAnyEmojiBottomSheetDialogFragment extends BottomSheetDialogFragment implements EmojiEventListener,
|
||||
EmojiPageViewGridAdapter.VariationSelectorListener
|
||||
{
|
||||
|
||||
private static final String REACTION_STORAGE_KEY = "reactions_recent_emoji";
|
||||
private static final String ABOUT_STORAGE_KEY = EmojiKeyboardProvider.RECENT_STORAGE_KEY;
|
||||
private static final String ABOUT_STORAGE_KEY = TextSecurePreferences.RECENT_STORAGE_KEY;
|
||||
|
||||
private static final String ARG_MESSAGE_ID = "arg_message_id";
|
||||
private static final String ARG_IS_MMS = "arg_is_mms";
|
||||
|
||||
@@ -10,7 +10,6 @@ import androidx.lifecycle.Transformations;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageModel;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter;
|
||||
import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel;
|
||||
@@ -21,6 +20,7 @@ import org.thoughtcrime.securesms.keyboard.emoji.search.EmojiSearchRepository;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.reactions.ReactionsLoader;
|
||||
import org.thoughtcrime.securesms.util.MappingModelList;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.livedata.LiveDataUtil;
|
||||
|
||||
import java.util.List;
|
||||
@@ -133,7 +133,7 @@ public final class ReactWithAnyEmojiViewModel extends ViewModel {
|
||||
}
|
||||
|
||||
private static @NonNull String getStartingKey() {
|
||||
if (RecentEmojiPageModel.hasRecents(ApplicationDependencies.getApplication(), EmojiKeyboardProvider.RECENT_STORAGE_KEY)) {
|
||||
if (RecentEmojiPageModel.hasRecents(ApplicationDependencies.getApplication(), TextSecurePreferences.RECENT_STORAGE_KEY)) {
|
||||
return RecentEmojiPageModel.KEY;
|
||||
} else {
|
||||
return EmojiCategory.PEOPLE.getKey();
|
||||
|
||||
@@ -18,11 +18,11 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardPage;
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardPagerViewModel;
|
||||
import org.thoughtcrime.securesms.stickers.StickerKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.stickers.StickerEventListener;
|
||||
import org.thoughtcrime.securesms.stickers.StickerManagementActivity;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public final class ImageEditorStickerSelectActivity extends AppCompatActivity implements StickerKeyboardProvider.StickerEventListener, MediaKeyboard.MediaKeyboardListener {
|
||||
public final class ImageEditorStickerSelectActivity extends AppCompatActivity implements StickerEventListener, MediaKeyboard.MediaKeyboardListener {
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(@NonNull Context newBase) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -197,6 +197,7 @@ public class TextSecurePreferences {
|
||||
private static final String SEEN_STICKER_INTRO_TOOLTIP = "pref_seen_sticker_intro_tooltip";
|
||||
|
||||
private static final String MEDIA_KEYBOARD_MODE = "pref_media_keyboard_mode";
|
||||
public static final String RECENT_STORAGE_KEY = "pref_recent_emoji2";
|
||||
|
||||
private static final String VIEW_ONCE_TOOLTIP_SEEN = "pref_revealable_message_tooltip_seen";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user