Stickers in image editor.

This commit is contained in:
Alan Evans 2019-08-30 17:45:35 -04:00 committed by GitHub
parent 15b650382e
commit 8d561ead21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 419 additions and 117 deletions

View file

@ -429,6 +429,10 @@
android:theme="@style/TextSecure.DarkTheme" android:theme="@style/TextSecure.DarkTheme"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".scribbles.NewStickerSelectActivity"
android:theme="@style/TextSecure.DarkTheme"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name="com.theartofdev.edmodo.cropper.CropImageActivity" <activity android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
android:theme="@style/TextSecure.DarkTheme"/> android:theme="@style/TextSecure.DarkTheme"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View file

@ -75,13 +75,21 @@
android:src="@drawable/ic_brush_highlight_32" /> android:src="@drawable/ic_brush_highlight_32" />
<ImageView <ImageView
android:id="@+id/scribble_sticker_button" android:id="@+id/old_scribble_sticker_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:padding="8dp" android:padding="8dp"
android:src="@drawable/ic_emoji_32" /> android:src="@drawable/ic_emoji_32" />
<ImageView
android:id="@+id/scribble_sticker_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="8dp"
android:src="@drawable/ic_sticker_32" />
<ImageView <ImageView
android:id="@+id/scribble_crop_button" android:id="@+id/scribble_crop_button"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -35,7 +35,7 @@
android:orientation="horizontal" android:orientation="horizontal"
app:layout_constraintEnd_toStartOf="@id/media_keyboard_backspace" app:layout_constraintEnd_toStartOf="@id/media_keyboard_backspace"
app:layout_constraintStart_toEndOf="@id/media_keyboard_search" app:layout_constraintStart_toEndOf="@id/media_keyboard_search"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toBottomOf="@id/media_keyboard_tabs_top" />
<org.thoughtcrime.securesms.components.RepeatableImageKey <org.thoughtcrime.securesms.components.RepeatableImageKey
android:id="@+id/media_keyboard_backspace" android:id="@+id/media_keyboard_backspace"
@ -66,14 +66,27 @@
app:layout_constraintBottom_toBottomOf="@id/media_keyboard_tabs" app:layout_constraintBottom_toBottomOf="@id/media_keyboard_tabs"
app:layout_constraintTop_toTopOf="@+id/media_keyboard_tabs" /> app:layout_constraintTop_toTopOf="@+id/media_keyboard_tabs" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/media_keyboard_tabs_top"
android:layout_width="0dp"
android:layout_height="40dp"
android:visibility="gone"
app:layout_constraintEnd_toStartOf="@id/media_keyboard_add"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_height="40dp"
tools:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/media_keyboard_tabs" android:id="@+id/media_keyboard_tabs"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="40dp" android:layout_height="40dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/media_keyboard_add" app:layout_constraintEnd_toStartOf="@id/media_keyboard_add"
tools:layout_height="40dp"/> app:layout_constraintStart_toStartOf="parent"
tools:layout_height="40dp"
tools:visibility="visible" />
<org.thoughtcrime.securesms.components.RepeatableImageKey <org.thoughtcrime.securesms.components.RepeatableImageKey
android:id="@+id/media_keyboard_backspace_backup" android:id="@+id/media_keyboard_backspace_backup"

View file

@ -1,23 +1,33 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:orientation="vertical"
android:background="?selectableItemBackground" android:background="?selectableItemBackground"
android:animateLayoutChanges="true"> android:animateLayoutChanges="true">
<View <View
android:id="@+id/media_keyboard_bottom_tab_indicator" android:id="@+id/media_keyboard_top_tab_indicator"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="2dp" android:layout_height="2dp"
android:background="?emoji_tab_indicator"/> android:background="?emoji_tab_indicator"
android:visibility="gone"
tools:visibility="visible" />
<ImageView <ImageView
android:id="@+id/media_keyboard_bottom_tab_image" android:id="@+id/media_keyboard_bottom_tab_image"
android:layout_width="36dp" android:layout_width="36dp"
android:layout_height="36dp" android:layout_height="36dp"
android:padding="6dp"/> android:padding="6dp" />
<View
android:id="@+id/media_keyboard_bottom_tab_indicator"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="?emoji_tab_indicator"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout> </LinearLayout>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.components.emoji.MediaKeyboard xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/emoji_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/core_grey_90"
app:tabs_gravity="top" />

View file

@ -355,4 +355,11 @@
<attr name="revealable_unopenedForegroundColor" format="color" /> <attr name="revealable_unopenedForegroundColor" format="color" />
<attr name="revealable_openedForegroundColor" format="color" /> <attr name="revealable_openedForegroundColor" format="color" />
</declare-styleable> </declare-styleable>
<declare-styleable name="MediaKeyboard">
<attr name="tabs_gravity" format="enum">
<enum name="bottom" value="0" />
<enum name="top" value="1" />
</attr>
</declare-styleable>
</resources> </resources>

View file

