Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/1.18.5 #1535

Merged
merged 51 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
31d388e
fix: Authenticate all Open Group API calls
Oct 25, 2022
60ea5ba
Hide send button when message contains only whitespace
bemusementpark Aug 9, 2023
0f04929
Fix bug displaying user ID when quoting own message
aaronkerckhoff Sep 29, 2023
4313eee
Fix notification update for incoming unsend request
bemusementpark Oct 10, 2023
e595cfb
Improve check if author is own user when quoting messages
aaronkerckhoff Oct 15, 2023
c647bab
Fixed video call auto rotate, when auto rotate is disabled
rugveddarwhekar Oct 29, 2023
3773f4f
Merge branch 'dev' into unsend-notification
bemusementpark Mar 25, 2024
ef157f9
refactor: simplify comparison
0x330a Mar 27, 2024
f7537ca
Merge remote-tracking branch 'upstream/dev' into display-own-name-in-…
0x330a Mar 28, 2024
1377e19
Stop playing message if deleted
May 17, 2024
580bf9e
Accidental change
May 17, 2024
23872af
Accidental change
May 17, 2024
e49d017
Comments
May 17, 2024
0389397
Feedback
May 19, 2024
a8cc9e2
Comments
May 19, 2024
10597f1
Import
May 19, 2024
0d3a33e
Fix delete message for everyone doesn't stop the audio playing
May 27, 2024
172edde
Correct the usage of flowOn
Jun 4, 2024
6e24df0
Import
Jun 4, 2024
54bb845
Optimise XML
Jun 6, 2024
072accb
Remove unused file
Jun 11, 2024
d0e4148
Remove view pools
Jun 11, 2024
2c90717
Merge remote-tracking branch 'upstream/dev' into ses-637-voice-messag…
Jun 12, 2024
d3c4e11
Merge pull request #1332 from aaronkerckhoff/display-own-name-in-quote
ThomasSession Jun 20, 2024
32cc6df
Merge pull request #1336 from bemusementpark/unsend-notification
ThomasSession Jun 20, 2024
46358f4
Merge pull request #1487 from simophin/ses-637-voice-message-keeps-pl…
ThomasSession Jun 21, 2024
ba9f729
Merge pull request #1512 from simophin/ses-2021-improve-xml-loading
ThomasSession Jun 21, 2024
0d0a868
Merge branch 'dev' into pr/1026
ThomasSession Jun 24, 2024
1619277
Merge pull request #1026 from ceokot/sogs-auth
ThomasSession Jun 24, 2024
0547dde
Remove the use of executor in ThreadUtils
Jun 24, 2024
9c20ca2
Merge pull request #1520 from simophin/fix-threading-issue
ThomasSession Jun 24, 2024
01655b8
Merge pull request #1508 from simophin/fix-home-screen-dispatcher
ThomasSession Jun 24, 2024
48aacae
Merge branch 'dev' into pr/1298
ThomasSession Jun 24, 2024
031a180
Using trim and empty to capture semantic concept of nothing being in …
ThomasSession Jun 24, 2024
752f8cc
Merge pull request #1298 from bemusementpark/fix-send-whitespace
ThomasSession Jun 24, 2024
d22cb1e
Remove config checks (PR 1294)
ThomasSession Jun 24, 2024
c711d35
Merge pull request #1521 from oxen-io/remove-config-cheks
ThomasSession Jun 25, 2024
a0e6167
Merge pull request #1352 from rugveddarwhekar/master
ThomasSession Jun 25, 2024
0f47076
[SES-2162] - Remove wrapping of config message (#1517)
simophin Jun 27, 2024
2dbdd6b
Update libsession
bemusementpark Jun 27, 2024
5cd2cf5
Merge pull request #1527 from bemusementpark/update-libsession
bemusementpark Jun 28, 2024
1d80bb0
[SES-337] Add rounded corners to thumbnail in QuoteView (#1285)
bemusementpark Jun 30, 2024
a260717
Highlight @You mentions (#985)
ceokot Jul 1, 2024
fec67e2
[SES-2018] Refactor mention (#1510)
simophin Jul 1, 2024
0da949c
[SES-1966] Attachment batch download and tidy-up (#1507)
simophin Jul 1, 2024
bbb1b2b
Fix issue with span being the full length (#1528)
ThomasSession Jul 4, 2024
15b3b18
Proper display of unresolved names in mentions (#1530)
ThomasSession Jul 5, 2024
e1f1372
Testnet build (#1532)
simophin Jul 8, 2024
075341a
Allow "public.loki.foundation" to be accessed by http (#1534)
simophin Jul 8, 2024
2b27b7d
Bumping the version code and name
ThomasSession Jul 8, 2024
0300be2
Reverting temporary change
ThomasSession Jul 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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