This commit is contained in:
0x330a 2023-08-08 14:37:52 +09:30 committed by GitHub
commit 1cd85f2d57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 151 additions and 206 deletions

View File

@ -130,36 +130,35 @@ dependencies {
testImplementation 'org.assertj:assertj-core:3.11.1' testImplementation 'org.assertj:assertj-core:3.11.1'
testImplementation "org.mockito:mockito-inline:4.10.0" testImplementation "org.mockito:mockito-inline:4.10.0"
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
androidTestImplementation "org.mockito:mockito-android:4.10.0" androidTestImplementation "org.mockito:mockito-android:$mockitoAndroidVersion"
androidTestImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" androidTestImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
testImplementation "androidx.test:core:$testCoreVersion" testImplementation "androidx.test:core:$testCoreVersion"
testImplementation "androidx.arch.core:core-testing:2.2.0" testImplementation "androidx.arch.core:core-testing:2.2.0"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion" testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion"
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion" androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion"
// Core library // Core library
androidTestImplementation "androidx.test:core:$testCoreVersion" androidTestImplementation("androidx.test:core:$testCoreVersion")
androidTestImplementation('com.adevinta.android:barista:4.2.0') { androidTestImplementation('com.adevinta.android:barista:4.2.0') {
exclude group: 'org.jetbrains.kotlin' exclude group: 'org.jetbrains.kotlin'
} }
// AndroidJUnitRunner and JUnit Rules // AndroidJUnitRunner and JUnit Rules
androidTestImplementation 'androidx.test:runner:1.5.2' androidTestImplementation "androidx.test:runner:$testRunnerVersion"
androidTestImplementation 'androidx.test:rules:1.5.0' androidTestImplementation "androidx.test:rules:$testRulesVersion"
// Assertions // Assertions
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation "androidx.test.ext:junit:1.1.5"
androidTestImplementation 'androidx.test.ext:truth:1.5.0' androidTestImplementation "androidx.test.ext:truth:$testExtTruthVersion"
androidTestImplementation 'com.google.truth:truth:1.1.3'
// Espresso dependencies // Espresso dependencies
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation "androidx.test.espresso:espresso-core:$testEspressoVersion"
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.1' androidTestImplementation "androidx.test.espresso:espresso-contrib:$testEspressoVersion"
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.5.1' androidTestImplementation "androidx.test.espresso:espresso-intents:$testEspressoVersion"
androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.5.1' androidTestImplementation "androidx.test.espresso:espresso-accessibility:$testEspressoVersion"
androidTestImplementation 'androidx.test.espresso:espresso-web:3.5.1' androidTestImplementation "androidx.test.espresso:espresso-web:$testEspressoVersion"
androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.5.1' androidTestImplementation "androidx.test.espresso.idling:idling-concurrent:$testEspressoVersion"
androidTestImplementation 'androidx.test.espresso:espresso-idling-resource:3.5.1' androidTestImplementation "androidx.test.espresso:espresso-idling-resource:$testEspressoVersion"
androidTestUtil 'androidx.test:orchestrator:1.4.2' androidTestUtil 'androidx.test:orchestrator:1.4.2'
testImplementation 'org.robolectric:robolectric:4.4' testImplementation 'org.robolectric:robolectric:4.4'
@ -187,7 +186,7 @@ def abiPostFix = ['armeabi-v7a' : 1,
'universal' : 5] 'universal' : 5]
android { android {
compileSdkVersion androidCompileSdkVersion compileSdk androidCompileSdkVersion
namespace 'network.loki.messenger' namespace 'network.loki.messenger'
useLibrary 'org.apache.http.legacy' useLibrary 'org.apache.http.legacy'

View File

@ -20,7 +20,6 @@ import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor; import android.database.Cursor;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
@ -35,7 +34,6 @@ import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.view.ActionMode; import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
@ -56,6 +54,10 @@ import org.session.libsession.messaging.messages.control.DataExtractionNotificat
import org.session.libsession.messaging.sending_receiving.MessageSender; import org.session.libsession.messaging.sending_receiving.MessageSender;
import org.session.libsession.snode.SnodeAPI; import org.session.libsession.snode.SnodeAPI;
import org.session.libsession.utilities.Address; import org.session.libsession.utilities.Address;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.ViewUtil;
import org.session.libsession.utilities.recipients.Recipient;
import org.session.libsession.utilities.task.ProgressDialogAsyncTask;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter; import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.database.MediaDatabase; import org.thoughtcrime.securesms.database.MediaDatabase;
import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader; import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader;
@ -63,13 +65,9 @@ import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader.Buc
import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader; import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader;
import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.permissions.Permissions;
import org.session.libsession.utilities.recipients.Recipient;
import org.thoughtcrime.securesms.util.AttachmentUtil; import org.thoughtcrime.securesms.util.AttachmentUtil;
import org.thoughtcrime.securesms.util.SaveAttachmentTask; import org.thoughtcrime.securesms.util.SaveAttachmentTask;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration; import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
import org.session.libsession.utilities.Util;
import org.session.libsession.utilities.ViewUtil;
import org.session.libsession.utilities.task.ProgressDialogAsyncTask;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
@ -436,17 +434,20 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity {
@Override @Override
public boolean onActionItemClicked(ActionMode mode, MenuItem menuItem) { public boolean onActionItemClicked(ActionMode mode, MenuItem menuItem) {
switch (menuItem.getItemId()) { int itemId = menuItem.getItemId();
case R.id.save: if (itemId == R.id.save) {
handleSaveMedia(getListAdapter().getSelectedMedia()); handleSaveMedia(getListAdapter().getSelectedMedia());
return true; return true;
case R.id.delete: } else if (itemId == R.id.save) {
handleDeleteMedia(getListAdapter().getSelectedMedia()); handleSaveMedia(getListAdapter().getSelectedMedia());
actionMode.finish(); return true;
return true; } else if (itemId == R.id.delete) {
case R.id.select_all: handleDeleteMedia(getListAdapter().getSelectedMedia());
handleSelectAllMedia(); actionMode.finish();
return true; return true;
} else if (itemId == R.id.select_all) {
handleSelectAllMedia();
return true;
} }
return false; return false;
} }

View File

@ -47,7 +47,6 @@ import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.core.util.Pair; import androidx.core.util.Pair;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.loader.app.LoaderManager; import androidx.loader.app.LoaderManager;
@ -491,12 +490,22 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item); super.onOptionsItemSelected(item);
switch (item.getItemId()) { int id = item.getItemId();
case R.id.media_preview__overview: showOverview(); return true; if (id == R.id.media_preview__overview) {
case R.id.media_preview__forward: forward(); return true; showOverview();
case R.id.save: saveToDisk(); return true; return true;
case R.id.delete: deleteMedia(); return true; } else if (id == R.id.media_preview__forward) {
case android.R.id.home: finish(); return true; forward();
return true;
} else if (id == R.id.save) {
saveToDisk();
return true;
} else if (id == R.id.delete) {
deleteMedia();
return true;
} else if (id == android.R.id.home) {
finish();
return true;
} }
return false; return false;

View File

@ -46,7 +46,6 @@ import org.thoughtcrime.securesms.crypto.BiometricSecretProvider;
import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.AnimationCompleteListener; import org.thoughtcrime.securesms.util.AnimationCompleteListener;
import java.security.InvalidKeyException;
import java.security.Signature; import java.security.Signature;
import network.loki.messenger.R; import network.loki.messenger.R;
@ -170,7 +169,7 @@ public class PassphrasePromptActivity extends BaseActionBarActivity {
hint.setSpan(new TypefaceSpan("sans-serif"), 0, hint.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); hint.setSpan(new TypefaceSpan("sans-serif"), 0, hint.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp); fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN); fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(org.session.libsession.R.color.signal_primary), PorterDuff.Mode.SRC_IN);
lockScreenButton.setOnClickListener(v -> resumeScreenLock()); lockScreenButton.setOnClickListener(v -> resumeScreenLock());
} }
@ -258,7 +257,7 @@ public class PassphrasePromptActivity extends BaseActionBarActivity {
handleAuthenticated(); handleAuthenticated();
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp); fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN); fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(org.session.libsession.R.color.signal_primary), PorterDuff.Mode.SRC_IN);
} }
}).start(); }).start();
} }
@ -288,7 +287,7 @@ public class PassphrasePromptActivity extends BaseActionBarActivity {
handleAuthenticated(); handleAuthenticated();
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp); fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN); fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(org.session.libsession.R.color.signal_primary), PorterDuff.Mode.SRC_IN);
} }
}).start(); }).start();
} }
@ -310,7 +309,7 @@ public class PassphrasePromptActivity extends BaseActionBarActivity {
@Override @Override
public void onAnimationEnd(Animation animation) { public void onAnimationEnd(Animation animation) {
fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp); fingerprintPrompt.setImageResource(R.drawable.ic_fingerprint_white_48dp);
fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(R.color.signal_primary), PorterDuff.Mode.SRC_IN); fingerprintPrompt.getBackground().setColorFilter(getResources().getColor(org.session.libsession.R.color.signal_primary), PorterDuff.Mode.SRC_IN);
} }
@Override @Override