@ -1,18 +1,20 @@
package org.thoughtcrime.securesms.components.emoji; package org.thoughtcrime.securesms.components.emoji;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import android.content.res.TypedArray;
import androidx.annotation.Nullable;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.InputAwareLayout.InputView; import org.thoughtcrime.securesms.components.InputAwareLayout.InputView;
import org.thoughtcrime.securesms.components.RepeatableImageKey; import org.thoughtcrime.securesms.components.RepeatableImageKey;
@ -29,16 +31,18 @@ public class MediaKeyboard extends FrameLayout implements InputView,
private static final String TAG = Log.tag(MediaKeyboard.class); private static final String TAG = Log.tag(MediaKeyboard.class);
private RecyclerView categoryTabs; private RecyclerView categoryTabs;
private ViewPager categoryPager; private ViewPager categoryPager;
private ViewGroup providerTabs; private ViewGroup providerTabs;
private RepeatableImageKey backspaceButton; private RepeatableImageKey backspaceButton;
private RepeatableImageKey backspaceButtonBackup; private RepeatableImageKey backspaceButtonBackup;
private View searchButton; private View searchButton;
private View addButton; private View addButton;
private MediaKeyboardListener keyboardListener; @Nullable private MediaKeyboardListener keyboardListener;
private MediaKeyboardProvider[] providers; private MediaKeyboardProvider[] providers;
private int providerIndex; private int providerIndex;
private final boolean tabsAtBottom;
private MediaKeyboardBottomTabAdapter categoryTabAdapter; private MediaKeyboardBottomTabAdapter categoryTabAdapter;
@ -48,6 +52,14 @@ public class MediaKeyboard extends FrameLayout implements InputView,
public MediaKeyboard(Context context, AttributeSet attrs) { public MediaKeyboard(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MediaKeyboard, 0, 0);
try {
tabsAtBottom = typedArray.getInt(R.styleable.MediaKeyboard_tabs_gravity, 0) == 0;
} finally {
typedArray.recycle();
}
} }
public void setProviders(int startIndex, MediaKeyboardProvider... providers) { public void setProviders(int startIndex, MediaKeyboardProvider... providers) {
@ -59,7 +71,7 @@ public class MediaKeyboard extends FrameLayout implements InputView,
} }
} }
public void setKeyboardListener(MediaKeyboardListener listener) { public void setKeyboardListener(@Nullable MediaKeyboardListener listener) {
this.keyboardListener = listener; this.keyboardListener = listener;
} }
@ -76,8 +88,14 @@ public class MediaKeyboard extends FrameLayout implements InputView,
params.height = height; params.height = height;
Log.i(TAG, "showing emoji drawer with height " + params.height); Log.i(TAG, "showing emoji drawer with height " + params.height);
setLayoutParams(params); setLayoutParams(params);
setVisibility(VISIBLE);
show();
}
public void show() {
if (this.categoryPager == null) initView();
setVisibility(VISIBLE);
if (keyboardListener != null) keyboardListener.onShown(); if (keyboardListener != null) keyboardListener.onShown();
requestPresent(providers, providerIndex); requestPresent(providers, providerIndex);
@ -122,7 +140,7 @@ public class MediaKeyboard extends FrameLayout implements InputView,
public void requestDismissal() { public void requestDismissal() {
hide(true); hide(true);
providerIndex = 0; providerIndex = 0;
keyboardListener.onKeyboardProviderChanged(providers[providerIndex]); if (keyboardListener != null) keyboardListener.onKeyboardProviderChanged(providers[providerIndex]);
} }
@Override @Override
@ -148,7 +166,10 @@ public class MediaKeyboard extends FrameLayout implements InputView,
private void initView() { private void initView() {
final View view = LayoutInflater.from(getContext()).inflate(R.layout.media_keyboard, this, true); final View view = LayoutInflater.from(getContext()).inflate(R.layout.media_keyboard, this, true);
this.categoryTabs = view.findViewById(R.id.media_keyboard_tabs); RecyclerView categoryTabsTop = view.findViewById(R.id.media_keyboard_tabs_top);
RecyclerView categoryTabsBottom = view.findViewById(R.id.media_keyboard_tabs);
this.categoryTabs = tabsAtBottom ? categoryTabsBottom : categoryTabsTop;
this.categoryPager = view.findViewById(R.id.media_keyboard_pager); this.categoryPager = view.findViewById(R.id.media_keyboard_pager);
this.providerTabs = view.findViewById(R.id.media_keyboard_provider_tabs); this.providerTabs = view.findViewById(R.id.media_keyboard_provider_tabs);
this.backspaceButton = view.findViewById(R.id.media_keyboard_backspace); this.backspaceButton = view.findViewById(R.id.media_keyboard_backspace);
@ -156,10 +177,11 @@ public class MediaKeyboard extends FrameLayout implements InputView,
this.searchButton = view.findViewById(R.id.media_keyboard_search); this.searchButton = view.findViewById(R.id.media_keyboard_search);
this.addButton = view.findViewById(R.id.media_keyboard_add); this.addButton = view.findViewById(R.id.media_keyboard_add);
this.categoryTabAdapter = new MediaKeyboardBottomTabAdapter(GlideApp.with(this), this); this.categoryTabAdapter = new MediaKeyboardBottomTabAdapter(GlideApp.with(this), this, tabsAtBottom);
categoryTabs.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false)); categoryTabs.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
categoryTabs.setAdapter(categoryTabAdapter); categoryTabs.setAdapter(categoryTabAdapter);
categoryTabs.setVisibility(VISIBLE);
} }
private void requestPresent(@NonNull MediaKeyboardProvider[] providers, int newIndex) { private void requestPresent(@NonNull MediaKeyboardProvider[] providers, int newIndex) {

View file

@ -15,19 +15,22 @@ public class MediaKeyboardBottomTabAdapter extends RecyclerView.Adapter<MediaKey
private final GlideRequests glideRequests; private final GlideRequests glideRequests;
private final EventListener eventListener; private final EventListener eventListener;
private final boolean highlightTop;
private TabIconProvider tabIconProvider; private TabIconProvider tabIconProvider;
private int activePosition; private int activePosition;
private int count; private int count;
public MediaKeyboardBottomTabAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) { public MediaKeyboardBottomTabAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener, boolean highlightTop) {
this.glideRequests = glideRequests; this.glideRequests = glideRequests;
this.eventListener = eventListener; this.eventListener = eventListener;
this.highlightTop = highlightTop;
} }
@Override @Override
public @NonNull MediaKeyboardBottomTabViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { 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)); return new MediaKeyboardBottomTabViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.media_keyboard_bottom_tab_item, viewGroup, false),
highlightTop);
} }
@Override @Override
@ -62,11 +65,16 @@ public class MediaKeyboardBottomTabAdapter extends RecyclerView.Adapter<MediaKey
private final ImageView image; private final ImageView image;
private final View indicator; private final View indicator;
public MediaKeyboardBottomTabViewHolder(@NonNull View itemView) { public MediaKeyboardBottomTabViewHolder(@NonNull View itemView, boolean highlightTop) {
super(itemView); super(itemView);
View indicatorTop = itemView.findViewById(R.id.media_keyboard_top_tab_indicator);
View indicatorBottom = itemView.findViewById(R.id.media_keyboard_bottom_tab_indicator);
this.image = itemView.findViewById(R.id.media_keyboard_bottom_tab_image); this.image = itemView.findViewById(R.id.media_keyboard_bottom_tab_image);
this.indicator = itemView.findViewById(R.id.media_keyboard_bottom_tab_indicator); this.indicator = highlightTop ? indicatorTop : indicatorBottom;
this.indicator.setVisibility(View.VISIBLE);
} }
void bind(@NonNull GlideRequests glideRequests, void bind(@NonNull GlideRequests glideRequests,

View file

@ -19,7 +19,6 @@ package org.thoughtcrime.securesms.conversation;
import android.Manifest; import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import androidx.lifecycle.ViewModelProviders;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@ -42,16 +41,6 @@ import android.os.Vibrator;
import android.provider.Browser; import android.provider.Browser;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.provider.Telephony; import android.provider.Telephony;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;
import androidx.core.view.MenuItemCompat;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import android.text.Editable; import android.text.Editable;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -71,6 +60,18 @@ import android.widget.ImageButton;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.IconCompat;
import androidx.core.view.MenuItemCompat;
import androidx.lifecycle.ViewModelProviders;
import com.annimon.stream.Stream; import com.annimon.stream.Stream;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
@ -217,6 +218,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener; import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener;
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
import org.thoughtcrime.securesms.util.concurrent.SettableFuture; import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.util.views.Stub; import org.thoughtcrime.securesms.util.views.Stub;
import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.InvalidMessageException;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
@ -2491,9 +2493,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void sendSticker(@NonNull StickerRecord stickerRecord, boolean clearCompose) { private void sendSticker(@NonNull StickerRecord stickerRecord, boolean clearCompose) {
sendSticker(new StickerLocator(stickerRecord.getPackId(), stickerRecord.getPackKey(), stickerRecord.getStickerId()), stickerRecord.getUri(), stickerRecord.getSize(), clearCompose); sendSticker(new StickerLocator(stickerRecord.getPackId(), stickerRecord.getPackKey(), stickerRecord.getStickerId()), stickerRecord.getUri(), stickerRecord.getSize(), clearCompose);
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { SignalExecutors.BOUNDED.execute(() ->
DatabaseFactory.getStickerDatabase(this).updateStickerLastUsedTime(stickerRecord.getRowId(), System.currentTimeMillis()); DatabaseFactory.getStickerDatabase(getApplicationContext())
}); .updateStickerLastUsedTime(stickerRecord.getRowId(), System.currentTimeMillis())
);
} }
private void sendSticker(@NonNull StickerLocator stickerLocator, @NonNull Uri uri, long size, boolean clearCompose) { private void sendSticker(@NonNull StickerLocator stickerLocator, @NonNull Uri uri, long size, boolean clearCompose) {

View file

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.database.model; package org.thoughtcrime.securesms.database.model;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.mms.PartAuthority; import org.thoughtcrime.securesms.mms.PartAuthority;

View file

@ -1,10 +1,5 @@
package org.thoughtcrime.securesms.mediasend; package org.thoughtcrime.securesms.mediasend;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.lifecycle.ViewModelProviders;
import android.Manifest; import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
@ -15,12 +10,6 @@ import android.graphics.Rect;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.text.Editable; import android.text.Editable;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.view.KeyEvent; import android.view.KeyEvent;
@ -32,6 +21,16 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ContextThemeWrapper;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity; import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.TransportOption; import org.thoughtcrime.securesms.TransportOption;
@ -438,10 +437,13 @@ public class MediaSendActivity extends PassphraseRequiredActionBarActivity imple
} }
@Override @Override
public void onRequestFullScreen(boolean fullScreen) { public void onRequestFullScreen(boolean fullScreen, boolean hideKeyboard) {
if (captionAndRail != null) { if (captionAndRail != null) {
captionAndRail.setVisibility(fullScreen ? View.GONE : View.VISIBLE); captionAndRail.setVisibility(fullScreen ? View.GONE : View.VISIBLE);
} }
if (hideKeyboard && hud.isKeyboardOpen()) {
hud.hideSoftkey(composeText, null);
}
} }
@Override @Override

View file

@ -6,14 +6,16 @@ import android.graphics.Bitmap;
import android.graphics.Paint; import android.graphics.Paint;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.imageeditor.ColorableRenderer; import org.thoughtcrime.securesms.imageeditor.ColorableRenderer;
import org.thoughtcrime.securesms.imageeditor.ImageEditorView; import org.thoughtcrime.securesms.imageeditor.ImageEditorView;
@ -28,6 +30,7 @@ import org.thoughtcrime.securesms.mms.PushMediaConstraints;
import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.providers.BlobProvider;
import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker; import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker;
import org.thoughtcrime.securesms.stickers.StickerSearchRepository;
import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ParcelUtil; import org.thoughtcrime.securesms.util.ParcelUtil;
import org.thoughtcrime.securesms.util.SaveAttachmentTask; import org.thoughtcrime.securesms.util.SaveAttachmentTask;
@ -36,7 +39,6 @@ import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
import org.thoughtcrime.securesms.util.concurrent.SimpleTask; import org.thoughtcrime.securesms.util.concurrent.SimpleTask;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
@ -48,14 +50,15 @@ public final class ImageEditorFragment extends Fragment implements ImageEditorHu
private static final String KEY_IMAGE_URI = "image_uri"; private static final String KEY_IMAGE_URI = "image_uri";
public static final int SELECT_STICKER_REQUEST_CODE = 123; private static final int SELECT_OLD_STICKER_REQUEST_CODE = 123;
private static final int SELECT_NEW_STICKER_REQUEST_CODE = 124;
private EditorModel restoredModel; private EditorModel restoredModel;
@Nullable @Nullable private EditorElement currentSelection;
private EditorElement currentSelection; private int imageMaxHeight;
private int imageMaxHeight; private int imageMaxWidth;
private int imageMaxWidth; private ImageEditorFragmentViewModel viewModel;
public static class Data { public static class Data {
private final Bundle bundle; private final Bundle bundle;
@ -118,6 +121,13 @@ public final class ImageEditorFragment extends Fragment implements ImageEditorHu
imageMaxWidth = mediaConstraints.getImageMaxWidth(requireContext()); imageMaxWidth = mediaConstraints.getImageMaxWidth(requireContext());
imageMaxHeight = mediaConstraints.getImageMaxHeight(requireContext()); imageMaxHeight = mediaConstraints.getImageMaxHeight(requireContext());
StickerSearchRepository repository = new StickerSearchRepository(requireContext());
viewModel = ViewModelProviders.of(this, new ImageEditorFragmentViewModel.Factory(requireActivity().getApplication(), repository))
.get(ImageEditorFragmentViewModel.class);
viewModel.getStickersAvailability().observe(this, isAvailable -> imageEditorHud.setStickersAvailable(isAvailable));
} }
@Nullable @Nullable
@ -233,15 +243,26 @@ public final class ImageEditorFragment extends Fragment implements ImageEditorHu
@Override @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == SELECT_STICKER_REQUEST_CODE && data != null) { if (resultCode == RESULT_OK && requestCode == SELECT_NEW_STICKER_REQUEST_CODE && data != null) {
final String stickerFile = data.getStringExtra(StickerSelectActivity.EXTRA_STICKER_FILE); final Uri uri = data.getData();
if (uri != null) {
UriGlideRenderer renderer = new UriGlideRenderer(Uri.parse("file:///android_asset/" + stickerFile), false, imageMaxWidth, imageMaxHeight); UriGlideRenderer renderer = new UriGlideRenderer(uri, true, imageMaxWidth, imageMaxHeight);
EditorElement element = new EditorElement(renderer); EditorElement element = new EditorElement(renderer);
imageEditorView.getModel().addElementCentered(element, 0.2f); imageEditorView.getModel().addElementCentered(element, 0.2f);
currentSelection = element; currentSelection = element;
imageEditorHud.setMode(ImageEditorHud.Mode.MOVE_DELETE);
}
} else if (resultCode == RESULT_OK && requestCode == SELECT_OLD_STICKER_REQUEST_CODE && data != null) {
final Uri uri = data.getData();
if (uri != null) {
UriGlideRenderer renderer = new UriGlideRenderer(uri, false, imageMaxWidth, imageMaxHeight);
EditorElement element = new EditorElement(renderer);
imageEditorView.getModel().addElementCentered(element, 0.2f);
currentSelection = element;
imageEditorHud.setMode(ImageEditorHud.Mode.MOVE_DELETE);
}
} else { } else {
imageEditorHud.enterMode(ImageEditorHud.Mode.NONE); imageEditorHud.setMode(ImageEditorHud.Mode.NONE);
} }
} }
@ -253,31 +274,46 @@ public final class ImageEditorFragment extends Fragment implements ImageEditorHu
controller.onTouchEventsNeeded(mode != ImageEditorHud.Mode.NONE); controller.onTouchEventsNeeded(mode != ImageEditorHud.Mode.NONE);
switch (mode) { switch (mode) {
case CROP: case CROP: {
imageEditorView.getModel().startCrop(); imageEditorView.getModel().startCrop();
break; break;
}
case DRAW: case DRAW: {
imageEditorView.startDrawing(0.01f, Paint.Cap.ROUND); imageEditorView.startDrawing(0.01f, Paint.Cap.ROUND);
break; break;
}
case HIGHLIGHT: case HIGHLIGHT: {
imageEditorView.startDrawing(0.03f, Paint.Cap.SQUARE); imageEditorView.startDrawing(0.03f, Paint.Cap.SQUARE);
break; break;
}
case TEXT: case TEXT: {
addText(); addText();
break; break;
}
case INSERT_ASSET_STICKER: {
Intent intent = new Intent(getContext(), StickerSelectActivity.class);
startActivityForResult(intent, SELECT_OLD_STICKER_REQUEST_CODE);
break;
}
case INSERT_STICKER: {
Intent intent = new Intent(getContext(), NewStickerSelectActivity.class);
startActivityForResult(intent, SELECT_NEW_STICKER_REQUEST_CODE);
break;
}
case MOVE_DELETE: case MOVE_DELETE:
Intent intent = new Intent(getContext(), StickerSelectActivity.class);
startActivityForResult(intent, SELECT_STICKER_REQUEST_CODE);
break; break;
case NONE: case NONE: {
imageEditorView.getModel().doneCrop(); imageEditorView.getModel().doneCrop();
currentSelection = null; currentSelection = null;
break; break;
}
} }
} }
@ -350,8 +386,8 @@ public final class ImageEditorFragment extends Fragment implements ImageEditorHu
} }
@Override @Override
public void onRequestFullScreen(boolean fullScreen) { public void onRequestFullScreen(boolean fullScreen, boolean hideKeyboard) {
controller.onRequestFullScreen(fullScreen); controller.onRequestFullScreen(fullScreen, hideKeyboard);
} }
private void refreshUniqueColors() { private void refreshUniqueColors() {
@ -371,8 +407,7 @@ public final class ImageEditorFragment extends Fragment implements ImageEditorHu
} else { } else {
currentSelection = null; currentSelection = null;
controller.onTouchEventsNeeded(false); controller.onTouchEventsNeeded(false);
imageEditorHud.enterMode(ImageEditorHud.Mode.NONE); imageEditorHud.setMode(ImageEditorHud.Mode.NONE);
imageEditorView.doneTextEditing();
} }
} }
@ -383,7 +418,7 @@ public final class ImageEditorFragment extends Fragment implements ImageEditorHu
if (editorElement.getRenderer() instanceof MultiLineTextRenderer) { if (editorElement.getRenderer() instanceof MultiLineTextRenderer) {
setTextElement(editorElement, (ColorableRenderer) editorElement.getRenderer(), imageEditorView.isTextEditing()); setTextElement(editorElement, (ColorableRenderer) editorElement.getRenderer(), imageEditorView.isTextEditing());
} else { } else {
imageEditorHud.enterMode(ImageEditorHud.Mode.MOVE_DELETE); imageEditorHud.setMode(ImageEditorHud.Mode.MOVE_DELETE);
} }
} }
} }
@ -412,6 +447,6 @@ public final class ImageEditorFragment extends Fragment implements ImageEditorHu
public interface Controller { public interface Controller {
void onTouchEventsNeeded(boolean needed); void onTouchEventsNeeded(boolean needed);
void onRequestFullScreen(boolean fullScreen); void onRequestFullScreen(boolean fullScreen, boolean hideKeyboard);
} }
} }

