Skip to content

Commit

Permalink
Merge pull request #1539 from oxen-io/release/1.18.5
Browse files Browse the repository at this point in the history
Master: Release/1.18.5
  • Loading branch information
ThomasSession authored Jul 9, 2024
2 parents cfd30bd + 0300be2 commit 84c5ebe
Show file tree
Hide file tree
Showing 78 changed files with 1,926 additions and 881 deletions.
11 changes: 7 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ configurations.all {
exclude module: "commons-logging"
}

def canonicalVersionCode = 373
def canonicalVersionName = "1.18.4"
def canonicalVersionCode = 374
def canonicalVersionName = "1.18.5"

def postFixSize = 10
def abiPostFix = ['armeabi-v7a' : 1,
Expand Down Expand Up @@ -368,8 +368,11 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-idling-resource:3.5.1'
androidTestUtil 'androidx.test:orchestrator:1.4.2'

testImplementation 'org.robolectric:robolectric:4.4'
testImplementation 'org.robolectric:shadows-multidex:4.4'
testImplementation 'org.robolectric:robolectric:4.12.2'
testImplementation 'org.robolectric:shadows-multidex:4.12.2'
testImplementation 'org.conscrypt:conscrypt-openjdk-uber:2.5.2' // For Robolectric
testImplementation 'app.cash.turbine:turbine:1.1.0'


implementation 'com.github.bumptech.glide:compose:1.0.0-alpha.5'
implementation 'androidx.compose.ui:ui:1.5.2'
Expand Down
5 changes: 3 additions & 2 deletions app/src/main/java/org/thoughtcrime/securesms/AppContext.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package org.thoughtcrime.securesms

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asExecutor
import nl.komponents.kovenant.Kovenant
import nl.komponents.kovenant.jvm.asDispatcher
import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.ThreadUtils
import java.util.concurrent.Executors

object AppContext {

fun configureKovenant() {
Kovenant.context {
callbackContext.dispatcher = Executors.newSingleThreadExecutor().asDispatcher()
workerContext.dispatcher = ThreadUtils.executorPool.asDispatcher()
workerContext.dispatcher = Dispatchers.IO.asExecutor().asDispatcher()
multipleCompletion = { v1, v2 ->
Log.d("Loki", "Promise resolved more than once (first with $v1, then with $v2); ignoring $v2.")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
private static final String TAG = BaseActionBarActivity.class.getSimpleName();
public ThemeState currentThemeState;

private Resources.Theme modifiedTheme;

private TextSecurePreferences getPreferences() {
ApplicationContext appContext = (ApplicationContext) getApplicationContext();
return appContext.textSecurePreferences;
}

@StyleRes
public int getDesiredTheme() {
private int getDesiredTheme() {
ThemeState themeState = ActivityUtilitiesKt.themeState(getPreferences());
int userSelectedTheme = themeState.getTheme();

Expand All @@ -58,16 +60,20 @@ public int getDesiredTheme() {
}

@StyleRes @Nullable
public Integer getAccentTheme() {
private Integer getAccentTheme() {
if (!getPreferences().hasPreference(SELECTED_ACCENT_COLOR)) return null;
ThemeState themeState = ActivityUtilitiesKt.themeState(getPreferences());
return themeState.getAccentStyle();
}

@Override
public Resources.Theme getTheme() {
if (modifiedTheme != null) {
return modifiedTheme;
}

// New themes
Resources.Theme modifiedTheme = super.getTheme();
modifiedTheme = super.getTheme();
modifiedTheme.applyStyle(getDesiredTheme(), true);
Integer accentTheme = getAccentTheme();
if (accentTheme != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public void onBindItemViewHolder(ItemViewHolder viewHolder, int section, int off
Slide slide = MediaUtil.getSlideForAttachment(context, mediaRecord.getAttachment());

if (slide != null) {
thumbnailView.setImageResource(glideRequests, slide, false, null);
thumbnailView.setImageResource(glideRequests, slide, false);
}

thumbnailView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ public synchronized static AudioSlidePlayer createFor(@NonNull Context context,
}
}

@Nullable
public synchronized static AudioSlidePlayer getInstance() {
return playing.orNull();
}

private AudioSlidePlayer(@NonNull Context context,
@NonNull AudioSlide slide,
@NonNull Listener listener)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import android.provider.Settings
import kotlinx.coroutines.launch
import network.loki.messenger.R
import network.loki.messenger.databinding.ActivityWebrtcBinding
Expand Down Expand Up @@ -100,7 +101,14 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() {

override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
super.onCreate(savedInstanceState, ready)
rotationListener.enable()

// Only enable auto-rotate if system auto-rotate is enabled
if (isAutoRotateOn()) {
rotationListener.enable()
} else {
rotationListener.disable()
}

binding = ActivityWebrtcBinding.inflate(layoutInflater)
setContentView(binding.root)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
Expand Down Expand Up @@ -185,6 +193,14 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() {

}

//Function to check if Android System Auto-rotate is on or off
private fun isAutoRotateOn(): Boolean {
return Settings.System.getInt(
contentResolver,
Settings.System.ACCELEROMETER_ROTATION, 0
) == 1
}

override fun onDestroy() {
super.onDestroy()
hangupReceiver?.let { receiver ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ import android.view.View
import android.widget.LinearLayout
import network.loki.messenger.R
import network.loki.messenger.databinding.ViewUserBinding
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.mms.GlideRequests

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import org.session.libsession.messaging.open_groups.OpenGroup
import org.session.libsession.utilities.ExpirationUtil
import org.session.libsession.utilities.modifyLayoutParams
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities
import org.thoughtcrime.securesms.database.GroupDatabase
import org.thoughtcrime.securesms.database.LokiAPIDatabase
import org.thoughtcrime.securesms.util.DateUtils
Expand Down Expand Up @@ -78,7 +77,6 @@ class ConversationActionBarView @JvmOverloads constructor(
binding.profilePictureView.layoutParams = resources.getDimensionPixelSize(
if (recipient.isClosedGroupRecipient) R.dimen.medium_profile_picture_size else R.dimen.small_profile_picture_size
).let { LayoutParams(it, it) }
MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded(threadId, context)
update(recipient, openGroup, config)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package org.thoughtcrime.securesms.conversation.v2

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.plus
import org.session.libsession.database.MessageDataProvider
import org.session.libsession.database.StorageProtocol
import org.session.libsession.messaging.jobs.AttachmentDownloadJob
import org.session.libsession.messaging.jobs.AttachmentUploadJob
import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.util.flatten
import org.thoughtcrime.securesms.util.timedBuffer

/**
* [AttachmentDownloadHandler] is responsible for handling attachment download requests. These
* requests will go through different level of checking before they are queued for download.
*
* To use this handler, call [onAttachmentDownloadRequest] with the attachment that needs to be
* downloaded. The call to [onAttachmentDownloadRequest] is cheap and can be called multiple times.
*/
class AttachmentDownloadHandler(
private val storage: StorageProtocol,
private val messageDataProvider: MessageDataProvider,
jobQueue: JobQueue = JobQueue.shared,
scope: CoroutineScope = CoroutineScope(Dispatchers.Default) + SupervisorJob(),
) {
companion object {
private const val BUFFER_TIMEOUT_MILLS = 500L
private const val BUFFER_MAX_ITEMS = 10
private const val LOG_TAG = "AttachmentDownloadHelper"
}

private val downloadRequests = Channel<DatabaseAttachment>(UNLIMITED)

init {
scope.launch(Dispatchers.Default) {
downloadRequests
.receiveAsFlow()
.timedBuffer(BUFFER_TIMEOUT_MILLS, BUFFER_MAX_ITEMS)
.map(::filterEligibleAttachments)
.flatten()
.collect { attachment ->
jobQueue.add(
AttachmentDownloadJob(
attachmentID = attachment.attachmentId.rowId,
databaseMessageID = attachment.mmsId
)
)
}
}
}

/**
* Filter attachments that are eligible for creating download jobs.
*
*/
private fun filterEligibleAttachments(attachments: List<DatabaseAttachment>): List<DatabaseAttachment> {
val pendingAttachmentIDs = storage
.getAllPendingJobs(AttachmentDownloadJob.KEY, AttachmentUploadJob.KEY)
.values
.mapNotNull {
(it as? AttachmentUploadJob)?.attachmentID
?: (it as? AttachmentDownloadJob)?.attachmentID
}
.toSet()


return attachments.filter { attachment ->
eligibleForDownloadTask(
attachment,
pendingAttachmentIDs,
)
}
}

/**
* Check if the attachment is eligible for download task.
*/
private fun eligibleForDownloadTask(
attachment: DatabaseAttachment,
pendingJobsAttachmentRowIDs: Set<Long>,
): Boolean {
if (attachment.attachmentId.rowId in pendingJobsAttachmentRowIDs) {
return false
}

val threadID = storage.getThreadIdForMms(attachment.mmsId)

return AttachmentDownloadJob.eligibleForDownload(
threadID, storage, messageDataProvider, attachment.mmsId,
)
}


fun onAttachmentDownloadRequest(attachment: DatabaseAttachment) {
if (attachment.transferState != AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING) {
Log.i(
LOG_TAG,
"Attachment ${attachment.attachmentId} is not pending, skipping download"
)
return
}

downloadRequests.trySend(attachment)
}
}
Loading

0 comments on commit 84c5ebe

Please sign in to comment.