mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-28 20:45:17 +00:00
Merge remote-tracking branch 'origin/dev' into release/1.19.1
# Conflicts: # app/build.gradle # app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt # app/src/main/java/org/thoughtcrime/securesms/components/AvatarImageView.java # gradle.properties
This commit is contained in:
commit
50929b8970
@ -10,22 +10,19 @@ buildscript {
|
|||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion"
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion"
|
||||||
classpath "com.google.gms:google-services:$googleServicesVersion"
|
classpath "com.google.gms:google-services:$googleServicesVersion"
|
||||||
classpath "com.google.dagger:hilt-android-gradle-plugin:$daggerVersion"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id 'kotlin-kapt'
|
id 'com.google.devtools.ksp'
|
||||||
id 'com.google.dagger.hilt.android'
|
id 'com.google.dagger.hilt.android'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'witness'
|
apply plugin: 'witness'
|
||||||
apply plugin: 'kotlin-kapt'
|
|
||||||
apply plugin: 'kotlin-parcelize'
|
apply plugin: 'kotlin-parcelize'
|
||||||
apply plugin: 'kotlinx-serialization'
|
apply plugin: 'kotlinx-serialization'
|
||||||
apply plugin: 'dagger.hilt.android.plugin'
|
|
||||||
|
|
||||||
configurations.all {
|
configurations.all {
|
||||||
exclude module: "commons-logging"
|
exclude module: "commons-logging"
|
||||||
@ -89,7 +86,7 @@ android {
|
|||||||
compose true
|
compose true
|
||||||
}
|
}
|
||||||
composeOptions {
|
composeOptions {
|
||||||
kotlinCompilerExtensionVersion '1.4.7'
|
kotlinCompilerExtensionVersion '1.5.14'
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
@ -239,8 +236,9 @@ android {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation("com.google.dagger:hilt-android:2.46.1")
|
implementation("com.google.dagger:hilt-android:$daggerHiltVersion")
|
||||||
kapt("com.google.dagger:hilt-android-compiler:2.44")
|
ksp("com.google.dagger:hilt-compiler:$daggerHiltVersion")
|
||||||
|
ksp("androidx.hilt:hilt-compiler:$jetpackHiltVersion")
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:$appcompatVersion"
|
implementation "androidx.appcompat:appcompat:$appcompatVersion"
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||||
@ -281,8 +279,7 @@ dependencies {
|
|||||||
implementation 'commons-net:commons-net:3.7.2'
|
implementation 'commons-net:commons-net:3.7.2'
|
||||||
implementation 'com.github.chrisbanes:PhotoView:2.1.3'
|
implementation 'com.github.chrisbanes:PhotoView:2.1.3'
|
||||||
implementation "com.github.bumptech.glide:glide:$glideVersion"
|
implementation "com.github.bumptech.glide:glide:$glideVersion"
|
||||||
annotationProcessor "com.github.bumptech.glide:compiler:$glideVersion"
|
ksp "com.github.bumptech.glide:ksp:$glideVersion"
|
||||||
kapt "com.github.bumptech.glide:compiler:$glideVersion"
|
|
||||||
implementation 'com.makeramen:roundedimageview:2.1.0'
|
implementation 'com.makeramen:roundedimageview:2.1.0'
|
||||||
implementation 'com.pnikosis:materialish-progress:1.5'
|
implementation 'com.pnikosis:materialish-progress:1.5'
|
||||||
implementation 'org.greenrobot:eventbus:3.0.0'
|
implementation 'org.greenrobot:eventbus:3.0.0'
|
||||||
@ -290,8 +287,6 @@ dependencies {
|
|||||||
implementation 'com.vanniktech:android-image-cropper:4.5.0'
|
implementation 'com.vanniktech:android-image-cropper:4.5.0'
|
||||||
implementation 'com.melnykov:floatingactionbutton:1.3.0'
|
implementation 'com.melnykov:floatingactionbutton:1.3.0'
|
||||||
implementation 'com.google.zxing:android-integration:3.1.0'
|
implementation 'com.google.zxing:android-integration:3.1.0'
|
||||||
implementation "com.google.dagger:hilt-android:$daggerVersion"
|
|
||||||
kapt "com.google.dagger:hilt-compiler:$daggerVersion"
|
|
||||||
implementation 'com.google.zxing:core:3.2.1'
|
implementation 'com.google.zxing:core:3.2.1'
|
||||||
implementation ('com.davemorrissey.labs:subsampling-scale-image-view:3.6.0') {
|
implementation ('com.davemorrissey.labs:subsampling-scale-image-view:3.6.0') {
|
||||||
exclude group: 'com.android.support', module: 'support-annotations'
|
exclude group: 'com.android.support', module: 'support-annotations'
|
||||||
@ -410,8 +405,3 @@ def autoResConfig() {
|
|||||||
.collect { matcher -> matcher.group(1) }
|
.collect { matcher -> matcher.group(1) }
|
||||||
.sort()
|
.sort()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow references to generated code
|
|
||||||
kapt {
|
|
||||||
correctErrorTypes = true
|
|
||||||
}
|
|
||||||
|
@ -40,7 +40,7 @@ import org.session.libsignal.utilities.guava.Optional
|
|||||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
||||||
import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBar
|
import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBar
|
||||||
import org.thoughtcrime.securesms.home.HomeActivity
|
import org.thoughtcrime.securesms.home.HomeActivity
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@ -71,7 +71,7 @@ class HomeActivityTests {
|
|||||||
onView(allOf(isDescendantOfA(withId(R.id.inputBar)),withId(R.id.inputBarEditText))).perform(ViewActions.replaceText(messageToSend))
|
onView(allOf(isDescendantOfA(withId(R.id.inputBar)),withId(R.id.inputBarEditText))).perform(ViewActions.replaceText(messageToSend))
|
||||||
if (linkPreview != null) {
|
if (linkPreview != null) {
|
||||||
val activity = activityMonitor.waitForActivity() as ConversationActivityV2
|
val activity = activityMonitor.waitForActivity() as ConversationActivityV2
|
||||||
val glide = GlideApp.with(activity)
|
val glide = Glide.with(activity)
|
||||||
activity.findViewById<InputBar>(R.id.inputBar).updateLinkPreviewDraft(glide, linkPreview)
|
activity.findViewById<InputBar>(R.id.inputBar).updateLinkPreviewDraft(glide, linkPreview)
|
||||||
}
|
}
|
||||||
onView(allOf(isDescendantOfA(withId(R.id.inputBar)),inputButtonWithDrawable(R.drawable.ic_arrow_up))).perform(ViewActions.click())
|
onView(allOf(isDescendantOfA(withId(R.id.inputBar)),inputButtonWithDrawable(R.drawable.ic_arrow_up))).perform(ViewActions.click())
|
||||||
|
@ -328,7 +328,6 @@
|
|||||||
<action android:name="android.service.chooser.ChooserTargetService" />
|
<action android:name="android.service.chooser.ChooserTargetService" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
<service android:name="org.thoughtcrime.securesms.service.GenericForegroundService" />
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name="org.thoughtcrime.securesms.notifications.MarkReadReceiver"
|
android:name="org.thoughtcrime.securesms.notifications.MarkReadReceiver"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
@ -440,9 +439,7 @@
|
|||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<service
|
|
||||||
android:name="org.thoughtcrime.securesms.jobmanager.KeepAliveService"
|
|
||||||
android:enabled="@bool/enable_alarm_manager" />
|
|
||||||
<uses-library
|
<uses-library
|
||||||
android:name="com.sec.android.app.multiwindow"
|
android:name="com.sec.android.app.multiwindow"
|
||||||
android:required="false" />
|
android:required="false" />
|
||||||
|
@ -29,7 +29,7 @@ import com.codewaves.stickyheadergrid.StickyHeaderGridAdapter;
|
|||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView;
|
import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView;
|
||||||
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord;
|
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord;
|
||||||
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader.BucketedThreadMedia;
|
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader.BucketedThreadMedia;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ class MediaGalleryAdapter extends StickyHeaderGridAdapter {
|
|||||||
private static final String TAG = MediaGalleryAdapter.class.getSimpleName();
|
private static final String TAG = MediaGalleryAdapter.class.getSimpleName();
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final GlideRequests glideRequests;
|
private final RequestManager glideRequests;
|
||||||
private final Locale locale;
|
private final Locale locale;
|
||||||
private final ItemClickListener itemClickListener;
|
private final ItemClickListener itemClickListener;
|
||||||
private final Set<MediaRecord> selected;
|
private final Set<MediaRecord> selected;
|
||||||
@ -74,7 +74,7 @@ class MediaGalleryAdapter extends StickyHeaderGridAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MediaGalleryAdapter(@NonNull Context context,
|
MediaGalleryAdapter(@NonNull Context context,
|
||||||
@NonNull GlideRequests glideRequests,
|
@NonNull RequestManager glideRequests,
|
||||||
BucketedThreadMedia media,
|
BucketedThreadMedia media,
|
||||||
Locale locale,
|
Locale locale,
|
||||||
ItemClickListener clickListener)
|
ItemClickListener clickListener)
|
||||||
|
@ -61,7 +61,7 @@ import org.thoughtcrime.securesms.database.MediaDatabase;
|
|||||||
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader;
|
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader;
|
||||||
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader.BucketedThreadMedia;
|
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader.BucketedThreadMedia;
|
||||||
import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader;
|
import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.session.libsession.utilities.recipients.Recipient;
|
import org.session.libsession.utilities.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.util.AttachmentUtil;
|
import org.thoughtcrime.securesms.util.AttachmentUtil;
|
||||||
@ -227,7 +227,7 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity {
|
|||||||
this.gridManager = new StickyHeaderGridLayoutManager(getResources().getInteger(R.integer.media_overview_cols));
|
this.gridManager = new StickyHeaderGridLayoutManager(getResources().getInteger(R.integer.media_overview_cols));
|
||||||
|
|
||||||
this.recyclerView.setAdapter(new MediaGalleryAdapter(getContext(),
|
this.recyclerView.setAdapter(new MediaGalleryAdapter(getContext(),
|
||||||
GlideApp.with(this),
|
Glide.with(this),
|
||||||
new BucketedThreadMedia(getContext()),
|
new BucketedThreadMedia(getContext()),
|
||||||
locale,
|
locale,
|
||||||
this));
|
this));
|
||||||
|
@ -72,8 +72,8 @@ import org.thoughtcrime.securesms.database.loaders.PagingMediaLoader;
|
|||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||||
import org.thoughtcrime.securesms.mediapreview.MediaPreviewViewModel;
|
import org.thoughtcrime.securesms.mediapreview.MediaPreviewViewModel;
|
||||||
import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter;
|
import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.thoughtcrime.securesms.util.AttachmentUtil;
|
import org.thoughtcrime.securesms.util.AttachmentUtil;
|
||||||
@ -281,7 +281,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
mediaPager.setOffscreenPageLimit(1);
|
mediaPager.setOffscreenPageLimit(1);
|
||||||
|
|
||||||
albumRail = findViewById(R.id.media_preview_album_rail);
|
albumRail = findViewById(R.id.media_preview_album_rail);
|
||||||
albumRailAdapter = new MediaRailAdapter(GlideApp.with(this), this, false);
|
albumRailAdapter = new MediaRailAdapter(Glide.with(this), this, false);
|
||||||
|
|
||||||
albumRail.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
|
albumRail.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
|
||||||
albumRail.setAdapter(albumRailAdapter);
|
albumRail.setAdapter(albumRailAdapter);
|
||||||
@ -370,7 +370,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
if (conversationRecipient != null) {
|
if (conversationRecipient != null) {
|
||||||
getSupportLoaderManager().restartLoader(0, null, this);
|
getSupportLoaderManager().restartLoader(0, null, this);
|
||||||
} else {
|
} else {
|
||||||
adapter = new SingleItemPagerAdapter(this, GlideApp.with(this), getWindow(), initialMediaUri, initialMediaType, initialMediaSize);
|
adapter = new SingleItemPagerAdapter(this, Glide.with(this), getWindow(), initialMediaUri, initialMediaType, initialMediaSize);
|
||||||
mediaPager.setAdapter(adapter);
|
mediaPager.setAdapter(adapter);
|
||||||
|
|
||||||
if (initialCaption != null) {
|
if (initialCaption != null) {
|
||||||
@ -518,7 +518,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
|
|
||||||
mediaPager.removeOnPageChangeListener(viewPagerListener);
|
mediaPager.removeOnPageChangeListener(viewPagerListener);
|
||||||
|
|
||||||
adapter = new CursorPagerAdapter(this, GlideApp.with(this), getWindow(), data.first, data.second, leftIsRecent);
|
adapter = new CursorPagerAdapter(this, Glide.with(this), getWindow(), data.first, data.second, leftIsRecent);
|
||||||
mediaPager.setAdapter(adapter);
|
mediaPager.setAdapter(adapter);
|
||||||
|
|
||||||
viewModel.setCursor(this, data.first, leftIsRecent);
|
viewModel.setCursor(this, data.first, leftIsRecent);
|
||||||
@ -588,7 +588,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
|
|
||||||
private static class SingleItemPagerAdapter extends MediaItemAdapter {
|
private static class SingleItemPagerAdapter extends MediaItemAdapter {
|
||||||
|
|
||||||
private final GlideRequests glideRequests;
|
private final RequestManager glideRequests;
|
||||||
private final Window window;
|
private final Window window;
|
||||||
private final Uri uri;
|
private final Uri uri;
|
||||||
private final String mediaType;
|
private final String mediaType;
|
||||||
@ -596,7 +596,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
|
|
||||||
private final LayoutInflater inflater;
|
private final LayoutInflater inflater;
|
||||||
|
|
||||||
SingleItemPagerAdapter(@NonNull Context context, @NonNull GlideRequests glideRequests,
|
SingleItemPagerAdapter(@NonNull Context context, @NonNull RequestManager glideRequests,
|
||||||
@NonNull Window window, @NonNull Uri uri, @NonNull String mediaType,
|
@NonNull Window window, @NonNull Uri uri, @NonNull String mediaType,
|
||||||
long size)
|
long size)
|
||||||
{
|
{
|
||||||
@ -663,14 +663,14 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
private final WeakHashMap<Integer, MediaView> mediaViews = new WeakHashMap<>();
|
private final WeakHashMap<Integer, MediaView> mediaViews = new WeakHashMap<>();
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final GlideRequests glideRequests;
|
private final RequestManager glideRequests;
|
||||||
private final Window window;
|
private final Window window;
|
||||||
private final Cursor cursor;
|
private final Cursor cursor;
|
||||||
private final boolean leftIsRecent;
|
private final boolean leftIsRecent;
|
||||||
|
|
||||||
private int autoPlayPosition;
|
private int autoPlayPosition;
|
||||||
|
|
||||||
CursorPagerAdapter(@NonNull Context context, @NonNull GlideRequests glideRequests,
|
CursorPagerAdapter(@NonNull Context context, @NonNull RequestManager glideRequests,
|
||||||
@NonNull Window window, @NonNull Cursor cursor, int autoPlayPosition,
|
@NonNull Window window, @NonNull Cursor cursor, int autoPlayPosition,
|
||||||
boolean leftIsRecent)
|
boolean leftIsRecent)
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA
|
|||||||
private BroadcastReceiver clearKeyReceiver;
|
private BroadcastReceiver clearKeyReceiver;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
Log.i(TAG, "onCreate(" + savedInstanceState + ")");
|
Log.i(TAG, "onCreate(" + savedInstanceState + ")");
|
||||||
onPreCreate();
|
onPreCreate();
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import android.view.Window;
|
|||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
import org.thoughtcrime.securesms.mms.VideoSlide;
|
import org.thoughtcrime.securesms.mms.VideoSlide;
|
||||||
import org.thoughtcrime.securesms.video.VideoPlayer;
|
import org.thoughtcrime.securesms.video.VideoPlayer;
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ public class MediaView extends FrameLayout {
|
|||||||
this.videoView = new Stub<>(findViewById(R.id.video_player_stub));
|
this.videoView = new Stub<>(findViewById(R.id.video_player_stub));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(@NonNull GlideRequests glideRequests,
|
public void set(@NonNull RequestManager glideRequests,
|
||||||
@NonNull Window window,
|
@NonNull Window window,
|
||||||
@NonNull Uri source,
|
@NonNull Uri source,
|
||||||
@NonNull String mediaType,
|
@NonNull String mediaType,
|
||||||
|
@ -20,8 +20,8 @@ import org.session.libsession.utilities.GroupUtil
|
|||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
|
|
||||||
class ProfilePictureView @JvmOverloads constructor(
|
class ProfilePictureView @JvmOverloads constructor(
|
||||||
context: Context, attrs: AttributeSet? = null
|
context: Context, attrs: AttributeSet? = null
|
||||||
@ -29,7 +29,7 @@ class ProfilePictureView @JvmOverloads constructor(
|
|||||||
private val TAG = "ProfilePictureView"
|
private val TAG = "ProfilePictureView"
|
||||||
|
|
||||||
private val binding = ViewProfilePictureBinding.inflate(LayoutInflater.from(context), this)
|
private val binding = ViewProfilePictureBinding.inflate(LayoutInflater.from(context), this)
|
||||||
private val glide: GlideRequests = GlideApp.with(this)
|
private val glide: RequestManager = Glide.with(this)
|
||||||
private val prefs = AppTextSecurePreferences(context)
|
private val prefs = AppTextSecurePreferences(context)
|
||||||
private val userPublicKey = prefs.getLocalNumber()
|
private val userPublicKey = prefs.getLocalNumber()
|
||||||
var publicKey: String? = null
|
var publicKey: String? = null
|
||||||
|
@ -28,7 +28,7 @@ import com.bumptech.glide.signature.MediaStoreSignature;
|
|||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
||||||
import org.thoughtcrime.securesms.database.loaders.RecentPhotosLoader;
|
import org.thoughtcrime.securesms.database.loaders.RecentPhotosLoader;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
|
|
||||||
import org.session.libsession.utilities.ViewUtil;
|
import org.session.libsession.utilities.ViewUtil;
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ public class RecentPhotoViewRail extends FrameLayout implements LoaderManager.Lo
|
|||||||
|
|
||||||
Key signature = new MediaStoreSignature(mimeType, dateModified, orientation);
|
Key signature = new MediaStoreSignature(mimeType, dateModified, orientation);
|
||||||
|
|
||||||
GlideApp.with(getContext().getApplicationContext())
|
Glide.with(getContext().getApplicationContext())
|
||||||
.load(uri)
|
.load(uri)
|
||||||
.signature(signature)
|
.signature(signature)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
@ -8,7 +8,7 @@ import android.view.View;
|
|||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView;
|
import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
import org.thoughtcrime.securesms.mms.SlideClickListener;
|
import org.thoughtcrime.securesms.mms.SlideClickListener;
|
||||||
|
@ -25,7 +25,7 @@ import network.loki.messenger.R;
|
|||||||
import org.thoughtcrime.securesms.components.subsampling.AttachmentBitmapDecoder;
|
import org.thoughtcrime.securesms.components.subsampling.AttachmentBitmapDecoder;
|
||||||
import org.thoughtcrime.securesms.components.subsampling.AttachmentRegionDecoder;
|
import org.thoughtcrime.securesms.components.subsampling.AttachmentRegionDecoder;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
@ -62,7 +62,7 @@ public class ZoomingImageView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
public void setImageUri(@NonNull GlideRequests glideRequests, @NonNull Uri uri, @NonNull String contentType)
|
public void setImageUri(@NonNull RequestManager glideRequests, @NonNull Uri uri, @NonNull String contentType)
|
||||||
{
|
{
|
||||||
final Context context = getContext();
|
final Context context = getContext();
|
||||||
final int maxTextureSize = BitmapUtil.getMaxTextureSize();
|
final int maxTextureSize = BitmapUtil.getMaxTextureSize();
|
||||||
@ -97,7 +97,7 @@ public class ZoomingImageView extends FrameLayout {
|
|||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setImageViewUri(@NonNull GlideRequests glideRequests, @NonNull Uri uri) {
|
private void setImageViewUri(@NonNull RequestManager glideRequests, @NonNull Uri uri) {
|
||||||
photoView.setVisibility(View.VISIBLE);
|
photoView.setVisibility(View.VISIBLE);
|
||||||
subsamplingImageView.setVisibility(View.GONE);
|
subsamplingImageView.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import android.widget.ImageView;
|
|||||||
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.VariationSelectorListener;
|
import org.thoughtcrime.securesms.components.emoji.EmojiPageViewGridAdapter.VariationSelectorListener;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
import org.thoughtcrime.securesms.util.ResUtil;
|
import org.thoughtcrime.securesms.util.ResUtil;
|
||||||
|
|
||||||
import org.session.libsession.utilities.ThemeUtil;
|
import org.session.libsession.utilities.ThemeUtil;
|
||||||
@ -87,7 +87,7 @@ public class EmojiKeyboardProvider implements MediaKeyboardProvider,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadCategoryTabIcon(@NonNull GlideRequests glideRequests, @NonNull ImageView imageView, int index) {
|
public void loadCategoryTabIcon(@NonNull RequestManager glideRequests, @NonNull ImageView imageView, int index) {
|
||||||
Drawable drawable = ResUtil.getDrawable(context, models.get(index).getIconAttr());
|
Drawable drawable = ResUtil.getDrawable(context, models.get(index).getIconAttr());
|
||||||
imageView.setImageDrawable(drawable);
|
imageView.setImageDrawable(drawable);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.components.emoji;
|
package org.thoughtcrime.securesms.components.emoji;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
@ -8,6 +9,8 @@ import android.widget.PopupWindow;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.session.libsession.utilities.ThemeUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
@ -26,7 +29,9 @@ public class EmojiVariationSelectorPopup extends PopupWindow {
|
|||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.list = (ViewGroup) getContentView();
|
this.list = (ViewGroup) getContentView();
|
||||||
|
|
||||||
setBackgroundDrawable(null);
|
setBackgroundDrawable(
|
||||||
|
new ColorDrawable(ThemeUtil.getThemedColor(context, R.attr.colorPrimary))
|
||||||
|
);
|
||||||
setOutsideTouchable(true);
|
setOutsideTouchable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import android.widget.FrameLayout;
|
|||||||
import org.thoughtcrime.securesms.components.InputAwareLayout.InputView;
|
import org.thoughtcrime.securesms.components.InputAwareLayout.InputView;
|
||||||
import org.thoughtcrime.securesms.components.RepeatableImageKey;
|
import org.thoughtcrime.securesms.components.RepeatableImageKey;
|
||||||
import org.session.libsignal.utilities.Log;
|
import org.session.libsignal.utilities.Log;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ public class MediaKeyboard extends FrameLayout implements InputView,
|
|||||||
this.searchButton = view.findViewById(R.id.media_keyboard_search);
|
this.searchButton = view.findViewById(R.id.media_keyboard_search);
|
||||||
this.addButton = view.findViewById(R.id.media_keyboard_add);
|
this.addButton = view.findViewById(R.id.media_keyboard_add);
|
||||||
|
|
||||||
this.categoryTabAdapter = new MediaKeyboardBottomTabAdapter(GlideApp.with(this), this);
|
this.categoryTabAdapter = new MediaKeyboardBottomTabAdapter(Glide.with(this), this);
|
||||||
|
|
||||||
categoryTabs.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
|
categoryTabs.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||||
categoryTabs.setAdapter(categoryTabAdapter);
|
categoryTabs.setAdapter(categoryTabAdapter);
|
||||||
|
@ -9,20 +9,20 @@ import android.widget.ImageView;
|
|||||||
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboardProvider.TabIconProvider;
|
import org.thoughtcrime.securesms.components.emoji.MediaKeyboardProvider.TabIconProvider;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
|
|
||||||
public class MediaKeyboardBottomTabAdapter extends RecyclerView.Adapter<MediaKeyboardBottomTabAdapter.MediaKeyboardBottomTabViewHolder> {
|
public class MediaKeyboardBottomTabAdapter extends RecyclerView.Adapter<MediaKeyboardBottomTabAdapter.MediaKeyboardBottomTabViewHolder> {
|
||||||
|
|
||||||
private final GlideRequests glideRequests;
|
private final RequestManager glideRequests;
|
||||||
private final EventListener eventListener;
|
private final EventListener eventListener;
|
||||||
|
|
||||||
private TabIconProvider tabIconProvider;
|
private TabIconProvider tabIconProvider;
|
||||||
private int activePosition;
|
private int activePosition;
|
||||||
private int count;
|
private int count;
|
||||||
|
|
||||||
public MediaKeyboardBottomTabAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) {
|
public MediaKeyboardBottomTabAdapter(@NonNull RequestManager glideRequests, @NonNull EventListener eventListener) {
|
||||||
this.glideRequests = glideRequests;
|
this.glideRequests = glideRequests;
|
||||||
this.eventListener = eventListener;
|
this.eventListener = eventListener;
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ public class MediaKeyboardBottomTabAdapter extends RecyclerView.Adapter<MediaKey
|
|||||||
this.indicator = itemView.findViewById(R.id.media_keyboard_bottom_tab_indicator);
|
this.indicator = itemView.findViewById(R.id.media_keyboard_bottom_tab_indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(@NonNull GlideRequests glideRequests,
|
void bind(@NonNull RequestManager glideRequests,
|
||||||
@NonNull EventListener eventListener,
|
@NonNull EventListener eventListener,
|
||||||
@NonNull TabIconProvider tabIconProvider,
|
@NonNull TabIconProvider tabIconProvider,
|
||||||
int index,
|
int index,
|
||||||
|
@ -8,7 +8,7 @@ import android.widget.ImageView;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
|
|
||||||
public interface MediaKeyboardProvider {
|
public interface MediaKeyboardProvider {
|
||||||
@LayoutRes int getProviderIconView(boolean selected);
|
@LayoutRes int getProviderIconView(boolean selected);
|
||||||
@ -48,6 +48,6 @@ public interface MediaKeyboardProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface TabIconProvider {
|
interface TabIconProvider {
|
||||||
void loadCategoryTabIcon(@NonNull GlideRequests glideRequests, @NonNull ImageView imageView, int index);
|
void loadCategoryTabIcon(@NonNull RequestManager glideRequests, @NonNull ImageView imageView, int index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,10 @@ import android.view.ViewGroup
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import network.loki.messenger.databinding.ContactSelectionListDividerBinding
|
import network.loki.messenger.databinding.ContactSelectionListDividerBinding
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
|
|
||||||
class ContactSelectionListAdapter(private val context: Context, private val multiSelect: Boolean) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
class ContactSelectionListAdapter(private val context: Context, private val multiSelect: Boolean) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
lateinit var glide: GlideRequests
|
lateinit var glide: RequestManager
|
||||||
val selectedContacts = mutableSetOf<Recipient>()
|
val selectedContacts = mutableSetOf<Recipient>()
|
||||||
var items = listOf<ContactSelectionListItem>()
|
var items = listOf<ContactSelectionListItem>()
|
||||||
set(value) { field = value; notifyDataSetChanged() }
|
set(value) { field = value; notifyDataSetChanged() }
|
||||||
|
@ -11,7 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||||||
import network.loki.messenger.databinding.ContactSelectionListFragmentBinding
|
import network.loki.messenger.databinding.ContactSelectionListFragmentBinding
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
|
|
||||||
class ContactSelectionListFragment : Fragment(), LoaderManager.LoaderCallbacks<List<ContactSelectionListItem>>, ContactClickListener {
|
class ContactSelectionListFragment : Fragment(), LoaderManager.LoaderCallbacks<List<ContactSelectionListItem>>, ContactClickListener {
|
||||||
private lateinit var binding: ContactSelectionListFragmentBinding
|
private lateinit var binding: ContactSelectionListFragmentBinding
|
||||||
@ -27,7 +27,7 @@ class ContactSelectionListFragment : Fragment(), LoaderManager.LoaderCallbacks<L
|
|||||||
|
|
||||||
private val listAdapter by lazy {
|
private val listAdapter by lazy {
|
||||||
val result = ContactSelectionListAdapter(requireActivity(), multiSelect)
|
val result = ContactSelectionListAdapter(requireActivity(), multiSelect)
|
||||||
result.glide = GlideApp.with(this)
|
result.glide = Glide.with(this)
|
||||||
result.contactClickListener = this
|
result.contactClickListener = this
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ActivitySelectContactsBinding
|
import network.loki.messenger.databinding.ActivitySelectContactsBinding
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
|
|
||||||
class SelectContactsActivity : PassphraseRequiredActionBarActivity(), LoaderManager.LoaderCallbacks<List<String>> {
|
class SelectContactsActivity : PassphraseRequiredActionBarActivity(), LoaderManager.LoaderCallbacks<List<String>> {
|
||||||
private lateinit var binding: ActivitySelectContactsBinding
|
private lateinit var binding: ActivitySelectContactsBinding
|
||||||
@ -21,7 +21,7 @@ class SelectContactsActivity : PassphraseRequiredActionBarActivity(), LoaderMana
|
|||||||
private lateinit var usersToExclude: Set<String>
|
private lateinit var usersToExclude: Set<String>
|
||||||
|
|
||||||
private val selectContactsAdapter by lazy {
|
private val selectContactsAdapter by lazy {
|
||||||
SelectContactsAdapter(this, GlideApp.with(this))
|
SelectContactsAdapter(this, Glide.with(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -4,10 +4,10 @@ import android.content.Context
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
|
|
||||||
class SelectContactsAdapter(private val context: Context, private val glide: GlideRequests) : RecyclerView.Adapter<SelectContactsAdapter.ViewHolder>() {
|
class SelectContactsAdapter(private val context: Context, private val glide: RequestManager) : RecyclerView.Adapter<SelectContactsAdapter.ViewHolder>() {
|
||||||
val selectedMembers = mutableSetOf<String>()
|
val selectedMembers = mutableSetOf<String>()
|
||||||
var members = listOf<String>()
|
var members = listOf<String>()
|
||||||
set(value) { field = value; notifyDataSetChanged() }
|
set(value) { field = value; notifyDataSetChanged() }
|
||||||
|
@ -10,7 +10,7 @@ import network.loki.messenger.databinding.ViewUserBinding
|
|||||||
import org.session.libsession.messaging.contacts.Contact
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
|
|
||||||
class UserView : LinearLayout {
|
class UserView : LinearLayout {
|
||||||
private lateinit var binding: ViewUserBinding
|
private lateinit var binding: ViewUserBinding
|
||||||
@ -45,7 +45,7 @@ class UserView : LinearLayout {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Updating
|
// region Updating
|
||||||
fun bind(user: Recipient, glide: GlideRequests, actionIndicator: ActionIndicator, isSelected: Boolean = false) {
|
fun bind(user: Recipient, glide: RequestManager, actionIndicator: ActionIndicator, isSelected: Boolean = false) {
|
||||||
val isLocalUser = user.isLocalNumber
|
val isLocalUser = user.isLocalNumber
|
||||||
fun getUserDisplayName(publicKey: String): String {
|
fun getUserDisplayName(publicKey: String): String {
|
||||||
if (isLocalUser) return context.getString(R.string.MessageRecord_you)
|
if (isLocalUser) return context.getString(R.string.MessageRecord_you)
|
||||||
|
@ -155,7 +155,7 @@ import org.thoughtcrime.securesms.mediasend.Media
|
|||||||
import org.thoughtcrime.securesms.mediasend.MediaSendActivity
|
import org.thoughtcrime.securesms.mediasend.MediaSendActivity
|
||||||
import org.thoughtcrime.securesms.mms.AudioSlide
|
import org.thoughtcrime.securesms.mms.AudioSlide
|
||||||
import org.thoughtcrime.securesms.mms.GifSlide
|
import org.thoughtcrime.securesms.mms.GifSlide
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
import org.thoughtcrime.securesms.mms.ImageSlide
|
import org.thoughtcrime.securesms.mms.ImageSlide
|
||||||
import org.thoughtcrime.securesms.mms.MediaConstraints
|
import org.thoughtcrime.securesms.mms.MediaConstraints
|
||||||
import org.thoughtcrime.securesms.mms.Slide
|
import org.thoughtcrime.securesms.mms.Slide
|
||||||
@ -347,7 +347,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
adapter
|
adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
private val glide by lazy { GlideApp.with(this) }
|
private val glide by lazy { Glide.with(this) }
|
||||||
private val lockViewHitMargin by lazy { toPx(40, resources) }
|
private val lockViewHitMargin by lazy { toPx(40, resources) }
|
||||||
private val gifButton by lazy { InputBarButton(this, R.drawable.ic_gif_white_24dp, hasOpaqueBackground = true, isGIFButton = true) }
|
private val gifButton by lazy { InputBarButton(this, R.drawable.ic_gif_white_24dp, hasOpaqueBackground = true, isGIFButton = true) }
|
||||||
private val documentButton by lazy { InputBarButton(this, R.drawable.ic_document_small_dark, hasOpaqueBackground = true) }
|
private val documentButton by lazy { InputBarButton(this, R.drawable.ic_document_small_dark, hasOpaqueBackground = true) }
|
||||||
|
@ -26,7 +26,7 @@ import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageViewDel
|
|||||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
|
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.preferences.PrivacySettingsActivity
|
import org.thoughtcrime.securesms.preferences.PrivacySettingsActivity
|
||||||
import org.thoughtcrime.securesms.showSessionDialog
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
@ -42,7 +42,7 @@ class ConversationAdapter(
|
|||||||
private val onItemLongPress: (MessageRecord, Int, VisibleMessageView) -> Unit,
|
private val onItemLongPress: (MessageRecord, Int, VisibleMessageView) -> Unit,
|
||||||
private val onDeselect: (MessageRecord, Int) -> Unit,
|
private val onDeselect: (MessageRecord, Int) -> Unit,
|
||||||
private val onAttachmentNeedsDownload: (DatabaseAttachment) -> Unit,
|
private val onAttachmentNeedsDownload: (DatabaseAttachment) -> Unit,
|
||||||
private val glide: GlideRequests,
|
private val glide: RequestManager,
|
||||||
lifecycleCoroutineScope: LifecycleCoroutineScope
|
lifecycleCoroutineScope: LifecycleCoroutineScope
|
||||||
) : CursorRecyclerViewAdapter<ViewHolder>(context, cursor) {
|
) : CursorRecyclerViewAdapter<ViewHolder>(context, cursor) {
|
||||||
private val messageDB by lazy { DatabaseComponent.get(context).mmsSmsDatabase() }
|
private val messageDB by lazy { DatabaseComponent.get(context).mmsSmsDatabase() }
|
||||||
|
@ -261,8 +261,14 @@ class ConversationViewModel(
|
|||||||
_recipient.updateTo(repository.maybeGetRecipientForThreadId(threadId))
|
_recipient.updateTo(repository.maybeGetRecipientForThreadId(threadId))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hidesInputBar(): Boolean = openGroup?.canWrite != true &&
|
/**
|
||||||
blindedRecipient?.blocksCommunityMessageRequests == true
|
* The input should be hidden when:
|
||||||
|
* - We are in a community without write access
|
||||||
|
* - We are dealing with a contact from a community (blinded recipient) that does not allow
|
||||||
|
* requests form community members
|
||||||
|
*/
|
||||||
|
fun hidesInputBar(): Boolean = openGroup?.canWrite == false ||
|
||||||
|
blindedRecipient?.blocksCommunityMessageRequests == true
|
||||||
|
|
||||||
fun legacyBannerRecipient(context: Context): Recipient? = recipient?.run {
|
fun legacyBannerRecipient(context: Context): Recipient? = recipient?.run {
|
||||||
storage.getLastLegacyRecipient(address.serialize())?.let { Recipient.from(context, Address.fromSerialized(it), false) }
|
storage.getLastLegacyRecipient(address.serialize())?.let { Recipient.from(context, Address.fromSerialized(it), false) }
|
||||||
|
@ -33,18 +33,16 @@ import android.view.View
|
|||||||
import com.annimon.stream.Stream
|
import com.annimon.stream.Stream
|
||||||
import com.google.android.mms.pdu_alt.CharacterSets
|
import com.google.android.mms.pdu_alt.CharacterSets
|
||||||
import com.google.android.mms.pdu_alt.EncodedStringValue
|
import com.google.android.mms.pdu_alt.EncodedStringValue
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.session.libsignal.utilities.Log
|
||||||
|
import org.thoughtcrime.securesms.components.ComposeText
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.UnsupportedEncodingException
|
import java.io.UnsupportedEncodingException
|
||||||
import java.security.SecureRandom
|
|
||||||
import java.util.Arrays
|
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import network.loki.messenger.R
|
|
||||||
import org.session.libsignal.utilities.Log
|
|
||||||
import org.thoughtcrime.securesms.components.ComposeText
|
|
||||||
|
|
||||||
object Util {
|
object Util {
|
||||||
private val TAG: String = Log.tag(Util::class.java)
|
private val TAG: String = Log.tag(Util::class.java)
|
||||||
@ -248,32 +246,6 @@ object Util {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSecretBytes(size: Int): ByteArray {
|
|
||||||
return getSecretBytes(SecureRandom(), size)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSecretBytes(secureRandom: SecureRandom, size: Int): ByteArray {
|
|
||||||
val secret = ByteArray(size)
|
|
||||||
secureRandom.nextBytes(secret)
|
|
||||||
return secret
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> getRandomElement(elements: Array<T>): T {
|
|
||||||
return elements[SecureRandom().nextInt(elements.size)]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> getRandomElement(elements: List<T>): T {
|
|
||||||
return elements[SecureRandom().nextInt(elements.size)]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun equals(a: Any?, b: Any?): Boolean {
|
|
||||||
return a === b || (a != null && a == b)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hashCode(vararg objects: Any?): Int {
|
|
||||||
return objects.contentHashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun uri(uri: String?): Uri? {
|
fun uri(uri: String?): Uri? {
|
||||||
return if (uri == null) null
|
return if (uri == null) null
|
||||||
else Uri.parse(uri)
|
else Uri.parse(uri)
|
||||||
|
@ -20,7 +20,7 @@ import org.thoughtcrime.securesms.MediaPreviewActivity
|
|||||||
import org.thoughtcrime.securesms.components.CornerMask
|
import org.thoughtcrime.securesms.components.CornerMask
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView
|
import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.mms.Slide
|
import org.thoughtcrime.securesms.mms.Slide
|
||||||
import org.thoughtcrime.securesms.util.ActivityDispatcher
|
import org.thoughtcrime.securesms.util.ActivityDispatcher
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ class AlbumThumbnailView : RelativeLayout {
|
|||||||
slideSize = -1
|
slideSize = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bind(glideRequests: GlideRequests, message: MmsMessageRecord,
|
fun bind(glideRequests: RequestManager, message: MmsMessageRecord,
|
||||||
isStart: Boolean, isEnd: Boolean) {
|
isStart: Boolean, isEnd: Boolean) {
|
||||||
slides = message.slideDeck.thumbnailSlides
|
slides = message.slideDeck.thumbnailSlides
|
||||||
if (slides.isEmpty()) {
|
if (slides.isEmpty()) {
|
||||||
|
@ -7,7 +7,7 @@ import android.widget.LinearLayout
|
|||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import network.loki.messenger.databinding.ViewLinkPreviewDraftBinding
|
import network.loki.messenger.databinding.ViewLinkPreviewDraftBinding
|
||||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
|
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.mms.ImageSlide
|
import org.thoughtcrime.securesms.mms.ImageSlide
|
||||||
import org.thoughtcrime.securesms.util.toPx
|
import org.thoughtcrime.securesms.util.toPx
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ class LinkPreviewDraftView : LinearLayout {
|
|||||||
binding.linkPreviewDraftCancelButton.setOnClickListener { cancel() }
|
binding.linkPreviewDraftCancelButton.setOnClickListener { cancel() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(glide: GlideRequests, linkPreview: LinkPreview) {
|
fun update(glide: RequestManager, linkPreview: LinkPreview) {
|
||||||
// Hide the loader and show the content view
|
// Hide the loader and show the content view
|
||||||
binding.linkPreviewDraftContainer.isVisible = true
|
binding.linkPreviewDraftContainer.isVisible = true
|
||||||
binding.linkPreviewDraftLoader.isVisible = false
|
binding.linkPreviewDraftLoader.isVisible = false
|
||||||
|
@ -9,13 +9,13 @@ import android.widget.BaseAdapter
|
|||||||
import android.widget.ListView
|
import android.widget.ListView
|
||||||
import org.session.libsession.messaging.mentions.Mention
|
import org.session.libsession.messaging.mentions.Mention
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.util.toPx
|
import org.thoughtcrime.securesms.util.toPx
|
||||||
|
|
||||||
class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : ListView(context, attrs, defStyleAttr) {
|
class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : ListView(context, attrs, defStyleAttr) {
|
||||||
private var mentionCandidates = listOf<Mention>()
|
private var mentionCandidates = listOf<Mention>()
|
||||||
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.mentionCandidates = newValue }
|
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.mentionCandidates = newValue }
|
||||||
var glide: GlideRequests? = null
|
var glide: RequestManager? = null
|
||||||
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.glide = newValue }
|
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.glide = newValue }
|
||||||
var openGroupServer: String? = null
|
var openGroupServer: String? = null
|
||||||
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.openGroupServer = openGroupServer }
|
set(newValue) { field = newValue; mentionCandidateSelectionViewAdapter.openGroupServer = openGroupServer }
|
||||||
@ -28,7 +28,7 @@ class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defS
|
|||||||
private class Adapter(private val context: Context) : BaseAdapter() {
|
private class Adapter(private val context: Context) : BaseAdapter() {
|
||||||
var mentionCandidates = listOf<Mention>()
|
var mentionCandidates = listOf<Mention>()
|
||||||
set(newValue) { field = newValue; notifyDataSetChanged() }
|
set(newValue) { field = newValue; notifyDataSetChanged() }
|
||||||
var glide: GlideRequests? = null
|
var glide: RequestManager? = null
|
||||||
var openGroupServer: String? = null
|
var openGroupServer: String? = null
|
||||||
var openGroupRoom: String? = null
|
var openGroupRoom: String? = null
|
||||||
|
|
||||||
|
@ -8,13 +8,13 @@ import android.widget.LinearLayout
|
|||||||
import network.loki.messenger.databinding.ViewMentionCandidateBinding
|
import network.loki.messenger.databinding.ViewMentionCandidateBinding
|
||||||
import org.session.libsession.messaging.mentions.Mention
|
import org.session.libsession.messaging.mentions.Mention
|
||||||
import org.thoughtcrime.securesms.groups.OpenGroupManager
|
import org.thoughtcrime.securesms.groups.OpenGroupManager
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
|
|
||||||
class MentionCandidateView : LinearLayout {
|
class MentionCandidateView : LinearLayout {
|
||||||
private lateinit var binding: ViewMentionCandidateBinding
|
private lateinit var binding: ViewMentionCandidateBinding
|
||||||
var mentionCandidate = Mention("", "")
|
var mentionCandidate = Mention("", "")
|
||||||
set(newValue) { field = newValue; update() }
|
set(newValue) { field = newValue; update() }
|
||||||
var glide: GlideRequests? = null
|
var glide: RequestManager? = null
|
||||||
var openGroupServer: String? = null
|
var openGroupServer: String? = null
|
||||||
var openGroupRoom: String? = null
|
var openGroupRoom: String? = null
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ import org.thoughtcrime.securesms.conversation.v2.messages.QuoteView
|
|||||||
import org.thoughtcrime.securesms.conversation.v2.messages.QuoteViewDelegate
|
import org.thoughtcrime.securesms.conversation.v2.messages.QuoteViewDelegate
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.util.addTextChangedListener
|
import org.thoughtcrime.securesms.util.addTextChangedListener
|
||||||
import org.thoughtcrime.securesms.util.contains
|
import org.thoughtcrime.securesms.util.contains
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ class InputBar @JvmOverloads constructor(
|
|||||||
|
|
||||||
private fun startRecordingVoiceMessage() { delegate?.startRecordingVoiceMessage() }
|
private fun startRecordingVoiceMessage() { delegate?.startRecordingVoiceMessage() }
|
||||||
|
|
||||||
fun draftQuote(thread: Recipient, message: MessageRecord, glide: GlideRequests) {
|
fun draftQuote(thread: Recipient, message: MessageRecord, glide: RequestManager) {
|
||||||
quoteView?.let(binding.inputBarAdditionalContentContainer::removeView)
|
quoteView?.let(binding.inputBarAdditionalContentContainer::removeView)
|
||||||
|
|
||||||
quote = message
|
quote = message
|
||||||
@ -238,7 +238,7 @@ class InputBar @JvmOverloads constructor(
|
|||||||
requestLayout()
|
requestLayout()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateLinkPreviewDraft(glide: GlideRequests, updatedLinkPreview: LinkPreview) {
|
fun updateLinkPreviewDraft(glide: RequestManager, updatedLinkPreview: LinkPreview) {
|
||||||
// Update our `linkPreview` property with the new (provided as an argument to this function)
|
// Update our `linkPreview` property with the new (provided as an argument to this function)
|
||||||
// then update the View from that.
|
// then update the View from that.
|
||||||
linkPreview = updatedLinkPreview.also { linkPreviewDraftView?.update(glide, it) }
|
linkPreview = updatedLinkPreview.also { linkPreviewDraftView?.update(glide, it) }
|
||||||
|
@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.components.CornerMask
|
|||||||
import org.thoughtcrime.securesms.conversation.v2.ModalUrlBottomSheet
|
import org.thoughtcrime.securesms.conversation.v2.ModalUrlBottomSheet
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MessageBubbleUtilities
|
import org.thoughtcrime.securesms.conversation.v2.utilities.MessageBubbleUtilities
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.mms.ImageSlide
|
import org.thoughtcrime.securesms.mms.ImageSlide
|
||||||
|
|
||||||
class LinkPreviewView : LinearLayout {
|
class LinkPreviewView : LinearLayout {
|
||||||
@ -32,7 +32,7 @@ class LinkPreviewView : LinearLayout {
|
|||||||
// region Updating
|
// region Updating
|
||||||
fun bind(
|
fun bind(
|
||||||
message: MmsMessageRecord,
|
message: MmsMessageRecord,
|
||||||
glide: GlideRequests,
|
glide: RequestManager,
|
||||||
isStartOfMessageCluster: Boolean,
|
isStartOfMessageCluster: Boolean,
|
||||||
isEndOfMessageCluster: Boolean
|
isEndOfMessageCluster: Boolean
|
||||||
) {
|
) {
|
||||||
|
@ -18,7 +18,7 @@ import org.session.libsession.utilities.getColorFromAttr
|
|||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities
|
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities
|
||||||
import org.thoughtcrime.securesms.database.SessionContactDatabase
|
import org.thoughtcrime.securesms.database.SessionContactDatabase
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck
|
import org.thoughtcrime.securesms.mms.SlideDeck
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil
|
import org.thoughtcrime.securesms.util.MediaUtil
|
||||||
import org.thoughtcrime.securesms.util.getAccentColor
|
import org.thoughtcrime.securesms.util.getAccentColor
|
||||||
@ -68,7 +68,7 @@ class QuoteView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
|
|||||||
// region Updating
|
// region Updating
|
||||||
fun bind(authorPublicKey: String, body: String?, attachments: SlideDeck?, thread: Recipient,
|
fun bind(authorPublicKey: String, body: String?, attachments: SlideDeck?, thread: Recipient,
|
||||||
isOutgoingMessage: Boolean, isOpenGroupInvitation: Boolean, threadID: Long,
|
isOutgoingMessage: Boolean, isOpenGroupInvitation: Boolean, threadID: Long,
|
||||||
isOriginalMissing: Boolean, glide: GlideRequests) {
|
isOriginalMissing: Boolean, glide: RequestManager) {
|
||||||
// Author
|
// Author
|
||||||
val author = contactDb.getContactWithAccountID(authorPublicKey)
|
val author = contactDb.getContactWithAccountID(authorPublicKey)
|
||||||
val localNumber = TextSecurePreferences.getLocalNumber(context)
|
val localNumber = TextSecurePreferences.getLocalNumber(context)
|
||||||
|
@ -38,8 +38,8 @@ import org.thoughtcrime.securesms.conversation.v2.utilities.TextUtilities.getInt
|
|||||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord
|
import org.thoughtcrime.securesms.database.model.SmsMessageRecord
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
||||||
import org.thoughtcrime.securesms.util.SearchUtil
|
import org.thoughtcrime.securesms.util.SearchUtil
|
||||||
import org.thoughtcrime.securesms.util.getAccentColor
|
import org.thoughtcrime.securesms.util.getAccentColor
|
||||||
@ -63,7 +63,7 @@ class VisibleMessageContentView : ConstraintLayout {
|
|||||||
message: MessageRecord,
|
message: MessageRecord,
|
||||||
isStartOfMessageCluster: Boolean = true,
|
isStartOfMessageCluster: Boolean = true,
|
||||||
isEndOfMessageCluster: Boolean = true,
|
isEndOfMessageCluster: Boolean = true,
|
||||||
glide: GlideRequests = GlideApp.with(this),
|
glide: RequestManager = Glide.with(this),
|
||||||
thread: Recipient,
|
thread: Recipient,
|
||||||
searchQuery: String? = null,
|
searchQuery: String? = null,
|
||||||
contactIsTrusted: Boolean = true,
|
contactIsTrusted: Boolean = true,
|
||||||
|
@ -52,8 +52,8 @@ import org.thoughtcrime.securesms.database.ThreadDatabase
|
|||||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||||
import org.thoughtcrime.securesms.groups.OpenGroupManager
|
import org.thoughtcrime.securesms.groups.OpenGroupManager
|
||||||
import org.thoughtcrime.securesms.home.UserDetailsBottomSheet
|
import org.thoughtcrime.securesms.home.UserDetailsBottomSheet
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.util.DateUtils
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
import org.thoughtcrime.securesms.util.disableClipping
|
import org.thoughtcrime.securesms.util.disableClipping
|
||||||
import org.thoughtcrime.securesms.util.toDp
|
import org.thoughtcrime.securesms.util.toDp
|
||||||
@ -141,7 +141,7 @@ class VisibleMessageView : FrameLayout {
|
|||||||
message: MessageRecord,
|
message: MessageRecord,
|
||||||
previous: MessageRecord? = null,
|
previous: MessageRecord? = null,
|
||||||
next: MessageRecord? = null,
|
next: MessageRecord? = null,
|
||||||
glide: GlideRequests = GlideApp.with(this),
|
glide: RequestManager = Glide.with(this),
|
||||||
searchQuery: String? = null,
|
searchQuery: String? = null,
|
||||||
contact: Contact? = null,
|
contact: Contact? = null,
|
||||||
senderAccountID: String,
|
senderAccountID: String,
|
||||||
|
@ -44,7 +44,7 @@ import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
|
|||||||
import org.thoughtcrime.securesms.mms.AudioSlide;
|
import org.thoughtcrime.securesms.mms.AudioSlide;
|
||||||
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
||||||
import org.thoughtcrime.securesms.mms.GifSlide;
|
import org.thoughtcrime.securesms.mms.GifSlide;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
import org.thoughtcrime.securesms.mms.ImageSlide;
|
import org.thoughtcrime.securesms.mms.ImageSlide;
|
||||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||||
@ -126,7 +126,7 @@ public class AttachmentManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
public ListenableFuture<Boolean> setMedia(@NonNull final GlideRequests glideRequests,
|
public ListenableFuture<Boolean> setMedia(@NonNull final RequestManager glideRequests,
|
||||||
@NonNull final Uri uri,
|
@NonNull final Uri uri,
|
||||||
@NonNull final MediaType mediaType,
|
@NonNull final MediaType mediaType,
|
||||||
@NonNull final MediaConstraints constraints,
|
@NonNull final MediaConstraints constraints,
|
||||||
|
@ -25,8 +25,8 @@ import org.session.libsignal.utilities.SettableFuture
|
|||||||
import org.thoughtcrime.securesms.components.GlideBitmapListeningTarget
|
import org.thoughtcrime.securesms.components.GlideBitmapListeningTarget
|
||||||
import org.thoughtcrime.securesms.components.GlideDrawableListeningTarget
|
import org.thoughtcrime.securesms.components.GlideDrawableListeningTarget
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequest
|
import com.bumptech.glide.RequestBuilder
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.mms.Slide
|
import org.thoughtcrime.securesms.mms.Slide
|
||||||
|
|
||||||
open class ThumbnailView @JvmOverloads constructor(
|
open class ThumbnailView @JvmOverloads constructor(
|
||||||
@ -104,13 +104,13 @@ open class ThumbnailView @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setImageResource(
|
fun setImageResource(
|
||||||
glide: GlideRequests,
|
glide: RequestManager,
|
||||||
slide: Slide,
|
slide: Slide,
|
||||||
isPreview: Boolean
|
isPreview: Boolean
|
||||||
): ListenableFuture<Boolean> = setImageResource(glide, slide, isPreview, 0, 0)
|
): ListenableFuture<Boolean> = setImageResource(glide, slide, isPreview, 0, 0)
|
||||||
|
|
||||||
fun setImageResource(
|
fun setImageResource(
|
||||||
glide: GlideRequests, slide: Slide,
|
glide: RequestManager, slide: Slide,
|
||||||
isPreview: Boolean, naturalWidth: Int,
|
isPreview: Boolean, naturalWidth: Int,
|
||||||
naturalHeight: Int
|
naturalHeight: Int
|
||||||
): ListenableFuture<Boolean> {
|
): ListenableFuture<Boolean> {
|
||||||
@ -152,9 +152,9 @@ open class ThumbnailView @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun buildThumbnailGlideRequest(
|
private fun buildThumbnailGlideRequest(
|
||||||
glide: GlideRequests,
|
glide: RequestManager,
|
||||||
slide: Slide
|
slide: Slide
|
||||||
): GlideRequest<Drawable> = glide.load(DecryptableUri(slide.thumbnailUri!!))
|
): RequestBuilder<Drawable> = glide.load(DecryptableUri(slide.thumbnailUri!!))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.overrideDimensions()
|
.overrideDimensions()
|
||||||
.transition(DrawableTransitionOptions.withCrossFade())
|
.transition(DrawableTransitionOptions.withCrossFade())
|
||||||
@ -162,21 +162,21 @@ open class ThumbnailView @JvmOverloads constructor(
|
|||||||
.missingThumbnailPicture(slide.isInProgress)
|
.missingThumbnailPicture(slide.isInProgress)
|
||||||
|
|
||||||
private fun buildPlaceholderGlideRequest(
|
private fun buildPlaceholderGlideRequest(
|
||||||
glide: GlideRequests,
|
glide: RequestManager,
|
||||||
slide: Slide
|
slide: Slide
|
||||||
): GlideRequest<Bitmap> = glide.asBitmap()
|
): RequestBuilder<Bitmap> = glide.asBitmap()
|
||||||
.load(slide.getPlaceholderRes(context.theme))
|
.load(slide.getPlaceholderRes(context.theme))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.overrideDimensions()
|
.overrideDimensions()
|
||||||
.fitCenter()
|
.fitCenter()
|
||||||
|
|
||||||
open fun clear(glideRequests: GlideRequests) {
|
open fun clear(glideRequests: RequestManager) {
|
||||||
glideRequests.clear(binding.thumbnailImage)
|
glideRequests.clear(binding.thumbnailImage)
|
||||||
slide = null
|
slide = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setImageResource(
|
fun setImageResource(
|
||||||
glideRequests: GlideRequests,
|
glideRequests: RequestManager,
|
||||||
uri: Uri
|
uri: Uri
|
||||||
): ListenableFuture<Boolean> = glideRequests.load(DecryptableUri(uri))
|
): ListenableFuture<Boolean> = glideRequests.load(DecryptableUri(uri))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
@ -184,19 +184,19 @@ open class ThumbnailView @JvmOverloads constructor(
|
|||||||
.transform(CenterCrop())
|
.transform(CenterCrop())
|
||||||
.intoDrawableTargetAsFuture()
|
.intoDrawableTargetAsFuture()
|
||||||
|
|
||||||
private fun GlideRequest<Drawable>.intoDrawableTargetAsFuture() =
|
private fun RequestBuilder<Drawable>.intoDrawableTargetAsFuture() =
|
||||||
SettableFuture<Boolean>().also {
|
SettableFuture<Boolean>().also {
|
||||||
binding.run {
|
binding.run {
|
||||||
GlideDrawableListeningTarget(thumbnailImage, thumbnailLoadIndicator, it)
|
GlideDrawableListeningTarget(thumbnailImage, thumbnailLoadIndicator, it)
|
||||||
}.let { into(it) }
|
}.let { into(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> GlideRequest<T>.overrideDimensions() =
|
private fun <T> RequestBuilder<T>.overrideDimensions() =
|
||||||
dimensDelegate.resourceSize().takeIf { 0 !in it }
|
dimensDelegate.resourceSize().takeIf { 0 !in it }
|
||||||
?.let { override(it[WIDTH], it[HEIGHT]) }
|
?.let { override(it[WIDTH], it[HEIGHT]) }
|
||||||
?: override(getDefaultWidth(), getDefaultHeight())
|
?: override(getDefaultWidth(), getDefaultHeight())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> GlideRequest<T>.missingThumbnailPicture(
|
private fun <T> RequestBuilder<T>.missingThumbnailPicture(
|
||||||
inProgress: Boolean
|
inProgress: Boolean
|
||||||
) = takeIf { inProgress } ?: apply(RequestOptions.errorOf(R.drawable.ic_missing_thumbnail_picture))
|
) = takeIf { inProgress } ?: apply(RequestOptions.errorOf(R.drawable.ic_missing_thumbnail_picture))
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package org.thoughtcrime.securesms.crypto;
|
package org.thoughtcrime.securesms.crypto;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A provider that is responsible for creating or retrieving the AttachmentSecret model.
|
* A provider that is responsible for creating or retrieving the AttachmentSecret model.
|
||||||
*
|
*
|
||||||
@ -81,9 +81,8 @@ public class AttachmentSecretProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private AttachmentSecret createAndStoreAttachmentSecret(@NonNull Context context) {
|
private AttachmentSecret createAndStoreAttachmentSecret(@NonNull Context context) {
|
||||||
SecureRandom random = new SecureRandom();
|
|
||||||
byte[] secret = new byte[32];
|
byte[] secret = new byte[32];
|
||||||
random.nextBytes(secret);
|
SECURE_RANDOM.nextBytes(secret);
|
||||||
|
|
||||||
AttachmentSecret attachmentSecret = new AttachmentSecret(null, null, secret);
|
AttachmentSecret attachmentSecret = new AttachmentSecret(null, null, secret);
|
||||||
storeAttachmentSecret(context, attachmentSecret);
|
storeAttachmentSecret(context, attachmentSecret);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package org.thoughtcrime.securesms.crypto;
|
package org.thoughtcrime.securesms.crypto;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@ -8,7 +10,6 @@ import androidx.annotation.NonNull;
|
|||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
public class DatabaseSecretProvider {
|
public class DatabaseSecretProvider {
|
||||||
|
|
||||||
@ -60,9 +61,8 @@ public class DatabaseSecretProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) {
|
private DatabaseSecret createAndStoreDatabaseSecret(@NonNull Context context) {
|
||||||
SecureRandom random = new SecureRandom();
|
|
||||||
byte[] secret = new byte[32];
|
byte[] secret = new byte[32];
|
||||||
random.nextBytes(secret);
|
SECURE_RANDOM.nextBytes(secret);
|
||||||
|
|
||||||
DatabaseSecret databaseSecret = new DatabaseSecret(secret);
|
DatabaseSecret databaseSecret = new DatabaseSecret(secret);
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package org.thoughtcrime.securesms.crypto;
|
package org.thoughtcrime.securesms.crypto;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
@ -11,7 +13,6 @@ import java.io.OutputStream;
|
|||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.CipherOutputStream;
|
import javax.crypto.CipherOutputStream;
|
||||||
@ -31,7 +32,7 @@ public class ModernEncryptingPartOutputStream {
|
|||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
byte[] random = new byte[32];
|
byte[] random = new byte[32];
|
||||||
new SecureRandom().nextBytes(random);
|
SECURE_RANDOM.nextBytes(random);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Mac mac = Mac.getInstance("HmacSHA256");
|
Mac mac = Mac.getInstance("HmacSHA256");
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.database;
|
package org.thoughtcrime.securesms.database;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -26,7 +28,6 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
|||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -303,7 +304,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
public void updateProfilePicture(String groupID, byte[] newValue) {
|
public void updateProfilePicture(String groupID, byte[] newValue) {
|
||||||
long avatarId;
|
long avatarId;
|
||||||
|
|
||||||
if (newValue != null) avatarId = Math.abs(new SecureRandom().nextLong());
|
if (newValue != null) avatarId = Math.abs(SECURE_RANDOM.nextLong());
|
||||||
else avatarId = 0;
|
else avatarId = 0;
|
||||||
|
|
||||||
|
|
||||||
@ -458,12 +459,6 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt
|
|||||||
database.update(TABLE_NAME, values, GROUP_ID + " = ?", new String[] {groupId});
|
database.update(TABLE_NAME, values, GROUP_ID + " = ?", new String[] {groupId});
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] allocateGroupId() {
|
|
||||||
byte[] groupId = new byte[16];
|
|
||||||
new SecureRandom().nextBytes(groupId);
|
|
||||||
return groupId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasGroup(@NonNull String groupId) {
|
public boolean hasGroup(@NonNull String groupId) {
|
||||||
try (Cursor cursor = databaseHelper.getReadableDatabase().rawQuery(
|
try (Cursor cursor = databaseHelper.getReadableDatabase().rawQuery(
|
||||||
"SELECT 1 FROM " + TABLE_NAME + " WHERE " + GROUP_ID + " = ? LIMIT 1",
|
"SELECT 1 FROM " + TABLE_NAME + " WHERE " + GROUP_ID + " = ? LIMIT 1",
|
||||||
|
@ -166,8 +166,6 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
|
|
||||||
const val RESET_SEQ_NO = "UPDATE $lastMessageServerIDTable SET $lastMessageServerID = 0;"
|
const val RESET_SEQ_NO = "UPDATE $lastMessageServerIDTable SET $lastMessageServerID = 0;"
|
||||||
|
|
||||||
const val EMPTY_VERSION = "0.0.0"
|
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,15 +173,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(snodePoolTable, "${Companion.dummyKey} = ?", wrap("dummy_key")) { cursor ->
|
return database.get(snodePoolTable, "${Companion.dummyKey} = ?", wrap("dummy_key")) { cursor ->
|
||||||
val snodePoolAsString = cursor.getString(cursor.getColumnIndexOrThrow(snodePool))
|
val snodePoolAsString = cursor.getString(cursor.getColumnIndexOrThrow(snodePool))
|
||||||
snodePoolAsString.split(", ").mapNotNull { snodeAsString ->
|
snodePoolAsString.split(", ").mapNotNull(::Snode)
|
||||||
val components = snodeAsString.split("-")
|
|
||||||
val address = components[0]
|
|
||||||
val port = components.getOrNull(1)?.toIntOrNull() ?: return@mapNotNull null
|
|
||||||
val ed25519Key = components.getOrNull(2) ?: return@mapNotNull null
|
|
||||||
val x25519Key = components.getOrNull(3) ?: return@mapNotNull null
|
|
||||||
val version = components.getOrNull(4) ?: EMPTY_VERSION
|
|
||||||
Snode(address, port, Snode.KeySet(ed25519Key, x25519Key), version)
|
|
||||||
}
|
|
||||||
}?.toSet() ?: setOf()
|
}?.toSet() ?: setOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,18 +221,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
fun get(indexPath: String): Snode? {
|
fun get(indexPath: String): Snode? {
|
||||||
return database.get(onionRequestPathTable, "${Companion.indexPath} = ?", wrap(indexPath)) { cursor ->
|
return database.get(onionRequestPathTable, "${Companion.indexPath} = ?", wrap(indexPath)) { cursor ->
|
||||||
val snodeAsString = cursor.getString(cursor.getColumnIndexOrThrow(snode))
|
Snode(cursor.getString(cursor.getColumnIndexOrThrow(snode)))
|
||||||
val components = snodeAsString.split("-")
|
|
||||||
val address = components[0]
|
|
||||||
val port = components.getOrNull(1)?.toIntOrNull()
|
|
||||||
val ed25519Key = components.getOrNull(2)
|
|
||||||
val x25519Key = components.getOrNull(3)
|
|
||||||
val version = components.getOrNull(4) ?: EMPTY_VERSION
|
|
||||||
if (port != null && ed25519Key != null && x25519Key != null) {
|
|
||||||
Snode(address, port, Snode.KeySet(ed25519Key, x25519Key), version)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val result = mutableListOf<List<Snode>>()
|
val result = mutableListOf<List<Snode>>()
|
||||||
@ -276,15 +255,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
|||||||
val database = databaseHelper.readableDatabase
|
val database = databaseHelper.readableDatabase
|
||||||
return database.get(swarmTable, "${Companion.swarmPublicKey} = ?", wrap(publicKey)) { cursor ->
|
return database.get(swarmTable, "${Companion.swarmPublicKey} = ?", wrap(publicKey)) { cursor ->
|
||||||
val swarmAsString = cursor.getString(cursor.getColumnIndexOrThrow(swarm))
|
val swarmAsString = cursor.getString(cursor.getColumnIndexOrThrow(swarm))
|
||||||
swarmAsString.split(", ").mapNotNull { targetAsString ->
|
swarmAsString.split(", ").mapNotNull(::Snode)
|
||||||
val components = targetAsString.split("-")
|
|
||||||
val address = components[0]
|
|
||||||
val port = components.getOrNull(1)?.toIntOrNull() ?: return@mapNotNull null
|
|
||||||
val ed25519Key = components.getOrNull(2) ?: return@mapNotNull null
|
|
||||||
val x25519Key = components.getOrNull(3) ?: return@mapNotNull null
|
|
||||||
val version = components.getOrNull(4) ?: EMPTY_VERSION
|
|
||||||
Snode(address, port, Snode.KeySet(ed25519Key, x25519Key), version)
|
|
||||||
}
|
|
||||||
}?.toSet()
|
}?.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,11 +46,11 @@ import org.session.libsession.utilities.IdentityKeyMismatchList
|
|||||||
import org.session.libsession.utilities.NetworkFailure
|
import org.session.libsession.utilities.NetworkFailure
|
||||||
import org.session.libsession.utilities.NetworkFailureList
|
import org.session.libsession.utilities.NetworkFailureList
|
||||||
import org.session.libsession.utilities.TextSecurePreferences.Companion.isReadReceiptsEnabled
|
import org.session.libsession.utilities.TextSecurePreferences.Companion.isReadReceiptsEnabled
|
||||||
import org.session.libsession.utilities.Util.toIsoBytes
|
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsignal.utilities.JsonUtil
|
import org.session.libsignal.utilities.JsonUtil
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.session.libsignal.utilities.ThreadUtils.queue
|
import org.session.libsignal.utilities.ThreadUtils.queue
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import org.session.libsignal.utilities.guava.Optional
|
import org.session.libsignal.utilities.guava.Optional
|
||||||
import org.thoughtcrime.securesms.attachments.MmsNotificationAttachment
|
import org.thoughtcrime.securesms.attachments.MmsNotificationAttachment
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase.InsertListener
|
import org.thoughtcrime.securesms.database.SmsDatabase.InsertListener
|
||||||
@ -66,7 +66,6 @@ import org.thoughtcrime.securesms.mms.SlideDeck
|
|||||||
import org.thoughtcrime.securesms.util.asSequence
|
import org.thoughtcrime.securesms.util.asSequence
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.security.SecureRandom
|
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
|
|
||||||
class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : MessagingDatabase(context, databaseHelper) {
|
class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : MessagingDatabase(context, databaseHelper) {
|
||||||
@ -1200,7 +1199,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
|||||||
|
|
||||||
inner class OutgoingMessageReader(private val message: OutgoingMediaMessage?,
|
inner class OutgoingMessageReader(private val message: OutgoingMediaMessage?,
|
||||||
private val threadId: Long) {
|
private val threadId: Long) {
|
||||||
private val id = SecureRandom().nextLong()
|
private val id = SECURE_RANDOM.nextLong()
|
||||||
val current: MessageRecord
|
val current: MessageRecord
|
||||||
get() {
|
get() {
|
||||||
val slideDeck = SlideDeck(context, message!!.attachments)
|
val slideDeck = SlideDeck(context, message!!.attachments)
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.thoughtcrime.securesms.database;
|
package org.thoughtcrime.securesms.database;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
@ -49,7 +51,6 @@ import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
|||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -784,7 +785,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
public OutgoingMessageReader(OutgoingTextMessage message, long threadId) {
|
public OutgoingMessageReader(OutgoingTextMessage message, long threadId) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.threadId = threadId;
|
this.threadId = threadId;
|
||||||
this.id = new SecureRandom().nextLong();
|
this.id = SECURE_RANDOM.nextLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageRecord getCurrent() {
|
public MessageRecord getCurrent() {
|
||||||
|
@ -29,8 +29,8 @@ import org.session.libsession.utilities.ViewUtil;
|
|||||||
import org.session.libsignal.utilities.Log;
|
import org.session.libsignal.utilities.Log;
|
||||||
import org.thoughtcrime.securesms.giph.model.ChunkedImageUrl;
|
import org.thoughtcrime.securesms.giph.model.ChunkedImageUrl;
|
||||||
import org.thoughtcrime.securesms.giph.model.GiphyImage;
|
import org.thoughtcrime.securesms.giph.model.GiphyImage;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
@ -43,7 +43,7 @@ class GiphyAdapter extends RecyclerView.Adapter<GiphyAdapter.GiphyViewHolder> {
|
|||||||
private static final String TAG = GiphyAdapter.class.getSimpleName();
|
private static final String TAG = GiphyAdapter.class.getSimpleName();
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private final GlideRequests glideRequests;
|
private final RequestManager glideRequests;
|
||||||
|
|
||||||
private List<GiphyImage> images;
|
private List<GiphyImage> images;
|
||||||
private OnItemClickListener listener;
|
private OnItemClickListener listener;
|
||||||
@ -117,7 +117,7 @@ class GiphyAdapter extends RecyclerView.Adapter<GiphyAdapter.GiphyViewHolder> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GiphyAdapter(@NonNull Context context, @NonNull GlideRequests glideRequests, @NonNull List<GiphyImage> images) {
|
GiphyAdapter(@NonNull Context context, @NonNull RequestManager glideRequests, @NonNull List<GiphyImage> images) {
|
||||||
this.context = context.getApplicationContext();
|
this.context = context.getApplicationContext();
|
||||||
this.glideRequests = glideRequests;
|
this.glideRequests = glideRequests;
|
||||||
this.images = images;
|
this.images = images;
|
||||||
@ -150,7 +150,7 @@ class GiphyAdapter extends RecyclerView.Adapter<GiphyAdapter.GiphyViewHolder> {
|
|||||||
holder.thumbnail.setAspectRatio(image.getGifAspectRatio());
|
holder.thumbnail.setAspectRatio(image.getGifAspectRatio());
|
||||||
holder.gifProgress.setVisibility(View.GONE);
|
holder.gifProgress.setVisibility(View.GONE);
|
||||||
|
|
||||||
RequestBuilder<Drawable> thumbnailRequest = GlideApp.with(context)
|
RequestBuilder<Drawable> thumbnailRequest = Glide.with(context)
|
||||||
.load(new ChunkedImageUrl(image.getStillUrl(), image.getStillSize()))
|
.load(new ChunkedImageUrl(image.getStillUrl(), image.getStillSize()))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE);
|
.diskCacheStrategy(DiskCacheStrategy.NONE);
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import android.widget.TextView;
|
|||||||
import org.thoughtcrime.securesms.giph.model.GiphyImage;
|
import org.thoughtcrime.securesms.giph.model.GiphyImage;
|
||||||
import org.thoughtcrime.securesms.giph.net.GiphyLoader;
|
import org.thoughtcrime.securesms.giph.net.GiphyLoader;
|
||||||
import org.thoughtcrime.securesms.giph.util.InfiniteScrollListener;
|
import org.thoughtcrime.securesms.giph.util.InfiniteScrollListener;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
import org.session.libsession.utilities.ViewUtil;
|
import org.session.libsession.utilities.ViewUtil;
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ public abstract class GiphyFragment extends Fragment implements LoaderManager.Lo
|
|||||||
public void onActivityCreated(Bundle bundle) {
|
public void onActivityCreated(Bundle bundle) {
|
||||||
super.onActivityCreated(bundle);
|
super.onActivityCreated(bundle);
|
||||||
|
|
||||||
this.giphyAdapter = new GiphyAdapter(getActivity(), GlideApp.with(this), new LinkedList<>());
|
this.giphyAdapter = new GiphyAdapter(getActivity(), Glide.with(this), new LinkedList<>());
|
||||||
this.giphyAdapter.setListener(this);
|
this.giphyAdapter.setListener(this);
|
||||||
|
|
||||||
setLayoutManager(TextSecurePreferences.isGifSearchInGridLayout(getContext()));
|
setLayoutManager(TextSecurePreferences.isGifSearchInGridLayout(getContext()));
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package org.thoughtcrime.securesms.glide;
|
package org.thoughtcrime.securesms.glide;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
import okhttp3.Headers;
|
import okhttp3.Headers;
|
||||||
import okhttp3.Interceptor;
|
import okhttp3.Interceptor;
|
||||||
@ -30,15 +31,15 @@ public class PaddedHeadersInterceptor implements Interceptor {
|
|||||||
|
|
||||||
private @NonNull Headers getPaddedHeaders(@NonNull Headers headers) {
|
private @NonNull Headers getPaddedHeaders(@NonNull Headers headers) {
|
||||||
return headers.newBuilder()
|
return headers.newBuilder()
|
||||||
.add(PADDING_HEADER, getRandomString(new SecureRandom(), MIN_RANDOM_BYTES, MAX_RANDOM_BYTES))
|
.add(PADDING_HEADER, getRandomString(MIN_RANDOM_BYTES, MAX_RANDOM_BYTES))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NonNull String getRandomString(@NonNull SecureRandom secureRandom, int minLength, int maxLength) {
|
private static @NonNull String getRandomString(int minLength, int maxLength) {
|
||||||
char[] buffer = new char[secureRandom.nextInt(maxLength - minLength) + minLength];
|
char[] buffer = new char[SECURE_RANDOM.nextInt(maxLength - minLength) + minLength];
|
||||||
|
|
||||||
for (int i = 0 ; i < buffer.length; i++) {
|
for (int i = 0 ; i < buffer.length; i++) {
|
||||||
buffer[i] = (char) (secureRandom.nextInt(74) + 48); // Random char from 0-Z
|
buffer[i] = (char) (SECURE_RANDOM.nextInt(74) + 48); // Random char from 0-Z
|
||||||
}
|
}
|
||||||
|
|
||||||
return new String(buffer);
|
return new String(buffer);
|
||||||
|
@ -29,7 +29,7 @@ import org.thoughtcrime.securesms.conversation.start.StartConversationDelegate
|
|||||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView
|
import org.thoughtcrime.securesms.keyboard.emoji.KeyboardPageSearchView
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
import org.thoughtcrime.securesms.util.fadeIn
|
import org.thoughtcrime.securesms.util.fadeIn
|
||||||
import org.thoughtcrime.securesms.util.fadeOut
|
import org.thoughtcrime.securesms.util.fadeOut
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -55,7 +55,7 @@ class CreateGroupFragment : Fragment() {
|
|||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
val adapter = SelectContactsAdapter(requireContext(), GlideApp.with(requireContext()))
|
val adapter = SelectContactsAdapter(requireContext(), Glide.with(requireContext()))
|
||||||
binding.backButton.setOnClickListener { delegate.onDialogBackPressed() }
|
binding.backButton.setOnClickListener { delegate.onDialogBackPressed() }
|
||||||
binding.closeButton.setOnClickListener { delegate.onDialogClosePressed() }
|
binding.closeButton.setOnClickListener { delegate.onDialogClosePressed() }
|
||||||
binding.contactSearch.callbacks = object : KeyboardPageSearchView.Callbacks {
|
binding.contactSearch.callbacks = object : KeyboardPageSearchView.Callbacks {
|
||||||
|
@ -37,7 +37,7 @@ import org.thoughtcrime.securesms.database.Storage
|
|||||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.groups.ClosedGroupManager.updateLegacyGroup
|
import org.thoughtcrime.securesms.groups.ClosedGroupManager.updateLegacyGroup
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
import org.thoughtcrime.securesms.util.fadeIn
|
import org.thoughtcrime.securesms.util.fadeIn
|
||||||
import org.thoughtcrime.securesms.util.fadeOut
|
import org.thoughtcrime.securesms.util.fadeOut
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -76,9 +76,9 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
|
|
||||||
private val memberListAdapter by lazy {
|
private val memberListAdapter by lazy {
|
||||||
if (isSelfAdmin)
|
if (isSelfAdmin)
|
||||||
EditClosedGroupMembersAdapter(this, GlideApp.with(this), isSelfAdmin, this::onMemberClick)
|
EditClosedGroupMembersAdapter(this, Glide.with(this), isSelfAdmin, this::onMemberClick)
|
||||||
else
|
else
|
||||||
EditClosedGroupMembersAdapter(this, GlideApp.with(this), isSelfAdmin)
|
EditClosedGroupMembersAdapter(this, Glide.with(this), isSelfAdmin)
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var mainContentContainer: LinearLayout
|
private lateinit var mainContentContainer: LinearLayout
|
||||||
|
@ -5,13 +5,13 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import org.session.libsession.utilities.Address
|
import org.session.libsession.utilities.Address
|
||||||
import org.thoughtcrime.securesms.contacts.UserView
|
import org.thoughtcrime.securesms.contacts.UserView
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
|
|
||||||
class EditClosedGroupMembersAdapter(
|
class EditClosedGroupMembersAdapter(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val glide: GlideRequests,
|
private val glide: RequestManager,
|
||||||
private val admin: Boolean,
|
private val admin: Boolean,
|
||||||
private val memberClickListener: ((String) -> Unit)? = null
|
private val memberClickListener: ((String) -> Unit)? = null
|
||||||
) : RecyclerView.Adapter<EditClosedGroupMembersAdapter.ViewHolder>() {
|
) : RecyclerView.Adapter<EditClosedGroupMembersAdapter.ViewHolder>() {
|
||||||
|
@ -62,8 +62,8 @@ import org.thoughtcrime.securesms.home.search.GlobalSearchInputLayout
|
|||||||
import org.thoughtcrime.securesms.home.search.GlobalSearchResult
|
import org.thoughtcrime.securesms.home.search.GlobalSearchResult
|
||||||
import org.thoughtcrime.securesms.home.search.GlobalSearchViewModel
|
import org.thoughtcrime.securesms.home.search.GlobalSearchViewModel
|
||||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity
|
import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.notifications.PushRegistry
|
import org.thoughtcrime.securesms.notifications.PushRegistry
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions
|
import org.thoughtcrime.securesms.permissions.Permissions
|
||||||
import org.thoughtcrime.securesms.preferences.SettingsActivity
|
import org.thoughtcrime.securesms.preferences.SettingsActivity
|
||||||
@ -89,7 +89,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
GlobalSearchInputLayout.GlobalSearchInputLayoutListener {
|
GlobalSearchInputLayout.GlobalSearchInputLayoutListener {
|
||||||
|
|
||||||
private lateinit var binding: ActivityHomeBinding
|
private lateinit var binding: ActivityHomeBinding
|
||||||
private lateinit var glide: GlideRequests
|
private lateinit var glide: RequestManager
|
||||||
|
|
||||||
@Inject lateinit var threadDb: ThreadDatabase
|
@Inject lateinit var threadDb: ThreadDatabase
|
||||||
@Inject lateinit var mmsSmsDatabase: MmsSmsDatabase
|
@Inject lateinit var mmsSmsDatabase: MmsSmsDatabase
|
||||||
@ -148,7 +148,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
// Set custom toolbar
|
// Set custom toolbar
|
||||||
setSupportActionBar(binding.toolbar)
|
setSupportActionBar(binding.toolbar)
|
||||||
// Set up Glide
|
// Set up Glide
|
||||||
glide = GlideApp.with(this)
|
glide = Glide.with(this)
|
||||||
// Set up toolbar buttons
|
// Set up toolbar buttons
|
||||||
binding.profileButton.setOnClickListener { openSettings() }
|
binding.profileButton.setOnClickListener { openSettings() }
|
||||||
binding.searchViewContainer.setOnClickListener {
|
binding.searchViewContainer.setOnClickListener {
|
||||||
|
@ -7,10 +7,10 @@ import androidx.recyclerview.widget.DiffUtil
|
|||||||
import androidx.recyclerview.widget.ListUpdateCallback
|
import androidx.recyclerview.widget.ListUpdateCallback
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.recyclerview.widget.RecyclerView.NO_ID
|
import androidx.recyclerview.widget.RecyclerView.NO_ID
|
||||||
|
import com.bumptech.glide.RequestManager
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ViewMessageRequestBannerBinding
|
import network.loki.messenger.databinding.ViewMessageRequestBannerBinding
|
||||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
|
||||||
|
|
||||||
class HomeAdapter(
|
class HomeAdapter(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
@ -74,7 +74,7 @@ class HomeAdapter(
|
|||||||
return data.threads[offsetPosition].threadId
|
return data.threads[offsetPosition].threadId
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var glide: GlideRequests
|
lateinit var glide: RequestManager
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
|
||||||
when (viewType) {
|
when (viewType) {
|
||||||
@ -104,7 +104,6 @@ class HomeAdapter(
|
|||||||
holder.binding.run {
|
holder.binding.run {
|
||||||
messageRequests?.let {
|
messageRequests?.let {
|
||||||
unreadCountTextView.text = it.count
|
unreadCountTextView.text = it.count
|
||||||
timestampTextView.text = it.timestamp
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.jobmanager;
|
|
||||||
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service that keeps the application in memory while the app is closed.
|
|
||||||
*
|
|
||||||
* Important: Should only be used on API < 26.
|
|
||||||
*/
|
|
||||||
public class KeepAliveService extends Service {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable IBinder onBind(Intent intent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
||||||
return START_STICKY;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.logging;
|
package org.thoughtcrime.securesms.logging;
|
||||||
|
|
||||||
import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
|
import static org.session.libsignal.crypto.CipherUtil.CIPHER_LOCK;
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
@ -17,7 +18,6 @@ import java.io.IOException;
|
|||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
@ -64,7 +64,7 @@ class LogFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void writeEntry(@NonNull String entry) throws IOException {
|
void writeEntry(@NonNull String entry) throws IOException {
|
||||||
new SecureRandom().nextBytes(ivBuffer);
|
SECURE_RANDOM.nextBytes(ivBuffer);
|
||||||
|
|
||||||
byte[] plaintext = entry.getBytes();
|
byte[] plaintext = entry.getBytes();
|
||||||
try {
|
try {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.logging;
|
package org.thoughtcrime.securesms.logging;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@ -9,7 +11,6 @@ import org.session.libsignal.utilities.Base64;
|
|||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
|
||||||
|
|
||||||
class LogSecretProvider {
|
class LogSecretProvider {
|
||||||
|
|
||||||
@ -40,9 +41,8 @@ class LogSecretProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] createAndStoreSecret(@NonNull Context context) {
|
private static byte[] createAndStoreSecret(@NonNull Context context) {
|
||||||
SecureRandom random = new SecureRandom();
|
|
||||||
byte[] secret = new byte[32];
|
byte[] secret = new byte[32];
|
||||||
random.nextBytes(secret);
|
SECURE_RANDOM.nextBytes(secret);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret);
|
KeyStoreHelper.SealedData encryptedSecret = KeyStoreHelper.seal(secret);
|
||||||
|
@ -14,7 +14,7 @@ import network.loki.messenger.R;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView;
|
import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView;
|
||||||
import org.thoughtcrime.securesms.mediasend.Media;
|
import org.thoughtcrime.securesms.mediasend.Media;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
import org.thoughtcrime.securesms.util.StableIdGenerator;
|
import org.thoughtcrime.securesms.util.StableIdGenerator;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -25,7 +25,7 @@ public class MediaRailAdapter extends RecyclerView.Adapter<MediaRailAdapter.Medi
|
|||||||
private static final int TYPE_MEDIA = 1;
|
private static final int TYPE_MEDIA = 1;
|
||||||
private static final int TYPE_BUTTON = 2;
|
private static final int TYPE_BUTTON = 2;
|
||||||
|
|
||||||
private final GlideRequests glideRequests;
|
private final RequestManager glideRequests;
|
||||||
private final List<Media> media;
|
private final List<Media> media;
|
||||||
private final RailItemListener listener;
|
private final RailItemListener listener;
|
||||||
private final boolean editable;
|
private final boolean editable;
|
||||||
@ -34,7 +34,7 @@ public class MediaRailAdapter extends RecyclerView.Adapter<MediaRailAdapter.Medi
|
|||||||
private RailItemAddListener addListener;
|
private RailItemAddListener addListener;
|
||||||
private int activePosition;
|
private int activePosition;
|
||||||
|
|
||||||
public MediaRailAdapter(@NonNull GlideRequests glideRequests, @NonNull RailItemListener listener, boolean editable) {
|
public MediaRailAdapter(@NonNull RequestManager glideRequests, @NonNull RailItemListener listener, boolean editable) {
|
||||||
this.glideRequests = glideRequests;
|
this.glideRequests = glideRequests;
|
||||||
this.media = new ArrayList<>();
|
this.media = new ArrayList<>();
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
@ -148,7 +148,7 @@ public class MediaRailAdapter extends RecyclerView.Adapter<MediaRailAdapter.Medi
|
|||||||
captionIndicator = itemView.findViewById(R.id.rail_item_caption);
|
captionIndicator = itemView.findViewById(R.id.rail_item_caption);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(@NonNull Media media, boolean isActive, @NonNull GlideRequests glideRequests,
|
void bind(@NonNull Media media, boolean isActive, @NonNull RequestManager glideRequests,
|
||||||
@NonNull RailItemListener railItemListener, int distanceFromActive, boolean editable)
|
@NonNull RailItemListener railItemListener, int distanceFromActive, boolean editable)
|
||||||
{
|
{
|
||||||
image.setImageResource(glideRequests, media.getUri());
|
image.setImageResource(glideRequests, media.getUri());
|
||||||
|
@ -36,7 +36,7 @@ import com.bumptech.glide.request.transition.Transition;
|
|||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
import org.session.libsignal.utilities.Log;
|
import org.session.libsignal.utilities.Log;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.session.libsession.utilities.ServiceUtil;
|
import org.session.libsession.utilities.ServiceUtil;
|
||||||
import org.thoughtcrime.securesms.util.Stopwatch;
|
import org.thoughtcrime.securesms.util.Stopwatch;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
@ -236,7 +236,7 @@ public class Camera1Fragment extends Fragment implements TextureView.SurfaceText
|
|||||||
Transformation<Bitmap> transformation = frontFacing ? new MultiTransformation<>(new CenterCrop(), new FlipTransformation())
|
Transformation<Bitmap> transformation = frontFacing ? new MultiTransformation<>(new CenterCrop(), new FlipTransformation())
|
||||||
: new CenterCrop();
|
: new CenterCrop();
|
||||||
|
|
||||||
GlideApp.with(this)
|
Glide.with(this)
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.load(jpegData)
|
.load(jpegData)
|
||||||
.transform(transformation)
|
.transform(transformation)
|
||||||
|
@ -14,18 +14,18 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
|||||||
|
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class MediaPickerFolderAdapter extends RecyclerView.Adapter<MediaPickerFolderAdapter.FolderViewHolder> {
|
class MediaPickerFolderAdapter extends RecyclerView.Adapter<MediaPickerFolderAdapter.FolderViewHolder> {
|
||||||
|
|
||||||
private final GlideRequests glideRequests;
|
private final RequestManager glideRequests;
|
||||||
private final EventListener eventListener;
|
private final EventListener eventListener;
|
||||||
private final List<MediaFolder> folders;
|
private final List<MediaFolder> folders;
|
||||||
|
|
||||||
MediaPickerFolderAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) {
|
MediaPickerFolderAdapter(@NonNull RequestManager glideRequests, @NonNull EventListener eventListener) {
|
||||||
this.glideRequests = glideRequests;
|
this.glideRequests = glideRequests;
|
||||||
this.eventListener = eventListener;
|
this.eventListener = eventListener;
|
||||||
this.folders = new ArrayList<>();
|
this.folders = new ArrayList<>();
|
||||||
@ -74,7 +74,7 @@ class MediaPickerFolderAdapter extends RecyclerView.Adapter<MediaPickerFolderAda
|
|||||||
count = itemView.findViewById(R.id.mediapicker_folder_item_count);
|
count = itemView.findViewById(R.id.mediapicker_folder_item_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(@NonNull MediaFolder folder, @NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) {
|
void bind(@NonNull MediaFolder folder, @NonNull RequestManager glideRequests, @NonNull EventListener eventListener) {
|
||||||
title.setText(folder.getTitle());
|
title.setText(folder.getTitle());
|
||||||
count.setText(String.valueOf(folder.getItemCount()));
|
count.setText(String.valueOf(folder.getItemCount()));
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.session.libsession.utilities.recipients.Recipient;
|
import org.session.libsession.utilities.recipients.Recipient;
|
||||||
import org.session.libsignal.utilities.guava.Optional;
|
import org.session.libsignal.utilities.guava.Optional;
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ public class MediaPickerFolderFragment extends Fragment implements MediaPickerFo
|
|||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
RecyclerView list = view.findViewById(R.id.mediapicker_folder_list);
|
RecyclerView list = view.findViewById(R.id.mediapicker_folder_list);
|
||||||
MediaPickerFolderAdapter adapter = new MediaPickerFolderAdapter(GlideApp.with(this), this);
|
MediaPickerFolderAdapter adapter = new MediaPickerFolderAdapter(Glide.with(this), this);
|
||||||
|
|
||||||
layoutManager = new GridLayoutManager(requireContext(), 2);
|
layoutManager = new GridLayoutManager(requireContext(), 2);
|
||||||
onScreenWidthChanged(getScreenWidth());
|
onScreenWidthChanged(getScreenWidth());
|
||||||
|
@ -12,7 +12,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
|||||||
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
import org.thoughtcrime.securesms.util.StableIdGenerator;
|
import org.thoughtcrime.securesms.util.StableIdGenerator;
|
||||||
@ -24,7 +24,7 @@ import java.util.List;
|
|||||||
|
|
||||||
public class MediaPickerItemAdapter extends RecyclerView.Adapter<MediaPickerItemAdapter.ItemViewHolder> {
|
public class MediaPickerItemAdapter extends RecyclerView.Adapter<MediaPickerItemAdapter.ItemViewHolder> {
|
||||||
|
|
||||||
private final GlideRequests glideRequests;
|
private final RequestManager glideRequests;
|
||||||
private final EventListener eventListener;
|
private final EventListener eventListener;
|
||||||
private final List<Media> media;
|
private final List<Media> media;
|
||||||
private final List<Media> selected;
|
private final List<Media> selected;
|
||||||
@ -33,7 +33,7 @@ public class MediaPickerItemAdapter extends RecyclerView.Adapter<MediaPickerItem
|
|||||||
|
|
||||||
private boolean forcedMultiSelect;
|
private boolean forcedMultiSelect;
|
||||||
|
|
||||||
public MediaPickerItemAdapter(@NonNull GlideRequests glideRequests, @NonNull EventListener eventListener, int maxSelection) {
|
public MediaPickerItemAdapter(@NonNull RequestManager glideRequests, @NonNull EventListener eventListener, int maxSelection) {
|
||||||
this.glideRequests = glideRequests;
|
this.glideRequests = glideRequests;
|
||||||
this.eventListener = eventListener;
|
this.eventListener = eventListener;
|
||||||
this.media = new ArrayList<>();
|
this.media = new ArrayList<>();
|
||||||
@ -109,7 +109,7 @@ public class MediaPickerItemAdapter extends RecyclerView.Adapter<MediaPickerItem
|
|||||||
selectOrder = itemView.findViewById(R.id.mediapicker_select_order);
|
selectOrder = itemView.findViewById(R.id.mediapicker_select_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(@NonNull Media media, boolean multiSelect, List<Media> selected, int maxSelection, @NonNull GlideRequests glideRequests, @NonNull EventListener eventListener) {
|
void bind(@NonNull Media media, boolean multiSelect, List<Media> selected, int maxSelection, @NonNull RequestManager glideRequests, @NonNull EventListener eventListener) {
|
||||||
glideRequests.load(media.getUri())
|
glideRequests.load(media.getUri())
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.transition(DrawableTransitionOptions.withCrossFade())
|
.transition(DrawableTransitionOptions.withCrossFade())
|
||||||
|
@ -21,7 +21,7 @@ import android.view.ViewGroup;
|
|||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -91,7 +91,7 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem
|
|||||||
|
|
||||||
RecyclerView imageList = view.findViewById(R.id.mediapicker_item_list);
|
RecyclerView imageList = view.findViewById(R.id.mediapicker_item_list);
|
||||||
|
|
||||||
adapter = new MediaPickerItemAdapter(GlideApp.with(this), this, maxSelection);
|
adapter = new MediaPickerItemAdapter(Glide.with(this), this, maxSelection);
|
||||||
layoutManager = new GridLayoutManager(requireContext(), 4);
|
layoutManager = new GridLayoutManager(requireContext(), 4);
|
||||||
|
|
||||||
imageList.setLayoutManager(layoutManager);
|
imageList.setLayoutManager(layoutManager);
|
||||||
|
@ -41,7 +41,7 @@ import org.thoughtcrime.securesms.util.SimpleTextWatcher;
|
|||||||
import org.thoughtcrime.securesms.imageeditor.model.EditorModel;
|
import org.thoughtcrime.securesms.imageeditor.model.EditorModel;
|
||||||
import org.session.libsignal.utilities.Log;
|
import org.session.libsignal.utilities.Log;
|
||||||
import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter;
|
import org.thoughtcrime.securesms.mediapreview.MediaRailAdapter;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||||
import org.session.libsession.utilities.recipients.Recipient;
|
import org.session.libsession.utilities.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.scribbles.ImageEditorFragment;
|
import org.thoughtcrime.securesms.scribbles.ImageEditorFragment;
|
||||||
@ -187,7 +187,7 @@ public class MediaSendFragment extends Fragment implements ViewTreeObserver.OnGl
|
|||||||
fragmentPager.addOnPageChangeListener(pageChangeListener);
|
fragmentPager.addOnPageChangeListener(pageChangeListener);
|
||||||
fragmentPager.post(() -> pageChangeListener.onPageSelected(fragmentPager.getCurrentItem()));
|
fragmentPager.post(() -> pageChangeListener.onPageSelected(fragmentPager.getCurrentItem()));
|
||||||
|
|
||||||
mediaRailAdapter = new MediaRailAdapter(GlideApp.with(this), this, true);
|
mediaRailAdapter = new MediaRailAdapter(Glide.with(this), this, true);
|
||||||
mediaRail.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
|
mediaRail.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
|
||||||
mediaRail.setAdapter(mediaRailAdapter);
|
mediaRail.setAdapter(mediaRailAdapter);
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import android.widget.ImageView;
|
|||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
|
|
||||||
public class MediaSendGifFragment extends Fragment implements MediaSendPageFragment {
|
public class MediaSendGifFragment extends Fragment implements MediaSendPageFragment {
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ public class MediaSendGifFragment extends Fragment implements MediaSendPageFragm
|
|||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
uri = getArguments().getParcelable(KEY_URI);
|
uri = getArguments().getParcelable(KEY_URI);
|
||||||
GlideApp.with(this).load(new DecryptableStreamUriLoader.DecryptableUri(uri)).into((ImageView) view);
|
Glide.with(this).load(new DecryptableStreamUriLoader.DecryptableUri(uri)).into((ImageView) view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -11,7 +11,7 @@ import network.loki.messenger.databinding.ViewMessageRequestBinding
|
|||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities.highlightMentions
|
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities.highlightMentions
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.util.DateUtils
|
import org.thoughtcrime.securesms.util.DateUtils
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ class MessageRequestView : LinearLayout {
|
|||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Updating
|
// region Updating
|
||||||
fun bind(thread: ThreadRecord, glide: GlideRequests) {
|
fun bind(thread: ThreadRecord, glide: RequestManager) {
|
||||||
this.thread = thread
|
this.thread = thread
|
||||||
|
|
||||||
val senderDisplayName = getUserDisplayName(thread.recipient) ?: thread.recipient.address.toString()
|
val senderDisplayName = getUserDisplayName(thread.recipient) ?: thread.recipient.address.toString()
|
||||||
|
@ -17,8 +17,8 @@ import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
|||||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
import org.thoughtcrime.securesms.showSessionDialog
|
import org.thoughtcrime.securesms.showSessionDialog
|
||||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
import org.thoughtcrime.securesms.util.push
|
import org.thoughtcrime.securesms.util.push
|
||||||
@ -28,7 +28,7 @@ import javax.inject.Inject
|
|||||||
class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), ConversationClickListener, LoaderManager.LoaderCallbacks<Cursor> {
|
class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), ConversationClickListener, LoaderManager.LoaderCallbacks<Cursor> {
|
||||||
|
|
||||||
private lateinit var binding: ActivityMessageRequestsBinding
|
private lateinit var binding: ActivityMessageRequestsBinding
|
||||||
private lateinit var glide: GlideRequests
|
private lateinit var glide: RequestManager
|
||||||
|
|
||||||
@Inject lateinit var threadDb: ThreadDatabase
|
@Inject lateinit var threadDb: ThreadDatabase
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ class MessageRequestsActivity : PassphraseRequiredActionBarActivity(), Conversat
|
|||||||
binding = ActivityMessageRequestsBinding.inflate(layoutInflater)
|
binding = ActivityMessageRequestsBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
glide = GlideApp.with(this)
|
glide = Glide.with(this)
|
||||||
|
|
||||||
adapter.setHasStableIds(true)
|
adapter.setHasStableIds(true)
|
||||||
adapter.glide = glide
|
adapter.glide = glide
|
||||||
|
@ -15,7 +15,7 @@ import org.session.libsession.utilities.ThemeUtil
|
|||||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
|
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import com.bumptech.glide.RequestManager
|
||||||
|
|
||||||
class MessageRequestsAdapter(
|
class MessageRequestsAdapter(
|
||||||
context: Context,
|
context: Context,
|
||||||
@ -23,7 +23,7 @@ class MessageRequestsAdapter(
|
|||||||
val listener: ConversationClickListener
|
val listener: ConversationClickListener
|
||||||
) : CursorRecyclerViewAdapter<MessageRequestsAdapter.ViewHolder>(context, cursor) {
|
) : CursorRecyclerViewAdapter<MessageRequestsAdapter.ViewHolder>(context, cursor) {
|
||||||
private val threadDatabase = DatabaseComponent.get(context).threadDatabase()
|
private val threadDatabase = DatabaseComponent.get(context).threadDatabase()
|
||||||
lateinit var glide: GlideRequests
|
lateinit var glide: RequestManager
|
||||||
|
|
||||||
class ViewHolder(val view: MessageRequestView) : RecyclerView.ViewHolder(view)
|
class ViewHolder(val view: MessageRequestView) : RecyclerView.ViewHolder(view)
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ import android.content.res.Resources
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import com.squareup.phrase.Phrase
|
import com.squareup.phrase.Phrase
|
||||||
import java.security.SecureRandom
|
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
|
||||||
@ -29,6 +28,7 @@ import org.session.libsession.messaging.sending_receiving.attachments.UriAttachm
|
|||||||
import org.session.libsession.utilities.StringSubstitutionConstants.EMOJI_KEY
|
import org.session.libsession.utilities.StringSubstitutionConstants.EMOJI_KEY
|
||||||
import org.session.libsession.utilities.Util.equals
|
import org.session.libsession.utilities.Util.equals
|
||||||
import org.session.libsession.utilities.Util.hashCode
|
import org.session.libsession.utilities.Util.hashCode
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import org.session.libsignal.utilities.guava.Optional
|
import org.session.libsignal.utilities.guava.Optional
|
||||||
import org.thoughtcrime.securesms.conversation.v2.Util
|
import org.thoughtcrime.securesms.conversation.v2.Util
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil
|
import org.thoughtcrime.securesms.util.MediaUtil
|
||||||
@ -160,7 +160,7 @@ abstract class Slide(@JvmField protected val context: Context, protected val att
|
|||||||
): Attachment {
|
): Attachment {
|
||||||
val resolvedType =
|
val resolvedType =
|
||||||
Optional.fromNullable(MediaUtil.getMimeType(context, uri)).or(defaultMime)
|
Optional.fromNullable(MediaUtil.getMimeType(context, uri)).or(defaultMime)
|
||||||
val fastPreflightId = SecureRandom().nextLong().toString()
|
val fastPreflightId = SECURE_RANDOM.nextLong().toString()
|
||||||
return UriAttachment(
|
return UriAttachment(
|
||||||
uri,
|
uri,
|
||||||
if (hasThumbnail) uri else null,
|
if (hasThumbnail) uri else null,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.net;
|
package org.thoughtcrime.securesms.net;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
@ -15,7 +17,6 @@ import org.session.libsignal.utilities.guava.Optional;
|
|||||||
import java.io.FilterInputStream;
|
import java.io.FilterInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -54,7 +55,7 @@ public class ChunkedDataFetcher {
|
|||||||
private RequestController fetchChunksWithUnknownTotalSize(@NonNull String url, @NonNull Callback callback) {
|
private RequestController fetchChunksWithUnknownTotalSize(@NonNull String url, @NonNull Callback callback) {
|
||||||
CompositeRequestController compositeController = new CompositeRequestController();
|
CompositeRequestController compositeController = new CompositeRequestController();
|
||||||
|
|
||||||
long chunkSize = new SecureRandom().nextInt(1024) + 1024;
|
long chunkSize = SECURE_RANDOM.nextInt(1024) + 1024;
|
||||||
Request request = new Request.Builder()
|
Request request = new Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.cacheControl(NO_CACHE)
|
.cacheControl(NO_CACHE)
|
||||||
|
@ -38,7 +38,7 @@ import org.session.libsignal.utilities.Log;
|
|||||||
import org.thoughtcrime.securesms.database.SessionContactDatabase;
|
import org.thoughtcrime.securesms.database.SessionContactDatabase;
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator;
|
import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator;
|
||||||
@ -91,7 +91,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
try {
|
try {
|
||||||
// AC: For some reason, if not use ".asBitmap()" method, the returned BitmapDrawable
|
// AC: For some reason, if not use ".asBitmap()" method, the returned BitmapDrawable
|
||||||
// wraps a recycled bitmap and leads to a crash.
|
// wraps a recycled bitmap and leads to a crash.
|
||||||
Bitmap iconBitmap = GlideApp.with(context.getApplicationContext())
|
Bitmap iconBitmap = Glide.with(context.getApplicationContext())
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.load(contactPhoto)
|
.load(contactPhoto)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
@ -293,7 +293,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
Uri uri = slideDeck.getThumbnailSlide().getThumbnailUri();
|
Uri uri = slideDeck.getThumbnailSlide().getThumbnailUri();
|
||||||
|
|
||||||
return GlideApp.with(context.getApplicationContext())
|
return Glide.with(context.getApplicationContext())
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.load(new DecryptableStreamUriLoader.DecryptableUri(uri))
|
.load(new DecryptableStreamUriLoader.DecryptableUri(uri))
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package org.thoughtcrime.securesms.permissions;
|
package org.thoughtcrime.securesms.permissions;
|
||||||
|
|
||||||
|
import static org.session.libsignal.utilities.Util.SECURE_RANDOM;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -11,9 +11,7 @@ import android.os.Build;
|
|||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.Button;
|
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
import androidx.annotation.DrawableRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@ -28,13 +26,10 @@ import org.session.libsession.utilities.ServiceUtil;
|
|||||||
import org.thoughtcrime.securesms.util.LRUCache;
|
import org.thoughtcrime.securesms.util.LRUCache;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
|
||||||
|
|
||||||
public class Permissions {
|
public class Permissions {
|
||||||
|
|
||||||
private static final Map<Integer, PermissionsRequest> OUTSTANDING = new LRUCache<>(2);
|
private static final Map<Integer, PermissionsRequest> OUTSTANDING = new LRUCache<>(2);
|
||||||
@ -172,7 +167,7 @@ public class Permissions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void executePermissionsRequest(PermissionsRequest request) {
|
private void executePermissionsRequest(PermissionsRequest request) {
|
||||||
int requestCode = new SecureRandom().nextInt(65434) + 100;
|
int requestCode = SECURE_RANDOM.nextInt(65434) + 100;
|
||||||
|
|
||||||
synchronized (OUTSTANDING) {
|
synchronized (OUTSTANDING) {
|
||||||
OUTSTANDING.put(requestCode, request);
|
OUTSTANDING.put(requestCode, request);
|
||||||
|
@ -9,7 +9,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.BlockedContactLayoutBinding
|
import network.loki.messenger.databinding.BlockedContactLayoutBinding
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
import org.thoughtcrime.securesms.util.adapter.SelectableItem
|
import org.thoughtcrime.securesms.util.adapter.SelectableItem
|
||||||
|
|
||||||
typealias SelectableRecipient = SelectableItem<Recipient>
|
typealias SelectableRecipient = SelectableItem<Recipient>
|
||||||
@ -43,7 +43,7 @@ class BlockedContactsAdapter(val viewModel: BlockedContactsViewModel) : ListAdap
|
|||||||
|
|
||||||
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
|
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
|
||||||
|
|
||||||
val glide = GlideApp.with(itemView)
|
val glide = Glide.with(itemView)
|
||||||
val binding = BlockedContactLayoutBinding.bind(itemView)
|
val binding = BlockedContactLayoutBinding.bind(itemView)
|
||||||
|
|
||||||
fun bind(selectable: SelectableRecipient, toggle: (SelectableRecipient) -> Unit) {
|
fun bind(selectable: SelectableRecipient, toggle: (SelectableRecipient) -> Unit) {
|
||||||
|
@ -10,7 +10,7 @@ import androidx.recyclerview.widget.ListAdapter
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.ItemSelectableBinding
|
import network.loki.messenger.databinding.ItemSelectableBinding
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import com.bumptech.glide.Glide
|
||||||
import org.thoughtcrime.securesms.ui.GetString
|
import org.thoughtcrime.securesms.ui.GetString
|
||||||
import java.util.Objects
|
import java.util.Objects
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ class RadioOptionAdapter<T>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ViewHolder<T>(itemView: View): RecyclerView.ViewHolder(itemView) {
|
class ViewHolder<T>(itemView: View): RecyclerView.ViewHolder(itemView) {
|
||||||
val glide = GlideApp.with(itemView)
|
val glide = Glide.with(itemView)
|
||||||
val binding = ItemSelectableBinding.bind(itemView)
|
val binding = ItemSelectableBinding.bind(itemView)
|
||||||
|
|
||||||
fun bind(option: RadioOption<T>, isSelected: Boolean, toggleSelection: (RadioOption<T>) -> Unit) {
|
fun bind(option: RadioOption<T>, isSelected: Boolean, toggleSelection: (RadioOption<T>) -> Unit) {
|
||||||
|
@ -65,6 +65,7 @@ import org.session.libsession.utilities.TextSecurePreferences
|
|||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsession.utilities.truncateIdForDisplay
|
import org.session.libsession.utilities.truncateIdForDisplay
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.avatar.AvatarSelection
|
import org.thoughtcrime.securesms.avatar.AvatarSelection
|
||||||
import org.thoughtcrime.securesms.components.ProfilePictureView
|
import org.thoughtcrime.securesms.components.ProfilePictureView
|
||||||
@ -93,7 +94,6 @@ import org.thoughtcrime.securesms.util.NetworkUtils
|
|||||||
import org.thoughtcrime.securesms.util.push
|
import org.thoughtcrime.securesms.util.push
|
||||||
import org.thoughtcrime.securesms.util.show
|
import org.thoughtcrime.securesms.util.show
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.security.SecureRandom
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -314,7 +314,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
|
|
||||||
val userConfig = configFactory.user
|
val userConfig = configFactory.user
|
||||||
AvatarHelper.setAvatar(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)!!), profilePicture)
|
AvatarHelper.setAvatar(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)!!), profilePicture)
|
||||||
prefs.setProfileAvatarId(SecureRandom().nextInt() )
|
prefs.setProfileAvatarId(SECURE_RANDOM.nextInt() )
|
||||||
ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey)
|
ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey)
|
||||||
|
|
||||||
// Attempt to grab the details we require to update the profile picture
|
// Attempt to grab the details we require to update the profile picture
|
||||||
|
@ -13,7 +13,7 @@ import org.session.libsession.messaging.utilities.AccountId;
|
|||||||
import org.thoughtcrime.securesms.components.ProfilePictureView;
|
import org.thoughtcrime.securesms.components.ProfilePictureView;
|
||||||
import org.thoughtcrime.securesms.components.emoji.EmojiImageView;
|
import org.thoughtcrime.securesms.components.emoji.EmojiImageView;
|
||||||
import org.thoughtcrime.securesms.database.model.MessageId;
|
import org.thoughtcrime.securesms.database.model.MessageId;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -8,7 +8,6 @@ import app.cash.copper.Query
|
|||||||
import app.cash.copper.flow.observeQuery
|
import app.cash.copper.flow.observeQuery
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.coroutines.resumeWithException
|
|
||||||
import kotlin.coroutines.suspendCoroutine
|
import kotlin.coroutines.suspendCoroutine
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
@ -59,15 +58,15 @@ interface ConversationRepository {
|
|||||||
fun deleteLocally(recipient: Recipient, message: MessageRecord)
|
fun deleteLocally(recipient: Recipient, message: MessageRecord)
|
||||||
fun deleteAllLocalMessagesInThreadFromSenderOfMessage(messageRecord: MessageRecord)
|
fun deleteAllLocalMessagesInThreadFromSenderOfMessage(messageRecord: MessageRecord)
|
||||||
fun setApproved(recipient: Recipient, isApproved: Boolean)
|
fun setApproved(recipient: Recipient, isApproved: Boolean)
|
||||||
suspend fun deleteForEveryone(threadId: Long, recipient: Recipient, message: MessageRecord): ResultOf<Unit>
|
suspend fun deleteForEveryone(threadId: Long, recipient: Recipient, message: MessageRecord): Result<Unit>
|
||||||
fun buildUnsendRequest(recipient: Recipient, message: MessageRecord): UnsendRequest?
|
fun buildUnsendRequest(recipient: Recipient, message: MessageRecord): UnsendRequest?
|
||||||
suspend fun deleteMessageWithoutUnsendRequest(threadId: Long, messages: Set<MessageRecord>): ResultOf<Unit>
|
suspend fun deleteMessageWithoutUnsendRequest(threadId: Long, messages: Set<MessageRecord>): Result<Unit>
|
||||||
suspend fun banUser(threadId: Long, recipient: Recipient): ResultOf<Unit>
|
suspend fun banUser(threadId: Long, recipient: Recipient): Result<Unit>
|
||||||
suspend fun banAndDeleteAll(threadId: Long, recipient: Recipient): ResultOf<Unit>
|
suspend fun banAndDeleteAll(threadId: Long, recipient: Recipient): Result<Unit>
|
||||||
suspend fun deleteThread(threadId: Long): ResultOf<Unit>
|
suspend fun deleteThread(threadId: Long): Result<Unit>
|
||||||
suspend fun deleteMessageRequest(thread: ThreadRecord): ResultOf<Unit>
|
suspend fun deleteMessageRequest(thread: ThreadRecord): Result<Unit>
|
||||||
suspend fun clearAllMessageRequests(block: Boolean): ResultOf<Unit>
|
suspend fun clearAllMessageRequests(block: Boolean): Result<Unit>
|
||||||
suspend fun acceptMessageRequest(threadId: Long, recipient: Recipient): ResultOf<Unit>
|
suspend fun acceptMessageRequest(threadId: Long, recipient: Recipient): Result<Unit>
|
||||||
fun declineMessageRequest(threadId: Long)
|
fun declineMessageRequest(threadId: Long)
|
||||||
fun hasReceived(threadId: Long): Boolean
|
fun hasReceived(threadId: Long): Boolean
|
||||||
}
|
}
|
||||||
@ -185,7 +184,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
threadId: Long,
|
threadId: Long,
|
||||||
recipient: Recipient,
|
recipient: Recipient,
|
||||||
message: MessageRecord
|
message: MessageRecord
|
||||||
): ResultOf<Unit> = suspendCoroutine { continuation ->
|
): Result<Unit> = suspendCoroutine { continuation ->
|
||||||
buildUnsendRequest(recipient, message)?.let { unsendRequest ->
|
buildUnsendRequest(recipient, message)?.let { unsendRequest ->
|
||||||
MessageSender.send(unsendRequest, recipient.address)
|
MessageSender.send(unsendRequest, recipient.address)
|
||||||
}
|
}
|
||||||
@ -196,10 +195,10 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
OpenGroupApi.deleteMessage(messageServerID, openGroup.room, openGroup.server)
|
OpenGroupApi.deleteMessage(messageServerID, openGroup.room, openGroup.server)
|
||||||
.success {
|
.success {
|
||||||
messageDataProvider.deleteMessage(message.id, !message.isMms)
|
messageDataProvider.deleteMessage(message.id, !message.isMms)
|
||||||
continuation.resume(ResultOf.Success(Unit))
|
continuation.resume(Result.success(Unit))
|
||||||
}.fail { error ->
|
}.fail { error ->
|
||||||
Log.w("TAG", "Call to OpenGroupApi.deleteForEveryone failed - attempting to resume..")
|
Log.w("TAG", "Call to OpenGroupApi.deleteForEveryone failed - attempting to resume..")
|
||||||
continuation.resumeWithException(error)
|
continuation.resume(Result.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,10 +228,10 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
SnodeAPI.deleteMessage(publicKey, listOf(serverHash))
|
SnodeAPI.deleteMessage(publicKey, listOf(serverHash))
|
||||||
.success {
|
.success {
|
||||||
continuation.resume(ResultOf.Success(Unit))
|
continuation.resume(Result.success(Unit))
|
||||||
}.fail { error ->
|
}.fail { error ->
|
||||||
Log.w("ConversationRepository", "Call to SnodeAPI.deleteMessage failed - attempting to resume..")
|
Log.w("ConversationRepository", "Call to SnodeAPI.deleteMessage failed - attempting to resume..")
|
||||||
continuation.resumeWithException(error)
|
continuation.resume(Result.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,7 +249,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
override suspend fun deleteMessageWithoutUnsendRequest(
|
override suspend fun deleteMessageWithoutUnsendRequest(
|
||||||
threadId: Long,
|
threadId: Long,
|
||||||
messages: Set<MessageRecord>
|
messages: Set<MessageRecord>
|
||||||
): ResultOf<Unit> = suspendCoroutine { continuation ->
|
): Result<Unit> = suspendCoroutine { continuation ->
|
||||||
val openGroup = lokiThreadDb.getOpenGroupChat(threadId)
|
val openGroup = lokiThreadDb.getOpenGroupChat(threadId)
|
||||||
if (openGroup != null) {
|
if (openGroup != null) {
|
||||||
val messageServerIDs = mutableMapOf<Long, MessageRecord>()
|
val messageServerIDs = mutableMapOf<Long, MessageRecord>()
|
||||||
@ -264,7 +263,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
.success {
|
.success {
|
||||||
messageDataProvider.deleteMessage(message.id, !message.isMms)
|
messageDataProvider.deleteMessage(message.id, !message.isMms)
|
||||||
}.fail { error ->
|
}.fail { error ->
|
||||||
continuation.resumeWithException(error)
|
continuation.resume(Result.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -276,22 +275,22 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continuation.resume(ResultOf.Success(Unit))
|
continuation.resume(Result.success(Unit))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun banUser(threadId: Long, recipient: Recipient): ResultOf<Unit> =
|
override suspend fun banUser(threadId: Long, recipient: Recipient): Result<Unit> =
|
||||||
suspendCoroutine { continuation ->
|
suspendCoroutine { continuation ->
|
||||||
val accountID = recipient.address.toString()
|
val accountID = recipient.address.toString()
|
||||||
val openGroup = lokiThreadDb.getOpenGroupChat(threadId)!!
|
val openGroup = lokiThreadDb.getOpenGroupChat(threadId)!!
|
||||||
OpenGroupApi.ban(accountID, openGroup.room, openGroup.server)
|
OpenGroupApi.ban(accountID, openGroup.room, openGroup.server)
|
||||||
.success {
|
.success {
|
||||||
continuation.resume(ResultOf.Success(Unit))
|
continuation.resume(Result.success(Unit))
|
||||||
}.fail { error ->
|
}.fail { error ->
|
||||||
continuation.resumeWithException(error)
|
continuation.resume(Result.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun banAndDeleteAll(threadId: Long, recipient: Recipient): ResultOf<Unit> =
|
override suspend fun banAndDeleteAll(threadId: Long, recipient: Recipient): Result<Unit> =
|
||||||
suspendCoroutine { continuation ->
|
suspendCoroutine { continuation ->
|
||||||
// Note: This accountId could be the blinded Id
|
// Note: This accountId could be the blinded Id
|
||||||
val accountID = recipient.address.toString()
|
val accountID = recipient.address.toString()
|
||||||
@ -299,25 +298,25 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
|
|
||||||
OpenGroupApi.banAndDeleteAll(accountID, openGroup.room, openGroup.server)
|
OpenGroupApi.banAndDeleteAll(accountID, openGroup.room, openGroup.server)
|
||||||
.success {
|
.success {
|
||||||
continuation.resume(ResultOf.Success(Unit))
|
continuation.resume(Result.success(Unit))
|
||||||
}.fail { error ->
|
}.fail { error ->
|
||||||
continuation.resumeWithException(error)
|
continuation.resume(Result.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteThread(threadId: Long): ResultOf<Unit> {
|
override suspend fun deleteThread(threadId: Long): Result<Unit> {
|
||||||
sessionJobDb.cancelPendingMessageSendJobs(threadId)
|
sessionJobDb.cancelPendingMessageSendJobs(threadId)
|
||||||
storage.deleteConversation(threadId)
|
storage.deleteConversation(threadId)
|
||||||
return ResultOf.Success(Unit)
|
return Result.success(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteMessageRequest(thread: ThreadRecord): ResultOf<Unit> {
|
override suspend fun deleteMessageRequest(thread: ThreadRecord): Result<Unit> {
|
||||||
sessionJobDb.cancelPendingMessageSendJobs(thread.threadId)
|
sessionJobDb.cancelPendingMessageSendJobs(thread.threadId)
|
||||||
storage.deleteConversation(thread.threadId)
|
storage.deleteConversation(thread.threadId)
|
||||||
return ResultOf.Success(Unit)
|
return Result.success(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun clearAllMessageRequests(block: Boolean): ResultOf<Unit> {
|
override suspend fun clearAllMessageRequests(block: Boolean): Result<Unit> {
|
||||||
threadDb.readerFor(threadDb.unapprovedConversationList).use { reader ->
|
threadDb.readerFor(threadDb.unapprovedConversationList).use { reader ->
|
||||||
while (reader.next != null) {
|
while (reader.next != null) {
|
||||||
deleteMessageRequest(reader.current)
|
deleteMessageRequest(reader.current)
|
||||||
@ -325,18 +324,18 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
if (block) { setBlocked(recipient, true) }
|
if (block) { setBlocked(recipient, true) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ResultOf.Success(Unit)
|
return Result.success(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun acceptMessageRequest(threadId: Long, recipient: Recipient): ResultOf<Unit> = suspendCoroutine { continuation ->
|
override suspend fun acceptMessageRequest(threadId: Long, recipient: Recipient): Result<Unit> = suspendCoroutine { continuation ->
|
||||||
storage.setRecipientApproved(recipient, true)
|
storage.setRecipientApproved(recipient, true)
|
||||||
val message = MessageRequestResponse(true)
|
val message = MessageRequestResponse(true)
|
||||||
MessageSender.send(message, Destination.from(recipient.address), isSyncMessage = recipient.isLocalNumber)
|
MessageSender.send(message, Destination.from(recipient.address), isSyncMessage = recipient.isLocalNumber)
|
||||||
.success {
|
.success {
|
||||||
threadDb.setHasSent(threadId, true)
|
threadDb.setHasSent(threadId, true)
|
||||||
continuation.resume(ResultOf.Success(Unit))
|
continuation.resume(Result.success(Unit))
|
||||||
}.fail { error ->
|
}.fail { error ->
|
||||||
continuation.resumeWithException(error)
|
continuation.resume(Result.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.repository
|
|
||||||
|
|
||||||
import kotlinx.coroutines.CancellationException
|
|
||||||
|
|
||||||
sealed class ResultOf<out T> {
|
|
||||||
|
|
||||||
data class Success<out R>(val value: R) : ResultOf<R>()
|
|
||||||
|
|
||||||
data class Failure(val throwable: Throwable) : ResultOf<Nothing>()
|
|
||||||
|
|
||||||
inline fun onFailure(block: (throwable: Throwable) -> Unit) = this.also {
|
|
||||||
if (this is Failure) {
|
|
||||||
block(throwable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun onSuccess(block: (value: T) -> Unit) = this.also {
|
|
||||||
if (this is Success) {
|
|
||||||
block(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <R> flatMap(mapper: (T) -> R): ResultOf<R> = when (this) {
|
|
||||||
is Success -> wrap { mapper(value) }
|
|
||||||
is Failure -> Failure(throwable)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOrThrow(): T = when (this) {
|
|
||||||
is Success -> value
|
|
||||||
is Failure -> throw throwable
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
inline fun <T> wrap(block: () -> T): ResultOf<T> =
|
|
||||||
try {
|
|
||||||
Success(block())
|
|
||||||
} catch (e: CancellationException) {
|
|
||||||
throw e
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Failure(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -37,13 +37,13 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
|||||||
|
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
import network.loki.messenger.R;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import com.bumptech.glide.RequestManager;
|
||||||
|
|
||||||
public class StickerSelectFragment extends Fragment implements LoaderManager.LoaderCallbacks<String[]> {
|
public class StickerSelectFragment extends Fragment implements LoaderManager.LoaderCallbacks<String[]> {
|
||||||
|
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private GlideRequests glideRequests;
|
private RequestManager glideRequests;
|
||||||
private String assetDirectory;
|
private String assetDirectory;
|
||||||
private StickerSelectionListener listener;
|
private StickerSelectionListener listener;
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ public class StickerSelectFragment extends Fragment implements LoaderManager.Loa
|
|||||||
public void onActivityCreated(Bundle bundle) {
|
public void onActivityCreated(Bundle bundle) {
|
||||||
super.onActivityCreated(bundle);
|
super.onActivityCreated(bundle);
|
||||||
|
|
||||||
this.glideRequests = GlideApp.with(this);
|
this.glideRequests = Glide.with(this);
|
||||||
this.assetDirectory = getArguments().getString("assetDirectory");
|
this.assetDirectory = getArguments().getString("assetDirectory");
|
||||||
|
|
||||||
getLoaderManager().initLoader(0, null, this);
|
getLoaderManager().initLoader(0, null, this);
|
||||||
@ -99,11 +99,11 @@ public class StickerSelectFragment extends Fragment implements LoaderManager.Loa
|
|||||||
|
|
||||||
class StickersAdapter extends RecyclerView.Adapter<StickersAdapter.StickerViewHolder> {
|
class StickersAdapter extends RecyclerView.Adapter<StickersAdapter.StickerViewHolder> {
|
||||||
|
|
||||||
private final GlideRequests glideRequests;
|
private final RequestManager glideRequests;
|
||||||
private final String[] stickerFiles;
|
private final String[] stickerFiles;
|
||||||
private final LayoutInflater layoutInflater;
|
private final LayoutInflater layoutInflater;
|
||||||
|
|
||||||
StickersAdapter(@NonNull Context context, @NonNull GlideRequests glideRequests, @NonNull String[] stickerFiles) {
|
StickersAdapter(@NonNull Context context, @NonNull RequestManager glideRequests, @NonNull String[] stickerFiles) {
|
||||||
this.glideRequests = glideRequests;
|
this.glideRequests = glideRequests;
|
||||||
this.stickerFiles = stickerFiles;
|
this.stickerFiles = stickerFiles;
|
||||||
this.layoutInflater = LayoutInflater.from(context);
|
this.layoutInflater = LayoutInflater.from(context);
|
||||||
|
@ -11,6 +11,7 @@ import android.os.Parcel;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.bumptech.glide.RequestBuilder;
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.bumptech.glide.request.target.SimpleTarget;
|
import com.bumptech.glide.request.target.SimpleTarget;
|
||||||
import com.bumptech.glide.request.transition.Transition;
|
import com.bumptech.glide.request.transition.Transition;
|
||||||
@ -20,8 +21,7 @@ import org.thoughtcrime.securesms.imageeditor.Bounds;
|
|||||||
import org.thoughtcrime.securesms.imageeditor.Renderer;
|
import org.thoughtcrime.securesms.imageeditor.Renderer;
|
||||||
import org.thoughtcrime.securesms.imageeditor.RendererContext;
|
import org.thoughtcrime.securesms.imageeditor.RendererContext;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequest;
|
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
@ -97,8 +97,8 @@ final class UriGlideRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private GlideRequest<Bitmap> getBitmapGlideRequest(@NonNull Context context) {
|
private RequestBuilder<Bitmap> getBitmapGlideRequest(@NonNull Context context) {
|
||||||
return GlideApp.with(context)
|
return Glide.with(context)
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.override(maxWidth, maxHeight)
|
.override(maxWidth, maxHeight)
|
||||||
|
@ -19,7 +19,7 @@ import org.thoughtcrime.securesms.ShareActivity;
|
|||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -50,7 +50,7 @@ public class DirectShareService extends ChooserTargetService {
|
|||||||
|
|
||||||
if (recipient.getContactPhoto() != null) {
|
if (recipient.getContactPhoto() != null) {
|
||||||
try {
|
try {
|
||||||
avatar = GlideApp.with(this)
|
avatar = Glide.with(this)
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.load(recipient.getContactPhoto())
|
.load(recipient.getContactPhoto())
|
||||||
.circleCrop()
|
.circleCrop()
|
||||||
|
@ -1,128 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.service;
|
|
||||||
|
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.IBinder;
|
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.core.app.NotificationCompat;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
|
|
||||||
import org.session.libsignal.utilities.Log;
|
|
||||||
import org.session.libsignal.utilities.guava.Preconditions;
|
|
||||||
import org.thoughtcrime.securesms.home.HomeActivity;
|
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
|
||||||
|
|
||||||
import network.loki.messenger.R;
|
|
||||||
|
|
||||||
public class GenericForegroundService extends Service {
|
|
||||||
|
|
||||||
private static final String TAG = GenericForegroundService.class.getSimpleName();
|
|
||||||
|
|
||||||
private static final int NOTIFICATION_ID = 827353982;
|
|
||||||
private static final String EXTRA_TITLE = "extra_title";
|
|
||||||
private static final String EXTRA_CHANNEL_ID = "extra_channel_id";
|
|
||||||
private static final String EXTRA_ICON_RES = "extra_icon_res";
|
|
||||||
|
|
||||||
private static final String ACTION_START = "start";
|
|
||||||
private static final String ACTION_STOP = "stop";
|
|
||||||
|
|
||||||
private int foregroundCount;
|
|
||||||
private String activeTitle;
|
|
||||||
private String activeChannelId;
|
|
||||||
private int activeIconRes;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
||||||
synchronized (GenericForegroundService.class) {
|
|
||||||
if (intent != null && ACTION_START.equals(intent.getAction())) handleStart(intent);
|
|
||||||
else if (intent != null && ACTION_STOP.equals(intent.getAction())) handleStop();
|
|
||||||
else throw new IllegalStateException("Action needs to be START or STOP.");
|
|
||||||
|
|
||||||
return START_NOT_STICKY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void handleStart(@NonNull Intent intent) {
|
|
||||||
String title = Preconditions.checkNotNull(intent.getStringExtra(EXTRA_TITLE));
|
|
||||||
String channelId = Preconditions.checkNotNull(intent.getStringExtra(EXTRA_CHANNEL_ID));
|
|
||||||
int iconRes = intent.getIntExtra(EXTRA_ICON_RES, R.drawable.ic_notification);
|
|
||||||
|
|
||||||
Log.i(TAG, "handleStart() Title: " + title + " ChannelId: " + channelId);
|
|
||||||
|
|
||||||
foregroundCount++;
|
|
||||||
|
|
||||||
if (foregroundCount == 1) {
|
|
||||||
Log.d(TAG, "First request. Title: " + title + " ChannelId: " + channelId);
|
|
||||||
activeTitle = title;
|
|
||||||
activeChannelId = channelId;
|
|
||||||
activeIconRes = iconRes;
|
|
||||||
}
|
|
||||||
|
|
||||||
postObligatoryForegroundNotification(activeTitle, activeChannelId, activeIconRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleStop() {
|
|
||||||
Log.i(TAG, "handleStop()");
|
|
||||||
|
|
||||||
postObligatoryForegroundNotification(activeTitle, activeChannelId, activeIconRes);
|
|
||||||
|
|
||||||
foregroundCount--;
|
|
||||||
|
|
||||||
if (foregroundCount == 0) {
|
|
||||||
Log.d(TAG, "Last request. Ending foreground service.");
|
|
||||||
stopForeground(true);
|
|
||||||
stopSelf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void postObligatoryForegroundNotification(String title, String channelId, @DrawableRes int iconRes) {
|
|
||||||
startForeground(NOTIFICATION_ID, new NotificationCompat.Builder(this, channelId)
|
|
||||||
.setSmallIcon(iconRes)
|
|
||||||
.setContentTitle(title)
|
|
||||||
.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, HomeActivity.class), PendingIntent.FLAG_IMMUTABLE))
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public IBinder onBind(Intent intent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startForegroundTask(@NonNull Context context, @NonNull String task) {
|
|
||||||
startForegroundTask(context, task, NotificationChannels.OTHER);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startForegroundTask(@NonNull Context context, @NonNull String task, @NonNull String channelId) {
|
|
||||||
startForegroundTask(context, task, channelId, R.drawable.ic_notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startForegroundTask(@NonNull Context context, @NonNull String task, @NonNull String channelId, @DrawableRes int iconRes) {
|
|
||||||
Intent intent = new Intent(context, GenericForegroundService.class);
|
|
||||||
intent.setAction(ACTION_START);
|
|
||||||
intent.putExtra(EXTRA_TITLE, task);
|
|
||||||
intent.putExtra(EXTRA_CHANNEL_ID, channelId);
|
|
||||||
intent.putExtra(EXTRA_ICON_RES, iconRes);
|
|
||||||
|
|
||||||
ContextCompat.startForegroundService(context, intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void stopForegroundTask(@NonNull Context context) {
|
|
||||||
Intent intent = new Intent(context, GenericForegroundService.class);
|
|
||||||
intent.setAction(ACTION_STOP);
|
|
||||||
|
|
||||||
ContextCompat.startForegroundService(context, intent);
|
|
||||||
}
|
|
||||||
}
|
|
@ -35,6 +35,7 @@ import android.os.SystemClock;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import androidx.core.app.ServiceCompat;
|
||||||
|
|
||||||
import org.session.libsession.utilities.ServiceUtil;
|
import org.session.libsession.utilities.ServiceUtil;
|
||||||
import org.session.libsession.utilities.TextSecurePreferences;
|
import org.session.libsession.utilities.TextSecurePreferences;
|
||||||
@ -252,11 +253,18 @@ public class KeyCachingService extends Service {
|
|||||||
builder.setContentIntent(buildLaunchIntent());
|
builder.setContentIntent(buildLaunchIntent());
|
||||||
|
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
|
|
||||||
|
int type = 0;
|
||||||
if (Build.VERSION.SDK_INT >= 34) {
|
if (Build.VERSION.SDK_INT >= 34) {
|
||||||
startForeground(SERVICE_RUNNING_ID, builder.build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
|
type = ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE;
|
||||||
} else {
|
|
||||||
startForeground(SERVICE_RUNNING_ID, builder.build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServiceCompat.startForeground(
|
||||||
|
this,
|
||||||
|
SERVICE_RUNNING_ID,
|
||||||
|
builder.build(),
|
||||||
|
type
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PendingIntent buildLockIntent() {
|
private PendingIntent buildLockIntent() {
|
||||||
|
@ -7,9 +7,12 @@ import android.content.Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
|
|||||||
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.ServiceInfo
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
|
import android.os.Build
|
||||||
import android.os.ResultReceiver
|
import android.os.ResultReceiver
|
||||||
import android.telephony.TelephonyManager
|
import android.telephony.TelephonyManager
|
||||||
|
import androidx.core.app.ServiceCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.lifecycle.LifecycleService
|
import androidx.lifecycle.LifecycleService
|
||||||
@ -723,9 +726,11 @@ class WebRtcCallService : LifecycleService(), CallManager.WebRtcListener {
|
|||||||
|
|
||||||
private fun setCallInProgressNotification(type: Int, recipient: Recipient?) {
|
private fun setCallInProgressNotification(type: Int, recipient: Recipient?) {
|
||||||
try {
|
try {
|
||||||
startForeground(
|
ServiceCompat.startForeground(
|
||||||
|
this,
|
||||||
CallNotificationBuilder.WEBRTC_NOTIFICATION,
|
CallNotificationBuilder.WEBRTC_NOTIFICATION,
|
||||||
CallNotificationBuilder.getCallInProgressNotification(this, type, recipient)
|
CallNotificationBuilder.getCallInProgressNotification(this, type, recipient),
|
||||||
|
if (Build.VERSION.SDK_INT >= 30) ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE else 0
|
||||||
)
|
)
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: IllegalStateException) {
|
||||||
Log.e(TAG, "Failed to setCallInProgressNotification as a foreground service for type: ${type}, trying to update instead", e)
|
Log.e(TAG, "Failed to setCallInProgressNotification as a foreground service for type: ${type}, trying to update instead", e)
|
||||||
|
@ -20,7 +20,7 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
|||||||
|
|
||||||
import org.session.libsession.utilities.MediaTypes;
|
import org.session.libsession.utilities.MediaTypes;
|
||||||
import org.session.libsignal.utilities.Log;
|
import org.session.libsignal.utilities.Log;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||||
|
|
||||||
import org.session.libsession.utilities.Util;
|
import org.session.libsession.utilities.Util;
|
||||||
@ -98,7 +98,7 @@ public class BitmapUtil {
|
|||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
|
|
||||||
Bitmap scaledBitmap = GlideApp.with(context.getApplicationContext())
|
Bitmap scaledBitmap = Glide.with(context.getApplicationContext())
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.load(model)
|
.load(model)
|
||||||
.skipMemoryCache(true)
|
.skipMemoryCache(true)
|
||||||
@ -164,7 +164,7 @@ public class BitmapUtil {
|
|||||||
throws BitmapDecodingException
|
throws BitmapDecodingException
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return GlideApp.with(context.getApplicationContext())
|
return Glide.with(context.getApplicationContext())
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.load(model)
|
.load(model)
|
||||||
.centerInside()
|
.centerInside()
|
||||||
|
@ -22,7 +22,7 @@ import org.thoughtcrime.securesms.mms.AudioSlide;
|
|||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
||||||
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
||||||
import org.thoughtcrime.securesms.mms.GifSlide;
|
import org.thoughtcrime.securesms.mms.GifSlide;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import com.bumptech.glide.Glide;
|
||||||
import org.thoughtcrime.securesms.mms.ImageSlide;
|
import org.thoughtcrime.securesms.mms.ImageSlide;
|
||||||
import org.thoughtcrime.securesms.mms.MmsSlide;
|
import org.thoughtcrime.securesms.mms.MmsSlide;
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||||
@ -115,7 +115,7 @@ public class MediaUtil {
|
|||||||
|
|
||||||
if (MediaUtil.isGif(contentType)) {
|
if (MediaUtil.isGif(contentType)) {
|
||||||
try {
|
try {
|
||||||
GifDrawable drawable = GlideApp.with(context)
|
GifDrawable drawable = Glide.with(context)
|
||||||
.asGif()
|
.asGif()
|
||||||
.skipMemoryCache(true)
|
.skipMemoryCache(true)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package org.thoughtcrime.securesms.webrtc
|
package org.thoughtcrime.securesms.webrtc
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import org.session.libsignal.crypto.shuffledRandom
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.session.libsignal.utilities.SettableFuture
|
import org.session.libsignal.utilities.SettableFuture
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import org.thoughtcrime.securesms.webrtc.video.Camera
|
import org.thoughtcrime.securesms.webrtc.video.Camera
|
||||||
import org.thoughtcrime.securesms.webrtc.video.CameraEventListener
|
import org.thoughtcrime.securesms.webrtc.video.CameraEventListener
|
||||||
import org.thoughtcrime.securesms.webrtc.video.CameraState
|
import org.thoughtcrime.securesms.webrtc.video.CameraState
|
||||||
@ -22,9 +24,7 @@ import org.webrtc.SurfaceTextureHelper
|
|||||||
import org.webrtc.VideoSink
|
import org.webrtc.VideoSink
|
||||||
import org.webrtc.VideoSource
|
import org.webrtc.VideoSource
|
||||||
import org.webrtc.VideoTrack
|
import org.webrtc.VideoTrack
|
||||||
import java.security.SecureRandom
|
|
||||||
import java.util.concurrent.ExecutionException
|
import java.util.concurrent.ExecutionException
|
||||||
import kotlin.random.asKotlinRandom
|
|
||||||
|
|
||||||
class PeerConnectionWrapper(private val context: Context,
|
class PeerConnectionWrapper(private val context: Context,
|
||||||
private val factory: PeerConnectionFactory,
|
private val factory: PeerConnectionFactory,
|
||||||
@ -49,8 +49,7 @@ class PeerConnectionWrapper(private val context: Context,
|
|||||||
private var isInitiator = false
|
private var isInitiator = false
|
||||||
|
|
||||||
private fun initPeerConnection() {
|
private fun initPeerConnection() {
|
||||||
val random = SecureRandom().asKotlinRandom()
|
val iceServers = listOf("freyr","angus","hereford","holstein", "brahman").shuffledRandom().take(2).map { sub ->
|
||||||
val iceServers = listOf("freyr","angus","hereford","holstein", "brahman").shuffled(random).take(2).map { sub ->
|
|
||||||
PeerConnection.IceServer.builder("turn:$sub.getsession.org")
|
PeerConnection.IceServer.builder("turn:$sub.getsession.org")
|
||||||
.setUsername("session202111")
|
.setUsername("session202111")
|
||||||
.setPassword("053c268164bc7bd7")
|
.setPassword("053c268164bc7bd7")
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/conversation_view_background"
|
android:background="@drawable/conversation_unread_background"
|
||||||
android:contentDescription="@string/AccessibilityId_message_request_banner"
|
android:contentDescription="@string/AccessibilityId_message_request_banner"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
@ -19,7 +19,8 @@
|
|||||||
android:layout_marginStart="@dimen/medium_spacing"
|
android:layout_marginStart="@dimen/medium_spacing"
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
android:src="@drawable/ic_outline_message_requests_24"
|
android:src="@drawable/ic_outline_message_requests_24"
|
||||||
app:circleColor="#585858"
|
android:tint="?unreadIndicatorTextColor"
|
||||||
|
app:circleColor="?unreadIndicatorBackgroundColor"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
@ -47,7 +48,7 @@
|
|||||||
android:layout_height="20dp"
|
android:layout_height="20dp"
|
||||||
android:layout_marginStart="4dp"
|
android:layout_marginStart="4dp"
|
||||||
android:background="@drawable/circle_tintable"
|
android:background="@drawable/circle_tintable"
|
||||||
android:backgroundTint="#585858"
|
android:backgroundTint="?unreadIndicatorBackgroundColor"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/conversationViewDisplayNameTextView"
|
app:layout_constraintStart_toEndOf="@id/conversationViewDisplayNameTextView"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
@ -57,30 +58,11 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:textColor="@color/white"
|
android:textColor="?unreadIndicatorTextColor"
|
||||||
android:textSize="@dimen/very_small_font_size"
|
android:textSize="@dimen/very_small_font_size"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
tools:text="8" />
|
tools:text="8" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/timestampTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/medium_spacing"
|
|
||||||
android:alpha="0.4"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:textAlignment="textEnd"
|
|
||||||
android:textColor="?android:textColorPrimary"
|
|
||||||
android:textSize="@dimen/small_font_size"
|
|
||||||
app:layout_constrainedWidth="true"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintHorizontal_bias="1"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/unreadCountIndicator"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="11 Apr, 9:41 AM" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<bool name="enable_alarm_manager">false</bool>
|
|
||||||
<bool name="enable_job_service">true</bool>
|
<bool name="enable_job_service">true</bool>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<bool name="enable_alarm_manager">true</bool>
|
|
||||||
<bool name="enable_job_service">false</bool>
|
<bool name="enable_job_service">false</bool>
|
||||||
<attr name="searchBackgroundColor" format="color"/>
|
<attr name="searchBackgroundColor" format="color"/>
|
||||||
<attr name="searchIconColor" format="color|reference"/>
|
<attr name="searchIconColor" format="color|reference"/>
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.session.libsignal.utilities
|
||||||
|
|
||||||
|
import org.hamcrest.MatcherAssert.assertThat
|
||||||
|
import org.hamcrest.core.IsEqual.equalTo
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.Parameterized
|
||||||
|
|
||||||
|
@RunWith(Parameterized::class)
|
||||||
|
class SnodeVersionTest(
|
||||||
|
private val v1: String,
|
||||||
|
private val v2: String,
|
||||||
|
private val expectedEqual: Boolean,
|
||||||
|
private val expectedLessThan: Boolean
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
@Parameterized.Parameters(name = "{index}: testVersion({0},{1}) = (equalTo: {2}, lessThan: {3})")
|
||||||
|
fun data(): Collection<Array<Any>> = listOf(
|
||||||
|
arrayOf("1", "1", true, false),
|
||||||
|
arrayOf("1", "2", false, true),
|
||||||
|
arrayOf("2", "1", false, false),
|
||||||
|
arrayOf("1.0", "1", true, false),
|
||||||
|
arrayOf("1.0", "1.0.0", true, false),
|
||||||
|
arrayOf("1.0", "1.0.0.0", true, false),
|
||||||
|
arrayOf("1.0", "1.0.0.0.0.0", true, false),
|
||||||
|
arrayOf("2.0", "1.2", false, false),
|
||||||
|
arrayOf("1.0.0.0", "1.0.0.1", false, true),
|
||||||
|
// Snode.Version only considers the first 4 integers, so these are equal
|
||||||
|
arrayOf("1.0.0.0", "1.0.0.0.1", true, false),
|
||||||
|
arrayOf("1.0.0.1", "1.0.0.1", true, false),
|
||||||
|
// parts can be up to 16 bits, around 65,535
|
||||||
|
arrayOf("65535.65535.65535.65535", "65535.65535.65535.65535", true, false),
|
||||||
|
// values higher than this are coerced to 65535 (:
|
||||||
|
arrayOf("65535.65535.65535.65535", "65535.65535.65535.99999", true, false),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testVersionEqual() {
|
||||||
|
val version1 = Snode.Version(v1)
|
||||||
|
val version2 = Snode.Version(v2)
|
||||||
|
assertThat(version1 == version2, equalTo(expectedEqual))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testVersionOnePartLessThan() {
|
||||||
|
val version1 = Snode.Version(v1)
|
||||||
|
val version2 = Snode.Version(v2)
|
||||||
|
assertThat(version1 < version2, equalTo(expectedLessThan))
|
||||||
|
}
|
||||||
|
}
|
@ -3,14 +3,12 @@ package org.thoughtcrime.securesms.conversation.v2
|
|||||||
import com.goterl.lazysodium.utils.KeyPair
|
import com.goterl.lazysodium.utils.KeyPair
|
||||||
import kotlinx.coroutines.flow.emptyFlow
|
import kotlinx.coroutines.flow.emptyFlow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import org.hamcrest.CoreMatchers.endsWith
|
import org.hamcrest.CoreMatchers.endsWith
|
||||||
import org.hamcrest.CoreMatchers.equalTo
|
import org.hamcrest.CoreMatchers.equalTo
|
||||||
import org.hamcrest.CoreMatchers.notNullValue
|
import org.hamcrest.CoreMatchers.notNullValue
|
||||||
import org.hamcrest.CoreMatchers.nullValue
|
import org.hamcrest.CoreMatchers.nullValue
|
||||||
import org.hamcrest.MatcherAssert.assertThat
|
import org.hamcrest.MatcherAssert.assertThat
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.BeforeClass
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.Mockito
|
import org.mockito.Mockito
|
||||||
import org.mockito.Mockito.anyLong
|
import org.mockito.Mockito.anyLong
|
||||||
@ -20,14 +18,11 @@ import org.mockito.kotlin.any
|
|||||||
import org.mockito.kotlin.mock
|
import org.mockito.kotlin.mock
|
||||||
import org.mockito.kotlin.whenever
|
import org.mockito.kotlin.whenever
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsignal.utilities.Log
|
|
||||||
import org.thoughtcrime.securesms.BaseViewModelTest
|
import org.thoughtcrime.securesms.BaseViewModelTest
|
||||||
import org.thoughtcrime.securesms.NoOpLogger
|
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase
|
import org.thoughtcrime.securesms.database.MmsDatabase
|
||||||
import org.thoughtcrime.securesms.database.Storage
|
import org.thoughtcrime.securesms.database.Storage
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||||
import org.thoughtcrime.securesms.repository.ConversationRepository
|
import org.thoughtcrime.securesms.repository.ConversationRepository
|
||||||
import org.thoughtcrime.securesms.repository.ResultOf
|
|
||||||
|
|
||||||
class ConversationViewModelTest: BaseViewModelTest() {
|
class ConversationViewModelTest: BaseViewModelTest() {
|
||||||
|
|
||||||
@ -107,7 +102,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
|
|||||||
val message = mock<MessageRecord>()
|
val message = mock<MessageRecord>()
|
||||||
val error = Throwable()
|
val error = Throwable()
|
||||||
whenever(repository.deleteForEveryone(anyLong(), any(), any()))
|
whenever(repository.deleteForEveryone(anyLong(), any(), any()))
|
||||||
.thenReturn(ResultOf.Failure(error))
|
.thenReturn(Result.failure(error))
|
||||||
|
|
||||||
viewModel.deleteForEveryone(message)
|
viewModel.deleteForEveryone(message)
|
||||||
|
|
||||||
@ -120,7 +115,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
|
|||||||
val message = mock<MessageRecord>()
|
val message = mock<MessageRecord>()
|
||||||
val error = Throwable()
|
val error = Throwable()
|
||||||
whenever(repository.deleteMessageWithoutUnsendRequest(anyLong(), anySet()))
|
whenever(repository.deleteMessageWithoutUnsendRequest(anyLong(), anySet()))
|
||||||
.thenReturn(ResultOf.Failure(error))
|
.thenReturn(Result.failure(error))
|
||||||
|
|
||||||
viewModel.deleteMessagesWithoutUnsendRequest(setOf(message))
|
viewModel.deleteMessagesWithoutUnsendRequest(setOf(message))
|
||||||
|
|
||||||
@ -130,7 +125,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
|
|||||||
@Test
|
@Test
|
||||||
fun `should emit error message on ban user failure`() = runBlockingTest {
|
fun `should emit error message on ban user failure`() = runBlockingTest {
|
||||||
val error = Throwable()
|
val error = Throwable()
|
||||||
whenever(repository.banUser(anyLong(), any())).thenReturn(ResultOf.Failure(error))
|
whenever(repository.banUser(anyLong(), any())).thenReturn(Result.failure(error))
|
||||||
|
|
||||||
viewModel.banUser(recipient)
|
viewModel.banUser(recipient)
|
||||||
|
|
||||||
@ -139,7 +134,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `should emit a message on ban user success`() = runBlockingTest {
|
fun `should emit a message on ban user success`() = runBlockingTest {
|
||||||
whenever(repository.banUser(anyLong(), any())).thenReturn(ResultOf.Success(Unit))
|
whenever(repository.banUser(anyLong(), any())).thenReturn(Result.success(Unit))
|
||||||
|
|
||||||
viewModel.banUser(recipient)
|
viewModel.banUser(recipient)
|
||||||
|
|
||||||
@ -152,7 +147,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
|
|||||||
@Test
|
@Test
|
||||||
fun `should emit error message on ban user and delete all failure`() = runBlockingTest {
|
fun `should emit error message on ban user and delete all failure`() = runBlockingTest {
|
||||||
val error = Throwable()
|
val error = Throwable()
|
||||||
whenever(repository.banAndDeleteAll(anyLong(), any())).thenReturn(ResultOf.Failure(error))
|
whenever(repository.banAndDeleteAll(anyLong(), any())).thenReturn(Result.failure(error))
|
||||||
|
|
||||||
viewModel.banAndDeleteAll(messageRecord)
|
viewModel.banAndDeleteAll(messageRecord)
|
||||||
|
|
||||||
@ -161,7 +156,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `should emit a message on ban user and delete all success`() = runBlockingTest {
|
fun `should emit a message on ban user and delete all success`() = runBlockingTest {
|
||||||
whenever(repository.banAndDeleteAll(anyLong(), any())).thenReturn(ResultOf.Success(Unit))
|
whenever(repository.banAndDeleteAll(anyLong(), any())).thenReturn(Result.success(Unit))
|
||||||
|
|
||||||
viewModel.banAndDeleteAll(messageRecord)
|
viewModel.banAndDeleteAll(messageRecord)
|
||||||
|
|
||||||
@ -188,7 +183,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
|
|||||||
@Test
|
@Test
|
||||||
fun `should remove shown message`() = runBlockingTest {
|
fun `should remove shown message`() = runBlockingTest {
|
||||||
// Given that a message is generated
|
// Given that a message is generated
|
||||||
whenever(repository.banUser(anyLong(), any())).thenReturn(ResultOf.Success(Unit))
|
whenever(repository.banUser(anyLong(), any())).thenReturn(Result.success(Unit))
|
||||||
viewModel.banUser(recipient)
|
viewModel.banUser(recipient)
|
||||||
assertThat(viewModel.uiState.value.uiMessages.size, equalTo(1))
|
assertThat(viewModel.uiState.value.uiMessages.size, equalTo(1))
|
||||||
// When the message is shown
|
// When the message is shown
|
||||||
|
@ -17,13 +17,15 @@ buildscript {
|
|||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion"
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlinVersion"
|
||||||
classpath "com.google.gms:google-services:$googleServicesVersion"
|
classpath "com.google.gms:google-services:$googleServicesVersion"
|
||||||
classpath "com.squareup:javapoet:1.13.0"
|
classpath "com.squareup:javapoet:1.13.0"
|
||||||
classpath "com.google.dagger:hilt-android-gradle-plugin:$daggerVersion"
|
|
||||||
if (project.hasProperty('huawei')) classpath 'com.huawei.agconnect:agcp:1.9.1.300'
|
if (project.hasProperty('huawei')) classpath 'com.huawei.agconnect:agcp:1.9.1.300'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins{
|
// List plugins AND their versions here, but don't apply. This allows you to use the plugin
|
||||||
id("com.google.dagger.hilt.android") version "2.44" apply false
|
// in your module without specifying the version.
|
||||||
|
plugins {
|
||||||
|
id 'com.google.devtools.ksp' version "$kotlinVersion-1.0.20" apply false
|
||||||
|
id 'com.google.dagger.hilt.android' version "$daggerHiltVersion" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
|
@ -14,19 +14,19 @@
|
|||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
|
||||||
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
|
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
|
||||||
#org.gradle.unsafe.configuration-cache=true
|
|
||||||
|
|
||||||
gradlePluginVersion=7.3.1
|
gradlePluginVersion=7.3.1
|
||||||
googleServicesVersion=4.3.12
|
googleServicesVersion=4.3.12
|
||||||
kotlinVersion=1.8.21
|
kotlinVersion=1.9.24
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
appcompatVersion=1.6.1
|
appcompatVersion=1.6.1
|
||||||
coreVersion=1.13.1
|
coreVersion=1.13.1
|
||||||
composeVersion=1.6.4
|
composeVersion=1.6.4
|
||||||
coroutinesVersion=1.6.4
|
coroutinesVersion=1.6.4
|
||||||
curve25519Version=0.6.0
|
curve25519Version=0.6.0
|
||||||
daggerVersion=2.46.1
|
jetpackHiltVersion=1.2.0
|
||||||
glideVersion=4.11.0
|
daggerHiltVersion=2.51.1
|
||||||
|
glideVersion=4.16.0
|
||||||
jacksonDatabindVersion=2.9.8
|
jacksonDatabindVersion=2.9.8
|
||||||
junitVersion=4.13.2
|
junitVersion=4.13.2
|
||||||
kotlinxJsonVersion=1.3.3
|
kotlinxJsonVersion=1.3.3
|
||||||
|
@ -2,6 +2,8 @@ plugins {
|
|||||||
id 'com.android.library'
|
id 'com.android.library'
|
||||||
id 'kotlin-android'
|
id 'kotlin-android'
|
||||||
id 'kotlinx-serialization'
|
id 'kotlinx-serialization'
|
||||||
|
id 'com.google.devtools.ksp'
|
||||||
|
id 'com.google.dagger.hilt.android'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@ -21,6 +23,11 @@ dependencies {
|
|||||||
implementation project(":libsignal")
|
implementation project(":libsignal")
|
||||||
implementation project(":libsession-util")
|
implementation project(":libsession-util")
|
||||||
implementation project(":liblazysodium")
|
implementation project(":liblazysodium")
|
||||||
|
|
||||||
|
implementation("com.google.dagger:hilt-android:$daggerHiltVersion")
|
||||||
|
ksp("com.google.dagger:hilt-compiler:$daggerHiltVersion")
|
||||||
|
ksp("androidx.hilt:hilt-compiler:$jetpackHiltVersion")
|
||||||
|
|
||||||
implementation "net.java.dev.jna:jna:5.12.1@aar"
|
implementation "net.java.dev.jna:jna:5.12.1@aar"
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
|
||||||
implementation "androidx.core:core-ktx:$coreVersion"
|
implementation "androidx.core:core-ktx:$coreVersion"
|
||||||
@ -28,7 +35,6 @@ dependencies {
|
|||||||
implementation "androidx.preference:preference-ktx:$preferenceVersion"
|
implementation "androidx.preference:preference-ktx:$preferenceVersion"
|
||||||
implementation "com.google.android.material:material:$materialVersion"
|
implementation "com.google.android.material:material:$materialVersion"
|
||||||
implementation "com.google.protobuf:protobuf-java:$protobufVersion"
|
implementation "com.google.protobuf:protobuf-java:$protobufVersion"
|
||||||
implementation "com.google.dagger:hilt-android:$daggerVersion"
|
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||||
implementation "com.github.bumptech.glide:glide:$glideVersion"
|
implementation "com.github.bumptech.glide:glide:$glideVersion"
|
||||||
|
@ -63,7 +63,6 @@ data class ConfigurationSyncJob(val destination: Destination): Job {
|
|||||||
// return a list of batch request objects
|
// return a list of batch request objects
|
||||||
val snodeMessage = MessageSender.buildConfigMessageToSnode(destination.destinationPublicKey(), message)
|
val snodeMessage = MessageSender.buildConfigMessageToSnode(destination.destinationPublicKey(), message)
|
||||||
val authenticated = SnodeAPI.buildAuthenticatedStoreBatchInfo(
|
val authenticated = SnodeAPI.buildAuthenticatedStoreBatchInfo(
|
||||||
destination.destinationPublicKey(),
|
|
||||||
config.configNamespace(),
|
config.configNamespace(),
|
||||||
snodeMessage
|
snodeMessage
|
||||||
) ?: return@map null // this entry will be null otherwise
|
) ?: return@map null // this entry will be null otherwise
|
||||||
|
@ -12,11 +12,11 @@ import org.session.libsession.utilities.Util.equals
|
|||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsignal.streams.ProfileCipherInputStream
|
import org.session.libsignal.streams.ProfileCipherInputStream
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.security.SecureRandom
|
|
||||||
import java.util.concurrent.ConcurrentSkipListSet
|
import java.util.concurrent.ConcurrentSkipListSet
|
||||||
|
|
||||||
class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipientAddress: Address): Job {
|
class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipientAddress: Address): Job {
|
||||||
@ -64,7 +64,7 @@ class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipient
|
|||||||
Log.w(TAG, "Removing profile avatar for: " + recipient.address.serialize())
|
Log.w(TAG, "Removing profile avatar for: " + recipient.address.serialize())
|
||||||
|
|
||||||
if (recipient.isLocalNumber) {
|
if (recipient.isLocalNumber) {
|
||||||
setProfileAvatarId(context, SecureRandom().nextInt())
|
setProfileAvatarId(context, SECURE_RANDOM.nextInt())
|
||||||
setProfilePictureURL(context, null)
|
setProfilePictureURL(context, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ class RetrieveProfileAvatarJob(private val profileAvatar: String?, val recipient
|
|||||||
decryptDestination.renameTo(AvatarHelper.getAvatarFile(context, recipient.address))
|
decryptDestination.renameTo(AvatarHelper.getAvatarFile(context, recipient.address))
|
||||||
|
|
||||||
if (recipient.isLocalNumber) {
|
if (recipient.isLocalNumber) {
|
||||||
setProfileAvatarId(context, SecureRandom().nextInt())
|
setProfileAvatarId(context, SECURE_RANDOM.nextInt())
|
||||||
setProfilePictureURL(context, profileAvatar)
|
setProfilePictureURL(context, profileAvatar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import org.session.libsession.messaging.jobs.JobQueue
|
|||||||
import org.session.libsession.messaging.jobs.MessageReceiveParameters
|
import org.session.libsession.messaging.jobs.MessageReceiveParameters
|
||||||
import org.session.libsession.snode.SnodeAPI
|
import org.session.libsession.snode.SnodeAPI
|
||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.session.libsignal.crypto.getRandomElementOrNull
|
import org.session.libsignal.crypto.secureRandomOrNull
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.session.libsignal.utilities.Namespace
|
import org.session.libsignal.utilities.Namespace
|
||||||
import org.session.libsignal.utilities.defaultRequiresAuth
|
import org.session.libsignal.utilities.defaultRequiresAuth
|
||||||
@ -104,7 +104,7 @@ class ClosedGroupPollerV2 {
|
|||||||
fun poll(groupPublicKey: String): Promise<Unit, Exception> {
|
fun poll(groupPublicKey: String): Promise<Unit, Exception> {
|
||||||
if (!isPolling(groupPublicKey)) { return Promise.of(Unit) }
|
if (!isPolling(groupPublicKey)) { return Promise.of(Unit) }
|
||||||
val promise = SnodeAPI.getSwarm(groupPublicKey).bind { swarm ->
|
val promise = SnodeAPI.getSwarm(groupPublicKey).bind { swarm ->
|
||||||
val snode = swarm.getRandomElementOrNull() ?: throw InsufficientSnodesException() // Should be cryptographically secure
|
val snode = swarm.secureRandomOrNull() ?: throw InsufficientSnodesException() // Should be cryptographically secure
|
||||||
if (!isPolling(groupPublicKey)) { throw PollingCanceledException() }
|
if (!isPolling(groupPublicKey)) { throw PollingCanceledException() }
|
||||||
val currentForkInfo = SnodeAPI.forkInfo
|
val currentForkInfo = SnodeAPI.forkInfo
|
||||||
when {
|
when {
|
||||||
|
@ -19,8 +19,6 @@ import org.session.libsession.messaging.MessagingModuleConfiguration
|
|||||||
import org.session.libsession.messaging.jobs.BatchMessageReceiveJob
|
import org.session.libsession.messaging.jobs.BatchMessageReceiveJob
|
||||||
import org.session.libsession.messaging.jobs.JobQueue
|
import org.session.libsession.messaging.jobs.JobQueue
|
||||||
import org.session.libsession.messaging.jobs.MessageReceiveParameters
|
import org.session.libsession.messaging.jobs.MessageReceiveParameters
|
||||||
import org.session.libsession.messaging.messages.control.SharedConfigurationMessage
|
|
||||||
import org.session.libsession.messaging.sending_receiving.MessageReceiver
|
|
||||||
import org.session.libsession.snode.RawResponse
|
import org.session.libsession.snode.RawResponse
|
||||||
import org.session.libsession.snode.SnodeAPI
|
import org.session.libsession.snode.SnodeAPI
|
||||||
import org.session.libsession.snode.SnodeModule
|
import org.session.libsession.snode.SnodeModule
|
||||||
@ -29,7 +27,7 @@ import org.session.libsignal.utilities.Base64
|
|||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.session.libsignal.utilities.Namespace
|
import org.session.libsignal.utilities.Namespace
|
||||||
import org.session.libsignal.utilities.Snode
|
import org.session.libsignal.utilities.Snode
|
||||||
import java.security.SecureRandom
|
import org.session.libsignal.utilities.Util.SECURE_RANDOM
|
||||||
import java.util.Timer
|
import java.util.Timer
|
||||||
import java.util.TimerTask
|
import java.util.TimerTask
|
||||||
import kotlin.time.Duration.Companion.days
|
import kotlin.time.Duration.Companion.days
|
||||||
@ -106,7 +104,7 @@ class Poller(private val configFactory: ConfigFactoryProtocol, debounceTimer: Ti
|
|||||||
val swarm = SnodeModule.shared.storage.getSwarm(userPublicKey) ?: setOf()
|
val swarm = SnodeModule.shared.storage.getSwarm(userPublicKey) ?: setOf()
|
||||||
val unusedSnodes = swarm.subtract(usedSnodes)
|
val unusedSnodes = swarm.subtract(usedSnodes)
|
||||||
if (unusedSnodes.isNotEmpty()) {
|
if (unusedSnodes.isNotEmpty()) {
|
||||||
val index = SecureRandom().nextInt(unusedSnodes.size)
|
val index = SECURE_RANDOM.nextInt(unusedSnodes.size)
|
||||||
val nextSnode = unusedSnodes.elementAt(index)
|
val nextSnode = unusedSnodes.elementAt(index)
|
||||||
usedSnodes.add(nextSnode)
|
usedSnodes.add(nextSnode)
|
||||||
Log.d(TAG, "Polling $nextSnode.")
|
Log.d(TAG, "Polling $nextSnode.")
|
||||||
@ -142,8 +140,7 @@ class Poller(private val configFactory: ConfigFactoryProtocol, debounceTimer: Ti
|
|||||||
val messages = rawMessages["messages"] as? List<*>
|
val messages = rawMessages["messages"] as? List<*>
|
||||||
val processed = if (!messages.isNullOrEmpty()) {
|
val processed = if (!messages.isNullOrEmpty()) {
|
||||||
SnodeAPI.updateLastMessageHashValueIfPossible(snode, userPublicKey, messages, namespace)
|
SnodeAPI.updateLastMessageHashValueIfPossible(snode, userPublicKey, messages, namespace)
|
||||||
SnodeAPI.removeDuplicates(userPublicKey, messages, namespace, true).mapNotNull { messageBody ->
|
SnodeAPI.removeDuplicates(userPublicKey, messages, namespace, true).mapNotNull { rawMessageAsJSON ->
|
||||||
val rawMessageAsJSON = messageBody as? Map<*, *> ?: return@mapNotNull null
|
|
||||||
val hashValue = rawMessageAsJSON["hash"] as? String ?: return@mapNotNull null
|
val hashValue = rawMessageAsJSON["hash"] as? String ?: return@mapNotNull null
|
||||||
val b64EncodedBody = rawMessageAsJSON["data"] as? String ?: return@mapNotNull null
|
val b64EncodedBody = rawMessageAsJSON["data"] as? String ?: return@mapNotNull null
|
||||||
val timestamp = rawMessageAsJSON["t"] as? Long ?: SnodeAPI.nowWithOffset
|
val timestamp = rawMessageAsJSON["t"] as? Long ?: SnodeAPI.nowWithOffset
|
||||||
|
@ -28,7 +28,7 @@ object MessageWrapper {
|
|||||||
val webSocketMessage = createWebSocketMessage(envelope)
|
val webSocketMessage = createWebSocketMessage(envelope)
|
||||||
return webSocketMessage.toByteArray()
|
return webSocketMessage.toByteArray()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw if (e is Error) { e } else { Error.FailedToWrapData }
|
throw if (e is Error) e else Error.FailedToWrapData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,15 +49,15 @@ object MessageWrapper {
|
|||||||
|
|
||||||
private fun createWebSocketMessage(envelope: Envelope): WebSocketMessage {
|
private fun createWebSocketMessage(envelope: Envelope): WebSocketMessage {
|
||||||
try {
|
try {
|
||||||
val requestBuilder = WebSocketRequestMessage.newBuilder()
|
return WebSocketMessage.newBuilder().apply {
|
||||||
requestBuilder.verb = "PUT"
|
request = WebSocketRequestMessage.newBuilder().apply {
|
||||||
requestBuilder.path = "/api/v1/message"
|
verb = "PUT"
|
||||||
requestBuilder.id = SecureRandom.getInstance("SHA1PRNG").nextLong()
|
path = "/api/v1/message"
|
||||||
requestBuilder.body = envelope.toByteString()
|
id = SecureRandom.getInstance("SHA1PRNG").nextLong()
|
||||||
val messageBuilder = WebSocketMessage.newBuilder()
|
body = envelope.toByteString()
|
||||||
messageBuilder.request = requestBuilder.build()
|
}.build()
|
||||||
messageBuilder.type = WebSocketMessage.Type.REQUEST
|
type = WebSocketMessage.Type.REQUEST
|
||||||
return messageBuilder.build()
|
}.build()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Loki", "Failed to wrap envelope in web socket message: ${e.message}.")
|
Log.d("Loki", "Failed to wrap envelope in web socket message: ${e.message}.")
|
||||||
throw Error.FailedToWrapEnvelopeInWebSocketMessage
|
throw Error.FailedToWrapEnvelopeInWebSocketMessage
|
||||||
|
@ -10,11 +10,10 @@ import okhttp3.Request
|
|||||||
import org.session.libsession.messaging.file_server.FileServerApi
|
import org.session.libsession.messaging.file_server.FileServerApi
|
||||||
import org.session.libsession.utilities.AESGCM
|
import org.session.libsession.utilities.AESGCM
|
||||||
import org.session.libsession.utilities.AESGCM.EncryptionResult
|
import org.session.libsession.utilities.AESGCM.EncryptionResult
|
||||||
import org.session.libsession.utilities.Util
|
|
||||||
import org.session.libsession.utilities.getBodyForOnionRequest
|
import org.session.libsession.utilities.getBodyForOnionRequest
|
||||||
import org.session.libsession.utilities.getHeadersForOnionRequest
|
import org.session.libsession.utilities.getHeadersForOnionRequest
|
||||||
import org.session.libsignal.crypto.getRandomElement
|
import org.session.libsignal.crypto.secureRandom
|
||||||
import org.session.libsignal.crypto.getRandomElementOrNull
|
import org.session.libsignal.crypto.secureRandomOrNull
|
||||||
import org.session.libsignal.database.LokiAPIDatabaseProtocol
|
import org.session.libsignal.database.LokiAPIDatabaseProtocol
|
||||||
import org.session.libsignal.utilities.Base64
|
import org.session.libsignal.utilities.Base64
|
||||||
import org.session.libsignal.utilities.Broadcaster
|
import org.session.libsignal.utilities.Broadcaster
|
||||||
@ -149,7 +148,7 @@ object OnionRequestAPI {
|
|||||||
val reusableGuardSnodeCount = reusableGuardSnodes.count()
|
val reusableGuardSnodeCount = reusableGuardSnodes.count()
|
||||||
if (unusedSnodes.count() < (targetGuardSnodeCount - reusableGuardSnodeCount)) { throw InsufficientSnodesException() }
|
if (unusedSnodes.count() < (targetGuardSnodeCount - reusableGuardSnodeCount)) { throw InsufficientSnodesException() }
|
||||||
fun getGuardSnode(): Promise<Snode, Exception> {
|
fun getGuardSnode(): Promise<Snode, Exception> {
|
||||||
val candidate = unusedSnodes.getRandomElementOrNull()
|
val candidate = unusedSnodes.secureRandomOrNull()
|
||||||
?: return Promise.ofFail(InsufficientSnodesException())
|
?: return Promise.ofFail(InsufficientSnodesException())
|
||||||
unusedSnodes = unusedSnodes.minus(candidate)
|
unusedSnodes = unusedSnodes.minus(candidate)
|
||||||
Log.d("Loki", "Testing guard snode: $candidate.")
|
Log.d("Loki", "Testing guard snode: $candidate.")
|
||||||
@ -191,7 +190,7 @@ object OnionRequestAPI {
|
|||||||
// Don't test path snodes as this would reveal the user's IP to them
|
// Don't test path snodes as this would reveal the user's IP to them
|
||||||
guardSnodes.minus(reusableGuardSnodes).map { guardSnode ->
|
guardSnodes.minus(reusableGuardSnodes).map { guardSnode ->
|
||||||
val result = listOf( guardSnode ) + (0 until (pathSize - 1)).mapIndexed() { index, _ ->
|
val result = listOf( guardSnode ) + (0 until (pathSize - 1)).mapIndexed() { index, _ ->
|
||||||
var pathSnode = unusedSnodes.getRandomElement()
|
var pathSnode = unusedSnodes.secureRandom()
|
||||||
|
|
||||||
// remove the snode from the unused list and return it
|
// remove the snode from the unused list and return it
|
||||||
unusedSnodes = unusedSnodes.minus(pathSnode)
|
unusedSnodes = unusedSnodes.minus(pathSnode)
|
||||||
@ -228,9 +227,9 @@ object OnionRequestAPI {
|
|||||||
OnionRequestAPI.guardSnodes = guardSnodes
|
OnionRequestAPI.guardSnodes = guardSnodes
|
||||||
fun getPath(paths: List<Path>): Path {
|
fun getPath(paths: List<Path>): Path {
|
||||||
return if (snodeToExclude != null) {
|
return if (snodeToExclude != null) {
|
||||||
paths.filter { !it.contains(snodeToExclude) }.getRandomElement()
|
paths.filter { !it.contains(snodeToExclude) }.secureRandom()
|
||||||
} else {
|
} else {
|
||||||
paths.getRandomElement()
|
paths.secureRandom()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when {
|
when {
|
||||||
@ -273,7 +272,7 @@ object OnionRequestAPI {
|
|||||||
path.removeAt(snodeIndex)
|
path.removeAt(snodeIndex)
|
||||||
val unusedSnodes = SnodeAPI.snodePool.minus(oldPaths.flatten())
|
val unusedSnodes = SnodeAPI.snodePool.minus(oldPaths.flatten())
|
||||||
if (unusedSnodes.isEmpty()) { throw InsufficientSnodesException() }
|
if (unusedSnodes.isEmpty()) { throw InsufficientSnodesException() }
|
||||||
path.add(unusedSnodes.getRandomElement())
|
path.add(unusedSnodes.secureRandom())
|
||||||
// Don't test the new snode as this would reveal the user's IP
|
// Don't test the new snode as this would reveal the user's IP
|
||||||
oldPaths.removeAt(pathIndex)
|
oldPaths.removeAt(pathIndex)
|
||||||
val newPaths = oldPaths + listOf( path )
|
val newPaths = oldPaths + listOf( path )
|
||||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user