View file

@ -0,0 +1,65 @@
package org.thoughtcrime.securesms.scribbles;
import android.app.Application;
import android.database.ContentObserver;
import android.os.Handler;
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.StickerSearchRepository;
import org.thoughtcrime.securesms.util.Throttler;
public final class ImageEditorFragmentViewModel extends ViewModel {
private final Application application;
private final StickerSearchRepository repository;
private final MutableLiveData<Boolean> stickersAvailable;
private final Throttler availabilityThrottler;
private final ContentObserver packObserver;
private ImageEditorFragmentViewModel(@NonNull Application application, @NonNull StickerSearchRepository repository) {
this.application = application;
this.repository = repository;
this.stickersAvailable = new MutableLiveData<>();
this.availabilityThrottler = new Throttler(500);
this.packObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
availabilityThrottler.publish(() -> repository.getStickerFeatureAvailability(stickersAvailable::postValue));
}
};
application.getContentResolver().registerContentObserver(DatabaseContentProviders.StickerPack.CONTENT_URI, true, packObserver);
}
@NonNull LiveData<Boolean> getStickersAvailability() {
repository.getStickerFeatureAvailability(stickersAvailable::postValue);
return stickersAvailable;
}
@Override
protected void onCleared() {
application.getContentResolver().unregisterContentObserver(packObserver);
}
static class Factory extends ViewModelProvider.NewInstanceFactory {
private final Application application;
private final StickerSearchRepository repository;
public Factory(@NonNull Application application, @NonNull StickerSearchRepository 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 ImageEditorFragmentViewModel(application, repository));
}
}
}

