diff --git a/app/src/main/java/org/thoughtcrime/securesms/attachments/AttachmentServer.java b/app/src/main/java/org/thoughtcrime/securesms/attachments/AttachmentServer.java index e186007ee3..176a8c290f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/attachments/AttachmentServer.java +++ b/app/src/main/java/org/thoughtcrime/securesms/attachments/AttachmentServer.java @@ -50,7 +50,7 @@ public class AttachmentServer implements Runnable { throws IOException { try { - this.context = context; + this.context = context.getApplicationContext(); this.attachment = attachment; this.socket = new ServerSocket(0, 0, InetAddress.getByAddress(new byte[]{127, 0, 0, 1})); this.port = socket.getLocalPort(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt b/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt index 9a5eb730de..52e2d52ab1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt @@ -122,7 +122,7 @@ class ProfilePictureView @JvmOverloads constructor( glide.clear(imageView) - val placeholder = PlaceholderAvatarPhoto(context, publicKey, displayName ?: "${publicKey.take(4)}...${publicKey.takeLast(4)}") + val placeholder = PlaceholderAvatarPhoto(publicKey, displayName ?: "${publicKey.take(4)}...${publicKey.takeLast(4)}") if (signalProfilePicture != null && avatar != "0" && avatar != "") { glide.load(signalProfilePicture) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index 84f43e014b..9aef9a68e8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -833,6 +833,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe override fun onDestroy() { viewModel.saveDraft(binding?.inputBar?.text?.trim() ?: "") + cancelVoiceMessage() tearDownRecipientObserver() super.onDestroy() binding = null diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarRecordingView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarRecordingView.kt index ec45b6ca82..14ac2cb99b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarRecordingView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarRecordingView.kt @@ -132,7 +132,12 @@ class InputBarRecordingView : RelativeLayout { private fun updateTimer() { val duration = (Date().time - startTimestamp) / 1000L binding.recordingViewDurationTextView.text = DateUtils.formatElapsedTime(duration) - snHandler.postDelayed({ updateTimer() }, 500) + + if (isAttachedToWindow) { + // Should only update the timer if the view is still attached to the window. + // Otherwise, the timer will keep running even after the view is detached. + snHandler.postDelayed({ updateTimer() }, 500) + } } fun lock() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/glide/PlaceholderAvatarLoader.kt b/app/src/main/java/org/thoughtcrime/securesms/glide/PlaceholderAvatarLoader.kt index 69c9b8c4f5..b163b5ed90 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/glide/PlaceholderAvatarLoader.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/glide/PlaceholderAvatarLoader.kt @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms.glide +import android.content.Context import android.graphics.drawable.BitmapDrawable import com.bumptech.glide.load.Options import com.bumptech.glide.load.model.ModelLoader @@ -8,7 +9,7 @@ import com.bumptech.glide.load.model.ModelLoaderFactory import com.bumptech.glide.load.model.MultiModelLoaderFactory import org.session.libsession.avatars.PlaceholderAvatarPhoto -class PlaceholderAvatarLoader(): ModelLoader { +class PlaceholderAvatarLoader(private val appContext: Context): ModelLoader { override fun buildLoadData( model: PlaceholderAvatarPhoto, @@ -16,14 +17,14 @@ class PlaceholderAvatarLoader(): ModelLoader { - return LoadData(model, PlaceholderAvatarFetcher(model.context, model)) + return LoadData(model, PlaceholderAvatarFetcher(appContext, model)) } override fun handles(model: PlaceholderAvatarPhoto): Boolean = true - class Factory() : ModelLoaderFactory { + class Factory(private val appContext: Context) : ModelLoaderFactory { override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader { - return PlaceholderAvatarLoader() + return PlaceholderAvatarLoader(appContext) } override fun teardown() {} } diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt index cb3322e039..672d2e0a1f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeViewModel.kt @@ -22,7 +22,7 @@ class HomeViewModel @Inject constructor(private val threadDb: ThreadDatabase): V private val executor = viewModelScope + SupervisorJob() private var lastContext: WeakReference? = null - private var updateJobs: MutableList = mutableListOf() + private val updateJobs: MutableList = mutableListOf() private val _conversations = MutableLiveData>() val conversations: LiveData> = _conversations @@ -31,6 +31,15 @@ class HomeViewModel @Inject constructor(private val threadDb: ThreadDatabase): V fun tryUpdateChannel() = listUpdateChannel.trySend(Unit) + override fun onCleared() { + super.onCleared() + + for (job in updateJobs) { + job.cancel() + } + updateJobs.clear() + } + fun getObservable(context: Context): LiveData> { // If the context has changed (eg. the activity gets recreated) then // we need to cancel the old executors and recreate them to prevent diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt index 1f3f2ff537..f100e06c0c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt @@ -240,19 +240,22 @@ class PathActivity : PassphraseRequiredActionBarActivity() { dotViewLayoutParams.addRule(CENTER_IN_PARENT) dotView.layoutParams = dotViewLayoutParams addView(dotView) - Handler().postDelayed({ + postDelayed({ performAnimation() }, dotAnimationStartDelay) } private fun performAnimation() { - expand() - Handler().postDelayed({ - collapse() - Handler().postDelayed({ - performAnimation() - }, dotAnimationRepeatInterval) - }, 1000) + if (isAttachedToWindow) { + expand() + + postDelayed({ + collapse() + postDelayed({ + performAnimation() + }, dotAnimationRepeatInterval) + }, 1000) + } } private fun expand() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java b/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java index 0a24c26fad..02172b7248 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java @@ -73,7 +73,7 @@ public class SignalGlideModule extends AppGlideModule { registry.append(DecryptableUri.class, InputStream.class, new DecryptableStreamUriLoader.Factory(context)); registry.append(AttachmentModel.class, InputStream.class, new AttachmentStreamUriLoader.Factory()); registry.append(ChunkedImageUrl.class, InputStream.class, new ChunkedImageUrlLoader.Factory()); - registry.append(PlaceholderAvatarPhoto.class, BitmapDrawable.class, new PlaceholderAvatarLoader.Factory()); + registry.append(PlaceholderAvatarPhoto.class, BitmapDrawable.class, new PlaceholderAvatarLoader.Factory(context)); registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/IP2Country.kt b/app/src/main/java/org/thoughtcrime/securesms/util/IP2Country.kt index 479a54fafa..bc76b80f2c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/IP2Country.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/IP2Country.kt @@ -55,7 +55,7 @@ class IP2Country private constructor(private val context: Context) { public fun configureIfNeeded(context: Context) { if (isInitialized) { return; } - shared = IP2Country(context) + shared = IP2Country(context.applicationContext) } } diff --git a/libsession/src/main/java/org/session/libsession/avatars/PlaceholderAvatarPhoto.kt b/libsession/src/main/java/org/session/libsession/avatars/PlaceholderAvatarPhoto.kt index 0fcbe36e90..916e9112de 100644 --- a/libsession/src/main/java/org/session/libsession/avatars/PlaceholderAvatarPhoto.kt +++ b/libsession/src/main/java/org/session/libsession/avatars/PlaceholderAvatarPhoto.kt @@ -1,13 +1,10 @@ package org.session.libsession.avatars -import android.content.Context import com.bumptech.glide.load.Key import java.security.MessageDigest -class PlaceholderAvatarPhoto(val context: Context, - val hashString: String, +class PlaceholderAvatarPhoto(val hashString: String, val displayName: String): Key { - override fun updateDiskCacheKey(messageDigest: MessageDigest) { messageDigest.update(hashString.encodeToByteArray()) messageDigest.update(displayName.encodeToByteArray()) diff --git a/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java b/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java index 094a9fc349..0601f3c1e9 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java +++ b/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java @@ -70,7 +70,7 @@ public class Recipient implements RecipientModifiedListener { private final @NonNull Address address; private final @NonNull List participants = new LinkedList<>(); - private Context context; + private final Context context; private @Nullable String name; private @Nullable String customLabel; private boolean resolving; @@ -132,7 +132,7 @@ public class Recipient implements RecipientModifiedListener { @NonNull Optional details, @NonNull ListenableFutureTask future) { - this.context = context; + this.context = context.getApplicationContext(); this.address = address; this.color = null; this.resolving = true; @@ -259,7 +259,7 @@ public class Recipient implements RecipientModifiedListener { } Recipient(@NonNull Context context, @NonNull Address address, @NonNull RecipientDetails details) { - this.context = context; + this.context = context.getApplicationContext(); this.address = address; this.contactUri = details.contactUri; this.name = details.name;