View File

@ -53,7 +53,7 @@ class SessionDialogBuilder(val context: Context) {
fun title(text: CharSequence?) = title(text?.toString()) fun title(text: CharSequence?) = title(text?.toString())
fun title(text: String?) { fun title(text: String?) {
text(text, R.style.TextAppearance_AppCompat_Title) { setPadding(dp20) } text(text, androidx.appcompat.R.style.TextAppearance_AppCompat_Title) { setPadding(dp20) }
} }
fun text(@StringRes id: Int, style: Int = 0) = text(context.getString(id), style) fun text(@StringRes id: Int, style: Int = 0) = text(context.getString(id), style)

View File

@ -22,7 +22,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import network.loki.messenger.R
import network.loki.messenger.databinding.ActivityWebrtcBinding import network.loki.messenger.databinding.ActivityWebrtcBinding
import org.apache.commons.lang3.time.DurationFormatUtils import org.apache.commons.lang3.time.DurationFormatUtils
import org.session.libsession.avatars.ProfileContactPhoto import org.session.libsession.avatars.ProfileContactPhoto
@ -269,7 +268,7 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() {
val signalProfilePicture = latestRecipient.recipient.contactPhoto val signalProfilePicture = latestRecipient.recipient.contactPhoto
val avatar = (signalProfilePicture as? ProfileContactPhoto)?.avatarObject val avatar = (signalProfilePicture as? ProfileContactPhoto)?.avatarObject
val sizeInPX = val sizeInPX =
resources.getDimensionPixelSize(R.dimen.extra_large_profile_picture_size) resources.getDimensionPixelSize(org.session.libsession.R.dimen.extra_large_profile_picture_size)
binding.remoteRecipientName.text = displayName binding.remoteRecipientName.text = displayName
if (signalProfilePicture != null && avatar != "0" && avatar != "") { if (signalProfilePicture != null && avatar != "0" && avatar != "") {
glide.clear(binding.remoteRecipient) glide.clear(binding.remoteRecipient)

View File

@ -24,7 +24,7 @@ public class EmojiEditText extends AppCompatEditText {
} }
public EmojiEditText(Context context, AttributeSet attrs) { public EmojiEditText(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.editTextStyle); this(context, attrs, android.R.attr.editTextStyle);
} }
public EmojiEditText(Context context, AttributeSet attrs, int defStyleAttr) { public EmojiEditText(Context context, AttributeSet attrs, int defStyleAttr) {

View File

@ -7,10 +7,8 @@ import android.view.View
import android.widget.LinearLayout import android.widget.LinearLayout
import network.loki.messenger.R import network.loki.messenger.R
import network.loki.messenger.databinding.ViewUserBinding import network.loki.messenger.databinding.ViewUserBinding
import org.session.libsession.messaging.MessagingModuleConfiguration
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.conversation.v2.utilities.MentionManagerUtilities
import org.thoughtcrime.securesms.dependencies.DatabaseComponent import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.mms.GlideRequests import org.thoughtcrime.securesms.mms.GlideRequests
@ -50,7 +48,7 @@ class UserView : LinearLayout {
fun bind(user: Recipient, glide: GlideRequests, actionIndicator: ActionIndicator, isSelected: Boolean = false) { fun bind(user: Recipient, glide: GlideRequests, 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(org.session.libsession.R.string.MessageRecord_you)
val contact = DatabaseComponent.get(context).sessionContactDatabase().getContactWithSessionID(publicKey) val contact = DatabaseComponent.get(context).sessionContactDatabase().getContactWithSessionID(publicKey)
return contact?.displayName(Contact.ContactContext.REGULAR) ?: publicKey return contact?.displayName(Contact.ContactContext.REGULAR) ?: publicKey
} }

View File

@ -50,7 +50,7 @@ class InputBarButton : RelativeLayout {
if (hasOpaqueBackground) { if (hasOpaqueBackground) {
R.attr.input_bar_button_background_opaque R.attr.input_bar_button_background_opaque
} else if (isSendButton) { } else if (isSendButton) {
R.attr.colorAccent androidx.appcompat.R.attr.colorAccent
} else { } else {
R.attr.input_bar_button_background R.attr.input_bar_button_background
} }

View File

@ -121,9 +121,9 @@ class QuoteView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
// region Convenience // region Convenience
@ColorInt private fun getLineColor(isOutgoingMessage: Boolean): Int { @ColorInt private fun getLineColor(isOutgoingMessage: Boolean): Int {
return when { return when {
mode == Mode.Regular && !isOutgoingMessage -> context.getColorFromAttr(R.attr.colorAccent) mode == Mode.Regular && !isOutgoingMessage -> context.getColorFromAttr(androidx.appcompat.R.attr.colorAccent)
mode == Mode.Regular -> context.getColorFromAttr(R.attr.message_sent_text_color) mode == Mode.Regular -> context.getColorFromAttr(R.attr.message_sent_text_color)
else -> context.getColorFromAttr(R.attr.colorAccent) else -> context.getColorFromAttr(androidx.appcompat.R.attr.colorAccent)
} }
} }

View File

@ -310,7 +310,7 @@ class VisibleMessageView : LinearLayout {
message.isSyncFailed -> message.isSyncFailed ->
MessageStatusInfo( MessageStatusInfo(
R.drawable.ic_delivery_status_failed, R.drawable.ic_delivery_status_failed,
context.getColor(R.color.accent_orange), context.getColor(org.session.libsession.R.color.accent_orange),
R.string.delivery_status_sync_failed, R.string.delivery_status_sync_failed,
null null
) )
@ -323,7 +323,7 @@ class VisibleMessageView : LinearLayout {
message.isResyncing -> message.isResyncing ->
MessageStatusInfo( MessageStatusInfo(
R.drawable.ic_delivery_status_sending, R.drawable.ic_delivery_status_sending,
context.getColor(R.color.accent_orange), R.string.delivery_status_syncing, context.getColor(org.session.libsession.R.color.accent_orange), R.string.delivery_status_syncing,
context.getString(R.string.AccessibilityId_message_sent_status_syncing) context.getString(R.string.AccessibilityId_message_sent_status_syncing)
) )
message.isRead -> message.isRead ->

View File

@ -7,7 +7,6 @@ import android.view.View
import android.widget.RelativeLayout import android.widget.RelativeLayout
import androidx.core.view.isVisible import androidx.core.view.isVisible
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import network.loki.messenger.R
import network.loki.messenger.databinding.ViewVoiceMessageBinding import network.loki.messenger.databinding.ViewVoiceMessageBinding
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
import org.thoughtcrime.securesms.audio.AudioSlidePlayer import org.thoughtcrime.securesms.audio.AudioSlidePlayer
@ -118,7 +117,9 @@ class VoiceMessageView : RelativeLayout, AudioSlidePlayer.Listener {
} }
private fun renderIcon() { private fun renderIcon() {
val iconID = if (isPlaying) R.drawable.exo_icon_pause else R.drawable.exo_icon_play val iconID =
if (isPlaying) com.google.android.exoplayer2.ui.R.drawable.exo_icon_pause
else com.google.android.exoplayer2.ui.R.drawable.exo_icon_play
binding.voiceMessagePlaybackImageView.setImageResource(iconID) binding.voiceMessagePlaybackImageView.setImageResource(iconID)
} }

View File

@ -39,7 +39,7 @@ object MentionUtilities {
val publicKey = text.subSequence(matcher.start() + 1, matcher.end()).toString() // +1 to get rid of the @ val publicKey = text.subSequence(matcher.start() + 1, matcher.end()).toString() // +1 to get rid of the @
val isUserBlindedPublicKey = openGroup?.let { SodiumUtilities.sessionId(userPublicKey, publicKey, it.publicKey) } ?: false val isUserBlindedPublicKey = openGroup?.let { SodiumUtilities.sessionId(userPublicKey, publicKey, it.publicKey) } ?: false
val userDisplayName: String? = if (publicKey.equals(userPublicKey, ignoreCase = true) || isUserBlindedPublicKey) { val userDisplayName: String? = if (publicKey.equals(userPublicKey, ignoreCase = true) || isUserBlindedPublicKey) {
context.getString(R.string.MessageRecord_you) context.getString(org.session.libsession.R.string.MessageRecord_you)
} else { } else {
val contact = DatabaseComponent.get(context).sessionContactDatabase().getContactWithSessionID(publicKey) val contact = DatabaseComponent.get(context).sessionContactDatabase().getContactWithSessionID(publicKey)
@Suppress("NAME_SHADOWING") val context = if (openGroup != null) Contact.ContactContext.OPEN_GROUP else Contact.ContactContext.REGULAR @Suppress("NAME_SHADOWING") val context = if (openGroup != null) Contact.ContactContext.OPEN_GROUP else Contact.ContactContext.REGULAR

View File

@ -255,7 +255,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId) NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_notification) .setSmallIcon(R.drawable.ic_notification)
.setColor(context.getResources().getColor(R.color.textsecure_primary)) .setColor(context.getResources().getColor(org.session.libsession.R.color.textsecure_primary))
.setCategory(NotificationCompat.CATEGORY_ERROR) .setCategory(NotificationCompat.CATEGORY_ERROR)
.setContentTitle(context.getString(R.string.ErrorNotifier_migration)) .setContentTitle(context.getString(R.string.ErrorNotifier_migration))
.setContentText(context.getString(R.string.ErrorNotifier_migration_downgrade)) .setContentText(context.getString(R.string.ErrorNotifier_migration_downgrade))

View File

@ -7,7 +7,6 @@ import network.loki.messenger.libsession_util.Contacts
import network.loki.messenger.libsession_util.ConversationVolatileConfig import network.loki.messenger.libsession_util.ConversationVolatileConfig
import network.loki.messenger.libsession_util.UserGroupsConfig import network.loki.messenger.libsession_util.UserGroupsConfig
import network.loki.messenger.libsession_util.UserProfile import network.loki.messenger.libsession_util.UserProfile
import org.session.libsession.snode.SnodeAPI
import org.session.libsession.utilities.ConfigFactoryProtocol import org.session.libsession.utilities.ConfigFactoryProtocol
import org.session.libsession.utilities.ConfigFactoryUpdateListener import org.session.libsession.utilities.ConfigFactoryUpdateListener
import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.TextSecurePreferences
@ -72,7 +71,6 @@ class ConfigFactory(
override val user: UserProfile? override val user: UserProfile?
get() = synchronizedWithLog(userLock) { get() = synchronizedWithLog(userLock) {
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
if (_userConfig == null) { if (_userConfig == null) {
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
val userDump = configDatabase.retrieveConfigAndHashes( val userDump = configDatabase.retrieveConfigAndHashes(
@ -92,7 +90,6 @@ class ConfigFactory(
override val contacts: Contacts? override val contacts: Contacts?
get() = synchronizedWithLog(contactsLock) { get() = synchronizedWithLog(contactsLock) {
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
if (_contacts == null) { if (_contacts == null) {
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
val contactsDump = configDatabase.retrieveConfigAndHashes( val contactsDump = configDatabase.retrieveConfigAndHashes(
@ -112,7 +109,6 @@ class ConfigFactory(
override val convoVolatile: ConversationVolatileConfig? override val convoVolatile: ConversationVolatileConfig?
get() = synchronizedWithLog(convoVolatileLock) { get() = synchronizedWithLog(convoVolatileLock) {
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
if (_convoVolatileConfig == null) { if (_convoVolatileConfig == null) {
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
val convoDump = configDatabase.retrieveConfigAndHashes( val convoDump = configDatabase.retrieveConfigAndHashes(
@ -133,7 +129,6 @@ class ConfigFactory(
override val userGroups: UserGroupsConfig? override val userGroups: UserGroupsConfig?
get() = synchronizedWithLog(userGroupsLock) { get() = synchronizedWithLog(userGroupsLock) {
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return null
if (_userGroups == null) { if (_userGroups == null) {
val (secretKey, publicKey) = maybeGetUserInfo() ?: return null val (secretKey, publicKey) = maybeGetUserInfo() ?: return null
val userGroupsDump = configDatabase.retrieveConfigAndHashes( val userGroupsDump = configDatabase.retrieveConfigAndHashes(
@ -207,8 +202,6 @@ class ConfigFactory(
openGroupId: String?, openGroupId: String?,
visibleOnly: Boolean visibleOnly: Boolean
): Boolean { ): Boolean {
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return true
val (_, userPublicKey) = maybeGetUserInfo() ?: return true val (_, userPublicKey) = maybeGetUserInfo() ?: return true
if (openGroupId != null) { if (openGroupId != null) {
@ -241,8 +234,6 @@ class ConfigFactory(
} }
override fun canPerformChange(variant: String, publicKey: String, changeTimestampMs: Long): Boolean { override fun canPerformChange(variant: String, publicKey: String, changeTimestampMs: Long): Boolean {
if (!ConfigBase.isNewConfigEnabled(isConfigForcedOn, SnodeAPI.nowWithOffset)) return true
val lastUpdateTimestampMs = configDatabase.retrieveConfigLastUpdateTimestamp(variant, publicKey) val lastUpdateTimestampMs = configDatabase.retrieveConfigLastUpdateTimestamp(variant, publicKey)
// Ensure the change occurred after the last config message was handled (minus the buffer period) // Ensure the change occurred after the last config message was handled (minus the buffer period)

View File

@ -3,9 +3,6 @@ package org.thoughtcrime.securesms.giph.ui;
import android.content.Context; import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import android.text.Editable; import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextWatcher; import android.text.TextWatcher;
@ -20,9 +17,14 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import network.loki.messenger.R; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import org.thoughtcrime.securesms.components.AnimatingToggle; import org.thoughtcrime.securesms.components.AnimatingToggle;
import network.loki.messenger.R;
public class GiphyActivityToolbar extends Toolbar { public class GiphyActivityToolbar extends Toolbar {
@Nullable private OnFilterChangedListener filterListener; @Nullable private OnFilterChangedListener filterListener;
@ -42,7 +44,7 @@ public class GiphyActivityToolbar extends Toolbar {
} }
public GiphyActivityToolbar(Context context, AttributeSet attrs) { public GiphyActivityToolbar(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.toolbarStyle); this(context, attrs, android.R.attr.toolbarStyle);
} }
public GiphyActivityToolbar(Context context, AttributeSet attrs, int defStyleAttr) { public GiphyActivityToolbar(Context context, AttributeSet attrs, int defStyleAttr) {

View File

@ -102,7 +102,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
setContentView(R.layout.activity_edit_closed_group) setContentView(R.layout.activity_edit_closed_group)
supportActionBar!!.setHomeAsUpIndicator( supportActionBar!!.setHomeAsUpIndicator(
ThemeUtil.getThemedDrawableResId(this, R.attr.actionModeCloseDrawable)) ThemeUtil.getThemedDrawableResId(this, androidx.appcompat.R.attr.actionModeCloseDrawable))
groupID = intent.getStringExtra(groupIDKey)!! groupID = intent.getStringExtra(groupIDKey)!!
val groupInfo = DatabaseComponent.get(this).groupDatabase().getGroup(groupID).get() val groupInfo = DatabaseComponent.get(this).groupDatabase().getGroup(groupID).get()

View File

@ -30,7 +30,6 @@ import kotlinx.coroutines.withContext
import network.loki.messenger.R import network.loki.messenger.R
import network.loki.messenger.databinding.ActivityHomeBinding import network.loki.messenger.databinding.ActivityHomeBinding
import network.loki.messenger.databinding.ViewMessageRequestBannerBinding import network.loki.messenger.databinding.ViewMessageRequestBannerBinding
import network.loki.messenger.libsession_util.ConfigBase
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
@ -71,8 +70,8 @@ import org.thoughtcrime.securesms.onboarding.SeedActivity
import org.thoughtcrime.securesms.onboarding.SeedReminderViewDelegate import org.thoughtcrime.securesms.onboarding.SeedReminderViewDelegate
import org.thoughtcrime.securesms.permissions.Permissions import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.preferences.SettingsActivity import org.thoughtcrime.securesms.preferences.SettingsActivity
import org.thoughtcrime.securesms.showSessionDialog
import org.thoughtcrime.securesms.showMuteDialog import org.thoughtcrime.securesms.showMuteDialog
import org.thoughtcrime.securesms.showSessionDialog
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
import org.thoughtcrime.securesms.util.DateUtils import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.util.IP2Country import org.thoughtcrime.securesms.util.IP2Country
@ -354,8 +353,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
} }
private fun updateLegacyConfigView() { private fun updateLegacyConfigView() {
binding.configOutdatedView.isVisible = ConfigBase.isNewConfigEnabled(textSecurePreferences.hasForcedNewConfig(), SnodeAPI.nowWithOffset) binding.configOutdatedView.isVisible = textSecurePreferences.getHasLegacyConfig()
&& textSecurePreferences.getHasLegacyConfig()
} }
override fun onResume() { override fun onResume() {

View File

@ -99,7 +99,7 @@ class PathStatusView : View {
val paths = withContext(Dispatchers.IO) { OnionRequestAPI.paths } val paths = withContext(Dispatchers.IO) { OnionRequestAPI.paths }
if (paths.isNotEmpty()) { if (paths.isNotEmpty()) {
setBackgroundResource(R.drawable.accent_dot) setBackgroundResource(R.drawable.accent_dot)
val hasPathsColor = context.getColor(R.color.accent_green) val hasPathsColor = context.getColor(org.session.libsession.R.color.accent_green)
mainColor = hasPathsColor mainColor = hasPathsColor
sessionShadowColor = hasPathsColor sessionShadowColor = hasPathsColor
} else { } else {

View File

@ -1,18 +1,9 @@
package org.thoughtcrime.securesms.mediasend; package org.thoughtcrime.securesms.mediasend;
import androidx.appcompat.app.ActionBar;
import androidx.lifecycle.ViewModelProvider;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Point; import android.graphics.Point;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.appcompat.widget.Toolbar;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
@ -21,8 +12,18 @@ 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 androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.session.libsession.utilities.Util; import org.session.libsession.utilities.Util;
import org.thoughtcrime.securesms.mms.GlideApp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -130,11 +131,10 @@ public class MediaPickerItemFragment extends Fragment implements MediaPickerItem
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { if (item.getItemId() == R.id.mediapicker_menu_add) {
case R.id.mediapicker_menu_add: adapter.setForcedMultiSelect(true);
adapter.setForcedMultiSelect(true); viewModel.onMultiSelectStarted();
viewModel.onMultiSelectStarted(); return true;
return true;
} }
return false; return false;
} }

View File

@ -31,7 +31,7 @@ public class MultipleRecipientNotificationBuilder extends AbstractNotificationBu
public MultipleRecipientNotificationBuilder(Context context, NotificationPrivacyPreference privacy) { public MultipleRecipientNotificationBuilder(Context context, NotificationPrivacyPreference privacy) {
super(context, privacy); super(context, privacy);
setColor(context.getResources().getColor(R.color.textsecure_primary)); setColor(context.getResources().getColor(org.session.libsession.R.color.textsecure_primary));
setSmallIcon(R.drawable.ic_notification); setSmallIcon(R.drawable.ic_notification);
setContentTitle(context.getString(R.string.app_name)); setContentTitle(context.getString(R.string.app_name));
setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, HomeActivity.class), PendingIntent.FLAG_IMMUTABLE)); setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, HomeActivity.class), PendingIntent.FLAG_IMMUTABLE));

View File

@ -22,7 +22,7 @@ public class PendingMessageNotificationBuilder extends AbstractNotificationBuild
Intent intent = new Intent(context, HomeActivity.class); Intent intent = new Intent(context, HomeActivity.class);
setSmallIcon(R.drawable.ic_notification); setSmallIcon(R.drawable.ic_notification);
setColor(context.getResources().getColor(R.color.textsecure_primary)); setColor(context.getResources().getColor(org.session.libsession.R.color.textsecure_primary));
setCategory(NotificationCompat.CATEGORY_MESSAGE); setCategory(NotificationCompat.CATEGORY_MESSAGE);
setContentTitle(context.getString(R.string.MessageNotifier_pending_signal_messages)); setContentTitle(context.getString(R.string.MessageNotifier_pending_signal_messages));

View File

@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.notifications
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage import com.google.firebase.messaging.RemoteMessage
import org.session.libsession.messaging.jobs.BatchMessageReceiveJob import org.session.libsession.messaging.jobs.BatchMessageReceiveJob
@ -37,7 +38,7 @@ class PushNotificationService : FirebaseMessagingService() {
Log.d("Loki", "Failed to decode data for message.") Log.d("Loki", "Failed to decode data for message.")
val builder = NotificationCompat.Builder(this, NotificationChannels.OTHER) val builder = NotificationCompat.Builder(this, NotificationChannels.OTHER)
.setSmallIcon(network.loki.messenger.R.drawable.ic_notification) .setSmallIcon(network.loki.messenger.R.drawable.ic_notification)
.setColor(this.getResources().getColor(network.loki.messenger.R.color.textsecure_primary)) .setColor(ContextCompat.getColor(this, org.session.libsession.R.color.textsecure_primary))
.setContentTitle("Session") .setContentTitle("Session")
.setContentText("You've got a new message.") .setContentText("You've got a new message.")
.setPriority(NotificationCompat.PRIORITY_DEFAULT) .setPriority(NotificationCompat.PRIORITY_DEFAULT)

View File

@ -65,7 +65,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
super(context, privacy); super(context, privacy);
setSmallIcon(R.drawable.ic_notification); setSmallIcon(R.drawable.ic_notification);
setColor(ContextCompat.getColor(context, R.color.accent_green)); setColor(ContextCompat.getColor(context, org.session.libsession.R.color.accent_green));
setCategory(NotificationCompat.CATEGORY_MESSAGE); setCategory(NotificationCompat.CATEGORY_MESSAGE);
if (!NotificationChannels.supported()) { if (!NotificationChannels.supported()) {

View File

@ -42,10 +42,10 @@ class PNModeActivity : BaseActionBarActivity() {
with(binding) { with(binding) {
contentView.disableClipping() contentView.disableClipping()
fcmOptionView.setOnClickListener { toggleFCM() } fcmOptionView.setOnClickListener { toggleFCM() }
fcmOptionView.mainColor = ThemeUtil.getThemedColor(root.context, R.attr.colorPrimary) fcmOptionView.mainColor = ThemeUtil.getThemedColor(root.context, androidx.appcompat.R.attr.colorPrimary)
fcmOptionView.strokeColor = resources.getColorWithID(R.color.pn_option_border, theme) fcmOptionView.strokeColor = resources.getColorWithID(R.color.pn_option_border, theme)
backgroundPollingOptionView.setOnClickListener { toggleBackgroundPolling() } backgroundPollingOptionView.setOnClickListener { toggleBackgroundPolling() }
backgroundPollingOptionView.mainColor = ThemeUtil.getThemedColor(root.context, R.attr.colorPrimary) backgroundPollingOptionView.mainColor = ThemeUtil.getThemedColor(root.context, androidx.appcompat.R.attr.colorPrimary)
backgroundPollingOptionView.strokeColor = resources.getColorWithID(R.color.pn_option_border, theme) backgroundPollingOptionView.strokeColor = resources.getColorWithID(R.color.pn_option_border, theme)
registerButton.setOnClickListener { register() } registerButton.setOnClickListener { register() }
} }
@ -153,7 +153,7 @@ class PNModeActivity : BaseActionBarActivity() {
if (selectedOptionView == null) { if (selectedOptionView == null) {
showSessionDialog { showSessionDialog {
title(R.string.activity_pn_mode_no_option_picked_dialog_title) title(R.string.activity_pn_mode_no_option_picked_dialog_title)
button(R.string.ok) button(android.R.string.ok)
} }
return return
} }

View File

@ -155,7 +155,7 @@ public abstract class CorrectedPreferenceFragment extends PreferenceFragmentComp
holder.itemView.setLayoutParams(layoutParams); holder.itemView.setLayoutParams(layoutParams);
setZeroPaddingToLayoutChildren(holder.itemView); setZeroPaddingToLayoutChildren(holder.itemView);
} else { } else {
View iconFrame = holder.itemView.findViewById(R.id.icon_frame); View iconFrame = holder.itemView.findViewById(androidx.preference.R.id.icon_frame);
if (iconFrame != null) { if (iconFrame != null) {
iconFrame.setVisibility(preference.getIcon() == null ? View.GONE : View.VISIBLE); iconFrame.setVisibility(preference.getIcon() == null ? View.GONE : View.VISIBLE);
} }

View File

@ -50,7 +50,7 @@ class PrivacySettingsPreferenceFragment : ListSummaryPreferenceFragment() {
.setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID)) .setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID))
} }
.apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } .apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }
.takeIf { IntentUtils.isResolvable(requireContext(), it) }.let { .takeIf { IntentUtils.isResolvable(requireContext(), it) }?.let {
startActivity(it) startActivity(it)
} }
} }

View File

@ -5,7 +5,6 @@ import android.os.Parcelable
import android.util.SparseArray import android.util.SparseArray
import android.view.View import android.view.View
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.widget.SwitchCompat
import androidx.core.view.children import androidx.core.view.children
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -33,13 +32,13 @@ class AppearanceSettingsActivity: PassphraseRequiredActionBarActivity(), View.On
private val accentColors private val accentColors
get() = mapOf( get() = mapOf(
binding.accentGreen to R.style.PrimaryGreen, binding.accentGreen to org.session.libsession.R.style.PrimaryGreen,
binding.accentBlue to R.style.PrimaryBlue, binding.accentBlue to org.session.libsession.R.style.PrimaryBlue,
binding.accentYellow to R.style.PrimaryYellow, binding.accentYellow to org.session.libsession.R.style.PrimaryYellow,
binding.accentPink to R.style.PrimaryPink, binding.accentPink to org.session.libsession.R.style.PrimaryPink,
binding.accentPurple to R.style.PrimaryPurple, binding.accentPurple to org.session.libsession.R.style.PrimaryPurple,
binding.accentOrange to R.style.PrimaryOrange, binding.accentOrange to org.session.libsession.R.style.PrimaryOrange,
binding.accentRed to R.style.PrimaryRed binding.accentRed to org.session.libsession.R.style.PrimaryRed
) )
private val themeViews private val themeViews
@ -73,9 +72,9 @@ class AppearanceSettingsActivity: PassphraseRequiredActionBarActivity(), View.On
viewModel.setNewStyle(mappedStyle) viewModel.setNewStyle(mappedStyle)
if (currentBase != newBase) { if (currentBase != newBase) {
if (newBase == R.style.Ocean) { if (newBase == R.style.Ocean) {
viewModel.setNewAccent(R.style.PrimaryBlue) viewModel.setNewAccent(org.session.libsession.R.style.PrimaryBlue)
} else if (newBase == R.style.Classic) { } else if (newBase == R.style.Classic) {
viewModel.setNewAccent(R.style.PrimaryGreen) viewModel.setNewAccent(org.session.libsession.R.style.PrimaryGreen)
} }
} }
} }

View File

@ -3,11 +3,11 @@ package org.thoughtcrime.securesms.preferences.widgets;
import android.content.Context; import android.content.Context;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.widget.ImageView;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder; import androidx.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import network.loki.messenger.R; import network.loki.messenger.R;
@ -58,7 +58,7 @@ public class ContactPreference extends Preference {
int color; int color;
if (secure) { if (secure) {
color = getContext().getResources().getColor(R.color.textsecure_primary); color = getContext().getResources().getColor(org.session.libsession.R.color.textsecure_primary);
} else { } else {
color = getContext().getResources().getColor(R.color.grey_600); color = getContext().getResources().getColor(R.color.grey_600);
} }

View File

@ -69,7 +69,7 @@ public class UpdateApkReadyListener extends BroadcastReceiver {
.setContentTitle(context.getString(R.string.UpdateApkReadyListener_Signal_update)) .setContentTitle(context.getString(R.string.UpdateApkReadyListener_Signal_update))
.setContentText(context.getString(R.string.UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update)) .setContentText(context.getString(R.string.UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update))
.setSmallIcon(R.drawable.ic_notification) .setSmallIcon(R.drawable.ic_notification)
.setColor(context.getResources().getColor(R.color.textsecure_primary)) .setColor(context.getResources().getColor(org.session.libsession.R.color.textsecure_primary))
.setPriority(NotificationCompat.PRIORITY_HIGH) .setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_REMINDER) .setCategory(NotificationCompat.CATEGORY_REMINDER)
.setContentIntent(pendingIntent) .setContentIntent(pendingIntent)

View File

@ -91,8 +91,8 @@ fun String.getThemeStyle(): Int = when (this) {
@StyleRes @StyleRes
fun Int.getDefaultAccentColor(): Int = fun Int.getDefaultAccentColor(): Int =
if (this == R.style.Ocean_Dark || this == R.style.Ocean_Light) R.style.PrimaryBlue if (this == R.style.Ocean_Dark || this == R.style.Ocean_Light) org.session.libsession.R.style.PrimaryBlue
else R.style.PrimaryGreen else org.session.libsession.R.style.PrimaryGreen
data class ThemeState ( data class ThemeState (
@StyleRes val theme: Int, @StyleRes val theme: Int,

View File

@ -17,8 +17,6 @@ import org.session.libsession.messaging.jobs.ConfigurationSyncJob
import org.session.libsession.messaging.jobs.JobQueue import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.messaging.messages.Destination import org.session.libsession.messaging.messages.Destination
import org.session.libsession.messaging.messages.control.ConfigurationMessage import org.session.libsession.messaging.messages.control.ConfigurationMessage
import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.snode.SnodeAPI
import org.session.libsession.utilities.Address import org.session.libsession.utilities.Address
import org.session.libsession.utilities.GroupUtil import org.session.libsession.utilities.GroupUtil
import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.TextSecurePreferences
@ -55,61 +53,17 @@ object ConfigurationMessageUtilities {
fun syncConfigurationIfNeeded(context: Context) { fun syncConfigurationIfNeeded(context: Context) {
// add if check here to schedule new config job process and return early // add if check here to schedule new config job process and return early
val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return
val forcedConfig = TextSecurePreferences.hasForcedNewConfig(context) scheduleConfigSync(userPublicKey)
val currentTime = SnodeAPI.nowWithOffset return
if (ConfigBase.isNewConfigEnabled(forcedConfig, currentTime)) {
scheduleConfigSync(userPublicKey)
return
}
val lastSyncTime = TextSecurePreferences.getLastConfigurationSyncTime(context)
val now = System.currentTimeMillis()
if (now - lastSyncTime < 7 * 24 * 60 * 60 * 1000) return
val contacts = ContactUtilities.getAllContacts(context).filter { recipient ->
!recipient.name.isNullOrEmpty() && !recipient.isLocalNumber && recipient.address.serialize().isNotEmpty()
}.map { recipient ->
ConfigurationMessage.Contact(
publicKey = recipient.address.serialize(),
name = recipient.name!!,
profilePicture = recipient.profileAvatar,
profileKey = recipient.profileKey,
isApproved = recipient.isApproved,
isBlocked = recipient.isBlocked,
didApproveMe = recipient.hasApprovedMe()
)
}
val configurationMessage = ConfigurationMessage.getCurrent(contacts) ?: return
MessageSender.send(configurationMessage, Address.fromSerialized(userPublicKey))
TextSecurePreferences.setLastConfigurationSyncTime(context, now)
} }
fun forceSyncConfigurationNowIfNeeded(context: Context): Promise<Unit, Exception> { fun forceSyncConfigurationNowIfNeeded(context: Context): Promise<Unit, Exception> {
// add if check here to schedule new config job process and return early // add if check here to schedule new config job process and return early
val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return Promise.ofFail(NullPointerException("User Public Key is null")) val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return Promise.ofFail(NullPointerException("User Public Key is null"))
val forcedConfig = TextSecurePreferences.hasForcedNewConfig(context) // schedule job if none exist
val currentTime = SnodeAPI.nowWithOffset // don't schedule job if we already have one
if (ConfigBase.isNewConfigEnabled(forcedConfig, currentTime)) { scheduleConfigSync(userPublicKey)
// schedule job if none exist return Promise.ofSuccess(Unit)
// don't schedule job if we already have one
scheduleConfigSync(userPublicKey)
return Promise.ofSuccess(Unit)
}
val contacts = ContactUtilities.getAllContacts(context).filter { recipient ->
!recipient.isGroupRecipient && !recipient.name.isNullOrEmpty() && !recipient.isLocalNumber && recipient.address.serialize().isNotEmpty()
}.map { recipient ->
ConfigurationMessage.Contact(
publicKey = recipient.address.serialize(),
name = recipient.name!!,
profilePicture = recipient.profileAvatar,
profileKey = recipient.profileKey,
isApproved = recipient.isApproved,
isBlocked = recipient.isBlocked,
didApproveMe = recipient.hasApprovedMe()
)
}
val configurationMessage = ConfigurationMessage.getCurrent(contacts) ?: return Promise.ofSuccess(Unit)
val promise = MessageSender.send(configurationMessage, Destination.from(Address.fromSerialized(userPublicKey)), isSyncMessage = true)
TextSecurePreferences.setLastConfigurationSyncTime(context, System.currentTimeMillis())
return promise
} }
private fun maybeUserSecretKey() = MessagingModuleConfiguration.shared.getUserED25519KeyPair()?.secretKey?.asBytes private fun maybeUserSecretKey() = MessagingModuleConfiguration.shared.getUserED25519KeyPair()?.secretKey?.asBytes

View File

@ -10,12 +10,11 @@ import android.graphics.PointF
import android.graphics.Rect import android.graphics.Rect
import android.util.Size import android.util.Size
import android.view.View import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.annotation.DimenRes import androidx.annotation.DimenRes
import network.loki.messenger.R
import org.session.libsession.utilities.getColorFromAttr
import android.view.inputmethod.InputMethodManager
import androidx.core.graphics.applyCanvas import androidx.core.graphics.applyCanvas
import org.session.libsession.utilities.getColorFromAttr
import kotlin.math.roundToInt import kotlin.math.roundToInt
fun View.contains(point: PointF): Boolean { fun View.contains(point: PointF): Boolean {
@ -30,7 +29,7 @@ val View.hitRect: Rect
} }
@ColorInt @ColorInt
fun Context.getAccentColor() = getColorFromAttr(R.attr.colorAccent) fun Context.getAccentColor() = getColorFromAttr(androidx.appcompat.R.attr.colorAccent)
fun View.animateSizeChange(@DimenRes startSizeID: Int, @DimenRes endSizeID: Int, animationDuration: Long = 250) { fun View.animateSizeChange(@DimenRes startSizeID: Int, @DimenRes endSizeID: Int, animationDuration: Long = 250) {
val startSize = resources.getDimension(startSizeID) val startSize = resources.getDimension(startSizeID)

View File

@ -30,11 +30,21 @@ jacksonDatabindVersion=2.9.8
junitVersion=4.13.2 junitVersion=4.13.2
kotlinxJsonVersion=1.3.3 kotlinxJsonVersion=1.3.3
kovenantVersion=3.3.0 kovenantVersion=3.3.0
lifecycleVersion=2.5.1 lifecycleVersion=2.6.1
materialVersion=1.8.0 materialVersion=1.9.0
mockitoAndroidVersion=4.10.0
mockitoKotlinVersion=4.1.0 mockitoKotlinVersion=4.1.0
okhttpVersion=3.12.1 okhttpVersion=3.12.1
pagingVersion=3.0.0 pagingVersion=3.2.0
preferenceVersion=1.2.0 preferenceVersion=1.2.0
protobufVersion=2.5.0 protobufVersion=2.5.0
testCoreVersion=1.5.0
testCoreVersion=1.4.0
testEspressoVersion=3.4.0
extJunitVersion=1.1.5
testRunnerVersion=1.4.0
testRulesVersion=1.4.0
testServicesVersion=1.4.2
testOrchestratorVersion=1.4.2
testExtTruthVersion=1.4.0
testAnnotationVersion=1.0.1

View File

@ -39,9 +39,9 @@ android {
} }
dependencies { dependencies {
testImplementation 'junit:junit:4.13.2' testImplementation "junit:junit:$junitVersion"
implementation(project(":libsignal")) implementation(project(":libsignal"))
implementation "com.google.protobuf:protobuf-java:$protobufVersion" implementation "com.google.protobuf:protobuf-java:$protobufVersion"
androidTestImplementation 'androidx.test.ext:junit:1.1.4' androidTestImplementation "androidx.test.ext:junit:$extJunitVersion"
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' androidTestImplementation "androidx.test.espresso:espresso-core:$testEspressoVersion"
} }

View File

@ -25,12 +25,6 @@ sealed class ConfigBase(protected val /* yucky */ pointer: Long) {
is UserGroupsConfig -> Kind.GROUPS is UserGroupsConfig -> Kind.GROUPS
} }
// TODO: time in future to activate (hardcoded to 1st jan 2024 for testing, change before release)
private const val ACTIVATE_TIME = 1690761600000
fun isNewConfigEnabled(forced: Boolean, currentTime: Long) =
forced || currentTime >= ACTIVATE_TIME
const val PRIORITY_HIDDEN = -1 const val PRIORITY_HIDDEN = -1
const val PRIORITY_VISIBLE = 0 const val PRIORITY_VISIBLE = 0
const val PRIORITY_PINNED = 1 const val PRIORITY_PINNED = 1

View File

@ -1,6 +1,5 @@
package org.session.libsession.messaging.jobs package org.session.libsession.messaging.jobs
import network.loki.messenger.libsession_util.ConfigBase
import network.loki.messenger.libsession_util.ConfigBase.Companion.protoKindFor import network.loki.messenger.libsession_util.ConfigBase.Companion.protoKindFor
import nl.komponents.kovenant.functional.bind import nl.komponents.kovenant.functional.bind
import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.MessagingModuleConfiguration
@ -10,7 +9,6 @@ import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.messaging.utilities.Data import org.session.libsession.messaging.utilities.Data
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.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.Log
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
@ -26,14 +24,10 @@ data class ConfigurationSyncJob(val destination: Destination): Job {
override suspend fun execute(dispatcherName: String) { override suspend fun execute(dispatcherName: String) {
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val forcedConfig = TextSecurePreferences.hasForcedNewConfig(MessagingModuleConfiguration.shared.context)
val currentTime = SnodeAPI.nowWithOffset
val userEdKeyPair = MessagingModuleConfiguration.shared.getUserED25519KeyPair() val userEdKeyPair = MessagingModuleConfiguration.shared.getUserED25519KeyPair()
val userPublicKey = storage.getUserPublicKey() val userPublicKey = storage.getUserPublicKey()
val delegate = delegate val delegate = delegate
if (destination is Destination.ClosedGroup // TODO: closed group configs will be handled in closed group feature if (destination is Destination.ClosedGroup
// if we haven't enabled the new configs don't run
|| !ConfigBase.isNewConfigEnabled(forcedConfig, currentTime)
// if we don't have a user ed key pair for signing updates // if we don't have a user ed key pair for signing updates
|| userEdKeyPair == null || userEdKeyPair == null
// this will be useful to not handle null delegate cases // this will be useful to not handle null delegate cases

View File

@ -1,7 +1,6 @@
package org.session.libsession.messaging.sending_receiving package org.session.libsession.messaging.sending_receiving
import android.text.TextUtils import android.text.TextUtils
import network.loki.messenger.libsession_util.ConfigBase
import org.session.libsession.avatars.AvatarHelper import org.session.libsession.avatars.AvatarHelper
import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.jobs.BackgroundGroupAddJob import org.session.libsession.messaging.jobs.BackgroundGroupAddJob
@ -181,18 +180,16 @@ private fun handleConfigurationMessage(message: ConfigurationMessage) {
TextSecurePreferences.setConfigurationMessageSynced(context, true) TextSecurePreferences.setConfigurationMessageSynced(context, true)
TextSecurePreferences.setLastProfileUpdateTime(context, message.sentTimestamp!!) TextSecurePreferences.setLastProfileUpdateTime(context, message.sentTimestamp!!)
val isForceSync = TextSecurePreferences.hasForcedNewConfig(context)
val currentTime = SnodeAPI.nowWithOffset TextSecurePreferences.setHasLegacyConfig(context, true)
if (ConfigBase.isNewConfigEnabled(isForceSync, currentTime)) { if (!firstTimeSync) return
TextSecurePreferences.setHasLegacyConfig(context, true)
if (!firstTimeSync) return
}
val allClosedGroupPublicKeys = storage.getAllClosedGroupPublicKeys() val allClosedGroupPublicKeys = storage.getAllClosedGroupPublicKeys()
for (closedGroup in message.closedGroups) { for (closedGroup in message.closedGroups) {
if (allClosedGroupPublicKeys.contains(closedGroup.publicKey)) { if (allClosedGroupPublicKeys.contains(closedGroup.publicKey)) {
// just handle the closed group encryption key pairs to avoid sync'd devices getting out of sync // just handle the closed group encryption key pairs to avoid sync'd devices getting out of sync
storage.addClosedGroupEncryptionKeyPair(closedGroup.encryptionKeyPair!!, closedGroup.publicKey, message.sentTimestamp!!) storage.addClosedGroupEncryptionKeyPair(closedGroup.encryptionKeyPair!!, closedGroup.publicKey, message.sentTimestamp!!)
} else if (firstTimeSync) { } else {
// only handle new closed group if it's first time sync // only handle new closed group if it's first time sync
handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, closedGroup.publicKey, closedGroup.name, handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, closedGroup.publicKey, closedGroup.name,
closedGroup.encryptionKeyPair!!, closedGroup.members, closedGroup.admins, message.sentTimestamp!!, closedGroup.expirationTimer) closedGroup.encryptionKeyPair!!, closedGroup.members, closedGroup.admins, message.sentTimestamp!!, closedGroup.expirationTimer)

View File

@ -740,7 +740,7 @@ interface TextSecurePreferences {
@JvmStatic @JvmStatic
fun getNotificationLedColor(context: Context): Int { fun getNotificationLedColor(context: Context): Int {
return getIntegerPreference(context, LED_COLOR_PREF_PRIMARY, ThemeUtil.getThemedColor(context, R.attr.colorAccent)) return getIntegerPreference(context, LED_COLOR_PREF_PRIMARY, ThemeUtil.getThemedColor(context, androidx.appcompat.R.attr.colorAccent))
} }
@JvmStatic @JvmStatic