View file

@ -2,15 +2,17 @@ package org.thoughtcrime.securesms.scribbles;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.scribbles.widget.ColorPaletteAdapter; import org.thoughtcrime.securesms.scribbles.widget.ColorPaletteAdapter;
import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker; import org.thoughtcrime.securesms.scribbles.widget.VerticalSlideColorPicker;
@ -34,7 +36,8 @@ public final class ImageEditorHud extends LinearLayout {
private View drawButton; private View drawButton;
private View highlightButton; private View highlightButton;
private View textButton; private View textButton;
private View stickerButton; private View oldStickerButton;
private View newStickerButton;
private View undoButton; private View undoButton;
private View saveButton; private View saveButton;
private View deleteButton; private View deleteButton;
@ -80,7 +83,8 @@ public final class ImageEditorHud extends LinearLayout {
drawButton = findViewById(R.id.scribble_draw_button); drawButton = findViewById(R.id.scribble_draw_button);
highlightButton = findViewById(R.id.scribble_highlight_button); highlightButton = findViewById(R.id.scribble_highlight_button);
textButton = findViewById(R.id.scribble_text_button); textButton = findViewById(R.id.scribble_text_button);
stickerButton = findViewById(R.id.scribble_sticker_button); oldStickerButton = findViewById(R.id.old_scribble_sticker_button);
newStickerButton = findViewById(R.id.scribble_sticker_button);
undoButton = findViewById(R.id.scribble_undo_button); undoButton = findViewById(R.id.scribble_undo_button);
saveButton = findViewById(R.id.scribble_save_button); saveButton = findViewById(R.id.scribble_save_button);
deleteButton = findViewById(R.id.scribble_delete_button); deleteButton = findViewById(R.id.scribble_delete_button);
@ -102,7 +106,7 @@ public final class ImageEditorHud extends LinearLayout {
} }
private void initializeVisibilityMap() { private void initializeVisibilityMap() {
setVisibleViewsWhenInMode(Mode.NONE, drawButton, highlightButton, textButton, stickerButton, cropButton, undoButton, saveButton); setStickersAvailable(false);
setVisibleViewsWhenInMode(Mode.DRAW, confirmButton, undoButton, colorPicker, colorPalette); setVisibleViewsWhenInMode(Mode.DRAW, confirmButton, undoButton, colorPicker, colorPalette);
@ -112,17 +116,34 @@ public final class ImageEditorHud extends LinearLayout {
setVisibleViewsWhenInMode(Mode.MOVE_DELETE, confirmButton, deleteButton); setVisibleViewsWhenInMode(Mode.MOVE_DELETE, confirmButton, deleteButton);
setVisibleViewsWhenInMode(Mode.INSERT_STICKER, confirmButton);
setVisibleViewsWhenInMode(Mode.INSERT_ASSET_STICKER, confirmButton);
setVisibleViewsWhenInMode(Mode.CROP, confirmButton, cropFlipButton, cropRotateButton, cropAspectLock, undoButton); setVisibleViewsWhenInMode(Mode.CROP, confirmButton, cropFlipButton, cropRotateButton, cropAspectLock, undoButton);
for (Set<View> views : visibilityModeMap.values()) { for (Set<View> views : visibilityModeMap.values()) {
allViews.addAll(views); allViews.addAll(views);
} }
allViews.add(newStickerButton);
allViews.add(oldStickerButton);
} }
private void setVisibleViewsWhenInMode(Mode mode, View... views) { private void setVisibleViewsWhenInMode(Mode mode, View... views) {
visibilityModeMap.put(mode, new HashSet<>(Arrays.asList(views))); visibilityModeMap.put(mode, new HashSet<>(Arrays.asList(views)));
} }
@MainThread
public void setStickersAvailable(boolean stickersAvailable) {
if (stickersAvailable) {
setVisibleViewsWhenInMode(Mode.NONE, drawButton, highlightButton, textButton, newStickerButton, cropButton, undoButton, saveButton);
} else {
setVisibleViewsWhenInMode(Mode.NONE, drawButton, highlightButton, textButton, oldStickerButton, cropButton, undoButton, saveButton);
}
updateButtonVisibility(currentMode);
}
private void initializeViews() { private void initializeViews() {
undoButton.setOnClickListener(v -> eventListener.onUndo()); undoButton.setOnClickListener(v -> eventListener.onUndo());
@ -146,7 +167,8 @@ public final class ImageEditorHud extends LinearLayout {
drawButton.setOnClickListener(v -> setMode(Mode.DRAW)); drawButton.setOnClickListener(v -> setMode(Mode.DRAW));
highlightButton.setOnClickListener(v -> setMode(Mode.HIGHLIGHT)); highlightButton.setOnClickListener(v -> setMode(Mode.HIGHLIGHT));
textButton.setOnClickListener(v -> setMode(Mode.TEXT)); textButton.setOnClickListener(v -> setMode(Mode.TEXT));
stickerButton.setOnClickListener(v -> setMode(Mode.MOVE_DELETE)); oldStickerButton.setOnClickListener(v -> setMode(Mode.INSERT_ASSET_STICKER));
newStickerButton.setOnClickListener(v -> setMode(Mode.INSERT_STICKER));
saveButton.setOnClickListener(v -> eventListener.onSave()); saveButton.setOnClickListener(v -> eventListener.onSave());
} }
@ -172,16 +194,13 @@ public final class ImageEditorHud extends LinearLayout {
setMode(mode, false); setMode(mode, false);
} }
private void setMode(@NonNull Mode mode) { public void setMode(@NonNull Mode mode) {
setMode(mode, true); setMode(mode, true);
} }
private void setMode(@NonNull Mode mode, boolean notify) { private void setMode(@NonNull Mode mode, boolean notify) {
this.currentMode = mode; this.currentMode = mode;
Set<View> visibleButtons = visibilityModeMap.get(mode); updateButtonVisibility(mode);
for (View button : allViews) {
button.setVisibility(buttonIsVisible(visibleButtons, button) ? VISIBLE : GONE);
}
switch (mode) { switch (mode) {
case CROP: presentModeCrop(); break; case CROP: presentModeCrop(); break;
@ -193,7 +212,14 @@ public final class ImageEditorHud extends LinearLayout {
if (notify) { if (notify) {
eventListener.onModeStarted(mode); eventListener.onModeStarted(mode);
} }
eventListener.onRequestFullScreen(mode != Mode.NONE); eventListener.onRequestFullScreen(mode != Mode.NONE, mode != Mode.TEXT);
}
private void updateButtonVisibility(@NonNull Mode mode) {
Set<View> visibleButtons = visibilityModeMap.get(mode);
for (View button : allViews) {
button.setVisibility(buttonIsVisible(visibleButtons, button) ? VISIBLE : GONE);
}
} }
private boolean buttonIsVisible(@Nullable Set<View> visibleButtons, @NonNull View button) { private boolean buttonIsVisible(@Nullable Set<View> visibleButtons, @NonNull View button) {
@ -236,7 +262,14 @@ public final class ImageEditorHud extends LinearLayout {
} }
public enum Mode { public enum Mode {
NONE, DRAW, HIGHLIGHT, TEXT, MOVE_DELETE, CROP NONE,
CROP,
TEXT,
DRAW,
HIGHLIGHT,
MOVE_DELETE,
INSERT_STICKER,
INSERT_ASSET_STICKER
} }
public interface EventListener { public interface EventListener {
@ -249,7 +282,7 @@ public final class ImageEditorHud extends LinearLayout {
void onRotate90AntiClockwise(); void onRotate90AntiClockwise();
void onCropAspectLock(boolean locked); void onCropAspectLock(boolean locked);
boolean isCropAspectLocked(); boolean isCropAspectLocked();
void onRequestFullScreen(boolean fullScreen); void onRequestFullScreen(boolean fullScreen, boolean hideKeyboard);
} }
private static final EventListener NULL_EVENT_LISTENER = new EventListener() { private static final EventListener NULL_EVENT_LISTENER = new EventListener() {
@ -292,7 +325,7 @@ public final class ImageEditorHud extends LinearLayout {
} }
@Override @Override
public void onRequestFullScreen(boolean fullScreen) { public void onRequestFullScreen(boolean fullScreen, boolean hideKeyboard) {
} }
}; };
} }

View file

@ -0,0 +1,82 @@
package org.thoughtcrime.securesms.scribbles;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard;
import org.thoughtcrime.securesms.components.emoji.MediaKeyboardProvider;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.model.StickerRecord;
import org.thoughtcrime.securesms.stickers.StickerKeyboardProvider;
import org.thoughtcrime.securesms.stickers.StickerManagementActivity;
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
public final class NewStickerSelectActivity extends FragmentActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.scribble_select_new_sticker_activity);
MediaKeyboard mediaKeyboard = findViewById(R.id.emoji_drawer);
mediaKeyboard.setProviders(0, new StickerKeyboardProvider(this, new StickerKeyboardProvider.StickerEventListener() {
@Override
public void onStickerSelected(@NonNull StickerRecord sticker) {
Intent intent = new Intent();
intent.setData(sticker.getUri());
setResult(RESULT_OK, intent);
SignalExecutors.BOUNDED.execute(() ->
DatabaseFactory.getStickerDatabase(getApplicationContext())
.updateStickerLastUsedTime(sticker.getRowId(), System.currentTimeMillis())
);
finish();
}
@Override
public void onStickerManagementClicked() {
startActivity(StickerManagementActivity.getIntent(NewStickerSelectActivity.this));
}
}
));
mediaKeyboard.setKeyboardListener(new MediaKeyboard.MediaKeyboardListener() {
@Override
public void onShown() {
}
@Override
public void onHidden() {
finish();
}
@Override
public void onKeyboardProviderChanged(@NonNull MediaKeyboardProvider provider) {
}
});
mediaKeyboard.show();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
}

View file

@ -63,9 +63,7 @@ final class UriGlideRenderer implements Renderer {
try { try {
Bitmap bitmap = getBitmapGlideRequest(rendererContext.context, false).submit().get(); Bitmap bitmap = getBitmapGlideRequest(rendererContext.context, false).submit().get();
setBitmap(rendererContext, bitmap); setBitmap(rendererContext, bitmap);
} catch (ExecutionException e) { } catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} else { } else {
@ -73,6 +71,8 @@ final class UriGlideRenderer implements Renderer {
@Override @Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) { public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
setBitmap(rendererContext, resource); setBitmap(rendererContext, resource);
rendererContext.invalidate.onInvalidate(UriGlideRenderer.this);
} }
@Override @Override
@ -99,7 +99,7 @@ final class UriGlideRenderer implements Renderer {
paint.setAlpha(alpha); paint.setAlpha(alpha);
rendererContext.restore(); rendererContext.restore();
} else { } else if (rendererContext.isBlockingLoad()) {
// If failed to load, we draw a black out, in case image was sticker positioned to cover private info. // If failed to load, we draw a black out, in case image was sticker positioned to cover private info.
rendererContext.canvas.drawRect(Bounds.FULL_BOUNDS, paint); rendererContext.canvas.drawRect(Bounds.FULL_BOUNDS, paint);
} }

View file

@ -1,16 +1,17 @@
package org.thoughtcrime.securesms.stickers; package org.thoughtcrime.securesms.stickers;
import androidx.lifecycle.ViewModelProviders;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.widget.ImageView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter; import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.appcompat.app.AppCompatActivity; import androidx.lifecycle.ViewModelProviders;
import android.widget.ImageView;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.emoji.MediaKeyboardProvider; import org.thoughtcrime.securesms.components.emoji.MediaKeyboardProvider;
@ -48,7 +49,7 @@ public final class StickerKeyboardProvider implements MediaKeyboardProvider,
private boolean isSoloProvider; private boolean isSoloProvider;
private StickerKeyboardViewModel viewModel; private StickerKeyboardViewModel viewModel;
public StickerKeyboardProvider(@NonNull AppCompatActivity activity, public StickerKeyboardProvider(@NonNull FragmentActivity activity,
@NonNull StickerEventListener eventListener) @NonNull StickerEventListener eventListener)
{ {
this.context = activity; this.context = activity;
@ -109,7 +110,7 @@ public final class StickerKeyboardProvider implements MediaKeyboardProvider,
} }
} }
private void initViewModel(@NonNull AppCompatActivity activity) { private void initViewModel(@NonNull FragmentActivity activity) {
StickerKeyboardRepository repository = new StickerKeyboardRepository(DatabaseFactory.getStickerDatabase(activity)); StickerKeyboardRepository repository = new StickerKeyboardRepository(DatabaseFactory.getStickerDatabase(activity));
viewModel = ViewModelProviders.of(activity, new StickerKeyboardViewModel.Factory(activity.getApplication(), repository)).get(StickerKeyboardViewModel.class); viewModel = ViewModelProviders.of(activity, new StickerKeyboardViewModel.Factory(activity.getApplication(), repository)).get(StickerKeyboardViewModel.class);