diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index c9dd0ce359..ec87f18321 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -62,7 +62,6 @@ import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer; import org.thoughtcrime.securesms.jobs.FastJobStorage; import org.thoughtcrime.securesms.jobs.JobManagerFactories; import org.thoughtcrime.securesms.jobs.PushContentReceiveJob; -import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob; import org.thoughtcrime.securesms.logging.AndroidLogger; import org.session.libsignal.utilities.logging.Log; import org.thoughtcrime.securesms.logging.PersistentLogger; diff --git a/app/src/main/java/org/thoughtcrime/securesms/BindableConversationItem.java b/app/src/main/java/org/thoughtcrime/securesms/BindableConversationItem.java index a4193c4e7c..5a1067b144 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/BindableConversationItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/BindableConversationItem.java @@ -36,6 +36,5 @@ public interface BindableConversationItem extends Unbindable { void onQuoteClicked(MmsMessageRecord messageRecord); void onLinkPreviewClicked(@NonNull LinkPreview linkPreview); void onMoreTextClicked(@NonNull Address conversationAddress, long messageId, boolean isMms); - void onStickerClicked(@NonNull StickerLocator stickerLocator); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt index ff5446a018..1e2738db2c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupExporter.kt @@ -86,12 +86,6 @@ object FullBackupExporter { }, count) } - StickerDatabase.TABLE_NAME -> { - exportTable(table, input, outputStream, - { true }, - { cursor: Cursor -> exportSticker(attachmentSecret, cursor, outputStream) }, - count) - } else -> { exportTable(table, input, outputStream, null, null, count) } @@ -236,20 +230,6 @@ object FullBackupExporter { } } - private fun exportSticker(attachmentSecret: AttachmentSecret, cursor: Cursor, outputStream: BackupFrameOutputStream) { - try { - val rowId = cursor.getLong(cursor.getColumnIndexOrThrow(StickerDatabase._ID)) - val size = cursor.getLong(cursor.getColumnIndexOrThrow(StickerDatabase.FILE_LENGTH)) - val data = cursor.getString(cursor.getColumnIndexOrThrow(StickerDatabase.FILE_PATH)) - val random = cursor.getBlob(cursor.getColumnIndexOrThrow(StickerDatabase.FILE_RANDOM)) - if (!TextUtils.isEmpty(data) && size > 0) { - ModernDecryptingPartInputStream.createFor(attachmentSecret, random, File(data), 0).use { inputStream -> outputStream.writeSticker(rowId, inputStream, size) } - } - } catch (e: IOException) { - Log.w(TAG, e) - } - } - @Throws(IOException::class) private fun calculateVeryOldStreamLength(attachmentSecret: AttachmentSecret, random: ByteArray?, data: String): Long { var result: Long = 0 diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt index de583a6b3c..0452f32b41 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/FullBackupImporter.kt @@ -67,7 +67,6 @@ object FullBackupImporter { frame.hasStatement() -> processStatement(db, frame.statement) frame.hasPreference() -> processPreference(context, frame.preference) frame.hasAttachment() -> processAttachment(context, attachmentSecret, db, frame.attachment, inputStream) - frame.hasSticker() -> processSticker(context, attachmentSecret, db, frame.sticker, inputStream) frame.hasAvatar() -> processAvatar(context, frame.avatar, inputStream) } } @@ -132,21 +131,6 @@ object FullBackupImporter { arrayOf(attachment.rowId.toString(), attachment.attachmentId.toString())) } - @Throws(IOException::class) - private fun processSticker(context: Context, attachmentSecret: AttachmentSecret, - db: SQLiteDatabase, sticker: Sticker, - inputStream: BackupRecordInputStream) { - val stickerDirectory = context.getDir(AttachmentDatabase.DIRECTORY, Context.MODE_PRIVATE) - val dataFile = File.createTempFile("sticker", ".mms", stickerDirectory) - val output = ModernEncryptingPartOutputStream.createFor(attachmentSecret, dataFile, false) - inputStream.readAttachmentTo(output.second, sticker.length) - val contentValues = ContentValues() - contentValues.put(StickerDatabase.FILE_PATH, dataFile.absolutePath) - contentValues.put(StickerDatabase.FILE_RANDOM, output.first) - db.update(StickerDatabase.TABLE_NAME, contentValues, - StickerDatabase._ID + " = ?", arrayOf(sticker.rowId.toString())) - } - @Throws(IOException::class) private fun processAvatar(context: Context, avatar: Avatar, inputStream: BackupRecordInputStream) { inputStream.readAttachmentTo(FileOutputStream( diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java index 6e1f760bac..5becb16292 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/emoji/EmojiToggle.java @@ -7,8 +7,6 @@ import android.util.AttributeSet; import androidx.annotation.NonNull; import androidx.appcompat.widget.AppCompatImageButton; - -import org.thoughtcrime.securesms.stickers.StickerKeyboardProvider; import org.session.libsession.utilities.TextSecurePreferences; import network.loki.messenger.R; @@ -82,8 +80,5 @@ public class EmojiToggle extends AppCompatImageButton implements MediaKeyboard.M @Override public void onKeyboardProviderChanged(@NonNull MediaKeyboardProvider provider) { - setStickerMode(provider instanceof StickerKeyboardProvider); - TextSecurePreferences.setMediaKeyboardMode(getContext(), (provider instanceof StickerKeyboardProvider) ? TextSecurePreferences.MediaKeyboardMode.STICKER - : TextSecurePreferences.MediaKeyboardMode.EMOJI); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 5831af49c9..26e02143d7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -182,10 +182,6 @@ 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.StickerManagementActivity; -import org.thoughtcrime.securesms.stickers.StickerPackInstallEvent; -import org.thoughtcrime.securesms.stickers.StickerSearchRepository; import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.MediaUtil; @@ -205,7 +201,6 @@ import org.session.libsession.utilities.concurrent.AssertedSuccessListener; import org.session.libsignal.utilities.concurrent.ListenableFuture; import org.session.libsignal.utilities.concurrent.SettableFuture; import org.session.libsession.utilities.TextSecurePreferences; -import org.session.libsession.utilities.TextSecurePreferences.MediaKeyboardMode; import java.io.IOException; import java.text.SimpleDateFormat; @@ -239,7 +234,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity InputPanel.MediaListener, ComposeText.CursorPositionChangedListener, ConversationSearchBottomBar.EventListener, - StickerKeyboardProvider.StickerEventListener, LokiThreadDatabaseDelegate { private static final String TAG = ConversationActivity.class.getSimpleName(); @@ -303,7 +297,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private LinkPreviewViewModel linkPreviewViewModel; private ConversationSearchViewModel searchViewModel; - private ConversationStickerViewModel stickerViewModel; private Recipient recipient; private long threadId; @@ -361,7 +354,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity initializeResources(); initializeLinkPreviewObserver(); initializeSearchObserver(); - initializeStickerObserver(); initializeSecurity(false, isDefaultSms).addListener(new AssertedSuccessListener() { @Override public void onSuccess(Boolean result) { @@ -1513,52 +1505,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity }); } - private void initializeStickerObserver() { - StickerSearchRepository repository = new StickerSearchRepository(this); - - stickerViewModel = ViewModelProviders.of(this, new ConversationStickerViewModel.Factory(getApplication(), repository)) - .get(ConversationStickerViewModel.class); - - stickerViewModel.getStickerResults().observe(this, stickers -> { - if (stickers == null) return; - - inputPanel.setStickerSuggestions(stickers); - }); - - stickerViewModel.getStickersAvailability().observe(this, stickersAvailable -> { - if (stickersAvailable == null) return; - - boolean isSystemEmojiPreferred = TextSecurePreferences.isSystemEmojiPreferred(this); - MediaKeyboardMode keyboardMode = TextSecurePreferences.getMediaKeyboardMode(this); - boolean stickerIntro = !TextSecurePreferences.hasSeenStickerIntroTooltip(this); - - if (stickersAvailable) { - inputPanel.showMediaKeyboardToggle(true); - inputPanel.setMediaKeyboardToggleMode(isSystemEmojiPreferred || keyboardMode == MediaKeyboardMode.STICKER); - if (stickerIntro) showStickerIntroductionTooltip(); - } - - if (emojiDrawerStub.resolved()) { - initializeMediaKeyboardProviders(emojiDrawerStub.get(), stickersAvailable); - } - }); - } - - private void showStickerIntroductionTooltip() { - TextSecurePreferences.setMediaKeyboardMode(this, MediaKeyboardMode.STICKER); - inputPanel.setMediaKeyboardToggleMode(true); - - TooltipPopup.forTarget(inputPanel.getMediaKeyboardToggleAnchorView()) - .setBackgroundTint(getResources().getColor(R.color.core_blue)) - .setTextColor(getResources().getColor(R.color.core_white)) - .setText(R.string.ConversationActivity_new_say_it_with_stickers) - .setOnDismissListener(() -> { - TextSecurePreferences.setHasSeenStickerIntroTooltip(this, true); - EventBus.getDefault().removeStickyEvent(StickerPackInstallEvent.class); - }) - .show(TooltipPopup.POSITION_ABOVE); - } - @Override public void onSearchMoveUpPressed() { searchViewModel.onMoveUp(); @@ -1588,17 +1534,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity }); } - @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) - public void onStickerPackInstalled(final StickerPackInstallEvent event) { - if (!TextSecurePreferences.hasSeenStickerIntroTooltip(this)) return; - - EventBus.getDefault().removeStickyEvent(event); - TooltipPopup.forTarget(inputPanel.getMediaKeyboardToggleAnchorView()) - .setText(R.string.ConversationActivity_sticker_pack_installed) - .setIconGlideModel(event.getIconGlideModel()) - .show(TooltipPopup.POSITION_ABOVE); - } - @Subscribe(threadMode = ThreadMode.MAIN) public void onOpenGroupInfoUpdated(OpenGroupUtilities.GroupInfoUpdatedEvent event) { PublicChat publicChat = DatabaseFactory.getLokiThreadDatabase(this).getPublicChat(threadId); @@ -1813,21 +1748,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } } - private void initializeMediaKeyboardProviders(@NonNull MediaKeyboard mediaKeyboard, boolean stickersAvailable) { + private void initializeMediaKeyboardProviders(@NonNull MediaKeyboard mediaKeyboard) { boolean isSystemEmojiPreferred = TextSecurePreferences.isSystemEmojiPreferred(this); - - if (stickersAvailable) { - if (isSystemEmojiPreferred) { - mediaKeyboard.setProviders(0, new StickerKeyboardProvider(this, this)); - } else { - MediaKeyboardMode keyboardMode = TextSecurePreferences.getMediaKeyboardMode(this); - int index = keyboardMode == MediaKeyboardMode.STICKER ? 1 : 0; - - mediaKeyboard.setProviders(index, - new EmojiKeyboardProvider(this, inputPanel), - new StickerKeyboardProvider(this, this)); - } - } else if (!isSystemEmojiPreferred) { + if (!isSystemEmojiPreferred) { mediaKeyboard.setProviders(0, new EmojiKeyboardProvider(this, inputPanel)); } } @@ -2230,9 +2153,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity @Override public void onEmojiToggle() { if (!emojiDrawerStub.resolved()) { - Boolean stickersAvailable = stickerViewModel.getStickersAvailability().getValue(); - - initializeMediaKeyboardProviders(emojiDrawerStub.get(), stickersAvailable == null ? false : stickersAvailable); + initializeMediaKeyboardProviders(emojiDrawerStub.get()); inputPanel.setMediaKeyboard(emojiDrawerStub.get()); } @@ -2272,23 +2193,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity linkPreviewViewModel.onTextChanged(this, composeText.getTextTrimmed(), start, end); } - @Override - public void onStickerSelected(@NonNull StickerRecord stickerRecord) { - sendSticker(stickerRecord, false); - } - - @Override - public void onStickerManagementClicked() { - startActivity(StickerManagementActivity.getIntent(this)); - container.hideAttachedInput(true); - } - private void sendSticker(@NonNull StickerRecord stickerRecord, boolean clearCompose) { sendSticker(new StickerLocator(stickerRecord.getPackId(), stickerRecord.getPackKey(), stickerRecord.getStickerId()), stickerRecord.getUri(), stickerRecord.getSize(), clearCompose); - - AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { - DatabaseFactory.getStickerDatabase(this).updateStickerLastUsedTime(stickerRecord.getRowId(), System.currentTimeMillis()); - }); } private void sendSticker(@NonNull StickerLocator stickerLocator, @NonNull Uri uri, long size, boolean clearCompose) { @@ -2404,12 +2310,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity @Override public void afterTextChanged(Editable s) { - if (composeText.getTextTrimmed().length() == 0 || beforeLength == 0) { composeText.postDelayed(ConversationActivity.this::updateToggleButtonState, 50); } - - stickerViewModel.onInputTextUpdated(s.toString()); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java index 438933bcc5..85103e38cd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -85,7 +85,6 @@ import org.thoughtcrime.securesms.profiles.UnknownSenderView; import org.session.libsession.messaging.threads.recipients.Recipient; import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.OutgoingTextMessage; -import org.thoughtcrime.securesms.stickers.StickerPackPreviewActivity; import org.thoughtcrime.securesms.util.CommunicationActions; import org.thoughtcrime.securesms.util.SaveAttachmentTask; import org.thoughtcrime.securesms.util.StickyHeaderDecoration; @@ -1084,13 +1083,6 @@ public class ConversationFragment extends Fragment startActivity(LongMessageActivity.getIntent(getContext(), conversationAddress, messageId, isMms)); } } - - @Override - public void onStickerClicked(@NonNull StickerLocator sticker) { - if (getContext() != null && getActivity() != null) { - startActivity(StickerPackPreviewActivity.getIntent(sticker.getPackId(), sticker.getPackKey())); - } - } } private class ActionModeCallback implements ActionMode.Callback { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java index d481a1f3fd..7786b52f94 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java @@ -96,7 +96,6 @@ import org.thoughtcrime.securesms.mms.SlidesClickedListener; import org.thoughtcrime.securesms.mms.TextSlide; import org.session.libsession.messaging.threads.recipients.Recipient; import org.session.libsession.messaging.threads.recipients.RecipientModifiedListener; -import org.thoughtcrime.securesms.stickers.StickerUrl; import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.LongClickCopySpan; import org.thoughtcrime.securesms.util.LongClickMovementMethod; @@ -460,8 +459,7 @@ public class ConversationItem extends LinearLayout int minWidth = getResources().getDimensionPixelSize(R.dimen.media_bubble_min_width); return linkPreview.getThumbnail().isPresent() && - linkPreview.getThumbnail().get().getWidth() >= minWidth && - !StickerUrl.isValidShareLink(linkPreview.getUrl()); + linkPreview.getThumbnail().get().getWidth() >= minWidth; } private void setBodyText(MessageRecord messageRecord, @Nullable String searchQuery, boolean isGroupThread) { @@ -1154,9 +1152,6 @@ public class ConversationItem extends LinearLayout public void onClick(View v, Slide slide) { if (shouldInterceptClicks(messageRecord) || !batchSelected.isEmpty()) { performClick(); - } else if (eventListener != null && hasSticker(messageRecord)){ - //noinspection ConstantConditions - eventListener.onStickerClicked(((MmsMessageRecord) messageRecord).getSlideDeck().getStickerSlide().asAttachment().getSticker()); } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationStickerViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationStickerViewModel.java deleted file mode 100644 index 7c61fa5d3e..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationStickerViewModel.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.thoughtcrime.securesms.conversation; - -import android.app.Application; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; -import android.database.ContentObserver; -import android.os.Handler; -import androidx.annotation.NonNull; -import android.text.TextUtils; - -import org.thoughtcrime.securesms.database.CursorList; -import org.thoughtcrime.securesms.database.DatabaseContentProviders; -import org.thoughtcrime.securesms.database.model.StickerRecord; -import org.thoughtcrime.securesms.stickers.StickerSearchRepository; -import org.thoughtcrime.securesms.util.CloseableLiveData; -import org.session.libsession.utilities.Throttler; - -class ConversationStickerViewModel extends ViewModel { - - private static final int SEARCH_LIMIT = 10; - - private final Application application; - private final StickerSearchRepository repository; - private final CloseableLiveData> stickers; - private final MutableLiveData stickersAvailable; - private final Throttler availabilityThrottler; - private final ContentObserver packObserver; - - private ConversationStickerViewModel(@NonNull Application application, @NonNull StickerSearchRepository repository) { - this.application = application; - this.repository = repository; - this.stickers = new CloseableLiveData<>(); - 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> getStickerResults() { - return stickers; - } - - @NonNull LiveData getStickersAvailability() { - repository.getStickerFeatureAvailability(stickersAvailable::postValue); - return stickersAvailable; - } - - void onInputTextUpdated(@NonNull String text) { - if (TextUtils.isEmpty(text) || text.length() > SEARCH_LIMIT) { - stickers.setValue(CursorList.emptyList()); - } else { - repository.searchByEmoji(text, stickers::postValue); - } - } - - @Override - protected void onCleared() { - stickers.close(); - 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 create(@NonNull Class modelClass) { - //noinspection ConstantConditions - return modelClass.cast(new ConversationStickerViewModel(application, repository)); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java index 36a2fc2068..11a4a40466 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java @@ -548,18 +548,6 @@ public class AttachmentDatabase extends Database { notifyConversationListeners(DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId)); } - /** - * Returns (pack_id, pack_key) pairs that are referenced in attachments but not in the stickers - * database. - */ - public @Nullable Cursor getUnavailableStickerPacks() { - String query = "SELECT DISTINCT " + STICKER_PACK_ID + ", " + STICKER_PACK_KEY + " FROM " + TABLE_NAME + " WHERE " + STICKER_PACK_ID + " NOT IN (" + - "SELECT DISTINCT " + StickerDatabase.PACK_ID + " FROM " + StickerDatabase.TABLE_NAME + - ")"; - - return databaseHelper.getReadableDatabase().rawQuery(query, null); - } - public boolean hasStickerAttachments() { String selection = STICKER_PACK_ID + " NOT NULL"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java index 9994a78ace..ea534c35f8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java @@ -55,7 +55,6 @@ public class DatabaseFactory { private final GroupReceiptDatabase groupReceiptDatabase; private final SearchDatabase searchDatabase; private final JobDatabase jobDatabase; - private final StickerDatabase stickerDatabase; // Loki private final LokiAPIDatabase lokiAPIDatabase; @@ -130,10 +129,6 @@ public class DatabaseFactory { return getInstance(context).jobDatabase; } - public static StickerDatabase getStickerDatabase(Context context) { - return getInstance(context).stickerDatabase; - } - public static SQLiteDatabase getBackupDatabase(Context context) { return getInstance(context).databaseHelper.getReadableDatabase(); } @@ -199,7 +194,6 @@ public class DatabaseFactory { this.groupReceiptDatabase = new GroupReceiptDatabase(context, databaseHelper); this.searchDatabase = new SearchDatabase(context, databaseHelper); this.jobDatabase = new JobDatabase(context, databaseHelper); - this.stickerDatabase = new StickerDatabase(context, databaseHelper, attachmentSecret); this.lokiAPIDatabase = new LokiAPIDatabase(context, databaseHelper); this.lokiMessageDatabase = new LokiMessageDatabase(context, databaseHelper); this.lokiThreadDatabase = new LokiThreadDatabase(context, databaseHelper); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/StickerDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/StickerDatabase.java deleted file mode 100644 index 13634eecdf..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/database/StickerDatabase.java +++ /dev/null @@ -1,481 +0,0 @@ -package org.thoughtcrime.securesms.database; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.text.TextUtils; -import android.util.Pair; - -import net.sqlcipher.database.SQLiteDatabase; - -import org.greenrobot.eventbus.EventBus; -import org.thoughtcrime.securesms.crypto.AttachmentSecret; -import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream; -import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream; -import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; -import org.thoughtcrime.securesms.database.model.IncomingSticker; -import org.thoughtcrime.securesms.database.model.StickerPackRecord; -import org.thoughtcrime.securesms.database.model.StickerRecord; -import org.session.libsignal.utilities.logging.Log; -import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; -import org.thoughtcrime.securesms.stickers.BlessedPacks; -import org.thoughtcrime.securesms.stickers.StickerPackInstallEvent; -import org.session.libsession.utilities.Util; - -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public class StickerDatabase extends Database { - - private static final String TAG = Log.tag(StickerDatabase.class); - - public static final String TABLE_NAME = "sticker"; - public static final String _ID = "_id"; - static final String PACK_ID = "pack_id"; - private static final String PACK_KEY = "pack_key"; - private static final String PACK_TITLE = "pack_title"; - private static final String PACK_AUTHOR = "pack_author"; - private static final String STICKER_ID = "sticker_id"; - private static final String EMOJI = "emoji"; - private static final String COVER = "cover"; - private static final String INSTALLED = "installed"; - private static final String LAST_USED = "last_used"; - public static final String FILE_PATH = "file_path"; - public static final String FILE_LENGTH = "file_length"; - public static final String FILE_RANDOM = "file_random"; - - public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + - PACK_ID + " TEXT NOT NULL, " + - PACK_KEY + " TEXT NOT NULL, " + - PACK_TITLE + " TEXT NOT NULL, " + - PACK_AUTHOR + " TEXT NOT NULL, " + - STICKER_ID + " INTEGER, " + - COVER + " INTEGER, " + - EMOJI + " TEXT NOT NULL, " + - LAST_USED + " INTEGER, " + - INSTALLED + " INTEGER," + - FILE_PATH + " TEXT NOT NULL, " + - FILE_LENGTH + " INTEGER, " + - FILE_RANDOM + " BLOB, " + - "UNIQUE(" + PACK_ID + ", " + STICKER_ID + ", " + COVER + ") ON CONFLICT IGNORE)"; - - public static final String[] CREATE_INDEXES = { - "CREATE INDEX IF NOT EXISTS sticker_pack_id_index ON " + TABLE_NAME + " (" + PACK_ID + ");", - "CREATE INDEX IF NOT EXISTS sticker_sticker_id_index ON " + TABLE_NAME + " (" + STICKER_ID + ");" - }; - - private static final String DIRECTORY = "stickers"; - - private final AttachmentSecret attachmentSecret; - - public StickerDatabase(Context context, SQLCipherOpenHelper databaseHelper, AttachmentSecret attachmentSecret) { - super(context, databaseHelper); - this.attachmentSecret = attachmentSecret; - } - - public void insertSticker(@NonNull IncomingSticker sticker, @NonNull InputStream dataStream) throws IOException { - FileInfo fileInfo = saveStickerImage(dataStream); - ContentValues contentValues = new ContentValues(); - - contentValues.put(PACK_ID, sticker.getPackId()); - contentValues.put(PACK_KEY, sticker.getPackKey()); - contentValues.put(PACK_TITLE, sticker.getPackTitle()); - contentValues.put(PACK_AUTHOR, sticker.getPackAuthor()); - contentValues.put(STICKER_ID, sticker.getStickerId()); - contentValues.put(EMOJI, sticker.getEmoji()); - contentValues.put(COVER, sticker.isCover() ? 1 : 0); - contentValues.put(INSTALLED, sticker.isInstalled() ? 1 : 0); - contentValues.put(FILE_PATH, fileInfo.getFile().getAbsolutePath()); - contentValues.put(FILE_LENGTH, fileInfo.getLength()); - contentValues.put(FILE_RANDOM, fileInfo.getRandom()); - - long id = databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues); - - if (id > 0) { - notifyStickerListeners(); - - if (sticker.isCover()) { - notifyStickerPackListeners(); - - if (sticker.isInstalled()) { - broadcastInstallEvent(sticker.getPackId()); - } - } - } - } - - public @Nullable StickerRecord getSticker(@NonNull String packId, int stickerId, boolean isCover) { - String selection = PACK_ID + " = ? AND " + STICKER_ID + " = ? AND " + COVER + " = ?"; - String[] args = new String[] { packId, String.valueOf(stickerId), String.valueOf(isCover ? 1 : 0) }; - - try (Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, selection, args, null, null, "1")) { - return new StickerRecordReader(cursor).getNext(); - } - } - - public @Nullable StickerPackRecord getStickerPack(@NonNull String packId) { - String query = PACK_ID + " = ? AND " + COVER + " = ?"; - String[] args = new String[] { packId, "1" }; - - try (Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, query, args, null, null, null, "1")) { - return new StickerPackRecordReader(cursor).getNext(); - } - } - - public @Nullable Cursor getInstalledStickerPacks() { - String selection = COVER + " = ? AND " + INSTALLED + " = ?"; - String[] args = new String[] { "1", "1" }; - Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, selection, args, null, null, null); - - setNotifyStickerPackListeners(cursor); - return cursor; - } - - public @Nullable Cursor getStickersByEmoji(@NonNull String emoji) { - String selection = EMOJI + " LIKE ? AND " + COVER + " = ?"; - String[] args = new String[] { "%"+emoji+"%", "0" }; - - Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, selection, args, null, null, null); - setNotifyStickerListeners(cursor); - - return cursor; - } - - public @Nullable Cursor getAllStickerPacks() { - return getAllStickerPacks(null); - } - - public @Nullable Cursor getAllStickerPacks(@Nullable String limit) { - String query = COVER + " = ?"; - String[] args = new String[] { "1" }; - Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, query, args, null, null, null, limit); - setNotifyStickerPackListeners(cursor); - - return cursor; - } - - public @Nullable Cursor getStickersForPack(@NonNull String packId) { - SQLiteDatabase db = databaseHelper.getReadableDatabase(); - String selection = PACK_ID + " = ? AND " + COVER + " = ?"; - String[] args = new String[] { packId, "0" }; - - Cursor cursor = db.query(TABLE_NAME, null, selection, args, null, null, null); - setNotifyStickerListeners(cursor); - - return cursor; - } - - public @Nullable Cursor getRecentlyUsedStickers(int limit) { - SQLiteDatabase db = databaseHelper.getReadableDatabase(); - String selection = LAST_USED + " > ? AND " + COVER + " = ?"; - String[] args = new String[] { "0", "0" }; - - Cursor cursor = db.query(TABLE_NAME, null, selection, args, null, null, LAST_USED + " DESC", String.valueOf(limit)); - setNotifyStickerListeners(cursor); - - return cursor; - } - - public @Nullable InputStream getStickerStream(long rowId) throws IOException { - String selection = _ID + " = ?"; - String[] args = new String[] { String.valueOf(rowId) }; - - try (Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, selection, args, null, null, null)) { - if (cursor != null && cursor.moveToNext()) { - String path = cursor.getString(cursor.getColumnIndexOrThrow(FILE_PATH)); - byte[] random = cursor.getBlob(cursor.getColumnIndexOrThrow(FILE_RANDOM)); - - if (path != null) { - return ModernDecryptingPartInputStream.createFor(attachmentSecret, random, new File(path), 0); - } else { - Log.w(TAG, "getStickerStream("+rowId+") - No sticker data"); - } - } else { - Log.i(TAG, "getStickerStream("+rowId+") - Sticker not found."); - } - } - - return null; - } - - public boolean isPackInstalled(@NonNull String packId) { - StickerPackRecord record = getStickerPack(packId); - - return (record != null && record.isInstalled()); - } - - public boolean isPackAvailableAsReference(@NonNull String packId) { - return getStickerPack(packId) != null; - } - - public void updateStickerLastUsedTime(long rowId, long lastUsed) { - String selection = _ID + " = ?"; - String[] args = new String[] { String.valueOf(rowId) }; - ContentValues values = new ContentValues(); - - values.put(LAST_USED, lastUsed); - - databaseHelper.getWritableDatabase().update(TABLE_NAME, values, selection, args); - - notifyStickerListeners(); - notifyStickerPackListeners(); - } - - public void markPackAsInstalled(@NonNull String packKey) { - updatePackInstalled(databaseHelper.getWritableDatabase(), packKey, true); - notifyStickerPackListeners(); - } - - public void deleteOrphanedPacks() { - SQLiteDatabase db = databaseHelper.getWritableDatabase(); - String query = "SELECT " + PACK_ID + " FROM " + TABLE_NAME + " WHERE " + INSTALLED + " = ? AND " + - PACK_ID + " NOT IN (" + - "SELECT DISTINCT " + AttachmentDatabase.STICKER_PACK_ID + " FROM " + AttachmentDatabase.TABLE_NAME + " " + - "WHERE " + AttachmentDatabase.STICKER_PACK_ID + " NOT NULL" + - ")"; - String[] args = new String[] { "0" }; - - db.beginTransaction(); - - try { - boolean performedDelete = false; - - try (Cursor cursor = db.rawQuery(query, args)) { - while (cursor != null && cursor.moveToNext()) { - String packId = cursor.getString(cursor.getColumnIndexOrThrow(PACK_ID)); - - if (!BlessedPacks.contains(packId)) { - deletePack(db, packId); - performedDelete = true; - } - } - } - - db.setTransactionSuccessful(); - - if (performedDelete) { - notifyStickerPackListeners(); - notifyStickerListeners(); - } - } finally { - db.endTransaction(); - } - } - - public void uninstallPack(@NonNull String packId) { - SQLiteDatabase db = databaseHelper.getWritableDatabase(); - - db.beginTransaction(); - try { - - updatePackInstalled(db, packId, false); - deleteStickersInPackExceptCover(db, packId); - - db.setTransactionSuccessful(); - notifyStickerPackListeners(); - notifyStickerListeners(); - } finally { - db.endTransaction(); - } - } - - private void updatePackInstalled(@NonNull SQLiteDatabase db, @NonNull String packId, boolean installed) { - StickerPackRecord existing = getStickerPack(packId); - - if (existing != null && existing.isInstalled() == installed) { - return; - } - - String selection = PACK_ID + " = ?"; - String[] args = new String[]{ packId }; - ContentValues values = new ContentValues(1); - - values.put(INSTALLED, installed ? 1 : 0); - db.update(TABLE_NAME, values, selection, args); - - if (installed) { - broadcastInstallEvent(packId); - } - } - - private FileInfo saveStickerImage(@NonNull InputStream inputStream) throws IOException { - File partsDirectory = context.getDir(DIRECTORY, Context.MODE_PRIVATE); - File file = File.createTempFile("sticker", ".mms", partsDirectory); - Pair out = ModernEncryptingPartOutputStream.createFor(attachmentSecret, file, false); - long length = Util.copy(inputStream, out.second); - - return new FileInfo(file, length, out.first); - } - - private void deleteSticker(@NonNull SQLiteDatabase db, long rowId, @Nullable String filePath) { - String selection = _ID + " = ?"; - String[] args = new String[] { String.valueOf(rowId) }; - - db.delete(TABLE_NAME, selection, args); - - if (!TextUtils.isEmpty(filePath)) { - new File(filePath).delete(); - } - } - - private void deletePack(@NonNull SQLiteDatabase db, @NonNull String packId) { - String selection = PACK_ID + " = ?"; - String[] args = new String[] { packId }; - - db.delete(TABLE_NAME, selection, args); - - deleteStickersInPack(db, packId); - } - - private void deleteStickersInPack(@NonNull SQLiteDatabase db, @NonNull String packId) { - String selection = PACK_ID + " = ?"; - String[] args = new String[] { packId }; - - db.beginTransaction(); - - try { - try (Cursor cursor = db.query(TABLE_NAME, null, selection, args, null, null, null)) { - while (cursor != null && cursor.moveToNext()) { - String filePath = cursor.getString(cursor.getColumnIndexOrThrow(FILE_PATH)); - long rowId = cursor.getLong(cursor.getColumnIndexOrThrow(_ID)); - - deleteSticker(db, rowId, filePath); - } - } - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - db.delete(TABLE_NAME, selection, args); - } - - private void deleteStickersInPackExceptCover(@NonNull SQLiteDatabase db, @NonNull String packId) { - String selection = PACK_ID + " = ? AND " + COVER + " = ?"; - String[] args = new String[] { packId, "0" }; - - db.beginTransaction(); - - try { - try (Cursor cursor = db.query(TABLE_NAME, null, selection, args, null, null, null)) { - while (cursor != null && cursor.moveToNext()) { - long rowId = cursor.getLong(cursor.getColumnIndexOrThrow(_ID)); - String filePath = cursor.getString(cursor.getColumnIndexOrThrow(FILE_PATH)); - - deleteSticker(db, rowId, filePath); - } - } - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - private void broadcastInstallEvent(@NonNull String packId) { - StickerPackRecord pack = getStickerPack(packId); - - if (pack != null) { - EventBus.getDefault().postSticky(new StickerPackInstallEvent(new DecryptableUri(pack.getCover().getUri()))); - } - } - - private static final class FileInfo { - private final File file; - private final long length; - private final byte[] random; - - private FileInfo(@NonNull File file, long length, @NonNull byte[] random) { - this.file = file; - this.length = length; - this.random = random; - } - - public File getFile() { - return file; - } - - public long getLength() { - return length; - } - - public byte[] getRandom() { - return random; - } - } - - public static final class StickerRecordReader implements Closeable { - - private final Cursor cursor; - - public StickerRecordReader(@Nullable Cursor cursor) { - this.cursor = cursor; - } - - public @Nullable StickerRecord getNext() { - if (cursor == null || !cursor.moveToNext()) { - return null; - } - - return getCurrent(); - } - - public @NonNull StickerRecord getCurrent() { - return new StickerRecord(cursor.getLong(cursor.getColumnIndexOrThrow(_ID)), - cursor.getString(cursor.getColumnIndexOrThrow(PACK_ID)), - cursor.getString(cursor.getColumnIndexOrThrow(PACK_KEY)), - cursor.getInt(cursor.getColumnIndexOrThrow(STICKER_ID)), - cursor.getString(cursor.getColumnIndexOrThrow(EMOJI)), - cursor.getLong(cursor.getColumnIndexOrThrow(FILE_LENGTH)), - cursor.getInt(cursor.getColumnIndexOrThrow(COVER)) == 1); - } - - @Override - public void close() { - if (cursor != null) { - cursor.close(); - } - } - } - - public static final class StickerPackRecordReader implements Closeable { - - private final Cursor cursor; - - public StickerPackRecordReader(@Nullable Cursor cursor) { - this.cursor = cursor; - } - - public @Nullable StickerPackRecord getNext() { - if (cursor == null || !cursor.moveToNext()) { - return null; - } - - return getCurrent(); - } - - public @NonNull StickerPackRecord getCurrent() { - StickerRecord cover = new StickerRecordReader(cursor).getCurrent(); - - return new StickerPackRecord(cursor.getString(cursor.getColumnIndexOrThrow(PACK_ID)), - cursor.getString(cursor.getColumnIndexOrThrow(PACK_KEY)), - cursor.getString(cursor.getColumnIndexOrThrow(PACK_TITLE)), - cursor.getString(cursor.getColumnIndexOrThrow(PACK_AUTHOR)), - cover, - cursor.getInt(cursor.getColumnIndexOrThrow(INSTALLED)) == 1); - } - - @Override - public void close() { - if (cursor != null) { - cursor.close(); - } - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index 4e81149342..2a4e6e0056 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -21,7 +21,6 @@ import org.thoughtcrime.securesms.database.PushDatabase; import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.database.SearchDatabase; import org.thoughtcrime.securesms.database.SmsDatabase; -import org.thoughtcrime.securesms.database.StickerDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase; import org.session.libsignal.utilities.logging.Log; import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase; @@ -97,8 +96,6 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { for (String sql : JobDatabase.CREATE_TABLE) { db.execSQL(sql); } - db.execSQL(StickerDatabase.CREATE_TABLE); - db.execSQL(LokiAPIDatabase.getCreateSnodePoolTableCommand()); db.execSQL(LokiAPIDatabase.getCreateOnionRequestPathTableCommand()); db.execSQL(LokiAPIDatabase.getCreateSwarmTableCommand()); @@ -132,7 +129,6 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { executeStatements(db, DraftDatabase.CREATE_INDEXS); executeStatements(db, GroupDatabase.CREATE_INDEXS); executeStatements(db, GroupReceiptDatabase.CREATE_INDEXES); - executeStatements(db, StickerDatabase.CREATE_INDEXES); } @Override @@ -246,7 +242,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { if (oldVersion < lokiV21) { deleteJobRecords(db, "ClosedGroupUpdateMessageSendJob", - "NullMessageSendJob"); + "NullMessageSendJob", + "StickerDownloadJob", + "StickerPackDownloadJob"); } db.setTransactionSuccessful(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java b/app/src/main/java/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java index 1e2aab477f..62d7e5a092 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java @@ -6,8 +6,6 @@ import org.session.libsignal.libsignal.util.guava.Optional; import org.session.libsignal.service.api.SignalServiceMessageReceiver; import org.session.libsignal.service.api.SignalServiceMessageSender; import org.session.libsignal.service.api.util.CredentialsProvider; -import org.session.libsignal.service.api.util.SleepTimer; -import org.session.libsignal.service.api.util.UptimeSleepTimer; import org.session.libsignal.service.api.websocket.ConnectivityListener; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl; @@ -24,16 +22,11 @@ import org.thoughtcrime.securesms.jobs.RequestGroupInfoJob; import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob; import org.thoughtcrime.securesms.jobs.SendDeliveryReceiptJob; import org.thoughtcrime.securesms.jobs.SendReadReceiptJob; -import org.thoughtcrime.securesms.jobs.StickerDownloadJob; -import org.thoughtcrime.securesms.jobs.StickerPackDownloadJob; import org.thoughtcrime.securesms.jobs.TypingSendJob; import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository; import org.session.libsignal.utilities.logging.Log; import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl; import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment; -import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess; -import org.thoughtcrime.securesms.stickers.StickerPackPreviewRepository; -import org.thoughtcrime.securesms.stickers.StickerRemoteUriLoader; import org.thoughtcrime.securesms.util.RealtimeSleepTimer; import org.session.libsession.utilities.TextSecurePreferences; @@ -55,10 +48,6 @@ import network.loki.messenger.BuildConfig; TypingSendJob.class, AttachmentUploadJob.class, PushDecryptJob.class, - StickerDownloadJob.class, - StickerPackPreviewRepository.class, - StickerRemoteUriLoader.Factory.class, - StickerPackDownloadJob.class, LinkPreviewRepository.class}) public class SignalCommunicationModule { @@ -95,12 +84,7 @@ public class SignalCommunicationModule { @Provides synchronized SignalServiceMessageReceiver provideSignalMessageReceiver() { if (this.messageReceiver == null) { - SleepTimer sleepTimer = TextSecurePreferences.isFcmDisabled(context) ? new RealtimeSleepTimer(context) : new UptimeSleepTimer(); - - this.messageReceiver = new SignalServiceMessageReceiver(new DynamicCredentialsProvider(context), - BuildConfig.USER_AGENT, - new PipeConnectivityListener(), - sleepTimer); + this.messageReceiver = new SignalServiceMessageReceiver(); } return this.messageReceiver; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java index a55637783b..3333555dc6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/JobManagerFactories.java @@ -45,7 +45,6 @@ public final class JobManagerFactories { put(PushGroupSendJob.KEY, new PushGroupSendJob.Factory()); put(PushGroupUpdateJob.KEY, new PushGroupUpdateJob.Factory()); put(PushMediaSendJob.KEY, new PushMediaSendJob.Factory()); - put(PushNotificationReceiveJob.KEY, new PushNotificationReceiveJob.Factory()); put(PushTextSendJob.KEY, new PushTextSendJob.Factory()); put(RequestGroupInfoJob.KEY, new RequestGroupInfoJob.Factory()); put(RetrieveProfileAvatarJob.KEY, new RetrieveProfileAvatarJob.Factory(application)); @@ -54,8 +53,6 @@ public final class JobManagerFactories { put(SmsReceiveJob.KEY, new SmsReceiveJob.Factory()); put(SmsSendJob.KEY, new SmsSendJob.Factory()); put(SmsSentJob.KEY, new SmsSentJob.Factory()); - put(StickerDownloadJob.KEY, new StickerDownloadJob.Factory()); - put(StickerPackDownloadJob.KEY, new StickerPackDownloadJob.Factory()); put(TrimThreadJob.KEY, new TrimThreadJob.Factory()); put(TypingSendJob.KEY, new TypingSendJob.Factory()); put(UpdateApkJob.KEY, new UpdateApkJob.Factory()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/StickerDownloadJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/StickerDownloadJob.java deleted file mode 100644 index 52a927f8aa..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/StickerDownloadJob.java +++ /dev/null @@ -1,119 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import androidx.annotation.NonNull; - -import org.session.libsession.messaging.jobs.Data; -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.StickerDatabase; -import org.thoughtcrime.securesms.database.model.IncomingSticker; -import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.session.libsignal.utilities.logging.Log; -import org.session.libsignal.utilities.Hex; -import org.session.libsignal.service.api.SignalServiceMessageReceiver; -import org.session.libsignal.service.api.push.exceptions.PushNetworkException; - -import java.io.InputStream; -import java.util.concurrent.TimeUnit; - -import javax.inject.Inject; - -public class StickerDownloadJob extends BaseJob implements InjectableType { - - public static final String KEY = "StickerDownloadJob"; - - private static final String TAG = Log.tag(StickerDownloadJob.class); - - private static final String KEY_PACK_ID = "pack_id"; - private static final String KEY_PACK_KEY = "pack_key"; - private static final String KEY_PACK_TITLE = "pack_title"; - private static final String KEY_PACK_AUTHOR = "pack_author"; - private static final String KEY_STICKER_ID = "sticker_id"; - private static final String KEY_EMOJI = "emoji"; - private static final String KEY_COVER = "cover"; - private static final String KEY_INSTALLED = "installed"; - - private final IncomingSticker sticker; - - @Inject SignalServiceMessageReceiver receiver; - - public StickerDownloadJob(@NonNull IncomingSticker sticker) { - this(new Job.Parameters.Builder() - .addConstraint(NetworkConstraint.KEY) - .setLifespan(TimeUnit.DAYS.toMillis(1)) - .build(), - sticker); - } - - private StickerDownloadJob(@NonNull Job.Parameters parameters, @NonNull IncomingSticker sticker) { - super(parameters); - this.sticker = sticker; - } - - @Override - protected void onRun() throws Exception { - StickerDatabase db = DatabaseFactory.getStickerDatabase(context); - - if (db.getSticker(sticker.getPackId(), sticker.getStickerId(), sticker.isCover()) != null) { - Log.w(TAG, "Sticker already downloaded."); - return; - } - - if (!db.isPackInstalled(sticker.getPackId()) && !sticker.isCover()) { - Log.w(TAG, "Pack is no longer installed."); - return; - } - - byte[] packIdBytes = Hex.fromStringCondensed(sticker.getPackId()); - byte[] packKeyBytes = Hex.fromStringCondensed(sticker.getPackKey()); - InputStream stream = receiver.retrieveSticker(packIdBytes, packKeyBytes, sticker.getStickerId()); - - db.insertSticker(sticker, stream); - } - - @Override - protected boolean onShouldRetry(@NonNull Exception e) { - return e instanceof PushNetworkException; - } - - @Override - public @NonNull - Data serialize() { - return new Data.Builder().putString(KEY_PACK_ID, sticker.getPackId()) - .putString(KEY_PACK_KEY, sticker.getPackKey()) - .putString(KEY_PACK_TITLE, sticker.getPackTitle()) - .putString(KEY_PACK_AUTHOR, sticker.getPackAuthor()) - .putInt(KEY_STICKER_ID, sticker.getStickerId()) - .putString(KEY_EMOJI, sticker.getEmoji()) - .putBoolean(KEY_COVER, sticker.isCover()) - .putBoolean(KEY_INSTALLED, sticker.isInstalled()) - .build(); - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public void onCanceled() { - Log.w(TAG, "Failed to download sticker!"); - } - - public static final class Factory implements Job.Factory { - @Override - public @NonNull StickerDownloadJob create(@NonNull Parameters parameters, @NonNull Data data) { - IncomingSticker sticker = new IncomingSticker(data.getString(KEY_PACK_ID), - data.getString(KEY_PACK_KEY), - data.getString(KEY_PACK_TITLE), - data.getString(KEY_PACK_AUTHOR), - data.getInt(KEY_STICKER_ID), - data.getString(KEY_EMOJI), - data.getBoolean(KEY_COVER), - data.getBoolean(KEY_INSTALLED)); - - return new StickerDownloadJob(parameters, sticker); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/StickerPackDownloadJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/StickerPackDownloadJob.java deleted file mode 100644 index b1c2f6aa36..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/StickerPackDownloadJob.java +++ /dev/null @@ -1,161 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - -import androidx.annotation.NonNull; - -import org.session.libsession.messaging.jobs.Data; -import org.thoughtcrime.securesms.ApplicationContext; -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.StickerDatabase; -import org.thoughtcrime.securesms.database.model.IncomingSticker; -import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.JobManager; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.session.libsignal.utilities.logging.Log; -import org.session.libsignal.utilities.Hex; -import org.session.libsignal.libsignal.InvalidMessageException; -import org.session.libsignal.service.api.SignalServiceMessageReceiver; -import org.session.libsignal.service.api.messages.SignalServiceStickerManifest; -import org.session.libsignal.service.api.messages.SignalServiceStickerManifest.StickerInfo; -import org.session.libsignal.service.api.push.exceptions.PushNetworkException; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import javax.inject.Inject; - -public class StickerPackDownloadJob extends BaseJob implements InjectableType { - - public static final String KEY = "StickerPackDownloadJob"; - - private static final String TAG = Log.tag(StickerPackDownloadJob.class); - - private static final String KEY_PACK_ID = "pack_key"; - private static final String KEY_PACK_KEY = "pack_id"; - private static final String KEY_REFERENCE_PACK = "reference_pack"; - - private final String packId; - private final String packKey; - private final boolean isReferencePack; - - @Inject SignalServiceMessageReceiver receiver; - - public StickerPackDownloadJob(@NonNull String packId, @NonNull String packKey, boolean isReferencePack) - { - this(new Parameters.Builder() - .addConstraint(NetworkConstraint.KEY) - .setLifespan(TimeUnit.DAYS.toMillis(1)) - .setQueue("StickerPackDownloadJob_" + packKey) - .build(), - packId, - packKey, - isReferencePack); - } - - private StickerPackDownloadJob(@NonNull Parameters parameters, - @NonNull String packId, - @NonNull String packKey, - boolean isReferencePack) - { - super(parameters); - this.packId = packId; - this.packKey = packKey; - this.isReferencePack = isReferencePack; - } - - @Override - protected void onRun() throws IOException, InvalidMessageException { - if (isReferencePack && !DatabaseFactory.getAttachmentDatabase(context).containsStickerPackId(packId)) { - Log.w(TAG, "There are no attachments with the requested packId present for this reference pack. Skipping."); - return; - } - - if (isReferencePack && DatabaseFactory.getStickerDatabase(context).isPackAvailableAsReference(packId)) { - Log.i(TAG, "Sticker pack already available for reference. Skipping."); - return; - } - - JobManager jobManager = ApplicationContext.getInstance(context).getJobManager(); - StickerDatabase stickerDatabase = DatabaseFactory.getStickerDatabase(context); - byte[] packIdBytes = Hex.fromStringCondensed(packId); - byte[] packKeyBytes = Hex.fromStringCondensed(packKey); - SignalServiceStickerManifest manifest = receiver.retrieveStickerManifest(packIdBytes, packKeyBytes); - - if (manifest.getStickers().isEmpty()) { - Log.w(TAG, "No stickers in pack!"); - return; - } - - if (!isReferencePack && stickerDatabase.isPackAvailableAsReference(packId)) { - stickerDatabase.markPackAsInstalled(packId); - } - - StickerInfo cover = manifest.getCover().or(manifest.getStickers().get(0)); - JobManager.Chain chain = jobManager.startChain(new StickerDownloadJob(new IncomingSticker(packId, - packKey, - manifest.getTitle().or(""), - manifest.getAuthor().or(""), - cover.getId(), - "", - true, - !isReferencePack))); - - - - if (!isReferencePack) { - List jobs = new ArrayList<>(manifest.getStickers().size()); - - for (StickerInfo stickerInfo : manifest.getStickers()) { - jobs.add(new StickerDownloadJob(new IncomingSticker(packId, - packKey, - manifest.getTitle().or(""), - manifest.getAuthor().or(""), - stickerInfo.getId(), - stickerInfo.getEmoji(), - false, - true))); - } - - chain.then(jobs); - } - - chain.enqueue(); - } - - @Override - protected boolean onShouldRetry(@NonNull Exception e) { - return e instanceof PushNetworkException; - } - - @Override - public @NonNull - Data serialize() { - return new Data.Builder().putString(KEY_PACK_ID, packId) - .putString(KEY_PACK_KEY, packKey) - .putBoolean(KEY_REFERENCE_PACK, isReferencePack) - .build(); - } - - @Override - public @NonNull String getFactoryKey() { - return KEY; - } - - @Override - public void onCanceled() { - Log.w(TAG, "Failed to download manifest with pack_id: " + packId); - } - - public static final class Factory implements Job.Factory { - @Override - public @NonNull - StickerPackDownloadJob create(@NonNull Parameters parameters, @NonNull Data data) { - return new StickerPackDownloadJob(parameters, - data.getString(KEY_PACK_ID), - data.getString(KEY_PACK_KEY), - data.getBoolean(KEY_REFERENCE_PACK)); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewRepository.java b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewRepository.java index 06560b4740..878f11e911 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewRepository.java @@ -7,30 +7,20 @@ import android.net.Uri; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.google.android.gms.common.util.IOUtils; - import org.session.libsession.utilities.MediaTypes; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.database.AttachmentDatabase; import org.thoughtcrime.securesms.dependencies.InjectableType; import org.session.libsignal.utilities.logging.Log; -import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.net.CallRequestController; import org.thoughtcrime.securesms.net.CompositeRequestController; import org.thoughtcrime.securesms.net.ContentProxySafetyInterceptor; import org.thoughtcrime.securesms.net.RequestController; import org.thoughtcrime.securesms.providers.BlobProvider; -import org.thoughtcrime.securesms.stickers.StickerRemoteUri; -import org.thoughtcrime.securesms.stickers.StickerUrl; -import org.session.libsignal.utilities.Hex; -import org.session.libsignal.libsignal.InvalidMessageException; -import org.session.libsignal.libsignal.util.Pair; import org.session.libsignal.libsignal.util.guava.Optional; import org.session.libsignal.service.api.SignalServiceMessageReceiver; -import org.session.libsignal.service.api.messages.SignalServiceStickerManifest; -import org.session.libsignal.service.api.messages.SignalServiceStickerManifest.StickerInfo; import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil.OpenGraph; import org.session.libsession.messaging.sending_receiving.attachments.Attachment; @@ -41,7 +31,6 @@ import org.session.libsession.utilities.concurrent.SignalExecutors; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.util.concurrent.ExecutionException; import javax.inject.Inject; @@ -82,31 +71,27 @@ public class LinkPreviewRepository implements InjectableType { RequestController metadataController; - if (StickerUrl.isValidShareLink(url)) { - metadataController = fetchStickerPackLinkPreview(context, url, callback); - } else { - metadataController = fetchMetadata(url, metadata -> { - if (metadata.isEmpty()) { + metadataController = fetchMetadata(url, metadata -> { + if (metadata.isEmpty()) { + callback.onComplete(Optional.absent()); + return; + } + + if (!metadata.getImageUrl().isPresent()) { + callback.onComplete(Optional.of(new LinkPreview(url, metadata.getTitle().get(), Optional.absent()))); + return; + } + + RequestController imageController = fetchThumbnail(context, metadata.getImageUrl().get(), attachment -> { + if (!metadata.getTitle().isPresent() && !attachment.isPresent()) { callback.onComplete(Optional.absent()); - return; + } else { + callback.onComplete(Optional.of(new LinkPreview(url, metadata.getTitle().or(""), attachment))); } - - if (!metadata.getImageUrl().isPresent()) { - callback.onComplete(Optional.of(new LinkPreview(url, metadata.getTitle().get(), Optional.absent()))); - return; - } - - RequestController imageController = fetchThumbnail(context, metadata.getImageUrl().get(), attachment -> { - if (!metadata.getTitle().isPresent() && !attachment.isPresent()) { - callback.onComplete(Optional.absent()); - } else { - callback.onComplete(Optional.of(new LinkPreview(url, metadata.getTitle().or(""), attachment))); - } - }); - - compositeController.addController(imageController); }); - } + + compositeController.addController(imageController); + }); compositeController.addController(metadataController); return compositeController; @@ -190,66 +175,6 @@ public class LinkPreviewRepository implements InjectableType { return controller; } - private RequestController fetchStickerPackLinkPreview(@NonNull Context context, - @NonNull String packUrl, - @NonNull Callback> callback) - { - SignalExecutors.UNBOUNDED.execute(() -> { - try { - Pair stickerParams = StickerUrl.parseShareLink(packUrl).or(new Pair<>("", "")); - String packIdString = stickerParams.first(); - String packKeyString = stickerParams.second(); - byte[] packIdBytes = Hex.fromStringCondensed(packIdString); - byte[] packKeyBytes = Hex.fromStringCondensed(packKeyString); - - SignalServiceStickerManifest manifest = messageReceiver.retrieveStickerManifest(packIdBytes, packKeyBytes); - - String title = manifest.getTitle().or(manifest.getAuthor()).or(""); - Optional firstSticker = Optional.fromNullable(manifest.getStickers().size() > 0 ? manifest.getStickers().get(0) : null); - Optional cover = manifest.getCover().or(firstSticker); - - if (cover.isPresent()) { - Bitmap bitmap = GlideApp.with(context).asBitmap() - .load(new StickerRemoteUri(packIdString, packKeyString, cover.get().getId())) - .skipMemoryCache(true) - .diskCacheStrategy(DiskCacheStrategy.NONE) - .centerInside() - .submit(512, 512) - .get(); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - bitmap.compress(Bitmap.CompressFormat.WEBP, 80, baos); - - byte[] bytes = baos.toByteArray(); - Uri uri = BlobProvider.getInstance().forData(bytes).createForSingleSessionInMemory(); - Optional thumbnail = Optional.of(new UriAttachment(uri, - uri, - MediaTypes.IMAGE_WEBP, - AttachmentDatabase.TRANSFER_PROGRESS_STARTED, - bytes.length, - bitmap.getWidth(), - bitmap.getHeight(), - null, - null, - false, - false, - null, - null)); - - callback.onComplete(Optional.of(new LinkPreview(packUrl, title, thumbnail))); - } else { - callback.onComplete(Optional.absent()); - } - } catch (IOException | InvalidMessageException | ExecutionException | InterruptedException e) { - Log.w(TAG, "Failed to fetch sticker pack link preview."); - callback.onComplete(Optional.absent()); - } - }); - - return () -> Log.i(TAG, "Cancelled sticker pack link preview fetch -- no effect."); - } - private static Optional bitmapToAttachment(@Nullable Bitmap bitmap, @NonNull Bitmap.CompressFormat format, @NonNull String contentType) diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java index 0a05c95b56..222b049a7b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java @@ -12,7 +12,6 @@ import android.text.util.Linkify; import com.annimon.stream.Stream; -import org.thoughtcrime.securesms.stickers.StickerUrl; import org.thoughtcrime.securesms.util.DateUtils; import org.session.libsignal.libsignal.util.guava.Optional; @@ -62,7 +61,6 @@ public final class LinkPreviewUtil { */ public static boolean isValidLinkUrl(@Nullable String linkUrl) { if (linkUrl == null) return false; - if (StickerUrl.isValidShareLink(linkUrl)) return true; HttpUrl url = HttpUrl.parse(linkUrl); return url != null && diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/PartAuthority.java b/app/src/main/java/org/thoughtcrime/securesms/mms/PartAuthority.java index e82332c310..0169e57c0a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/PartAuthority.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/PartAuthority.java @@ -52,7 +52,6 @@ public class PartAuthority { switch (match) { case PART_ROW: return DatabaseFactory.getAttachmentDatabase(context).getAttachmentStream(new PartUriParser(uri).getPartId(), 0); case THUMB_ROW: return DatabaseFactory.getAttachmentDatabase(context).getThumbnailStream(new PartUriParser(uri).getPartId()); - case STICKER_ROW: return DatabaseFactory.getStickerDatabase(context).getStickerStream(ContentUris.parseId(uri)); case PERSISTENT_ROW: return DeprecatedPersistentBlobProvider.getInstance(context).getStream(context, ContentUris.parseId(uri)); case BLOB_ROW: return BlobProvider.getInstance().getStream(context, uri); default: return context.getContentResolver().openInputStream(uri); diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java b/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java index a15f9ef06f..1d03cfb2f1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java @@ -34,8 +34,6 @@ import org.thoughtcrime.securesms.glide.cache.EncryptedGifCacheDecoder; import org.thoughtcrime.securesms.glide.cache.EncryptedGifDrawableResourceEncoder; import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; -import org.thoughtcrime.securesms.stickers.StickerRemoteUri; -import org.thoughtcrime.securesms.stickers.StickerRemoteUriLoader; import java.io.File; import java.io.InputStream; @@ -71,7 +69,6 @@ public class SignalGlideModule extends AppGlideModule { registry.append(DecryptableUri.class, InputStream.class, new DecryptableStreamUriLoader.Factory(context)); registry.append(AttachmentModel.class, InputStream.class, new AttachmentStreamUriLoader.Factory()); registry.append(ChunkedImageUrl.class, InputStream.class, new ChunkedImageUrlLoader.Factory()); - registry.append(StickerRemoteUri.class, InputStream.class, new StickerRemoteUriLoader.Factory(context)); registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/BootReceiver.java b/app/src/main/java/org/thoughtcrime/securesms/service/BootReceiver.java index 7435a6acee..f09e017cbe 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/BootReceiver.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/BootReceiver.java @@ -4,13 +4,9 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import org.thoughtcrime.securesms.ApplicationContext; -import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob; - public class BootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - ApplicationContext.getInstance(context).getJobManager().add(new PushNotificationReceiveJob(context)); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/BlessedPacks.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/BlessedPacks.java deleted file mode 100644 index 9aa2a3b46c..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/BlessedPacks.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import androidx.annotation.NonNull; - -import java.util.HashSet; -import java.util.Set; - -/** - * Maintains a list of "blessed" sticker packs that essentially serve as defaults. - */ -public final class BlessedPacks { - - private static final Set BLESSED_PACK_IDS = new HashSet<>(); - - public static boolean contains(@NonNull String packId) { - return BLESSED_PACK_IDS.contains(packId); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardPageAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardPageAdapter.java deleted file mode 100644 index 8e19a66543..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardPageAdapter.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.Px; -import androidx.recyclerview.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; - -import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; - - -import org.thoughtcrime.securesms.database.model.StickerRecord; -import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; -import org.thoughtcrime.securesms.mms.GlideRequests; - -import java.util.ArrayList; -import java.util.List; - -import network.loki.messenger.R; - -/** - * Adapter for a specific page in the sticker keyboard. Shows the stickers in a grid. - * @see StickerKeyboardPageFragment - */ -final class StickerKeyboardPageAdapter extends RecyclerView.Adapter { - - private final GlideRequests glideRequests; - private final EventListener eventListener; - private final List stickers; - - private int stickerSize; - - StickerKeyboardPageAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) { - this.glideRequests = glideRequests; - this.eventListener = eventListener; - 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); - } - - @Override - public void onViewRecycled(@NonNull StickerKeyboardPageViewHolder holder) { - holder.recycle(); - } - - @Override - public int getItemCount() { - return stickers.size(); - } - - void setStickers(@NonNull List stickers, @Px int stickerSize) { - this.stickers.clear(); - this.stickers.addAll(stickers); - - this.stickerSize = stickerSize; - - notifyDataSetChanged(); - } - - 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) - { - currentSticker = sticker; - - itemView.getLayoutParams().height = size; - itemView.getLayoutParams().width = size; - itemView.requestLayout(); - - glideRequests.load(new DecryptableUri(sticker.getUri())) - .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; - } - } - - interface EventListener { - void onStickerClicked(@NonNull StickerRecord sticker); - void onStickerLongClicked(@NonNull View targetView); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardPageFragment.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardPageFragment.java deleted file mode 100644 index edc4d3664a..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardPageFragment.java +++ /dev/null @@ -1,217 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import androidx.lifecycle.ViewModelProviders; -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Point; -import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.Px; -import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.GridLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; - - - -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.model.StickerRecord; -import org.session.libsignal.utilities.logging.Log; -import org.thoughtcrime.securesms.mms.GlideApp; -import org.thoughtcrime.securesms.mms.GlideRequests; -import org.thoughtcrime.securesms.stickers.StickerKeyboardPageAdapter.StickerKeyboardPageViewHolder; -import org.session.libsession.utilities.ViewUtil; - -import network.loki.messenger.R; - -/** - * An individual page of stickers in the {@link StickerKeyboardProvider}. - */ -public final class StickerKeyboardPageFragment extends Fragment implements StickerKeyboardPageAdapter.EventListener { - - private static final String TAG = Log.tag(StickerKeyboardPageFragment.class); - - private static final String KEY_PACK_ID = "pack_id"; - - public static final String RECENT_PACK_ID = StickerKeyboardPageViewModel.RECENT_PACK_ID; - - private RecyclerView list; - private StickerKeyboardPageAdapter adapter; - private GridLayoutManager layoutManager; - - private StickerKeyboardPageViewModel viewModel; - private EventListener eventListener; - private ListTouchListener listTouchListener; - - private String packId; - - public static StickerKeyboardPageFragment newInstance(@NonNull String packId) { - Bundle args = new Bundle(); - args.putString(KEY_PACK_ID, packId); - - StickerKeyboardPageFragment fragment = new StickerKeyboardPageFragment(); - fragment.setArguments(args); - fragment.packId = packId; - - return fragment; - } - - @Override - public @Nullable View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.sticker_keyboard_page, container, false); - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - GlideRequests glideRequests = GlideApp.with(this); - - this.list = view.findViewById(R.id.sticker_keyboard_list); - this.adapter = new StickerKeyboardPageAdapter(glideRequests, this); - this.layoutManager = new GridLayoutManager(requireContext(), 2); - this.listTouchListener = new ListTouchListener(requireContext(), glideRequests); - this.packId = getArguments().getString(KEY_PACK_ID); - - list.setLayoutManager(layoutManager); - list.setAdapter(adapter); - list.addOnItemTouchListener(listTouchListener); - - initViewModel(packId); - onScreenWidthChanged(getScreenWidth()); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - onScreenWidthChanged(getScreenWidth()); - } - - @Override - public void onStickerClicked(@NonNull StickerRecord sticker) { - if (eventListener != null) { - eventListener.onStickerSelected(sticker); - } - } - - @Override - public void onStickerLongClicked(@NonNull View targetView) { - if (listTouchListener != null) { - listTouchListener.enterHoverMode(list, targetView); - } - } - - public void setEventListener(@NonNull EventListener eventListener) { - this.eventListener = eventListener; - } - - public @NonNull String getPackId() { - return packId; - } - - private void initViewModel(@NonNull String packId) { - StickerKeyboardRepository repository = new StickerKeyboardRepository(DatabaseFactory.getStickerDatabase(requireContext())); - viewModel = ViewModelProviders.of(this, new StickerKeyboardPageViewModel.Factory(requireActivity().getApplication(), repository)).get(StickerKeyboardPageViewModel.class); - - viewModel.getStickers(packId).observe(getViewLifecycleOwner(), stickerRecords -> { - if (stickerRecords == null) return; - - adapter.setStickers(stickerRecords, calculateStickerSize(getScreenWidth())); - }); - } - - private void onScreenWidthChanged(@Px int newWidth) { - if (layoutManager != null) { - layoutManager.setSpanCount(calculateColumnCount(newWidth)); - adapter.setStickerSize(calculateStickerSize(newWidth)); - } - } - - private int getScreenWidth() { - Point size = new Point(); - requireActivity().getWindowManager().getDefaultDisplay().getSize(size); - return size.x; - } - - private int calculateColumnCount(@Px int screenWidth) { - float modifier = getResources().getDimensionPixelOffset(R.dimen.sticker_page_item_padding); - float divisor = getResources().getDimensionPixelOffset(R.dimen.sticker_page_item_divisor); - return (int) ((screenWidth - modifier) / divisor); - } - - private int calculateStickerSize(@Px int screenWidth) { - float multiplier = getResources().getDimensionPixelOffset(R.dimen.sticker_page_item_multiplier); - int columnCount = calculateColumnCount(screenWidth); - - return (int) ((screenWidth - ((columnCount + 1) * multiplier)) / columnCount); - } - - private final class ListTouchListener implements RecyclerView.OnItemTouchListener { - - private final StickerPreviewPopup popup; - - private boolean hoverMode; - - ListTouchListener(@NonNull Context context, @NonNull GlideRequests glideRequests) { - this.popup = new StickerPreviewPopup(context, glideRequests); - popup.setAnimationStyle(R.style.StickerPopupAnimation); - } - - @Override - public boolean onInterceptTouchEvent(@NonNull RecyclerView recyclerView, @NonNull MotionEvent motionEvent) { - return hoverMode; - } - - @Override - public void onTouchEvent(@NonNull RecyclerView recyclerView, @NonNull MotionEvent motionEvent) { - switch (motionEvent.getAction()) { - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - hoverMode = false; - popup.dismiss(); - eventListener.onStickerPopupEnded(); - break; - default: - for (int i = 0, len = recyclerView.getChildCount(); i < len; i++) { - View child = recyclerView.getChildAt(i); - - if (ViewUtil.isPointInsideView(recyclerView, motionEvent.getRawX(), motionEvent.getRawY()) && - ViewUtil.isPointInsideView(child, motionEvent.getRawX(), motionEvent.getRawY())) - { - showStickerForView(recyclerView, child); - } - } - } - } - - @Override - public void onRequestDisallowInterceptTouchEvent(boolean b) { - } - - void enterHoverMode(@NonNull RecyclerView recyclerView, View targetView) { - this.hoverMode = true; - showStickerForView(recyclerView, targetView); - } - - private void showStickerForView(@NonNull RecyclerView recyclerView, @NonNull View view) { - StickerKeyboardPageViewHolder holder = (StickerKeyboardPageViewHolder) recyclerView.getChildViewHolder(view); - - if (holder != null && holder.getCurrentSticker() != null) { - if (!popup.isShowing()) { - popup.showAtLocation(recyclerView, Gravity.NO_GRAVITY, 0, 0); - eventListener.onStickerPopupStarted(); - } - popup.presentSticker(holder.getCurrentSticker()); - } - } - } - - interface EventListener { - void onStickerSelected(@NonNull StickerRecord sticker); - void onStickerPopupStarted(); - void onStickerPopupEnded(); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardPageViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardPageViewModel.java deleted file mode 100644 index 3649f04eb4..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardPageViewModel.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.app.Application; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; -import android.database.ContentObserver; -import android.os.Handler; -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.database.DatabaseContentProviders; -import org.thoughtcrime.securesms.database.model.StickerRecord; -import org.session.libsession.utilities.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> 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()) { - @Override - public void onChange(boolean selfChange) { - observerThrottler.publish(() -> getStickers(packId)); - } - }; - - application.getContentResolver().registerContentObserver(DatabaseContentProviders.Sticker.CONTENT_URI, true, observer); - } - - LiveData> 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 create(@NonNull Class modelClass) { - //noinspection ConstantConditions - return modelClass.cast(new StickerKeyboardPageViewModel(application, repository)); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardProvider.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardProvider.java deleted file mode 100644 index 35fd79da4d..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardProvider.java +++ /dev/null @@ -1,259 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import androidx.lifecycle.ViewModelProviders; -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentStatePagerAdapter; -import androidx.appcompat.app.AppCompatActivity; -import android.widget.ImageView; - - -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.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.ResUtil; -import org.session.libsession.utilities.ThemeUtil; -import org.session.libsession.utilities.Throttler; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import network.loki.messenger.R; - -/** - * 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 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; - - public StickerKeyboardProvider(@NonNull AppCompatActivity activity, - @NonNull StickerEventListener eventListener) - { - this.context = activity; - this.eventListener = eventListener; - this.pagerAdapter = new StickerPagerAdapter(activity.getSupportFragmentManager(), this); - this.stickerThrottler = new Throttler(100); - - initViewModel(activity); - } - - @Override - public int getProviderIconView(boolean selected) { - if (selected) { - return ThemeUtil.isDarkTheme(context) ? R.layout.sticker_keyboard_icon_dark_selected : R.layout.sticker_keyboard_icon_light_selected; - } else { - return ThemeUtil.isDarkTheme(context) ? R.layout.sticker_keyboard_icon_dark : R.layout.sticker_keyboard_icon_light; - } - } - - @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, true); - } - } - - @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); - } - } - - private void initViewModel(@NonNull AppCompatActivity 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 = presenter.getCurrentPosition(); - - if (calculateStartingIndex) { - startingIndex = !result.hasRecents() && result.getPacks().size() > 0 ? 1 : 0; - } - - presenter.present(this, pagerAdapter, new IconProvider(context, result.getPacks()), 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 packs; - private final Map 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 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 a, @NonNull List 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 packs; - - private IconProvider(@NonNull Context context, List packs) { - this.context = context; - this.packs = packs; - } - - @Override - public void loadCategoryTabIcon(@NonNull GlideRequests glideRequests, @NonNull ImageView imageView, int index) { - if (index == 0) { - Drawable icon = ResUtil.getDrawable(context, R.attr.emoji_category_recent); - imageView.setImageDrawable(icon); - } else { - Uri uri = packs.get(index - 1).getCover().getUri(); - - glideRequests.load(new DecryptableStreamUriLoader.DecryptableUri(uri)) - .into(imageView); - } - } - } - - public interface StickerEventListener { - void onStickerSelected(@NonNull StickerRecord sticker); - void onStickerManagementClicked(); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardRepository.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardRepository.java deleted file mode 100644 index 430f98aca7..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardRepository.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.database.Cursor; -import androidx.annotation.NonNull; - -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 org.session.libsession.utilities.concurrent.SignalExecutors; - -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 callback) { - SignalExecutors.BOUNDED.execute(() -> { - List 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> callback) { - SignalExecutors.BOUNDED.execute(() -> { - List 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> callback) { - SignalExecutors.BOUNDED.execute(() -> { - List 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 packs; - private final boolean hasRecents; - - PackListResult(List packs, boolean hasRecents) { - this.packs = packs; - this.hasRecents = hasRecents; - } - - List getPacks() { - return packs; - } - - boolean hasRecents() { - return hasRecents; - } - } - - interface Callback { - void onComplete(T result); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardViewModel.java deleted file mode 100644 index 726aa54e55..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerKeyboardViewModel.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.app.Application; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; -import android.database.ContentObserver; -import android.os.Handler; -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.database.DatabaseContentProviders; -import org.thoughtcrime.securesms.stickers.StickerKeyboardRepository.PackListResult; -import org.session.libsession.utilities.Throttler; - -final class StickerKeyboardViewModel extends ViewModel { - - private final Application application; - private final MutableLiveData 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()) { - @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 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 create(@NonNull Class modelClass) { - //noinspection ConstantConditions - return modelClass.cast(new StickerKeyboardViewModel(application, repository)); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementActivity.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementActivity.java deleted file mode 100644 index 6b694b2376..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementActivity.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import androidx.lifecycle.ViewModelProviders; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import android.view.MenuItem; - -import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity; -import org.thoughtcrime.securesms.ShareActivity; -import org.thoughtcrime.securesms.mms.GlideApp; - -import network.loki.messenger.R; - -/** - * Allows the user to view and manage (install, uninstall, etc) their stickers. - */ -public final class StickerManagementActivity extends PassphraseRequiredActionBarActivity implements StickerManagementAdapter.EventListener { - - private RecyclerView list; - private StickerManagementAdapter adapter; - - private StickerManagementViewModel viewModel; - - public static Intent getIntent(@NonNull Context context) { - return new Intent(context, StickerManagementActivity.class); - } - - @Override - protected void onPreCreate() { - super.onPreCreate(); - } - - @Override - protected void onCreate(Bundle savedInstanceState, boolean ready) { - setContentView(R.layout.sticker_management_activity); - - initView(); - initToolbar(); - initViewModel(); - } - - @Override - protected void onStart() { - super.onStart(); - viewModel.onVisible(); - } - - @Override - protected void onResume() { - super.onResume(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - onBackPressed(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - public void onStickerPackClicked(@NonNull String packId, @NonNull String packKey) { - startActivity(StickerPackPreviewActivity.getIntent(packId, packKey)); - } - - @Override - public void onStickerPackUninstallClicked(@NonNull String packId, @NonNull String packKey) { - viewModel.onStickerPackUninstallClicked(packId, packKey); - } - - @Override - public void onStickerPackInstallClicked(@NonNull String packId, @NonNull String packKey) { - viewModel.onStickerPackInstallClicked(packId, packKey); - } - - @Override - public void onStickerPackShareClicked(@NonNull String packId, @NonNull String packKey) { - Intent composeIntent = new Intent(this, ShareActivity.class); - composeIntent.putExtra(Intent.EXTRA_TEXT, StickerUrl.createShareLink(packId, packKey)); - startActivity(composeIntent); - finish(); - } - - private void initView() { - this.list = findViewById(R.id.sticker_management_list); - this.adapter = new StickerManagementAdapter(GlideApp.with(this), this); - - list.setLayoutManager(new LinearLayoutManager(this)); - list.setAdapter(adapter); - } - - private void initToolbar() { - getSupportActionBar().setTitle(R.string.StickerManagementActivity_stickers); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - } - - private void initViewModel() { - StickerManagementRepository repository = new StickerManagementRepository(this); - viewModel = ViewModelProviders.of(this, new StickerManagementViewModel.Factory(getApplication(), repository)).get(StickerManagementViewModel.class); - - viewModel.init(); - viewModel.getStickerPacks().observe(this, packResult -> { - if (packResult == null) return; - - adapter.setPackLists(packResult.getInstalledPacks(), packResult.getAvailablePacks(), packResult.getBlessedPacks()); - }); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementAdapter.java deleted file mode 100644 index 93eeaa3078..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementAdapter.java +++ /dev/null @@ -1,330 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import androidx.annotation.NonNull; -import androidx.annotation.StringRes; -import androidx.recyclerview.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import com.annimon.stream.Stream; -import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; - - -import org.thoughtcrime.securesms.database.model.StickerPackRecord; -import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; -import org.thoughtcrime.securesms.mms.GlideRequests; -import org.thoughtcrime.securesms.util.StableIdGenerator; - -import java.util.ArrayList; -import java.util.List; - -import network.loki.messenger.R; - -final class StickerManagementAdapter extends RecyclerView.Adapter { - - private static final int TYPE_HEADER = 1; - private static final int TYPE_EMPTY = 2; - private static final int TYPE_PACK = 3; - - private static final String TAG_YOUR_STICKERS = "YourStickers"; - private static final String TAG_MESSAGE_STICKERS = "MessageStickers"; - private static final String TAG_BLESSED_STICKERS = "BlessedStickers"; - - private final GlideRequests glideRequests; - private final EventListener eventListener; - private final StableIdGenerator stableIdGenerator; - - private final List
sections = new ArrayList
(3) {{ - Section yourStickers = new Section(TAG_YOUR_STICKERS, - R.string.StickerManagementAdapter_installed_stickers, - R.string.StickerManagementAdapter_no_stickers_installed, - new ArrayList<>(), - 0); - Section messageStickers = new Section(TAG_MESSAGE_STICKERS, - R.string.StickerManagementAdapter_stickers_you_received, - R.string.StickerManagementAdapter_stickers_from_incoming_messages_will_appear_here, - new ArrayList<>(), - yourStickers.size()); - - add(yourStickers); - add(messageStickers); - }}; - - StickerManagementAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) { - this.glideRequests = glideRequests; - this.eventListener = eventListener; - this.stableIdGenerator = new StableIdGenerator<>(); - - setHasStableIds(true); - } - - @Override - public long getItemId(int position) { - for (Section section : sections) { - if (section.handles(position)) { - return section.getItemId(stableIdGenerator, position); - } - } - throw new NoSectionException(); - } - - @Override - public int getItemViewType(int position) { - for (Section section : sections) { - if (section.handles(position)) { - return section.getViewType(position); - } - } - throw new NoSectionException(); - } - - @Override - public @NonNull RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) { - switch (viewType) { - case TYPE_HEADER: - return new HeaderViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.sticker_management_header_item, viewGroup, false)); - case TYPE_EMPTY: - return new EmptyViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.sticker_management_empty_item, viewGroup, false)); - case TYPE_PACK: - return new StickerViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.sticker_management_sticker_item, viewGroup, false)); - default: - throw new AssertionError("Unexpected viewType! " + viewType); - } - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { - for (Section section : sections) { - if (section.handles(position)) { - section.bindViewHolder(viewHolder, position, glideRequests, eventListener); - return; - } - } - throw new NoSectionException(); - } - - @Override - public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { - if (holder instanceof StickerViewHolder) { - ((StickerViewHolder) holder).recycle(); - } - } - - @Override - public int getItemCount() { - return Stream.of(sections).reduce(0, (sum, section) -> sum + section.size()); - } - - void setPackLists(@NonNull List installedPacks, - @NonNull List availablePacks, - @NonNull List blessedPacks) - { - Section yourStickers = new Section(TAG_YOUR_STICKERS, - R.string.StickerManagementAdapter_installed_stickers, - R.string.StickerManagementAdapter_no_stickers_installed, - installedPacks, - 0); - Section blessedStickers = new Section(TAG_BLESSED_STICKERS, - R.string.StickerManagementAdapter_signal_artist_series, - 0, - blessedPacks, - yourStickers.size()); - Section messageStickers = new Section(TAG_MESSAGE_STICKERS, - R.string.StickerManagementAdapter_stickers_you_received, - R.string.StickerManagementAdapter_stickers_from_incoming_messages_will_appear_here, - availablePacks, - yourStickers.size() + (blessedPacks.isEmpty() ? 0 : blessedStickers.size())); - - sections.clear(); - sections.add(yourStickers); - - if (!blessedPacks.isEmpty()) { - sections.add(blessedStickers); - } - - sections.add(messageStickers); - - notifyDataSetChanged(); - } - - private static class Section { - private static final String STABLE_ID_HEADER = "header"; - private static final String STABLE_ID_TEXT = "text"; - - private final String tag; - private final int titleResId; - private final int emptyResId; - private final List records; - private final int offset; - - Section(@NonNull String tag, - @StringRes int titleResId, - @StringRes int emptyResId, - @NonNull List records, - int offset) - { - this.tag = tag; - this.titleResId = titleResId; - this.emptyResId = emptyResId; - this.records = records; - this.offset = offset; - } - - int getViewType(int globalPosition) { - int localPosition = globalPosition - offset; - - if (localPosition == 0) { - return TYPE_HEADER; - } else if (records.isEmpty()) { - return TYPE_EMPTY; - } else { - return TYPE_PACK; - } - } - - long getItemId(@NonNull StableIdGenerator idGenerator, int globalPosition) { - int localPosition = globalPosition - offset; - - if (localPosition == 0) { - return idGenerator.getId(tag + "_" + STABLE_ID_HEADER); - } else if (records.isEmpty()) { - return idGenerator.getId(tag + "_" + STABLE_ID_TEXT); - } else { - return idGenerator.getId(records.get(localPosition - 1).getPackId()); - } - } - - void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, - int globalPosition, - @NonNull GlideRequests glideRequests, - @NonNull EventListener eventListener) - { - int localPosition = globalPosition - offset; - - if (localPosition == 0) { - ((HeaderViewHolder) viewHolder).bind(titleResId); - } else if (records.isEmpty()) { - ((EmptyViewHolder) viewHolder).bind(emptyResId); - } else { - ((StickerViewHolder) viewHolder).bind(glideRequests, eventListener, records.get(localPosition - 1), localPosition == records.size()); - } - } - - boolean handles(int globalPosition) { - int localPosition = globalPosition - offset; - return localPosition >= 0 && localPosition < size(); - } - - int size() { - return records.isEmpty() ? 2 : records.size() + 1; - } - } - - static class StickerViewHolder extends RecyclerView.ViewHolder { - - private final ImageView cover; - private final TextView title; - private final TextView author; - private final View badge; - private final View divider; - private final View actionButton; - private final ImageView actionButtonImage; - private final View shareButton; - private final ImageView shareButtonImage; - - StickerViewHolder(@NonNull View itemView) { - super(itemView); - - this.cover = itemView.findViewById(R.id.sticker_management_cover); - this.title = itemView.findViewById(R.id.sticker_management_title); - this.author = itemView.findViewById(R.id.sticker_management_author); - this.badge = itemView.findViewById(R.id.sticker_management_blessed_badge); - this.divider = itemView.findViewById(R.id.sticker_management_divider); - this.actionButton = itemView.findViewById(R.id.sticker_management_action_button); - this.actionButtonImage = itemView.findViewById(R.id.sticker_management_action_button_image); - this.shareButton = itemView.findViewById(R.id.sticker_management_share_button); - this.shareButtonImage = itemView.findViewById(R.id.sticker_management_share_button_image); - } - - void bind(@NonNull GlideRequests glideRequests, - @NonNull EventListener eventListener, - @NonNull StickerPackRecord stickerPack, - boolean lastInList) - { - title.setText(stickerPack.getTitle().or(itemView.getResources().getString(R.string.StickerManagementAdapter_untitled))); - author.setText(stickerPack.getAuthor().or(itemView.getResources().getString(R.string.StickerManagementAdapter_unknown))); - divider.setVisibility(lastInList ? View.GONE : View.VISIBLE); - badge.setVisibility(BlessedPacks.contains(stickerPack.getPackId()) ? View.VISIBLE : View.GONE); - - glideRequests.load(new DecryptableUri(stickerPack.getCover().getUri())) - .transition(DrawableTransitionOptions.withCrossFade()) - .into(cover); - - if (stickerPack.isInstalled()) { - actionButtonImage.setImageResource(R.drawable.ic_x); - actionButton.setOnClickListener(v -> eventListener.onStickerPackUninstallClicked(stickerPack.getPackId(), stickerPack.getPackKey())); - - shareButton.setVisibility(View.VISIBLE); - shareButtonImage.setVisibility(View.VISIBLE); - shareButton.setOnClickListener(v -> eventListener.onStickerPackShareClicked(stickerPack.getPackId(), stickerPack.getPackKey())); - } else { - actionButtonImage.setImageResource(R.drawable.ic_arrow_down); - actionButton.setOnClickListener(v -> eventListener.onStickerPackInstallClicked(stickerPack.getPackId(), stickerPack.getPackKey())); - - shareButton.setVisibility(View.GONE); - shareButtonImage.setVisibility(View.GONE); - shareButton.setOnClickListener(null); - } - - itemView.setOnClickListener(v -> eventListener.onStickerPackClicked(stickerPack.getPackId(), stickerPack.getPackKey())); - } - - void recycle() { - actionButton.setOnClickListener(null); - shareButton.setOnClickListener(null); - itemView.setOnClickListener(null); - } - } - - static class HeaderViewHolder extends RecyclerView.ViewHolder { - - private final TextView titleView; - - HeaderViewHolder(@NonNull View itemView) { - super(itemView); - - this.titleView = itemView.findViewById(R.id.sticker_management_header); - } - - void bind(@StringRes int title) { - titleView.setText(title); - } - } - - static class EmptyViewHolder extends RecyclerView.ViewHolder { - - private final TextView text; - - EmptyViewHolder(@NonNull View itemView) { - super(itemView); - - this.text = itemView.findViewById(R.id.sticker_management_empty_text); - } - - void bind(@StringRes int title) { - text.setText(title); - } - } - - interface EventListener { - void onStickerPackClicked(@NonNull String packId, @NonNull String packKey); - void onStickerPackUninstallClicked(@NonNull String packId, @NonNull String packKey); - void onStickerPackInstallClicked(@NonNull String packId, @NonNull String packKey); - void onStickerPackShareClicked(@NonNull String packId, @NonNull String packKey); - } - - private static class NoSectionException extends IllegalStateException {} -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementRepository.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementRepository.java deleted file mode 100644 index 185d3f1061..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementRepository.java +++ /dev/null @@ -1,124 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.content.Context; -import android.database.Cursor; -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.ApplicationContext; -import org.thoughtcrime.securesms.database.AttachmentDatabase; -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.StickerDatabase; -import org.thoughtcrime.securesms.database.StickerDatabase.StickerPackRecordReader; -import org.thoughtcrime.securesms.database.model.StickerPackRecord; -import org.thoughtcrime.securesms.jobmanager.JobManager; -import org.thoughtcrime.securesms.jobs.StickerPackDownloadJob; -import org.session.libsession.utilities.TextSecurePreferences; -import org.session.libsession.utilities.concurrent.SignalExecutors; - -import java.util.ArrayList; -import java.util.List; - -final class StickerManagementRepository { - - private final Context context; - private final StickerDatabase stickerDatabase; - private final AttachmentDatabase attachmentDatabase; - - StickerManagementRepository(@NonNull Context context) { - this.context = context.getApplicationContext(); - this.stickerDatabase = DatabaseFactory.getStickerDatabase(context); - this.attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context); - } - - void deleteOrphanedStickerPacks() { - SignalExecutors.SERIAL.execute(stickerDatabase::deleteOrphanedPacks); - } - - void fetchUnretrievedReferencePacks() { - SignalExecutors.SERIAL.execute(() -> { - JobManager jobManager = ApplicationContext.getInstance(context).getJobManager(); - - try (Cursor cursor = attachmentDatabase.getUnavailableStickerPacks()) { - while (cursor != null && cursor.moveToNext()) { - String packId = cursor.getString(cursor.getColumnIndexOrThrow(AttachmentDatabase.STICKER_PACK_ID)); - String packKey = cursor.getString(cursor.getColumnIndexOrThrow(AttachmentDatabase.STICKER_PACK_KEY)); - - jobManager.add(new StickerPackDownloadJob(packId, packKey, true)); - } - } - }); - } - - void getStickerPacks(@NonNull Callback callback) { - SignalExecutors.SERIAL.execute(() -> { - List installedPacks = new ArrayList<>(); - List availablePacks = new ArrayList<>(); - List blessedPacks = new ArrayList<>(); - - try (StickerPackRecordReader reader = new StickerPackRecordReader(stickerDatabase.getAllStickerPacks())) { - StickerPackRecord record; - while ((record = reader.getNext()) != null) { - if (record.isInstalled()) { - installedPacks.add(record); - } else if (BlessedPacks.contains(record.getPackId())) { - blessedPacks.add(record); - } else { - availablePacks.add(record); - } - } - } - - callback.onComplete(new PackResult(installedPacks, availablePacks, blessedPacks)); - }); - } - - void uninstallStickerPack(@NonNull String packId, @NonNull String packKey) { - SignalExecutors.SERIAL.execute(() -> { - stickerDatabase.uninstallPack(packId); - }); - } - - void installStickerPack(@NonNull String packId, @NonNull String packKey) { - SignalExecutors.SERIAL.execute(() -> { - JobManager jobManager = ApplicationContext.getInstance(context).getJobManager(); - - if (stickerDatabase.isPackAvailableAsReference(packId)) { - stickerDatabase.markPackAsInstalled(packId); - } - - jobManager.add(new StickerPackDownloadJob(packId, packKey, false)); - }); - } - - static class PackResult { - - private final List installedPacks; - private final List availablePacks; - private final List blessedPacks; - - PackResult(@NonNull List installedPacks, - @NonNull List availablePacks, - @NonNull List blessedPacks) - { - this.installedPacks = installedPacks; - this.availablePacks = availablePacks; - this.blessedPacks = blessedPacks; - } - - @NonNull List getInstalledPacks() { - return installedPacks; - } - - @NonNull List getAvailablePacks() { - return availablePacks; - } - - @NonNull List getBlessedPacks() { - return blessedPacks; - } - } - - interface Callback { - void onComplete(T result); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementViewModel.java deleted file mode 100644 index 2135deae16..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManagementViewModel.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.app.Application; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; -import android.database.ContentObserver; -import android.os.Handler; -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.database.DatabaseContentProviders; -import org.thoughtcrime.securesms.stickers.StickerManagementRepository.PackResult; - -final class StickerManagementViewModel extends ViewModel { - - private final Application application; - private final StickerManagementRepository repository; - private final MutableLiveData packs; - private final ContentObserver observer; - - private StickerManagementViewModel(@NonNull Application application, @NonNull StickerManagementRepository repository) { - this.application = application; - this.repository = repository; - this.packs = new MutableLiveData<>(); - this.observer = new ContentObserver(new Handler()) { - @Override - public void onChange(boolean selfChange) { - repository.deleteOrphanedStickerPacks(); - repository.getStickerPacks(packs::postValue); - } - }; - - application.getContentResolver().registerContentObserver(DatabaseContentProviders.StickerPack.CONTENT_URI, true, observer); - } - - void init() { - repository.deleteOrphanedStickerPacks(); - repository.fetchUnretrievedReferencePacks(); - } - - void onVisible() { - repository.deleteOrphanedStickerPacks(); - } - - @NonNull LiveData getStickerPacks() { - repository.getStickerPacks(packs::postValue); - return packs; - } - - void onStickerPackUninstallClicked(@NonNull String packId, @NonNull String packKey) { - repository.uninstallStickerPack(packId, packKey); - } - - void onStickerPackInstallClicked(@NonNull String packId, @NonNull String packKey) { - repository.installStickerPack(packId, packKey); - } - - @Override - protected void onCleared() { - application.getContentResolver().unregisterContentObserver(observer); - } - - static class Factory extends ViewModelProvider.NewInstanceFactory { - - private final Application application; - private final StickerManagementRepository repository; - - Factory(@NonNull Application application, @NonNull StickerManagementRepository repository) { - this.application = application; - this.repository = repository; - } - - @Override - public @NonNull T create(@NonNull Class modelClass) { - //noinspection ConstantConditions - return modelClass.cast(new StickerManagementViewModel(application, repository)); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManifest.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManifest.java deleted file mode 100644 index 21d14982ff..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerManifest.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.net.Uri; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.session.libsignal.libsignal.util.guava.Optional; - -import java.util.ArrayList; -import java.util.List; - -/** - * Local model that represents the data present in the libsignal model - * {@link org.session.libsignal.service.api.messages.SignalServiceStickerManifest}. - */ -public final class StickerManifest { - - private final String packId; - private final String packKey; - private final Optional title; - private final Optional author; - private final Optional cover; - private final List stickers; - - public StickerManifest(@NonNull String packId, - @NonNull String packKey, - @NonNull Optional title, - @NonNull Optional author, - @NonNull Optional cover, - @NonNull List stickers) - { - this.packId = packId; - this.packKey = packKey; - this.title = title; - this.author = author; - this.cover = cover; - this.stickers = new ArrayList<>(stickers); - } - - public @NonNull String getPackId() { - return packId; - } - - public @NonNull String getPackKey() { - return packKey; - } - - public @NonNull Optional getTitle() { - return title; - } - - public @NonNull Optional getAuthor() { - return author; - } - - public @NonNull Optional getCover() { - return cover; - } - - public @NonNull List getStickers() { - return stickers; - } - - public static class Sticker { - private final String packId; - private final String packKey; - private final int id; - private final String emoji; - private final Optional uri; - - public Sticker(@NonNull String packId, @NonNull String packKey, int id, @NonNull String emoji) { - this(packId, packKey, id, emoji, null); - } - - public Sticker(@NonNull String packId, @NonNull String packKey, int id, @NonNull String emoji, @Nullable Uri uri) { - this.packId = packId; - this.packKey = packKey; - this.id = id; - this.emoji = emoji; - this.uri = Optional.fromNullable(uri); - } - - public @NonNull String getPackId() { - return packId; - } - - public @NonNull String getPackKey() { - return packKey; - } - - public int getId() { - return id; - } - - public String getEmoji() { - return emoji; - } - - public Optional getUri() { - return uri; - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackInstallEvent.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackInstallEvent.java deleted file mode 100644 index 22b2505dae..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackInstallEvent.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import androidx.annotation.NonNull; - -public class StickerPackInstallEvent { - private final Object iconGlideModel; - - public StickerPackInstallEvent(@NonNull Object iconGlideModel) { - this.iconGlideModel = iconGlideModel; - } - - public @NonNull Object getIconGlideModel() { - return iconGlideModel; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewActivity.java deleted file mode 100644 index 28112b5a1c..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewActivity.java +++ /dev/null @@ -1,218 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.content.Intent; -import android.content.res.Configuration; -import android.graphics.Point; -import android.os.Bundle; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.annotation.NonNull; -import androidx.appcompat.widget.Toolbar; -import androidx.lifecycle.ViewModelProviders; -import androidx.recyclerview.widget.GridLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; - -import org.session.libsignal.libsignal.util.Pair; -import org.session.libsignal.libsignal.util.guava.Optional; -import org.thoughtcrime.securesms.ApplicationContext; -import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity; -import org.thoughtcrime.securesms.ShareActivity; -import org.thoughtcrime.securesms.jobs.StickerPackDownloadJob; -import org.session.libsignal.utilities.logging.Log; -import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; -import org.thoughtcrime.securesms.mms.GlideApp; -import org.thoughtcrime.securesms.stickers.StickerManifest.Sticker; -import org.session.libsession.utilities.concurrent.SimpleTask; - -import network.loki.messenger.R; - -/** - * Shows the contents of a pack and allows the user to install it (if not installed) or remove it - * (if installed). This is also the handler for sticker pack deep links. - */ -public final class StickerPackPreviewActivity extends PassphraseRequiredActionBarActivity { - - private static final String TAG = Log.tag(StickerPackPreviewActivity.class); - - private StickerPackPreviewViewModel viewModel; - - private ImageView coverImage; - private TextView stickerTitle; - private TextView stickerAuthor; - private View installButton; - private View removeButton; - private RecyclerView stickerList; - private View shareButton; - private View shareButtonImage; - - private StickerPackPreviewAdapter adapter; - private GridLayoutManager layoutManager; - - public static Intent getIntent(@NonNull String packId, @NonNull String packKey) { - Intent intent = new Intent(Intent.ACTION_VIEW, StickerUrl.createActionUri(packId, packKey)); - intent.addCategory(Intent.CATEGORY_DEFAULT); - intent.addCategory(Intent.CATEGORY_BROWSABLE); - return intent; - } - - @Override - protected void onCreate(Bundle savedInstanceState, boolean ready) { - setContentView(R.layout.sticker_preview_activity); - - Optional> stickerParams = StickerUrl.parseActionUri(getIntent().getData()); - - if (!stickerParams.isPresent()) { - Log.w(TAG, "Invalid URI!"); - finish(); - return; - } - - String packId = stickerParams.get().first(); - String packKey = stickerParams.get().second(); - - initToolbar(); - initView(); - initViewModel(packId, packKey); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - onScreenWidthChanged(getScreenWidth()); - } - - private void initView() { - this.coverImage = findViewById(R.id.sticker_install_cover); - this.stickerTitle = findViewById(R.id.sticker_install_title); - this.stickerAuthor = findViewById(R.id.sticker_install_author); - this.installButton = findViewById(R.id.sticker_install_button); - this.removeButton = findViewById(R.id.sticker_install_remove_button); - this.stickerList = findViewById(R.id.sticker_install_list); - this.shareButton = findViewById(R.id.sticker_install_share_button); - this.shareButtonImage = findViewById(R.id.sticker_install_share_button_image); - - this.adapter = new StickerPackPreviewAdapter(GlideApp.with(this)); - this.layoutManager = new GridLayoutManager(this, 2); - onScreenWidthChanged(getScreenWidth()); - - stickerList.setLayoutManager(layoutManager); - stickerList.setAdapter(adapter); - } - - private void initToolbar() { - Toolbar toolbar = findViewById(R.id.sticker_install_toolbar); - - setSupportActionBar(toolbar); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - getSupportActionBar().setTitle(R.string.StickerPackPreviewActivity_stickers); - - toolbar.setNavigationOnClickListener(v -> onBackPressed()); - } - - private void initViewModel(@NonNull String packId, @NonNull String packKey) { - viewModel = ViewModelProviders.of(this, new StickerPackPreviewViewModel.Factory(getApplication(), - new StickerPackPreviewRepository(this), - new StickerManagementRepository(this))) - .get(StickerPackPreviewViewModel.class); - - viewModel.getStickerManifest(packId, packKey).observe(this, manifest -> { - if (manifest == null) return; - - if (manifest.isPresent()) { - presentManifest(manifest.get().getManifest()); - presentButton(manifest.get().isInstalled()); - presentShareButton(manifest.get().isInstalled(), manifest.get().getManifest().getPackId(), manifest.get().getManifest().getPackKey()); - } else { - presentError(); - } - }); - } - - private void presentManifest(@NonNull StickerManifest manifest) { - stickerTitle.setText(manifest.getTitle().or(getString(R.string.StickerPackPreviewActivity_untitled))); - stickerAuthor.setText(manifest.getAuthor().or(getString(R.string.StickerPackPreviewActivity_unknown))); - adapter.setStickers(manifest.getStickers()); - - installButton.setOnClickListener(v -> { - SimpleTask.run(() -> { - ApplicationContext.getInstance(this) - .getJobManager() - .add(new StickerPackDownloadJob(manifest.getPackId(), manifest.getPackKey(), false)); - - return null; - }, (nothing) -> finish()); - }); - - Sticker first = manifest.getStickers().isEmpty() ? null : manifest.getStickers().get(0); - Sticker cover = manifest.getCover().or(Optional.fromNullable(first)).orNull(); - - if (cover != null) { - Object model = cover.getUri().isPresent() ? new DecryptableStreamUriLoader.DecryptableUri(cover.getUri().get()) - : new StickerRemoteUri(cover.getPackId(), cover.getPackKey(), cover.getId()); - GlideApp.with(this).load(model) - .transition(DrawableTransitionOptions.withCrossFade()) - .into(coverImage); - } else { - coverImage.setImageDrawable(null); - } - } - - private void presentButton(boolean installed) { - if (installed) { - removeButton.setVisibility(View.VISIBLE); - removeButton.setOnClickListener(v -> { - viewModel.onRemoveClicked(); - finish(); - }); - installButton.setVisibility(View.GONE); - installButton.setOnClickListener(null); - } else { - installButton.setVisibility(View.VISIBLE); - installButton.setOnClickListener(v -> { - viewModel.onInstallClicked(); - finish(); - }); - removeButton.setVisibility(View.GONE); - removeButton.setOnClickListener(null); - } - } - - private void presentShareButton(boolean installed, @NonNull String packId, @NonNull String packKey) { - if (installed) { - shareButton.setVisibility(View.VISIBLE); - shareButtonImage.setVisibility(View.VISIBLE); - shareButton.setOnClickListener(v -> { - Intent composeIntent = new Intent(this, ShareActivity.class); - composeIntent.putExtra(Intent.EXTRA_TEXT, StickerUrl.createShareLink(packId, packKey)); - startActivity(composeIntent); - finish(); - }); - } else { - shareButton.setVisibility(View.GONE); - shareButtonImage.setVisibility(View.GONE); - shareButton.setOnClickListener(null); - } - } - - private void presentError() { - Toast.makeText(this, R.string.StickerPackPreviewActivity_failed_to_load_sticker_pack, Toast.LENGTH_SHORT).show(); - finish(); - } - - private void onScreenWidthChanged(int newWidth) { - if (layoutManager != null) { - layoutManager.setSpanCount(newWidth / getResources().getDimensionPixelOffset(R.dimen.sticker_preview_sticker_size)); - } - } - - private int getScreenWidth() { - Point size = new Point(); - getWindowManager().getDefaultDisplay().getSize(size); - return size.x; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewAdapter.java deleted file mode 100644 index ea59cfe1a2..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewAdapter.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; - -import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions; - - -import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader; -import org.thoughtcrime.securesms.mms.GlideRequests; - -import java.util.ArrayList; -import java.util.List; - -import network.loki.messenger.R; - -public final class StickerPackPreviewAdapter extends RecyclerView.Adapter { - - private final GlideRequests glideRequests; - private final List list; - - public StickerPackPreviewAdapter(@NonNull GlideRequests glideRequests) { - this.glideRequests = glideRequests; - this.list = new ArrayList<>(); - } - - @Override - public @NonNull StickerViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { - return new StickerViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.sticker_preview_list_item, viewGroup, false)); - } - - @Override - public void onBindViewHolder(@NonNull StickerViewHolder stickerViewHolder, int i) { - stickerViewHolder.bind(glideRequests, list.get(i)); - } - - @Override - public int getItemCount() { - return list.size(); - } - - void setStickers(List stickers) { - list.clear(); - list.addAll(stickers); - notifyDataSetChanged(); - } - - static class StickerViewHolder extends RecyclerView.ViewHolder { - - private final ImageView image; - - private StickerViewHolder(@NonNull View itemView) { - super(itemView); - this.image = itemView.findViewById(R.id.sticker_install_item_image); - } - - void bind(@NonNull GlideRequests glideRequests, @NonNull StickerManifest.Sticker sticker) { - Object model = sticker.getUri().isPresent() ? new DecryptableStreamUriLoader.DecryptableUri(sticker.getUri().get()) - : new StickerRemoteUri(sticker.getPackId(), sticker.getPackKey(), sticker.getId()); - glideRequests.load(model) - .transition(DrawableTransitionOptions.withCrossFade()) - .into(image); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewRepository.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewRepository.java deleted file mode 100644 index 0aa53038c2..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewRepository.java +++ /dev/null @@ -1,161 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.content.Context; -import android.database.Cursor; -import androidx.annotation.NonNull; -import androidx.annotation.WorkerThread; - -import com.annimon.stream.Stream; - -import org.thoughtcrime.securesms.ApplicationContext; -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.StickerDatabase; -import org.thoughtcrime.securesms.database.model.StickerPackRecord; -import org.thoughtcrime.securesms.database.model.StickerRecord; -import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.session.libsignal.utilities.logging.Log; -import org.session.libsignal.utilities.Hex; -import org.session.libsession.utilities.concurrent.SignalExecutors; -import org.session.libsignal.libsignal.InvalidMessageException; -import org.session.libsignal.libsignal.util.guava.Optional; -import org.session.libsignal.service.api.SignalServiceMessageReceiver; -import org.session.libsignal.service.api.messages.SignalServiceStickerManifest; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; - -public final class StickerPackPreviewRepository implements InjectableType { - - private static final String TAG = Log.tag(StickerPackPreviewRepository.class); - - private final StickerDatabase stickerDatabase; - - @Inject SignalServiceMessageReceiver receiver; - - public StickerPackPreviewRepository(@NonNull Context context) { - ApplicationContext.getInstance(context).injectDependencies(this); - this.stickerDatabase = DatabaseFactory.getStickerDatabase(context); - } - - public void getStickerManifest(@NonNull String packId, - @NonNull String packKey, - @NonNull Callback> callback) - { - SignalExecutors.UNBOUNDED.execute(() -> { - Optional localManifest = getManifestFromDatabase(packId); - - if (localManifest.isPresent()) { - Log.d(TAG, "Found manifest locally."); - callback.onComplete(localManifest); - } else { - Log.d(TAG, "Looking for manifest remotely."); - callback.onComplete(getManifestRemote(packId, packKey)); - } - }); - } - - @WorkerThread - private Optional getManifestFromDatabase(@NonNull String packId) { - StickerPackRecord record = stickerDatabase.getStickerPack(packId); - - if (record != null && record.isInstalled()) { - StickerManifest.Sticker cover = toSticker(record.getCover()); - List stickers = getStickersFromDatabase(packId); - - StickerManifest manifest = new StickerManifest(record.getPackId(), - record.getPackKey(), - record.getTitle(), - record.getAuthor(), - Optional.of(cover), - stickers); - - return Optional.of(new StickerManifestResult(manifest, record.isInstalled())); - } - - return Optional.absent(); - } - - @WorkerThread - private Optional getManifestRemote(@NonNull String packId, @NonNull String packKey) { - try { - byte[] packIdBytes = Hex.fromStringCondensed(packId); - byte[] packKeyBytes = Hex.fromStringCondensed(packKey); - SignalServiceStickerManifest remoteManifest = receiver.retrieveStickerManifest(packIdBytes, packKeyBytes); - StickerManifest localManifest = new StickerManifest(packId, - packKey, - remoteManifest.getTitle(), - remoteManifest.getAuthor(), - toOptionalSticker(packId, packKey, remoteManifest.getCover()), - Stream.of(remoteManifest.getStickers()) - .map(s -> toSticker(packId, packKey, s)) - .toList()); - - return Optional.of(new StickerManifestResult(localManifest, false)); - } catch (IOException | InvalidMessageException e) { - Log.w(TAG, "Failed to retrieve pack manifest.", e); - } - - return Optional.absent(); - } - - @WorkerThread - private List getStickersFromDatabase(@NonNull String packId) { - List stickers = new ArrayList<>(); - - try (Cursor cursor = stickerDatabase.getStickersForPack(packId)) { - StickerDatabase.StickerRecordReader reader = new StickerDatabase.StickerRecordReader(cursor); - - StickerRecord record; - while ((record = reader.getNext()) != null) { - stickers.add(toSticker(record)); - } - } - - return stickers; - } - - - private Optional toOptionalSticker(@NonNull String packId, - @NonNull String packKey, - @NonNull Optional remoteSticker) - { - return remoteSticker.isPresent() ? Optional.of(toSticker(packId, packKey, remoteSticker.get())) - : Optional.absent(); - } - - private StickerManifest.Sticker toSticker(@NonNull String packId, - @NonNull String packKey, - @NonNull SignalServiceStickerManifest.StickerInfo remoteSticker) - { - return new StickerManifest.Sticker(packId, packKey, remoteSticker.getId(), remoteSticker.getEmoji()); - } - - private StickerManifest.Sticker toSticker(@NonNull StickerRecord record) { - return new StickerManifest.Sticker(record.getPackId(), record.getPackKey(), record.getStickerId(), record.getEmoji(), record.getUri()); - } - - static class StickerManifestResult { - private final StickerManifest manifest; - private final boolean isInstalled; - - StickerManifestResult(StickerManifest manifest, boolean isInstalled) { - this.manifest = manifest; - this.isInstalled = isInstalled; - } - - public StickerManifest getManifest() { - return manifest; - } - - public boolean isInstalled() { - return isInstalled; - } - } - - interface Callback { - void onComplete(T result); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewViewModel.java deleted file mode 100644 index 2db52b80ff..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPackPreviewViewModel.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.app.Application; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; -import android.database.ContentObserver; -import android.os.Handler; -import androidx.annotation.NonNull; -import android.text.TextUtils; - -import org.thoughtcrime.securesms.database.DatabaseContentProviders; -import org.thoughtcrime.securesms.stickers.StickerPackPreviewRepository.StickerManifestResult; -import org.session.libsignal.libsignal.util.guava.Optional; - -final class StickerPackPreviewViewModel extends ViewModel { - - private final Application application; - private final StickerPackPreviewRepository previewRepository; - private final StickerManagementRepository managementRepository; - private final MutableLiveData> stickerManifest; - private final ContentObserver packObserver; - - private String packId; - private String packKey; - - private StickerPackPreviewViewModel(@NonNull Application application, - @NonNull StickerPackPreviewRepository previewRepository, - @NonNull StickerManagementRepository managementRepository) - { - this.application = application; - this.previewRepository = previewRepository; - this.managementRepository = managementRepository; - this.stickerManifest = new MutableLiveData<>(); - this.packObserver = new ContentObserver(new Handler()) { - @Override - public void onChange(boolean selfChange) { - if (!TextUtils.isEmpty(packId) && !TextUtils.isEmpty(packKey)) { - previewRepository.getStickerManifest(packId, packKey, stickerManifest::postValue); - } - } - }; - - application.getContentResolver().registerContentObserver(DatabaseContentProviders.StickerPack.CONTENT_URI, true, packObserver); - } - - LiveData> getStickerManifest(@NonNull String packId, @NonNull String packKey) { - this.packId = packId; - this.packKey = packKey; - - previewRepository.getStickerManifest(packId, packKey, stickerManifest::postValue); - - return stickerManifest; - } - - void onInstallClicked() { - managementRepository.installStickerPack(packId, packKey); - } - - void onRemoveClicked() { - managementRepository.uninstallStickerPack(packId, packKey); - } - - @Override - protected void onCleared() { - application.getContentResolver().unregisterContentObserver(packObserver); - } - - static class Factory extends ViewModelProvider.NewInstanceFactory { - private final Application application; - private final StickerPackPreviewRepository previewRepository; - private final StickerManagementRepository managementRepository; - - Factory(@NonNull Application application, - @NonNull StickerPackPreviewRepository previewRepository, - @NonNull StickerManagementRepository managementRepository) - { - this.application = application; - this.previewRepository = previewRepository; - this.managementRepository = managementRepository; - } - - @Override - public @NonNull T create(@NonNull Class modelClass) { - //noinspection ConstantConditions - return modelClass.cast(new StickerPackPreviewViewModel(application, previewRepository, managementRepository)); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPreviewPopup.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPreviewPopup.java deleted file mode 100644 index 499a2c171a..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerPreviewPopup.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.content.Context; -import androidx.annotation.NonNull; -import android.view.LayoutInflater; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.PopupWindow; - - -import org.thoughtcrime.securesms.database.model.StickerRecord; -import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; -import org.thoughtcrime.securesms.mms.GlideRequests; - -import network.loki.messenger.R; - - -/** - * A popup that shows a given sticker fullscreen. - */ -final class StickerPreviewPopup extends PopupWindow { - - private final GlideRequests glideRequests; - private final ImageView image; - - StickerPreviewPopup(@NonNull Context context, @NonNull GlideRequests glideRequests) { - super(LayoutInflater.from(context).inflate(R.layout.sticker_preview_popup, null), - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT); - this.glideRequests = glideRequests; - this.image = getContentView().findViewById(R.id.sticker_popup_image); - - setTouchable(false); - } - - void presentSticker(@NonNull StickerRecord stickerRecord) { - glideRequests.load(new DecryptableUri(stickerRecord.getUri())) - .into(image); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerRemoteUri.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerRemoteUri.java deleted file mode 100644 index 5b5733ec49..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerRemoteUri.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import androidx.annotation.NonNull; - -import com.bumptech.glide.load.Key; - -import java.nio.ByteBuffer; -import java.security.MessageDigest; -import java.util.Objects; - -/** - * Used as a model to be given to Glide for a sticker that isn't present locally. - */ -public final class StickerRemoteUri implements Key { - - private final String packId; - private final String packKey; - private final int stickerId; - - public StickerRemoteUri(@NonNull String packId, @NonNull String packKey, int stickerId) { - this.packId = packId; - this.packKey = packKey; - this.stickerId = stickerId; - } - - public @NonNull String getPackId() { - return packId; - } - - public @NonNull String getPackKey() { - return packKey; - } - - public int getStickerId() { - return stickerId; - } - - @Override - public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) { - messageDigest.update(packId.getBytes()); - messageDigest.update(packKey.getBytes()); - messageDigest.update(ByteBuffer.allocate(4).putInt(stickerId).array()); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - StickerRemoteUri that = (StickerRemoteUri) o; - return stickerId == that.stickerId && - Objects.equals(packId, that.packId) && - Objects.equals(packKey, that.packKey); - } - - @Override - public int hashCode() { - return Objects.hash(packId, packKey, stickerId); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerRemoteUriFetcher.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerRemoteUriFetcher.java deleted file mode 100644 index 8a9769ff45..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerRemoteUriFetcher.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import androidx.annotation.NonNull; - -import com.bumptech.glide.Priority; -import com.bumptech.glide.load.DataSource; -import com.bumptech.glide.load.data.DataFetcher; - -import org.session.libsignal.utilities.logging.Log; -import org.session.libsignal.utilities.Hex; -import org.session.libsignal.libsignal.InvalidMessageException; -import org.session.libsignal.service.api.SignalServiceMessageReceiver; - -import java.io.IOException; -import java.io.InputStream; - -/** - * Downloads a sticker remotely. Used with Glide. - */ -public final class StickerRemoteUriFetcher implements DataFetcher { - - private static final String TAG = Log.tag(StickerRemoteUriFetcher.class); - - private final SignalServiceMessageReceiver receiver; - private final StickerRemoteUri stickerUri; - - public StickerRemoteUriFetcher(@NonNull SignalServiceMessageReceiver receiver, @NonNull StickerRemoteUri stickerUri) { - this.receiver = receiver; - this.stickerUri = stickerUri; - } - - @Override - public void loadData(@NonNull Priority priority, @NonNull DataCallback callback) { - try { - byte[] packIdBytes = Hex.fromStringCondensed(stickerUri.getPackId()); - byte[] packKeyBytes = Hex.fromStringCondensed(stickerUri.getPackKey()); - InputStream stream = receiver.retrieveSticker(packIdBytes, packKeyBytes, stickerUri.getStickerId()); - - callback.onDataReady(stream); - } catch (IOException | InvalidMessageException e) { - callback.onLoadFailed(e); - } - } - - @Override - public void cleanup() { - - } - - @Override - public void cancel() { - Log.d(TAG, "Canceled."); - } - - @Override - public @NonNull Class getDataClass() { - return InputStream.class; - } - - @Override - public @NonNull DataSource getDataSource() { - return DataSource.REMOTE; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerRemoteUriLoader.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerRemoteUriLoader.java deleted file mode 100644 index 9b93090d11..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerRemoteUriLoader.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.content.Context; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.bumptech.glide.load.Options; -import com.bumptech.glide.load.model.ModelLoader; -import com.bumptech.glide.load.model.ModelLoaderFactory; -import com.bumptech.glide.load.model.MultiModelLoaderFactory; - -import org.thoughtcrime.securesms.ApplicationContext; -import org.thoughtcrime.securesms.dependencies.InjectableType; -import org.session.libsignal.service.api.SignalServiceMessageReceiver; - -import java.io.InputStream; - -import javax.inject.Inject; - -/** - * Glide loader to fetch a sticker remotely. - */ -public final class StickerRemoteUriLoader implements ModelLoader { - - private final SignalServiceMessageReceiver receiver; - - public StickerRemoteUriLoader(@NonNull SignalServiceMessageReceiver receiver) { - this.receiver = receiver; - } - - - @Override - public @Nullable LoadData buildLoadData(@NonNull StickerRemoteUri sticker, int width, int height, @NonNull Options options) { - return new LoadData<>(sticker, new StickerRemoteUriFetcher(receiver, sticker)); - } - - @Override - public boolean handles(@NonNull StickerRemoteUri sticker) { - return true; - } - - public static class Factory implements ModelLoaderFactory, InjectableType { - - @Inject SignalServiceMessageReceiver receiver; - - public Factory(@NonNull Context context) { - ApplicationContext.getInstance(context).injectDependencies(this); - } - - @Override - public @NonNull ModelLoader build(@NonNull MultiModelLoaderFactory multiFactory) { - return new StickerRemoteUriLoader(receiver); - } - - @Override - public void teardown() { - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerSearchRepository.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerSearchRepository.java deleted file mode 100644 index 73f5a1cdef..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerSearchRepository.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.content.Context; -import android.database.Cursor; -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.database.AttachmentDatabase; -import org.thoughtcrime.securesms.database.CursorList; -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.database.StickerDatabase; -import org.thoughtcrime.securesms.database.model.StickerPackRecord; -import org.thoughtcrime.securesms.database.model.StickerRecord; -import org.session.libsession.utilities.concurrent.SignalExecutors; - -public final class StickerSearchRepository { - - private final StickerDatabase stickerDatabase; - private final AttachmentDatabase attachmentDatabase; - - public StickerSearchRepository(@NonNull Context context) { - this.stickerDatabase = DatabaseFactory.getStickerDatabase(context); - this.attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context); - } - - public void searchByEmoji(@NonNull String emoji, @NonNull Callback> callback) { - SignalExecutors.BOUNDED.execute(() -> { - Cursor cursor = stickerDatabase.getStickersByEmoji(emoji); - - if (cursor != null) { - callback.onResult(new CursorList<>(cursor, new StickerModelBuilder())); - } else { - callback.onResult(CursorList.emptyList()); - } - }); - } - - public void getStickerFeatureAvailability(@NonNull Callback callback) { - SignalExecutors.BOUNDED.execute(() -> { - try (Cursor cursor = stickerDatabase.getAllStickerPacks("1")) { - if (cursor != null && cursor.moveToFirst()) { - callback.onResult(true); - } else { - callback.onResult(attachmentDatabase.hasStickerAttachments()); - } - } - }); - } - - private static class StickerModelBuilder implements CursorList.ModelBuilder { - @Override - public StickerRecord build(@NonNull Cursor cursor) { - return new StickerDatabase.StickerRecordReader(cursor).getCurrent(); - } - } - - private static class StickerPackModelBuilder implements CursorList.ModelBuilder { - @Override - public StickerPackRecord build(@NonNull Cursor cursor) { - return new StickerDatabase.StickerPackRecordReader(cursor).getCurrent(); - } - } - - public interface Callback { - void onResult(T result); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerUrl.java b/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerUrl.java deleted file mode 100644 index 1205cf63b4..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/stickers/StickerUrl.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.thoughtcrime.securesms.stickers; - -import android.net.Uri; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.text.TextUtils; - -import org.session.libsignal.libsignal.util.Pair; -import org.session.libsignal.libsignal.util.guava.Optional; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Manages creating and parsing the various sticker pack URLs. - */ -public class StickerUrl { - - private static final Pattern STICKER_URL_PATTERN = Pattern.compile("^https://signal\\.org/addstickers/#pack_id=(.*)&pack_key=(.*)$"); - - public static Optional> parseActionUri(@Nullable Uri uri) { - if (uri == null) return Optional.absent(); - - String packId = uri.getQueryParameter("pack_id"); - String packKey = uri.getQueryParameter("pack_key"); - - if (TextUtils.isEmpty(packId) || TextUtils.isEmpty(packKey)) { - return Optional.absent(); - } - - return Optional.of(new Pair<>(packId, packKey)); - } - - public static @NonNull Uri createActionUri(@NonNull String packId, @NonNull String packKey) { - return Uri.parse(String.format("sgnl://addstickers?pack_id=%s&pack_key=%s", packId, packKey)); - } - - public static boolean isValidShareLink(@Nullable String url) { - return parseShareLink(url).isPresent(); - } - - public static @NonNull Optional> parseShareLink(@Nullable String url) { - if (url == null) return Optional.absent(); - - Matcher matcher = STICKER_URL_PATTERN.matcher(url); - - if (matcher.matches() && matcher.groupCount() == 2) { - return Optional.of(new Pair<>(matcher.group(1), matcher.group(2))); - } - - return Optional.absent(); - } - - public static String createShareLink(@NonNull String packId, @NonNull String packKey) { - return "https://signal.org/addstickers/#pack_id=" + packId + "&pack_key=" + packKey; - } -} diff --git a/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt b/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt index e1c1eda085..ca87ad4c74 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt @@ -116,10 +116,6 @@ object TextSecurePreferences { private const val GIF_GRID_LAYOUT = "pref_gif_grid_layout" - private const val SEEN_STICKER_INTRO_TOOLTIP = "pref_seen_sticker_intro_tooltip" - - private const val MEDIA_KEYBOARD_MODE = "pref_media_keyboard_mode" - // region FCM const val IS_USING_FCM = "pref_is_using_fcm" private const val FCM_TOKEN = "pref_fcm_token" @@ -764,27 +760,6 @@ object TextSecurePreferences { setIntegerPrefrence(context, NOTIFICATION_MESSAGES_CHANNEL_VERSION, version) } - @JvmStatic - fun hasSeenStickerIntroTooltip(context: Context): Boolean { - return getBooleanPreference(context, SEEN_STICKER_INTRO_TOOLTIP, false) - } - - @JvmStatic - fun setHasSeenStickerIntroTooltip(context: Context, seenStickerTooltip: Boolean) { - setBooleanPreference(context, SEEN_STICKER_INTRO_TOOLTIP, seenStickerTooltip) - } - - @JvmStatic - fun setMediaKeyboardMode(context: Context, mode: MediaKeyboardMode) { - setStringPreference(context, MEDIA_KEYBOARD_MODE, mode.name) - } - - @JvmStatic - fun getMediaKeyboardMode(context: Context): MediaKeyboardMode { - val name = getStringPreference(context, MEDIA_KEYBOARD_MODE, MediaKeyboardMode.EMOJI.name)!! - return MediaKeyboardMode.valueOf(name) - } - @JvmStatic fun setBooleanPreference(context: Context, key: String?, value: Boolean) { getDefaultSharedPreferences(context).edit().putBoolean(key, value).apply() diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java b/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java index 16cac09520..0178d36ef2 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/SignalServiceMessageSender.java @@ -864,7 +864,7 @@ public class SignalServiceMessageSender { String body = Base64.encodeBytes(ciphertext); int type = isClosedGroup ? SignalServiceProtos.Envelope.Type.CLOSED_GROUP_CIPHERTEXT_VALUE : SignalServiceProtos.Envelope.Type.UNIDENTIFIED_SENDER_VALUE; - OutgoingPushMessage message = new OutgoingPushMessage(type, 1, 0, body); + OutgoingPushMessage message = new OutgoingPushMessage(type, body); messages.add(message); return new OutgoingPushMessageList(publicKey, timestamp, messages, false); diff --git a/libsignal/src/main/java/org/session/libsignal/service/internal/crypto/ProvisioningCipher.java b/libsignal/src/main/java/org/session/libsignal/service/internal/crypto/ProvisioningCipher.java deleted file mode 100644 index 93119e05b9..0000000000 --- a/libsignal/src/main/java/org/session/libsignal/service/internal/crypto/ProvisioningCipher.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (C) 2014-2016 Open Whisper Systems - * - * Licensed according to the LICENSE file in this repository. - */ - -package org.session.libsignal.service.internal.crypto; - -import com.google.protobuf.ByteString; - -import org.session.libsignal.libsignal.InvalidKeyException; -import org.session.libsignal.libsignal.ecc.Curve; -import org.session.libsignal.libsignal.ecc.ECKeyPair; -import org.session.libsignal.libsignal.ecc.ECPublicKey; -import org.session.libsignal.libsignal.kdf.HKDFv3; -import org.session.libsignal.service.internal.util.Util; - -import java.security.NoSuchAlgorithmException; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.Mac; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.spec.SecretKeySpec; - -import static org.session.libsignal.service.internal.push.ProvisioningProtos.ProvisionEnvelope; -import static org.session.libsignal.service.internal.push.ProvisioningProtos.ProvisionMessage; - - -public class ProvisioningCipher { - - private static final String TAG = ProvisioningCipher.class.getSimpleName(); - - private final ECPublicKey theirPublicKey; - - public ProvisioningCipher(ECPublicKey theirPublicKey) { - this.theirPublicKey = theirPublicKey; - } - - public byte[] encrypt(ProvisionMessage message) throws InvalidKeyException { - ECKeyPair ourKeyPair = Curve.generateKeyPair(); - byte[] sharedSecret = Curve.calculateAgreement(theirPublicKey, ourKeyPair.getPrivateKey()); - byte[] derivedSecret = new HKDFv3().deriveSecrets(sharedSecret, "TextSecure Provisioning Message".getBytes(), 64); - byte[][] parts = Util.split(derivedSecret, 32, 32); - - byte[] version = {0x01}; - byte[] ciphertext = getCiphertext(parts[0], message.toByteArray()); - byte[] mac = getMac(parts[1], Util.join(version, ciphertext)); - byte[] body = Util.join(version, ciphertext, mac); - - return ProvisionEnvelope.newBuilder() - .setPublicKey(ByteString.copyFrom(ourKeyPair.getPublicKey().serialize())) - .setBody(ByteString.copyFrom(body)) - .build() - .toByteArray(); - } - - private byte[] getCiphertext(byte[] key, byte[] message) { - try { - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES")); - - return Util.join(cipher.getIV(), cipher.doFinal(message)); - } catch (NoSuchAlgorithmException e) { - throw new AssertionError(e); - } catch (NoSuchPaddingException e) { - throw new AssertionError(e); - } catch (java.security.InvalidKeyException e) { - throw new AssertionError(e); - } catch (IllegalBlockSizeException e) { - throw new AssertionError(e); - } catch (BadPaddingException e) { - throw new AssertionError(e); - } - } - - private byte[] getMac(byte[] key, byte[] message) { - try { - Mac mac = Mac.getInstance("HmacSHA256"); - mac.init(new SecretKeySpec(key, "HmacSHA256")); - - return mac.doFinal(message); - } catch (NoSuchAlgorithmException e) { - throw new AssertionError(e); - } catch (java.security.InvalidKeyException e) { - throw new AssertionError(e); - } - } - -} diff --git a/libsignal/src/main/java/org/session/libsignal/service/internal/push/OutgoingPushMessage.java b/libsignal/src/main/java/org/session/libsignal/service/internal/push/OutgoingPushMessage.java index 8926503ed2..2744ee97a5 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/internal/push/OutgoingPushMessage.java +++ b/libsignal/src/main/java/org/session/libsignal/service/internal/push/OutgoingPushMessage.java @@ -14,20 +14,11 @@ public class OutgoingPushMessage { @JsonProperty public int type; @JsonProperty - private int destinationDeviceId; - @JsonProperty - private int destinationRegistrationId; - @JsonProperty public String content; - public OutgoingPushMessage(int type, - int destinationDeviceId, - int destinationRegistrationId, - String content) + public OutgoingPushMessage(int type, String content) { this.type = type; - this.destinationDeviceId = destinationDeviceId; - this.destinationRegistrationId = destinationRegistrationId; this.content = content; } }