diff --git a/app/src/main/java/org/thoughtcrime/securesms/AppContext.kt b/app/src/main/java/org/thoughtcrime/securesms/AppContext.kt new file mode 100644 index 0000000000..206e794605 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/AppContext.kt @@ -0,0 +1,20 @@ +package org.thoughtcrime.securesms + +import android.util.Log +import nl.komponents.kovenant.Kovenant +import nl.komponents.kovenant.jvm.asDispatcher +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() + multipleCompletion = { v1, v2 -> + Log.d("Loki", "Promise resolved more than once (first with $v1, then with $v2); ignoring $v2.") + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index e5b8b7fd5a..33e55e18d3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -49,7 +49,7 @@ import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWr import org.session.libsession.utilities.dynamiclanguage.LocaleParser; import org.session.libsession.utilities.preferences.ProfileKeyUtil; import org.session.libsignal.service.api.util.StreamDetails; -import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol; +import org.session.libsignal.service.loki.LokiAPIDatabaseProtocol; import org.session.libsignal.utilities.logging.Log; import org.signal.aesgcmprovider.AesGcmProvider; import org.thoughtcrime.securesms.components.TypingStatusSender; @@ -93,7 +93,6 @@ import org.webrtc.voiceengine.WebRtcAudioUtils; import java.io.File; import java.io.FileInputStream; -import java.io.IOException; import java.security.SecureRandom; import java.security.Security; import java.util.Date; @@ -104,6 +103,7 @@ import dagger.ObjectGraph; import kotlin.Unit; import kotlinx.coroutines.Job; import network.loki.messenger.BuildConfig; +import nl.komponents.kovenant.Kovenant; import static nl.komponents.kovenant.android.KovenantAndroid.startKovenant; import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant; @@ -164,6 +164,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc ProcessLifecycleOwner.get().getLifecycle().addObserver(this); // Loki // ======== + AppContext.INSTANCE.configureKovenant(); messageNotifier = new OptimizedMessageNotifier(new DefaultMessageNotifier()); broadcaster = new Broadcaster(this); threadNotificationHandler = new Handler(Looper.getMainLooper()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/PassphrasePromptActivity.java b/app/src/main/java/org/thoughtcrime/securesms/PassphrasePromptActivity.java index b058c99c91..ad75d60330 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/PassphrasePromptActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/PassphrasePromptActivity.java @@ -84,6 +84,7 @@ public class PassphrasePromptActivity extends BaseActionBarActivity { } @Override public void onServiceDisconnected(ComponentName name) { + keyCachingService.setMasterSecret(new Object()); keyCachingService = null; } }, Context.BIND_AUTO_CREATE); @@ -133,7 +134,9 @@ public class PassphrasePromptActivity extends BaseActionBarActivity { private void handleAuthenticated() { authenticated = true; //TODO Replace with a proper call. - keyCachingService.setMasterSecret(new Object()); + if (keyCachingService != null) { + keyCachingService.setMasterSecret(new Object()); + } // Finish and proceed with the next intent. Intent nextIntent = getIntent().getParcelableExtra("next_intent"); @@ -188,6 +191,8 @@ public class PassphrasePromptActivity extends BaseActionBarActivity { if (!keyguardManager.isKeyguardSecure()) { Log.w(TAG ,"Keyguard not secure..."); + TextSecurePreferences.setScreenLockEnabled(getApplicationContext(), false); + TextSecurePreferences.setScreenLockTimeout(getApplicationContext(), 0); handleAuthenticated(); return; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java index addf213317..5b3125add6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -109,10 +109,10 @@ import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.Util; import org.session.libsession.utilities.ViewUtil; import org.session.libsession.utilities.concurrent.AssertedSuccessListener; -import org.session.libsession.utilities.mentions.Mention; import org.session.libsession.utilities.views.Stub; import org.session.libsignal.libsignal.InvalidMessageException; import org.session.libsignal.libsignal.util.guava.Optional; +import org.session.libsignal.service.loki.Mention; import org.session.libsignal.service.loki.utilities.HexEncodingKt; import org.session.libsignal.service.loki.utilities.PublicKeyValidation; import org.session.libsignal.utilities.concurrent.ListenableFuture; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java index 790b215003..7f3d0cd97f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java @@ -25,10 +25,9 @@ import org.session.libsession.utilities.Util; import org.session.libsignal.libsignal.util.guava.Optional; import org.session.libsignal.service.api.messages.SignalServiceAttachmentPointer; -import org.session.libsignal.service.loki.database.LokiOpenGroupDatabaseProtocol; +import org.session.libsignal.service.loki.LokiOpenGroupDatabaseProtocol; import java.io.Closeable; -import java.io.IOException; import java.security.SecureRandom; import java.util.Collections; import java.util.LinkedList; @@ -44,6 +43,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt static final String GROUP_ID = "group_id"; private static final String TITLE = "title"; private static final String MEMBERS = "members"; + private static final String ZOMBIE_MEMBERS = "zombie_members"; private static final String AVATAR = "avatar"; private static final String AVATAR_ID = "avatar_id"; private static final String AVATAR_KEY = "avatar_key"; @@ -64,6 +64,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt GROUP_ID + " TEXT, " + TITLE + " TEXT, " + MEMBERS + " TEXT, " + + ZOMBIE_MEMBERS + " TEXT, " + AVATAR + " BLOB, " + AVATAR_ID + " INTEGER, " + AVATAR_KEY + " BLOB, " + @@ -81,7 +82,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt }; private static final String[] GROUP_PROJECTION = { - GROUP_ID, TITLE, MEMBERS, AVATAR, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST, + GROUP_ID, TITLE, MEMBERS, ZOMBIE_MEMBERS, AVATAR, AVATAR_ID, AVATAR_KEY, AVATAR_CONTENT_TYPE, AVATAR_RELAY, AVATAR_DIGEST, TIMESTAMP, ACTIVE, MMS, AVATAR_URL, ADMINS }; @@ -162,7 +163,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt } public @NonNull List getGroupMembers(String groupId, boolean includeSelf) { - List
members = getCurrentMembers(groupId); + List
members = getCurrentMembers(groupId, false); List recipients = new LinkedList<>(); for (Address member : members) { @@ -177,6 +178,17 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt return recipients; } + public @NonNull List getGroupZombieMembers(String groupId) { + List
members = getCurrentZombieMembers(groupId); + List recipients = new LinkedList<>(); + + for (Address member : members) { + recipients.add(Recipient.from(context, member, false)); + } + + return recipients; + } + public long create(@NonNull String groupId, @Nullable String title, @NonNull List
members, @Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay, @Nullable List
admins, @NonNull Long formationTimestamp) { @@ -300,6 +312,16 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt }); } + public void updateZombieMembers(String groupId, List
members) { + Collections.sort(members); + + ContentValues contents = new ContentValues(); + contents.put(ZOMBIE_MEMBERS, Address.toSerializedList(members, ',')); + contents.put(ACTIVE, 1); + databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?", + new String[] {groupId}); + } + public void updateAdmins(String groupId, List
admins) { Collections.sort(admins); @@ -311,7 +333,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt } public void removeMember(String groupId, Address source) { - List
currentMembers = getCurrentMembers(groupId); + List
currentMembers = getCurrentMembers(groupId, false); currentMembers.remove(source); ContentValues contents = new ContentValues(); @@ -329,18 +351,22 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt }); } - private List
getCurrentMembers(String groupId) { + private List
getCurrentMembers(String groupId, boolean zombieMembers) { Cursor cursor = null; + String membersColumn = MEMBERS; + if (zombieMembers) membersColumn = ZOMBIE_MEMBERS; + try { - cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {MEMBERS}, + cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {membersColumn}, GROUP_ID + " = ?", new String[] {groupId}, null, null, null); if (cursor != null && cursor.moveToFirst()) { - String serializedMembers = cursor.getString(cursor.getColumnIndexOrThrow(MEMBERS)); - return Address.fromSerializedList(serializedMembers, ','); + String serializedMembers = cursor.getString(cursor.getColumnIndexOrThrow(membersColumn)); + if (serializedMembers != null && !serializedMembers.isEmpty()) + return Address.fromSerializedList(serializedMembers, ','); } return new LinkedList<>(); @@ -350,6 +376,10 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt } } + private List
getCurrentZombieMembers(String groupId) { + return getCurrentMembers(groupId, true); + } + public boolean isActive(String groupId) { Optional record = getGroup(groupId); return record.isPresent() && record.get().isActive(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 55fa1d2adf..970b0793a9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -455,6 +455,10 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, DatabaseFactory.getGroupDatabase(context).setActive(groupID, value) } + override fun getZombieMember(groupID: String): Set { + return DatabaseFactory.getGroupDatabase(context).getGroupZombieMembers(groupID).map { it.address.serialize() }.toHashSet() + } + override fun removeMember(groupID: String, member: Address) { DatabaseFactory.getGroupDatabase(context).removeMember(groupID, member) } @@ -463,6 +467,10 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, DatabaseFactory.getGroupDatabase(context).updateMembers(groupID, members) } + override fun updateZombieMembers(groupID: String, members: List
) { + DatabaseFactory.getGroupDatabase(context).updateZombieMembers(groupID, members) + } + override fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type: SignalServiceGroup.Type, name: String, members: Collection, admins: Collection, sentTimestamp: Long) { val group = SignalServiceGroup(type, GroupUtil.getDecodedGroupIDAsData(groupID), SignalServiceGroup.GroupType.SIGNAL, name, members.toList(), null, admins.toList()) val m = IncomingTextMessage(Address.fromSerialized(senderPublicKey), 1, sentTimestamp, "", Optional.of(group), 0, true) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index 05a940b443..dc7a0f7ee4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -276,6 +276,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { } if (oldVersion < lokiV23) { + db.execSQL("ALTER TABLE groups ADD COLUMN zombie_members TEXT"); db.execSQL(LokiMessageDatabase.getUpdateMessageIDTableForType()); db.execSQL(LokiMessageDatabase.getUpdateMessageMappingTable()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt index e969819d07..88c89f7319 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt @@ -37,8 +37,14 @@ import java.io.IOException class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { private val originalMembers = HashSet() + private val zombies = HashSet() private val members = HashSet() + private val allMembers: Set + get() { + return members + zombies + } private var hasNameChanged = false + private var isSelfAdmin = false private var isLoading = false set(newValue) { field = newValue; invalidateOptionsMenu() } @@ -54,7 +60,10 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { } private val memberListAdapter by lazy { - EditClosedGroupMembersAdapter(this, GlideApp.with(this), this::onMemberClick) + if (isSelfAdmin) + EditClosedGroupMembersAdapter(this, GlideApp.with(this), isSelfAdmin, this::onMemberClick) + else + EditClosedGroupMembersAdapter(this, GlideApp.with(this), isSelfAdmin) } private lateinit var mainContentContainer: LinearLayout @@ -81,7 +90,10 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { ThemeUtil.getThemedDrawableResId(this, R.attr.actionModeCloseDrawable)) groupID = intent.getStringExtra(groupIDKey)!! - originalName = DatabaseFactory.getGroupDatabase(this).getGroup(groupID).get().title + val groupInfo = DatabaseFactory.getGroupDatabase(this).getGroup(groupID).get() + originalName = groupInfo.title + isSelfAdmin = groupInfo.admins.any{ it.serialize() == TextSecurePreferences.getLocalNumber(this) } + name = originalName mainContentContainer = findViewById(R.id.mainContentContainer) @@ -116,31 +128,35 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { } } - LoaderManager.getInstance(this).initLoader(loaderID, null, object : LoaderManager.LoaderCallbacks> { + LoaderManager.getInstance(this).initLoader(loaderID, null, object : LoaderManager.LoaderCallbacks { - override fun onCreateLoader(id: Int, bundle: Bundle?): Loader> { + override fun onCreateLoader(id: Int, bundle: Bundle?): Loader { return EditClosedGroupLoader(this@EditClosedGroupActivity, groupID) } - override fun onLoadFinished(loader: Loader>, members: List) { + override fun onLoadFinished(loader: Loader, groupMembers: GroupMembers) { // We no longer need any subsequent loading events // (they will occur on every activity resume). LoaderManager.getInstance(this@EditClosedGroupActivity).destroyLoader(loaderID) + members.clear() + members.addAll(groupMembers.members.toHashSet()) + zombies.clear() + zombies.addAll(groupMembers.zombieMembers.toHashSet()) originalMembers.clear() - originalMembers.addAll(members.toHashSet()) - updateMembers(originalMembers) + originalMembers.addAll(members + zombies) + updateMembers() } - override fun onLoaderReset(loader: Loader>) { - updateMembers(setOf()) + override fun onLoaderReset(loader: Loader) { + updateMembers() } }) } override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_edit_closed_group, menu) - return members.isNotEmpty() && !isLoading + return allMembers.isNotEmpty() && !isLoading } // endregion @@ -153,8 +169,8 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { if (data == null || data.extras == null || !data.hasExtra(SelectContactsActivity.selectedContactsKey)) return val selectedContacts = data.extras!!.getStringArray(SelectContactsActivity.selectedContactsKey)!!.toSet() - val changedMembers = members + selectedContacts - updateMembers(changedMembers) + members.addAll(selectedContacts) + updateMembers() } } } @@ -173,17 +189,12 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { } } - private fun updateMembers(members: Set) { - this.members.clear() - this.members.addAll(members) - memberListAdapter.setMembers(members) + private fun updateMembers() { + memberListAdapter.setMembers(allMembers) + memberListAdapter.setZombieMembers(zombies) - val admins = DatabaseFactory.getGroupDatabase(this).getGroup(groupID).get().admins.map { it.toString() }.toMutableSet() - admins.remove(TextSecurePreferences.getLocalNumber(this)) - memberListAdapter.setLockedMembers(admins) - - mainContentContainer.visibility = if (members.isEmpty()) View.GONE else View.VISIBLE - emptyStateContainer.visibility = if (members.isEmpty()) View.VISIBLE else View.GONE + mainContentContainer.visibility = if (allMembers.isEmpty()) View.GONE else View.VISIBLE + emptyStateContainer.visibility = if (allMembers.isEmpty()) View.VISIBLE else View.GONE invalidateOptionsMenu() } @@ -200,8 +211,9 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { private fun onMemberClick(member: String) { val bottomSheet = ClosedGroupEditingOptionsBottomSheet() bottomSheet.onRemoveTapped = { - val changedMembers = members - member - updateMembers(changedMembers) + if (zombies.contains(member)) zombies.remove(member) + else members.remove(member) + updateMembers() bottomSheet.dismiss() } bottomSheet.show(supportFragmentManager, "GroupEditingOptionsBottomSheet") @@ -209,7 +221,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { private fun onAddMembersClick() { val intent = Intent(this@EditClosedGroupActivity, SelectContactsActivity::class.java) - intent.putExtra(SelectContactsActivity.usersToExcludeKey, members.toTypedArray()) + intent.putExtra(SelectContactsActivity.usersToExcludeKey, allMembers.toTypedArray()) intent.putExtra(SelectContactsActivity.emptyStateTextKey, "No contacts to add") startActivityForResult(intent, addUsersRequestCode) } @@ -229,7 +241,7 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { } private fun commitChanges() { - val hasMemberListChanges = (members != originalMembers) + val hasMemberListChanges = (allMembers != originalMembers) if (!hasNameChanged && !hasMemberListChanges) { return finish() @@ -237,15 +249,13 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { val name = if (hasNameChanged) this.name else originalName - val members = this.members.map { + val members = this.allMembers.map { Recipient.from(this, Address.fromSerialized(it), false) }.toSet() val originalMembers = this.originalMembers.map { Recipient.from(this, Address.fromSerialized(it), false) }.toSet() - val admins = members.toSet() //TODO For now, consider all the users to be admins. - var isClosedGroup: Boolean var groupPublicKey: String? try { @@ -303,4 +313,6 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { } } } + + class GroupMembers(val members: List, val zombieMembers: List) { } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt index 4f49501fc6..d2bb17a732 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt @@ -4,12 +4,19 @@ import android.content.Context import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.util.AsyncLoader -class EditClosedGroupLoader(context: Context, val groupID: String) : AsyncLoader>(context) { +class EditClosedGroupLoader(context: Context, val groupID: String) : AsyncLoader(context) { - override fun loadInBackground(): List { - val members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupID, true) - return members.map { - it.address.toString() - } + override fun loadInBackground(): EditClosedGroupActivity.GroupMembers { + val groupDatabase = DatabaseFactory.getGroupDatabase(context) + val members = groupDatabase.getGroupMembers(groupID, true) + val zombieMembers = groupDatabase.getGroupZombieMembers(groupID) + return EditClosedGroupActivity.GroupMembers( + members.map { + it.address.toString() + }, + zombieMembers.map { + it.address.toString() + } + ) } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupMembersAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupMembersAdapter.kt index 3c07136f1a..7d5ed34086 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupMembersAdapter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/EditClosedGroupMembersAdapter.kt @@ -7,15 +7,17 @@ import org.session.libsession.messaging.threads.Address import org.thoughtcrime.securesms.loki.views.UserView import org.thoughtcrime.securesms.mms.GlideRequests import org.session.libsession.messaging.threads.recipients.Recipient +import org.session.libsession.utilities.TextSecurePreferences class EditClosedGroupMembersAdapter( private val context: Context, private val glide: GlideRequests, + private val admin: Boolean, private val memberClickListener: ((String) -> Unit)? = null ) : RecyclerView.Adapter() { private val members = ArrayList() - private val lockedMembers = HashSet() + private val zombieMembers = ArrayList() fun setMembers(members: Collection) { this.members.clear() @@ -23,9 +25,9 @@ class EditClosedGroupMembersAdapter( notifyDataSetChanged() } - fun setLockedMembers(members: Collection) { - this.lockedMembers.clear() - this.lockedMembers.addAll(members) + fun setZombieMembers(members: Collection) { + this.zombieMembers.clear() + this.zombieMembers.addAll(members) notifyDataSetChanged() } @@ -39,15 +41,20 @@ class EditClosedGroupMembersAdapter( override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) { val member = members[position] - val lockedMember = lockedMembers.contains(member) + val unlocked = admin && member != TextSecurePreferences.getLocalNumber(context) viewHolder.view.bind(Recipient.from( context, Address.fromSerialized(member), false), glide, - if (lockedMember) UserView.ActionIndicator.None else UserView.ActionIndicator.Menu) + if (unlocked) UserView.ActionIndicator.Menu else UserView.ActionIndicator.None) - if (!lockedMember) { + if (zombieMembers.contains(member)) + viewHolder.view.alpha = 0.5F + else + viewHolder.view.alpha = 1F + + if (unlocked) { viewHolder.view.setOnClickListener { this.memberClickListener?.invoke(member) } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LinkDeviceActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LinkDeviceActivity.kt index 6f3ef464bc..2d6854f774 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LinkDeviceActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/LinkDeviceActivity.kt @@ -27,7 +27,7 @@ import kotlinx.coroutines.launch import network.loki.messenger.R import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.libsignal.util.KeyHelper -import org.session.libsignal.service.loki.crypto.MnemonicCodec +import org.session.libsignal.service.loki.MnemonicCodec import org.session.libsignal.service.loki.utilities.hexEncodedPublicKey import org.session.libsignal.utilities.Hex import org.session.libsignal.utilities.logging.Log @@ -45,7 +45,7 @@ class LinkDeviceActivity : BaseActionBarActivity(), ScanQRCodeWrapperFragmentDel private var restoreJob: Job? = null override fun onBackPressed() { - if (restoreJob?.isActive == true) return // don't allow going back with pending job + if (restoreJob?.isActive == true) return // Don't allow going back with a pending job super.onBackPressed() } @@ -53,14 +53,12 @@ class LinkDeviceActivity : BaseActionBarActivity(), ScanQRCodeWrapperFragmentDel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setUpActionBarSessionLogo() - // Set the registration sync variables TextSecurePreferences.apply { setHasViewedSeed(this@LinkDeviceActivity, true) setConfigurationMessageSynced(this@LinkDeviceActivity, false) setRestorationTime(this@LinkDeviceActivity, System.currentTimeMillis()) setLastProfileUpdateTime(this@LinkDeviceActivity, 0) } - // registration variables are synced setContentView(R.layout.activity_link_device) viewPager.adapter = adapter tabLayout.setupWithViewPager(viewPager) diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RecoveryPhraseRestoreActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RecoveryPhraseRestoreActivity.kt index 24d160f880..841b9e789a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RecoveryPhraseRestoreActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RecoveryPhraseRestoreActivity.kt @@ -15,7 +15,7 @@ import kotlinx.android.synthetic.main.activity_recovery_phrase_restore.* import network.loki.messenger.R import org.session.libsession.utilities.TextSecurePreferences import org.session.libsignal.libsignal.util.KeyHelper -import org.session.libsignal.service.loki.crypto.MnemonicCodec +import org.session.libsignal.service.loki.MnemonicCodec import org.session.libsignal.service.loki.utilities.hexEncodedPublicKey import org.session.libsignal.utilities.Hex import org.thoughtcrime.securesms.BaseActionBarActivity @@ -30,14 +30,12 @@ class RecoveryPhraseRestoreActivity : BaseActionBarActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setUpActionBarSessionLogo() - // Set the registration sync variables TextSecurePreferences.apply { setHasViewedSeed(this@RecoveryPhraseRestoreActivity, true) setConfigurationMessageSynced(this@RecoveryPhraseRestoreActivity, false) setRestorationTime(this@RecoveryPhraseRestoreActivity, System.currentTimeMillis()) setLastProfileUpdateTime(this@RecoveryPhraseRestoreActivity, System.currentTimeMillis()) } - // registration variables are synced setContentView(R.layout.activity_recovery_phrase_restore) mnemonicEditText.imeOptions = mnemonicEditText.imeOptions or 16777216 // Always use incognito keyboard restoreButton.setOnClickListener { restore() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt index 229edab444..79f462b9f8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/RegisterActivity.kt @@ -39,14 +39,12 @@ class RegisterActivity : BaseActionBarActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_register) setUpActionBarSessionLogo() - // Set the registration sync variables TextSecurePreferences.apply { setHasViewedSeed(this@RegisterActivity, false) setConfigurationMessageSynced(this@RegisterActivity, true) setRestorationTime(this@RegisterActivity, 0) setLastProfileUpdateTime(this@RegisterActivity, System.currentTimeMillis()) } - // registration variables are synced registerButton.setOnClickListener { register() } copyButton.setOnClickListener { copyPublicKey() } val termsExplanation = SpannableStringBuilder("By using this service, you agree to our Terms of Service and Privacy Policy") diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt index 2c79b4fc87..9ee8025335 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SeedActivity.kt @@ -16,7 +16,7 @@ import org.session.libsession.utilities.IdentityKeyUtil import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities import org.thoughtcrime.securesms.loki.utilities.getColorWithID import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsignal.service.loki.crypto.MnemonicCodec +import org.session.libsignal.service.loki.MnemonicCodec import org.session.libsignal.service.loki.utilities.hexEncodedPrivateKey class SeedActivity : BaseActionBarActivity() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt index 7e7d291870..13db15f9b2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiAPIDatabase.kt @@ -8,7 +8,7 @@ import org.session.libsignal.libsignal.ecc.DjbECPrivateKey import org.session.libsignal.libsignal.ecc.DjbECPublicKey import org.session.libsignal.libsignal.ecc.ECKeyPair import org.session.libsignal.service.loki.Snode -import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol +import org.session.libsignal.service.loki.LokiAPIDatabaseProtocol import org.session.libsignal.service.loki.utilities.PublicKeyValidation import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded import org.session.libsignal.service.loki.utilities.toHexString diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiMessageDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiMessageDatabase.kt index 78a1b91051..85a66b159c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiMessageDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiMessageDatabase.kt @@ -2,12 +2,11 @@ package org.thoughtcrime.securesms.loki.database import android.content.ContentValues import android.content.Context -import org.session.libsignal.service.loki.database.LokiMessageDatabaseProtocol -import org.session.libsignal.utilities.logging.Log import org.thoughtcrime.securesms.database.Database import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper import org.thoughtcrime.securesms.loki.utilities.* +import org.session.libsignal.service.loki.LokiMessageDatabaseProtocol class LokiMessageDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiMessageDatabaseProtocol { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiUserDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiUserDatabase.kt index 05e5f666db..cea0f52d9f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiUserDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/database/LokiUserDatabase.kt @@ -11,7 +11,7 @@ import org.thoughtcrime.securesms.loki.utilities.get import org.thoughtcrime.securesms.loki.utilities.insertOrUpdate import org.session.libsession.messaging.threads.recipients.Recipient import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol +import org.session.libsignal.service.loki.LokiUserDatabaseProtocol class LokiUserDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), LokiUserDatabaseProtocol { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt index 12446cf57b..d327efe973 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/dialogs/SeedDialog.kt @@ -15,7 +15,7 @@ import kotlinx.android.synthetic.main.dialog_seed.view.* import network.loki.messenger.R import org.session.libsession.utilities.IdentityKeyUtil import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities -import org.session.libsignal.service.loki.crypto.MnemonicCodec +import org.session.libsignal.service.loki.MnemonicCodec import org.session.libsignal.service.loki.utilities.hexEncodedPrivateKey diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt index b58f608502..f25833902e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt @@ -1,6 +1,8 @@ package org.thoughtcrime.securesms.loki.protocol import android.content.Context +import com.google.protobuf.ByteString +import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.messages.Destination import org.session.libsession.messaging.messages.control.ConfigurationMessage import org.session.libsession.messaging.sending_receiving.MessageSender diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/Broadcaster.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/Broadcaster.kt index 5156ff2572..dfc42c9340 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/Broadcaster.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/Broadcaster.kt @@ -3,8 +3,9 @@ package org.thoughtcrime.securesms.loki.utilities import android.content.Context import android.content.Intent import androidx.localbroadcastmanager.content.LocalBroadcastManager +import org.session.libsignal.service.loki.Broadcaster -class Broadcaster(private val context: Context) : org.session.libsignal.service.loki.utilities.Broadcaster { +class Broadcaster(private val context: Context) : Broadcaster { override fun broadcast(event: String) { val intent = Intent(event) diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/MnemonicUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/MnemonicUtilities.kt index 27a2a78cfc..226bb1abfd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/MnemonicUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/utilities/MnemonicUtilities.kt @@ -1,10 +1,6 @@ package org.thoughtcrime.securesms.loki.utilities import android.content.Context -import org.session.libsignal.service.loki.crypto.MnemonicCodec -import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded -import java.io.File -import java.io.FileOutputStream object MnemonicUtilities { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/views/MentionCandidateSelectionView.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/views/MentionCandidateSelectionView.kt index 63445c4ee4..2da55501cf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/views/MentionCandidateSelectionView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/views/MentionCandidateSelectionView.kt @@ -7,10 +7,10 @@ import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter import android.widget.ListView -import org.session.libsession.utilities.mentions.Mention import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.loki.utilities.toPx import org.thoughtcrime.securesms.mms.GlideRequests +import org.session.libsignal.service.loki.Mention class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : ListView(context, attrs, defStyleAttr) { private var mentionCandidates = listOf() diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt index 4563129185..f353402806 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/views/MentionCandidateView.kt @@ -9,7 +9,7 @@ import android.widget.LinearLayout import kotlinx.android.synthetic.main.view_mention_candidate.view.* import network.loki.messenger.R import org.session.libsession.messaging.open_groups.OpenGroupAPI -import org.session.libsession.utilities.mentions.Mention +import org.session.libsignal.service.loki.Mention import org.thoughtcrime.securesms.mms.GlideRequests class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : LinearLayout(context, attrs, defStyleAttr) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt index c731a354d2..acfa2470da 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/views/ProfilePictureView.kt @@ -146,13 +146,13 @@ class ProfilePictureView : RelativeLayout { private fun setProfilePictureIfNeeded(imageView: ImageView, publicKey: String, displayName: String?, @DimenRes sizeResId: Int) { if (publicKey.isNotEmpty()) { val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false) - if (imagesCached.contains(recipient.profileAvatar.orEmpty())) return + if (imagesCached.contains(publicKey)) return val signalProfilePicture = recipient.contactPhoto if (signalProfilePicture != null && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "0" && (signalProfilePicture as? ProfileContactPhoto)?.avatarObject != "") { glide.clear(imageView) glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.AUTOMATIC).circleCrop().into(imageView) - imagesCached.add(recipient.profileAvatar.orEmpty()) + imagesCached.add(publicKey) } else { val sizeInPX = resources.getDimensionPixelSize(sizeResId) glide.clear(imageView) @@ -162,7 +162,7 @@ class ProfilePictureView : RelativeLayout { publicKey, displayName )).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView) - imagesCached.add(recipient.profileAvatar.orEmpty()) + imagesCached.add(publicKey) } } else { imageView.setImageDrawable(null) diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java b/app/src/main/java/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java index db9484f9b0..e516916de4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java @@ -102,7 +102,8 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment if (duration == 0) { TextSecurePreferences.setScreenLockTimeout(getContext(), 0); } else { - long timeoutSeconds = Math.max(TimeUnit.MILLISECONDS.toSeconds(duration), 60); + long timeoutSeconds = TimeUnit.MILLISECONDS.toSeconds(duration); +// long timeoutSeconds = Math.max(TimeUnit.MILLISECONDS.toSeconds(duration), 60); TextSecurePreferences.setScreenLockTimeout(getContext(), timeoutSeconds); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java b/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java index e1c2350ef1..e204c3f503 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/KeyCachingService.java @@ -119,7 +119,6 @@ public class KeyCachingService extends Service { KeyCachingService.masterSecret = masterSecret; foregroundService(); - startTimeoutIfAppropriate(this); new AsyncTask() { @Override @@ -210,7 +209,7 @@ public class KeyCachingService extends Service { boolean passLockActive = timeoutEnabled && !TextSecurePreferences.isPasswordDisabled(context); long screenTimeout = TextSecurePreferences.getScreenLockTimeout(context); - boolean screenLockActive = screenTimeout >= 60 && TextSecurePreferences.isScreenLockEnabled(context); + boolean screenLockActive = screenTimeout >= 0 && TextSecurePreferences.isScreenLockEnabled(context); if (!appVisible && secretSet && (passLockActive || screenLockActive)) { long passphraseTimeoutMinutes = TextSecurePreferences.getPassphraseTimeoutInterval(context); diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index 437246f230..49b5d36053 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -98,13 +98,6 @@ android:layout_height="match_parent" android:background="@drawable/home_activity_gradient" /> - - + + \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt index 2fab491203..87ff89c3a4 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt @@ -110,8 +110,10 @@ interface StorageProtocol { fun createGroup(groupID: String, title: String?, members: List
, avatar: SignalServiceAttachmentPointer?, relay: String?, admins: List
, formationTimestamp: Long) fun isGroupActive(groupPublicKey: String): Boolean fun setActive(groupID: String, value: Boolean) + fun getZombieMember(groupID: String): Set fun removeMember(groupID: String, member: Address) fun updateMembers(groupID: String, members: List
) + fun updateZombieMembers(groupID: String, members: List
) // Closed Group fun getAllClosedGroupPublicKeys(): Set fun getAllActiveClosedGroupPublicKeys(): Set diff --git a/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerAPI.kt b/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerAPI.kt index 5e78caf6f0..b4a1861875 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerAPI.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerAPI.kt @@ -8,7 +8,7 @@ import org.session.libsession.snode.OnionRequestAPI import org.session.libsignal.utilities.logging.Log import org.session.libsignal.utilities.Base64 import org.session.libsignal.utilities.JsonUtil -import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol +import org.session.libsignal.service.loki.LokiAPIDatabaseProtocol import org.session.libsignal.service.loki.utilities.* import java.net.URL diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt index daf4971aa1..f135178618 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/AttachmentUploadJob.kt @@ -15,7 +15,7 @@ import org.session.libsignal.service.internal.crypto.PaddingInputStream import org.session.libsignal.service.internal.push.PushAttachmentData import org.session.libsignal.service.internal.push.http.AttachmentCipherOutputStreamFactory import org.session.libsignal.service.internal.util.Util -import org.session.libsignal.service.loki.utilities.PlaintextOutputStreamFactory +import org.session.libsignal.service.loki.PlaintextOutputStreamFactory import org.session.libsignal.utilities.logging.Log class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val message: Message, val messageSendJobID: String) : Job { diff --git a/libsession/src/main/java/org/session/libsession/messaging/mentions/MentionsManager.kt b/libsession/src/main/java/org/session/libsession/messaging/mentions/MentionsManager.kt index 3dac848a4a..e421489b19 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/mentions/MentionsManager.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/mentions/MentionsManager.kt @@ -1,9 +1,9 @@ package org.session.libsession.messaging.mentions import org.session.libsession.messaging.MessagingModuleConfiguration -import org.session.libsession.utilities.mentions.Mention +import org.session.libsignal.service.loki.Mention -import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol +import org.session.libsignal.service.loki.LokiUserDatabaseProtocol class MentionsManager(private val userPublicKey: String, private val userDatabase: LokiUserDatabaseProtocol) { var userPublicKeyCache = mutableMapOf>() // Thread ID to set of user hex encoded public keys diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt index 75af2abd6a..78275ca3b2 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ClosedGroupControlMessage.kt @@ -145,7 +145,7 @@ class ClosedGroupControlMessage() : ControlMessage() { } is Kind.EncryptionKeyPair -> { closedGroupControlMessage.type = DataMessage.ClosedGroupControlMessage.Type.ENCRYPTION_KEY_PAIR - closedGroupControlMessage.publicKey = kind.publicKey + closedGroupControlMessage.publicKey = kind.publicKey ?: ByteString.EMPTY closedGroupControlMessage.addAllWrappers(kind.wrappers.map { it.toProto() }) } is Kind.NameChange -> { diff --git a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupAPI.kt b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupAPI.kt index bd70118abd..0aba366d9f 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupAPI.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupAPI.kt @@ -21,7 +21,6 @@ import java.util.* object OpenGroupAPI: DotNetAPI() { private val moderators: HashMap>> = hashMapOf() // Server URL to (channel ID to set of moderator IDs) - val sharedContext = Kovenant.createContext() // region Settings private val fallbackBatchCount = 64 @@ -61,7 +60,7 @@ object OpenGroupAPI: DotNetAPI() { parameters["count"] = fallbackBatchCount parameters["include_deleted"] = 0 } - return execute(HTTPVerb.GET, server, "channels/$channel/messages", parameters = parameters).then(sharedContext) { json -> + return execute(HTTPVerb.GET, server, "channels/$channel/messages", parameters = parameters).then { json -> try { val data = json["data"] as List> val messages = data.mapNotNull { message -> @@ -166,7 +165,7 @@ object OpenGroupAPI: DotNetAPI() { } else { parameters["count"] = fallbackBatchCount } - return execute(HTTPVerb.GET, server, "loki/v1/channel/$channel/deletes", parameters = parameters).then(sharedContext) { json -> + return execute(HTTPVerb.GET, server, "loki/v1/channel/$channel/deletes", parameters = parameters).then { json -> try { val deletedMessageServerIDs = (json["data"] as List>).mapNotNull { deletion -> try { @@ -202,7 +201,7 @@ object OpenGroupAPI: DotNetAPI() { retryIfNeeded(maxRetryCount) { Log.d("Loki", "Sending message to open group with ID: $channel on server: $server.") val parameters = signedMessage.toJSON() - execute(HTTPVerb.POST, server, "channels/$channel/messages", parameters = parameters).then(sharedContext) { json -> + execute(HTTPVerb.POST, server, "channels/$channel/messages", parameters = parameters).then { json -> try { val data = json["data"] as Map<*, *> val serverID = (data["id"] as? Long) ?: (data["id"] as? Int)?.toLong() ?: (data["id"] as String).toLong() @@ -255,7 +254,7 @@ object OpenGroupAPI: DotNetAPI() { @JvmStatic fun getModerators(channel: Long, server: String): Promise, Exception> { - return execute(HTTPVerb.GET, server, "loki/v1/channel/$channel/get_moderators").then(sharedContext) { json -> + return execute(HTTPVerb.GET, server, "loki/v1/channel/$channel/get_moderators").then { json -> try { @Suppress("UNCHECKED_CAST") val moderators = json["moderators"] as? List val moderatorsAsSet = moderators.orEmpty().toSet() @@ -276,7 +275,7 @@ object OpenGroupAPI: DotNetAPI() { fun getChannelInfo(channel: Long, server: String): Promise { return retryIfNeeded(maxRetryCount) { val parameters = mapOf( "include_annotations" to 1 ) - execute(HTTPVerb.GET, server, "/channels/$channel", parameters = parameters).then(sharedContext) { json -> + execute(HTTPVerb.GET, server, "/channels/$channel", parameters = parameters).then { json -> try { val data = json["data"] as Map<*, *> val annotations = data["annotations"] as List> @@ -357,7 +356,7 @@ object OpenGroupAPI: DotNetAPI() { @JvmStatic fun getDisplayNames(publicKeys: Set, server: String): Promise, Exception> { - return getUserProfiles(publicKeys, server, false).map(sharedContext) { json -> + return getUserProfiles(publicKeys, server, false).map { json -> val mapping = mutableMapOf() for (user in json) { if (user["username"] != null) { diff --git a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupAPIV2.kt b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupAPIV2.kt index e7f45d2f03..d7ecbd5f14 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupAPIV2.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupAPIV2.kt @@ -17,16 +17,13 @@ import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.open_groups.OpenGroupAPIV2.Error import org.session.libsession.snode.OnionRequestAPI import org.session.libsession.utilities.AESGCM -import org.session.libsession.utilities.GroupUtil -import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsignal.service.loki.api.utilities.HTTP -import org.session.libsignal.service.loki.api.utilities.HTTP.Verb.* +import org.session.libsignal.service.loki.HTTP +import org.session.libsignal.service.loki.HTTP.Verb.* import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded import org.session.libsignal.service.loki.utilities.toHexString import org.session.libsignal.utilities.Base64.* import org.session.libsignal.utilities.Hex import org.session.libsignal.utilities.JsonUtil -import org.session.libsignal.utilities.createContext import org.session.libsignal.utilities.logging.Log import org.whispersystems.curve25519.Curve25519 import java.util.* @@ -39,7 +36,6 @@ object OpenGroupAPIV2 { val defaultRooms = MutableSharedFlow>(replay = 1) - private val sharedContext = Kovenant.createContext() private val curve = Curve25519.getInstance(Curve25519.BEST) sealed class Error : Exception() { @@ -128,8 +124,8 @@ object OpenGroupAPIV2 { } when (request.verb) { GET -> requestBuilder.get() - PUT -> requestBuilder.put(createBody(request.parameters)) - POST -> requestBuilder.post(createBody(request.parameters)) + PUT -> requestBuilder.put(createBody(request.parameters)!!) + POST -> requestBuilder.post(createBody(request.parameters)!!) DELETE -> requestBuilder.delete(createBody(request.parameters)) } @@ -156,7 +152,7 @@ object OpenGroupAPIV2 { } } return if (request.isAuthRequired) { - getAuthToken(request.room!!, request.server).bind(sharedContext) { execute(it) } + getAuthToken(request.room!!, request.server).bind { execute(it) } } else { execute(null) } @@ -164,7 +160,7 @@ object OpenGroupAPIV2 { fun downloadOpenGroupProfilePicture(roomID: String, server: String): Promise { val request = Request(verb = GET, room = roomID, server = server, endpoint = "rooms/$roomID/image", isAuthRequired = false) - return send(request).map(sharedContext) { json -> + return send(request).map { json -> val result = json["result"] as? String ?: throw Error.PARSING_FAILED decode(result) } @@ -176,7 +172,7 @@ object OpenGroupAPIV2 { Promise.of(it) } ?: run { requestNewAuthToken(room, server) - .bind(sharedContext) { claimAuthToken(it, room, server) } + .bind { claimAuthToken(it, room, server) } .success { authToken -> storage.setAuthToken(room, server, authToken) } @@ -188,7 +184,7 @@ object OpenGroupAPIV2 { ?: return Promise.ofFail(Error.GENERIC) val queryParameters = mutableMapOf("public_key" to publicKey) val request = Request(GET, room, server, "auth_token_challenge", queryParameters, isAuthRequired = false, parameters = null) - return send(request).map(sharedContext) { json -> + return send(request).map { json -> val challenge = json["challenge"] as? Map<*, *> ?: throw Error.PARSING_FAILED val base64EncodedCiphertext = challenge["ciphertext"] as? String ?: throw Error.PARSING_FAILED @@ -211,12 +207,12 @@ object OpenGroupAPIV2 { val headers = mapOf("Authorization" to authToken) val request = Request(verb = POST, room = room, server = server, endpoint = "claim_auth_token", parameters = parameters, headers = headers, isAuthRequired = false) - return send(request).map(sharedContext) { authToken } + return send(request).map { authToken } } fun deleteAuthToken(room: String, server: String): Promise { val request = Request(verb = DELETE, room = room, server = server, endpoint = "auth_token") - return send(request).map(sharedContext) { + return send(request).map { MessagingModuleConfiguration.shared.storage.removeAuthToken(room, server) } } @@ -226,14 +222,14 @@ object OpenGroupAPIV2 { val base64EncodedFile = encodeBytes(file) val parameters = mapOf("file" to base64EncodedFile) val request = Request(verb = POST, room = room, server = server, endpoint = "files", parameters = parameters) - return send(request).map(sharedContext) { json -> + return send(request).map { json -> json["result"] as? Long ?: throw Error.PARSING_FAILED } } fun download(file: Long, room: String, server: String): Promise { val request = Request(verb = GET, room = room, server = server, endpoint = "files/$file") - return send(request).map(sharedContext) { json -> + return send(request).map { json -> val base64EncodedFile = json["result"] as? String ?: throw Error.PARSING_FAILED decode(base64EncodedFile) ?: throw Error.PARSING_FAILED } @@ -243,7 +239,7 @@ object OpenGroupAPIV2 { val signedMessage = message.sign() ?: return Promise.ofFail(Error.SIGNING_FAILED) val jsonMessage = signedMessage.toJSON() val request = Request(verb = POST, room = room, server = server, endpoint = "messages", parameters = jsonMessage) - return send(request).map(sharedContext) { json -> + return send(request).map { json -> @Suppress("UNCHECKED_CAST") val rawMessage = json["message"] as? Map ?: throw Error.PARSING_FAILED OpenGroupMessageV2.fromJSON(rawMessage) ?: throw Error.PARSING_FAILED @@ -259,7 +255,7 @@ object OpenGroupAPIV2 { queryParameters += "from_server_id" to lastId.toString() } val request = Request(verb = GET, room = room, server = server, endpoint = "messages", queryParameters = queryParameters) - return send(request).map(sharedContext) { jsonList -> + return send(request).map { jsonList -> @Suppress("UNCHECKED_CAST") val rawMessages = jsonList["messages"] as? List> ?: throw Error.PARSING_FAILED val lastMessageServerId = storage.getLastMessageServerId(room, server) ?: 0 @@ -296,7 +292,7 @@ object OpenGroupAPIV2 { @JvmStatic fun deleteMessage(serverID: Long, room: String, server: String): Promise { val request = Request(verb = DELETE, room = room, server = server, endpoint = "messages/$serverID") - return send(request).map(sharedContext) { + return send(request).map { Log.d("Loki", "Deleted server message") } } @@ -308,7 +304,7 @@ object OpenGroupAPIV2 { queryParameters["from_server_id"] = last.toString() } val request = Request(verb = GET, room = room, server = server, endpoint = "deleted_messages", queryParameters = queryParameters) - return send(request).map(sharedContext) { json -> + return send(request).map { json -> val type = TypeFactory.defaultInstance().constructCollectionType(List::class.java, MessageDeletion::class.java) val idsAsString = JsonUtil.toJson(json["ids"]) val serverIDs = JsonUtil.fromJson>(idsAsString, type) ?: throw Error.PARSING_FAILED @@ -329,7 +325,7 @@ object OpenGroupAPIV2 { fun getModerators(room: String, server: String): Promise, Exception> { val request = Request(verb = GET, room = room, server = server, endpoint = "moderators") - return send(request).map(sharedContext) { json -> + return send(request).map { json -> @Suppress("UNCHECKED_CAST") val moderatorsJson = json["moderators"] as? List ?: throw Error.PARSING_FAILED val id = "$server.$room" @@ -342,14 +338,14 @@ object OpenGroupAPIV2 { fun ban(publicKey: String, room: String, server: String): Promise { val parameters = mapOf("public_key" to publicKey) val request = Request(verb = POST, room = room, server = server, endpoint = "block_list", parameters = parameters) - return send(request).map(sharedContext) { + return send(request).map { Log.d("Loki", "Banned user $publicKey from $server.$room") } } fun unban(publicKey: String, room: String, server: String): Promise { val request = Request(verb = DELETE, room = room, server = server, endpoint = "block_list/$publicKey") - return send(request).map(sharedContext) { + return send(request).map { Log.d("Loki", "Unbanned user $publicKey from $server.$room") } } @@ -380,7 +376,7 @@ object OpenGroupAPIV2 { } val request = Request(verb = POST, room = null, server = server, endpoint = "compact_poll", isAuthRequired = false, parameters = mapOf("requests" to requests)) // build a request for all rooms - return send(request = request).map(sharedContext) { json -> + return send(request = request).map { json -> val results = json["results"] as? List<*> ?: throw Error.PARSING_FAILED results.mapNotNull { roomJson -> @@ -462,7 +458,7 @@ object OpenGroupAPIV2 { fun getInfo(room: String, server: String): Promise { val request = Request(verb = GET, room = null, server = server, endpoint = "rooms/$room", isAuthRequired = false) - return send(request).map(sharedContext) { json -> + return send(request).map { json -> val rawRoom = json["room"] as? Map<*, *> ?: throw Error.PARSING_FAILED val id = rawRoom["id"] as? String ?: throw Error.PARSING_FAILED val name = rawRoom["name"] as? String ?: throw Error.PARSING_FAILED @@ -473,7 +469,7 @@ object OpenGroupAPIV2 { fun getAllRooms(server: String): Promise, Exception> { val request = Request(verb = GET, room = null, server = server, endpoint = "rooms", isAuthRequired = false) - return send(request).map(sharedContext) { json -> + return send(request).map { json -> val rawRooms = json["rooms"] as? List> ?: throw Error.PARSING_FAILED rawRooms.mapNotNull { val roomJson = it as? Map<*, *> ?: return@mapNotNull null @@ -487,7 +483,7 @@ object OpenGroupAPIV2 { fun getMemberCount(room: String, server: String): Promise { val request = Request(verb = GET, room = room, server = server, endpoint = "member_count") - return send(request).map(sharedContext) { json -> + return send(request).map { json -> val memberCount = json["member_count"] as? Long ?: throw Error.PARSING_FAILED val storage = MessagingModuleConfiguration.shared.storage storage.setUserCount(room, server, memberCount) diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroupHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroupHandler.kt index 427bf4b832..a7c6dd97f7 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroupHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSenderClosedGroupHandler.kt @@ -169,15 +169,24 @@ fun MessageSender.removeMembers(groupPublicKey: String, membersToRemove: List { diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt index 93a960e4fe..49ead00424 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt @@ -298,7 +298,8 @@ private fun MessageReceiver.handleClosedGroupEncryptionKeyPair(message: ClosedGr val storage = MessagingModuleConfiguration.shared.storage val senderPublicKey = message.sender ?: return val kind = message.kind!! as? ClosedGroupControlMessage.Kind.EncryptionKeyPair ?: return - val groupPublicKey = kind.publicKey?.toByteArray()?.toHexString() ?: message.groupPublicKey ?: return + var groupPublicKey = kind.publicKey?.toByteArray()?.toHexString() + if (groupPublicKey.isNullOrEmpty()) groupPublicKey = message.groupPublicKey ?: return val userPublicKey = storage.getUserPublicKey()!! val userKeyPair = storage.getUserX25519KeyPair() // Unwrap the message @@ -312,7 +313,7 @@ private fun MessageReceiver.handleClosedGroupEncryptionKeyPair(message: ClosedGr return } if (!group.admins.map { it.toString() }.contains(senderPublicKey)) { - Log.d("Loki", "Ignoring closed group encryption key pair from non-member.") + Log.d("Loki", "Ignoring closed group encryption key pair from non-admin.") return } // Find our wrapper and decrypt it if possible @@ -393,6 +394,7 @@ private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupCo val updateMembers = kind.members.map { it.toByteArray().toHexString() } val newMembers = members + updateMembers storage.updateMembers(groupID, newMembers.map { Address.fromSerialized(it) }) + // Notify the user if (userPublicKey == senderPublicKey) { // sender is a linked device @@ -415,6 +417,11 @@ private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupCo } } +/// Removes the given members from the group IF +/// • it wasn't the admin that was removed (that should happen through a `MEMBER_LEFT` message). +/// • the admin sent the message (only the admin can truly remove members). +/// If we're among the users that were removed, delete all encryption key pairs and the group public key, unsubscribe +/// from push notifications for this closed group, and remove the given members from the zombie list for this group. private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroupControlMessage) { val context = MessagingModuleConfiguration.shared.context val storage = MessagingModuleConfiguration.shared.storage @@ -428,7 +435,7 @@ private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroup return } if (!group.isActive) { - Log.d("Loki", "Ignoring closed group info message for inactive group") + Log.d("Loki", "Ignoring closed group info message for inactive group.") return } val name = group.title @@ -439,6 +446,18 @@ private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroup // Users that are part of this remove update val updateMembers = kind.members.map { it.toByteArray().toHexString() } + // Check that the admin wasn't removed + if (updateMembers.contains(admins.first())) { + Log.d("Loki", "Ignoring invalid closed group update.") + return + } + + // Check that the message was sent by the group admin + if (!admins.contains(senderPublicKey)) { + Log.d("Loki", "Ignoring invalid closed group update.") + return + } + if (!isValidGroupUpdate(group, message.sentTimestamp!!, senderPublicKey)) { return } // If admin leaves the group is disbanded val didAdminLeave = admins.any { it in updateMembers } @@ -455,25 +474,34 @@ private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroup if (didAdminLeave || wasCurrentUserRemoved) { disableLocalGroupAndUnsubscribe(groupPublicKey, groupID, userPublicKey) } else { - val isCurrentUserAdmin = admins.contains(userPublicKey) storage.updateMembers(groupID, newMembers.map { Address.fromSerialized(it) }) - if (isCurrentUserAdmin) { - MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey, newMembers) - } } + // update zombie members + val zombies = storage.getZombieMember(groupID) + storage.updateZombieMembers(groupID, zombies.minus(updateMembers).map { Address.fromSerialized(it) }) + val type = if (senderLeft) SignalServiceGroup.Type.QUIT else SignalServiceGroup.Type.MEMBER_REMOVED // Notify the user - if (userPublicKey == senderPublicKey) { - // sender is a linked device - val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID)) - storage.insertOutgoingInfoMessage(context, groupID, type, name, updateMembers, admins, threadID, message.sentTimestamp!!) - } else { - storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, type, name, updateMembers, admins, message.sentTimestamp!!) + // we don't display zombie members in the notification as users have already been notified when those members left + val notificationMembers = updateMembers.minus(zombies) + if (notificationMembers.isNotEmpty()) { + // no notification to display when only zombies have been removed + if (userPublicKey == senderPublicKey) { + // sender is a linked device + val threadID = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID)) + storage.insertOutgoingInfoMessage(context, groupID, type, name, notificationMembers, admins, threadID, message.sentTimestamp!!) + } else { + storage.insertIncomingInfoMessage(context, senderPublicKey, groupID, type, name, notificationMembers, admins, message.sentTimestamp!!) + } } } +/// If a regular member left: +/// • Mark them as a zombie (to be removed by the admin later). +/// If the admin left: +/// • Unsubscribe from PNs, delete the group public key, etc. as the group will be disbanded. private fun MessageReceiver.handleClosedGroupMemberLeft(message: ClosedGroupControlMessage) { val context = MessagingModuleConfiguration.shared.context val storage = MessagingModuleConfiguration.shared.storage @@ -506,11 +534,10 @@ private fun MessageReceiver.handleClosedGroupMemberLeft(message: ClosedGroupCont // admin left the group of linked device left the group disableLocalGroupAndUnsubscribe(groupPublicKey, groupID, userPublicKey) } else { - val isCurrentUserAdmin = admins.contains(userPublicKey) storage.updateMembers(groupID, updatedMemberList.map { Address.fromSerialized(it) }) - if (isCurrentUserAdmin) { - MessageSender.generateAndSendNewEncryptionKeyPair(groupPublicKey, updatedMemberList) - } + // update zombie members + val zombies = storage.getZombieMember(groupID) + storage.updateZombieMembers(groupID, zombies.plus(senderPublicKey).map { Address.fromSerialized(it) }) } // Notify the user if (userLeft) { diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/ClosedGroupPoller.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/ClosedGroupPoller.kt index 69a9eaa5de..b9093e94cd 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/ClosedGroupPoller.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/ClosedGroupPoller.kt @@ -7,10 +7,8 @@ import nl.komponents.kovenant.functional.map import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.jobs.JobQueue import org.session.libsession.messaging.jobs.MessageReceiveJob -import org.session.libsession.messaging.utilities.MessageWrapper import org.session.libsession.snode.SnodeAPI import org.session.libsignal.service.loki.utilities.getRandomElementOrNull -import org.session.libsignal.utilities.Base64 import org.session.libsignal.utilities.logging.Log import org.session.libsignal.utilities.successBackground @@ -71,11 +69,8 @@ class ClosedGroupPoller { // ignore inactive group's messages return@successBackground } - messages.forEach { message -> - val rawMessageAsJSON = message as? Map<*, *> - val base64EncodedData = rawMessageAsJSON?.get("data") as? String - val data = base64EncodedData?.let { Base64.decode(it) } ?: return@forEach - val job = MessageReceiveJob(MessageWrapper.unwrap(data).toByteArray(), false) + messages.forEach { envelope -> + val job = MessageReceiveJob(envelope.toByteArray(), false) JobQueue.shared.add(job) } } diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt index e2754b4090..805bac8a8c 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/pollers/Poller.kt @@ -5,11 +5,9 @@ import nl.komponents.kovenant.functional.bind import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.jobs.JobQueue import org.session.libsession.messaging.jobs.MessageReceiveJob -import org.session.libsession.messaging.utilities.MessageWrapper import org.session.libsession.snode.SnodeAPI import org.session.libsession.snode.SnodeModule import org.session.libsignal.service.loki.Snode -import org.session.libsignal.utilities.Base64 import org.session.libsignal.utilities.logging.Log import java.security.SecureRandom import java.util.* diff --git a/libsession/src/main/java/org/session/libsession/messaging/utilities/DotNetAPI.kt b/libsession/src/main/java/org/session/libsession/messaging/utilities/DotNetAPI.kt index 95c663e3af..e93ed936e4 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/utilities/DotNetAPI.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/utilities/DotNetAPI.kt @@ -20,9 +20,10 @@ import org.session.libsignal.service.internal.push.ProfileAvatarData import org.session.libsignal.service.internal.push.PushAttachmentData import org.session.libsignal.service.internal.push.http.DigestingRequestBody import org.session.libsignal.service.internal.push.http.ProfileCipherOutputStreamFactory -import org.session.libsignal.service.loki.api.utilities.HTTP -import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded -import org.session.libsignal.service.loki.utilities.retryIfNeeded +import org.session.libsignal.utilities.Hex +import org.session.libsignal.utilities.JsonUtil +import org.session.libsignal.service.loki.HTTP +import org.session.libsignal.service.loki.utilities.* import org.session.libsignal.utilities.* import org.session.libsignal.utilities.Base64 import org.session.libsignal.utilities.logging.Log diff --git a/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt b/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt index e6c969a272..086b911933 100644 --- a/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt +++ b/libsession/src/main/java/org/session/libsession/snode/OnionRequestAPI.kt @@ -12,11 +12,13 @@ import org.session.libsignal.utilities.logging.Log import org.session.libsignal.utilities.Base64 import org.session.libsignal.utilities.* import org.session.libsignal.service.loki.Snode -import org.session.libsignal.service.loki.api.utilities.* +import org.session.libsignal.service.loki.* import org.session.libsession.utilities.AESGCM.EncryptionResult import org.session.libsession.utilities.getBodyForOnionRequest import org.session.libsession.utilities.getHeadersForOnionRequest -import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol +import org.session.libsignal.service.loki.Broadcaster +import org.session.libsignal.service.loki.HTTP +import org.session.libsignal.service.loki.LokiAPIDatabaseProtocol import org.session.libsignal.service.loki.utilities.* private typealias Path = List diff --git a/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt b/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt index 09f99fc2d9..1eec0c8e0a 100644 --- a/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt +++ b/libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt @@ -10,9 +10,9 @@ import org.session.libsession.messaging.utilities.MessageWrapper import org.session.libsession.snode.utilities.getRandomElement import org.session.libsignal.service.internal.push.SignalServiceProtos import org.session.libsignal.service.loki.Snode -import org.session.libsignal.service.loki.api.utilities.HTTP -import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol -import org.session.libsignal.service.loki.utilities.Broadcaster +import org.session.libsignal.service.loki.HTTP +import org.session.libsignal.service.loki.LokiAPIDatabaseProtocol +import org.session.libsignal.service.loki.Broadcaster import org.session.libsignal.service.loki.utilities.prettifiedDescription import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded import org.session.libsignal.service.loki.utilities.retryIfNeeded diff --git a/libsession/src/main/java/org/session/libsession/snode/SnodeModule.kt b/libsession/src/main/java/org/session/libsession/snode/SnodeModule.kt index 95613ffda2..0d9381ab95 100644 --- a/libsession/src/main/java/org/session/libsession/snode/SnodeModule.kt +++ b/libsession/src/main/java/org/session/libsession/snode/SnodeModule.kt @@ -1,7 +1,7 @@ package org.session.libsession.snode -import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol -import org.session.libsignal.service.loki.utilities.Broadcaster +import org.session.libsignal.service.loki.LokiAPIDatabaseProtocol +import org.session.libsignal.service.loki.Broadcaster class SnodeModule(val storage: LokiAPIDatabaseProtocol, val broadcaster: Broadcaster) { diff --git a/libsession/src/main/java/org/session/libsession/utilities/mentions/Mention.kt b/libsession/src/main/java/org/session/libsession/utilities/mentions/Mention.kt index 7900439d57..e69de29bb2 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/mentions/Mention.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/mentions/Mention.kt @@ -1,3 +0,0 @@ -package org.session.libsession.utilities.mentions - -data class Mention(val publicKey: String, val displayName: String) diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java b/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java index a8c2ca0bd9..5e425464ea 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java @@ -22,7 +22,6 @@ import org.session.libsignal.service.api.messages.SignalServiceEnvelope; import org.session.libsignal.service.api.messages.SignalServiceGroup; import org.session.libsignal.service.api.messages.SignalServiceReceiptMessage; import org.session.libsignal.service.api.messages.SignalServiceTypingMessage; -import org.session.libsignal.service.api.messages.shared.SharedContact; import org.session.libsignal.service.api.push.SignalServiceAddress; import org.session.libsignal.service.internal.push.PushTransportDetails; import org.session.libsignal.service.internal.push.SignalServiceProtos; @@ -34,7 +33,7 @@ import org.session.libsignal.service.internal.push.SignalServiceProtos.ReceiptMe import org.session.libsignal.service.internal.push.SignalServiceProtos.TypingMessage; import org.session.libsignal.service.loki.api.crypto.SessionProtocol; import org.session.libsignal.service.loki.api.crypto.SessionProtocolUtilities; -import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol; +import org.session.libsignal.service.loki.LokiAPIDatabaseProtocol; import java.util.ArrayList; import java.util.LinkedList; diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/messages/shared/SharedContact.java b/libsignal/src/main/java/org/session/libsignal/service/api/messages/shared/SharedContact.java index 75ee56835d..6993eb8189 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/messages/shared/SharedContact.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/messages/shared/SharedContact.java @@ -1,6 +1,5 @@ package org.session.libsignal.service.api.messages.shared; - import org.session.libsignal.libsignal.util.guava.Optional; import org.session.libsignal.service.api.messages.SignalServiceAttachment; diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Broadcaster.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/Broadcaster.kt similarity index 66% rename from libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Broadcaster.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/Broadcaster.kt index 17106c00b8..a251b89459 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Broadcaster.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/Broadcaster.kt @@ -1,4 +1,4 @@ -package org.session.libsignal.service.loki.utilities +package org.session.libsignal.service.loki interface Broadcaster { diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/api/utilities/HTTP.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/HTTP.kt similarity index 98% rename from libsignal/src/main/java/org/session/libsignal/service/loki/api/utilities/HTTP.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/HTTP.kt index 29d1cddb6e..11e7ed6154 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/api/utilities/HTTP.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/HTTP.kt @@ -1,4 +1,4 @@ -package org.session.libsignal.service.loki.api.utilities +package org.session.libsignal.service.loki import okhttp3.* import org.session.libsignal.utilities.logging.Log diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/utilities/HexEncoding.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/HexEncoding.kt similarity index 100% rename from libsignal/src/main/java/org/session/libsignal/service/loki/utilities/HexEncoding.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/HexEncoding.kt diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiAPIDatabaseProtocol.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/LokiAPIDatabaseProtocol.kt similarity index 97% rename from libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiAPIDatabaseProtocol.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/LokiAPIDatabaseProtocol.kt index 53c1c70984..da97eefb15 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiAPIDatabaseProtocol.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/LokiAPIDatabaseProtocol.kt @@ -1,4 +1,4 @@ -package org.session.libsignal.service.loki.database +package org.session.libsignal.service.loki import org.session.libsignal.libsignal.ecc.ECKeyPair import org.session.libsignal.service.loki.Snode diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiMessageDatabaseProtocol.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/LokiMessageDatabaseProtocol.kt similarity index 78% rename from libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiMessageDatabaseProtocol.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/LokiMessageDatabaseProtocol.kt index 0a279bc1b7..3f4c21e341 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiMessageDatabaseProtocol.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/LokiMessageDatabaseProtocol.kt @@ -1,4 +1,4 @@ -package org.session.libsignal.service.loki.database +package org.session.libsignal.service.loki interface LokiMessageDatabaseProtocol { diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiOpenGroupDatabaseProtocol.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/LokiOpenGroupDatabaseProtocol.kt similarity index 76% rename from libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiOpenGroupDatabaseProtocol.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/LokiOpenGroupDatabaseProtocol.kt index 5380c1a8fe..4c983e33fc 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiOpenGroupDatabaseProtocol.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/LokiOpenGroupDatabaseProtocol.kt @@ -1,4 +1,4 @@ -package org.session.libsignal.service.loki.database +package org.session.libsignal.service.loki interface LokiOpenGroupDatabaseProtocol { diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiUserDatabaseProtocol.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/LokiUserDatabaseProtocol.kt similarity index 81% rename from libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiUserDatabaseProtocol.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/LokiUserDatabaseProtocol.kt index 6879ee893a..b4428a4edf 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/database/LokiUserDatabaseProtocol.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/LokiUserDatabaseProtocol.kt @@ -1,4 +1,4 @@ -package org.session.libsignal.service.loki.database +package org.session.libsignal.service.loki interface LokiUserDatabaseProtocol { diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/Mention.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/Mention.kt new file mode 100644 index 0000000000..0dd2165854 --- /dev/null +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/Mention.kt @@ -0,0 +1,3 @@ +package org.session.libsignal.service.loki + +data class Mention(val publicKey: String, val displayName: String) diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/crypto/MnemonicCodec.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/MnemonicCodec.kt similarity index 97% rename from libsignal/src/main/java/org/session/libsignal/service/loki/crypto/MnemonicCodec.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/MnemonicCodec.kt index b3c15dd132..122354f33d 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/crypto/MnemonicCodec.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/MnemonicCodec.kt @@ -1,6 +1,5 @@ -package org.session.libsignal.service.loki.crypto +package org.session.libsignal.service.loki -import java.io.File import java.util.zip.CRC32 /** @@ -95,8 +94,10 @@ class MnemonicCodec(private val loadFileContents: (String) -> String) { var result = "" val n = truncatedWordSet.size.toLong() // Check preconditions - if (words.size < 12) { throw DecodingError.InputTooShort } - if (words.size % 3 == 0) { throw DecodingError.MissingLastWord } + if (words.size < 12) { throw DecodingError.InputTooShort + } + if (words.size % 3 == 0) { throw DecodingError.MissingLastWord + } // Get checksum word val checksumWord = words.removeAt(words.lastIndex) // Decode @@ -106,7 +107,8 @@ class MnemonicCodec(private val loadFileContents: (String) -> String) { val w2 = truncatedWordSet.indexOf(words[chunkStartIndex + 1].substring(0 until prefixLength)) val w3 = truncatedWordSet.indexOf(words[chunkStartIndex + 2].substring(0 until prefixLength)) val x = w1 + n * ((n - w1 + w2) % n) + n * n * ((n - w2 + w3) % n) - if (x % n != w1.toLong()) { throw DecodingError.Generic } + if (x % n != w1.toLong()) { throw DecodingError.Generic + } val string = "0000000" + x.toString(16) result += swap(string.substring(string.length - 8 until string.length)) } catch (e: Exception) { @@ -116,7 +118,8 @@ class MnemonicCodec(private val loadFileContents: (String) -> String) { // Verify checksum val checksumIndex = determineChecksumIndex(words, prefixLength) val expectedChecksumWord = words[checksumIndex] - if (expectedChecksumWord.substring(0 until prefixLength) != checksumWord.substring(0 until prefixLength)) { throw DecodingError.VerificationFailed } + if (expectedChecksumWord.substring(0 until prefixLength) != checksumWord.substring(0 until prefixLength)) { throw DecodingError.VerificationFailed + } // Return return result } diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/utilities/PlaintextOutputStreamFactory.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/PlaintextOutputStreamFactory.kt similarity index 92% rename from libsignal/src/main/java/org/session/libsignal/service/loki/utilities/PlaintextOutputStreamFactory.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/PlaintextOutputStreamFactory.kt index b913289b08..412f66458f 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/utilities/PlaintextOutputStreamFactory.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/PlaintextOutputStreamFactory.kt @@ -1,4 +1,4 @@ -package org.session.libsignal.service.loki.utilities +package org.session.libsignal.service.loki import org.session.libsignal.service.api.crypto.DigestingOutputStream import org.session.libsignal.service.internal.push.http.OutputStreamFactory diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/utilities/PrettifiedDescription.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/PrettifiedDescription.kt similarity index 100% rename from libsignal/src/main/java/org/session/libsignal/service/loki/utilities/PrettifiedDescription.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/PrettifiedDescription.kt diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Random.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/Random.kt similarity index 100% rename from libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Random.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/Random.kt diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Reflection.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/Reflection.kt similarity index 100% rename from libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Reflection.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/Reflection.kt diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Retrying.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/Retrying.kt similarity index 100% rename from libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Retrying.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/Retrying.kt diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/api/crypto/SessionProtocol.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/SessionProtocol.kt similarity index 97% rename from libsignal/src/main/java/org/session/libsignal/service/loki/api/crypto/SessionProtocol.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/SessionProtocol.kt index 3851919052..201ad4e85d 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/api/crypto/SessionProtocol.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/SessionProtocol.kt @@ -1,7 +1,7 @@ package org.session.libsignal.service.loki.api.crypto import org.session.libsignal.libsignal.ecc.ECKeyPair -import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol +import org.session.libsignal.service.loki.LokiAPIDatabaseProtocol interface SessionProtocol { diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/api/SignalMessageInfo.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/SignalMessageInfo.kt similarity index 88% rename from libsignal/src/main/java/org/session/libsignal/service/loki/api/SignalMessageInfo.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/SignalMessageInfo.kt index 5b41d26a5f..f5e20f4168 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/api/SignalMessageInfo.kt +++ b/libsignal/src/main/java/org/session/libsignal/service/loki/SignalMessageInfo.kt @@ -1,4 +1,4 @@ -package org.session.libsignal.service.loki.api +package org.session.libsignal.service.loki import org.session.libsignal.service.internal.push.SignalServiceProtos diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Trimming.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/Trimming.kt similarity index 100% rename from libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Trimming.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/Trimming.kt diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Validation.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/Validation.kt similarity index 100% rename from libsignal/src/main/java/org/session/libsignal/service/loki/utilities/Validation.kt rename to libsignal/src/main/java/org/session/libsignal/service/loki/Validation.kt diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/api/utilities/OKHTTPUtilities.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/api/utilities/OKHTTPUtilities.kt deleted file mode 100644 index 442edc5549..0000000000 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/api/utilities/OKHTTPUtilities.kt +++ /dev/null @@ -1,49 +0,0 @@ -package org.session.libsignal.service.loki.api.utilities - -import okhttp3.MultipartBody -import okhttp3.Request -import okio.Buffer -import org.session.libsignal.utilities.Base64 -import java.io.IOException -import java.util.* - -internal fun Request.getHeadersForOnionRequest(): Map { - val result = mutableMapOf() - val contentType = body()?.contentType() - if (contentType != null) { - result["content-type"] = contentType.toString() - } - val headers = headers() - for (name in headers.names()) { - val value = headers.get(name) - if (value != null) { - if (value.toLowerCase(Locale.US) == "true" || value.toLowerCase(Locale.US) == "false") { - result[name] = value.toBoolean() - } else if (value.toIntOrNull() != null) { - result[name] = value.toInt() - } else { - result[name] = value - } - } - } - return result -} - -internal fun Request.getBodyForOnionRequest(): Any? { - try { - val copyOfThis = newBuilder().build() - val buffer = Buffer() - val body = copyOfThis.body() ?: return null - body.writeTo(buffer) - val bodyAsData = buffer.readByteArray() - if (body is MultipartBody) { - val base64EncodedBody: String = Base64.encodeBytes(bodyAsData) - return mapOf( "fileUpload" to base64EncodedBody ) - } else { - val charset = body.contentType()?.charset() ?: Charsets.UTF_8 - return bodyAsData?.toString(charset) - } - } catch (e: IOException) { - return null - } -} diff --git a/libsignal/src/main/java/org/session/libsignal/utilities/JsonUtil.java b/libsignal/src/main/java/org/session/libsignal/utilities/JsonUtil.java index 71ac9d548f..046afeb34f 100644 --- a/libsignal/src/main/java/org/session/libsignal/utilities/JsonUtil.java +++ b/libsignal/src/main/java/org/session/libsignal/utilities/JsonUtil.java @@ -64,7 +64,7 @@ public class JsonUtil { return objectMapper.writeValueAsString(object); } - public static String toJson(Object object) { + public static String toJson(Object object) { try { return objectMapper.writeValueAsString(object); } catch (JsonProcessingException e) { @@ -73,32 +73,11 @@ public class JsonUtil { } } - public static class IdentityKeySerializer extends JsonSerializer { - @Override - public void serialize(IdentityKey value, JsonGenerator gen, SerializerProvider serializers) - throws IOException - { - gen.writeString(Base64.encodeBytesWithoutPadding(value.serialize())); - } - } - - public static class IdentityKeyDeserializer extends JsonDeserializer { - @Override - public IdentityKey deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - try { - return new IdentityKey(Base64.decodeWithoutPadding(p.getValueAsString()), 0); - } catch (InvalidKeyException e) { - throw new IOException(e); - } - } - } - public static ObjectMapper getMapper() { return objectMapper; } public static class SaneJSONObject { - private final JSONObject delegate; public SaneJSONObject(JSONObject delegate) { diff --git a/libsignal/src/main/java/org/session/libsignal/utilities/PromiseUtilities.kt b/libsignal/src/main/java/org/session/libsignal/utilities/PromiseUtilities.kt index 8fe7ce7355..530d432d57 100644 --- a/libsignal/src/main/java/org/session/libsignal/utilities/PromiseUtilities.kt +++ b/libsignal/src/main/java/org/session/libsignal/utilities/PromiseUtilities.kt @@ -1,25 +1,11 @@ @file:JvmName("PromiseUtilities") package org.session.libsignal.utilities -import nl.komponents.kovenant.Context -import nl.komponents.kovenant.Kovenant import nl.komponents.kovenant.Promise import nl.komponents.kovenant.deferred -import nl.komponents.kovenant.jvm.asDispatcher import org.session.libsignal.utilities.logging.Log -import java.util.concurrent.Executors import java.util.concurrent.TimeoutException -fun Kovenant.createContext(): Context { - return createContext { - callbackContext.dispatcher = Executors.newSingleThreadExecutor().asDispatcher() - workerContext.dispatcher = ThreadUtils.executorPool.asDispatcher() - multipleCompletion = { v1, v2 -> - Log.d("Loki", "Promise resolved more than once (first with $v1, then with $v2); ignoring $v2.") - } - } -} - fun Promise.get(defaultValue: V): V { return try { get() diff --git a/libsignal/src/main/java/org/session/libsignal/utilities/ThreadUtils.kt b/libsignal/src/main/java/org/session/libsignal/utilities/ThreadUtils.kt index 1ad277f345..9436a54832 100644 --- a/libsignal/src/main/java/org/session/libsignal/utilities/ThreadUtils.kt +++ b/libsignal/src/main/java/org/session/libsignal/utilities/ThreadUtils.kt @@ -3,7 +3,6 @@ package org.session.libsignal.utilities import java.util.concurrent.* object ThreadUtils { - val executorPool = Executors.newCachedThreadPool() @JvmStatic @@ -17,10 +16,8 @@ object ThreadUtils { @JvmStatic fun newDynamicSingleThreadedExecutor(): ExecutorService { - val executor = ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, - LinkedBlockingQueue()) + val executor = ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, LinkedBlockingQueue()) executor.allowCoreThreadTimeOut(true) return executor } - } \ No newline at end of file