mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-03 11:22:21 +00:00
Merge branch 'dev' into version
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
package org.thoughtcrime.securesms.loki
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
import org.thoughtcrime.securesms.jobmanager.Data
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.jobs.BaseJob
|
||||
import org.thoughtcrime.securesms.logging.Log
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage
|
||||
import org.whispersystems.signalservice.loki.api.LokiPublicChat
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
class MultiDeviceOpenGroupUpdateJob private constructor(parameters: Parameters) : BaseJob(parameters), InjectableType {
|
||||
|
||||
companion object {
|
||||
const val KEY = "MultiDeviceOpenGroupUpdateJob"
|
||||
}
|
||||
|
||||
@Inject
|
||||
lateinit var messageSender: SignalServiceMessageSender
|
||||
|
||||
constructor() : this(Parameters.Builder()
|
||||
.addConstraint(NetworkConstraint.KEY)
|
||||
.setQueue("MultiDeviceOpenGroupUpdateJob")
|
||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
||||
.setMaxAttempts(Parameters.UNLIMITED)
|
||||
.build())
|
||||
|
||||
override fun getFactoryKey(): String { return KEY }
|
||||
|
||||
override fun serialize(): Data { return Data.EMPTY }
|
||||
|
||||
@Throws(Exception::class)
|
||||
public override fun onRun() {
|
||||
if (!TextSecurePreferences.isMultiDevice(context)) {
|
||||
Log.d("Loki", "Not multi device; aborting...")
|
||||
return
|
||||
}
|
||||
|
||||
val openGroups = mutableListOf<LokiPublicChat>()
|
||||
DatabaseFactory.getGroupDatabase(context).groups.use { reader ->
|
||||
while (true) {
|
||||
val record = reader.next ?: return@use
|
||||
if (!record.isPublicChat) { continue; }
|
||||
|
||||
val threadID = GroupManager.getThreadIdFromGroupId(record.encodedId, context)
|
||||
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
||||
if (openGroup != null) {
|
||||
openGroups.add(openGroup)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (openGroups.size > 0) {
|
||||
messageSender.sendMessage(0, SignalServiceSyncMessage.forOpenGroups(openGroups),
|
||||
UnidentifiedAccessUtil.getAccessForSync(context))
|
||||
} else {
|
||||
Log.d("Loki", "No open groups to sync.")
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onShouldRetry(exception: Exception): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onCanceled() { }
|
||||
|
||||
class Factory : Job.Factory<MultiDeviceOpenGroupUpdateJob> {
|
||||
|
||||
override fun create(parameters: Parameters, data: Data): MultiDeviceOpenGroupUpdateJob {
|
||||
return MultiDeviceOpenGroupUpdateJob(parameters)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,12 @@ fun checkIsRevokedSlaveDevice(context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
fun updateDeviceLinksOnServer(context: Context) {
|
||||
val hexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
val deviceLinks = DatabaseFactory.getLokiAPIDatabase(context).getDeviceLinks(hexEncodedPublicKey)
|
||||
LokiFileServerAPI.shared.setDeviceLinks(deviceLinks)
|
||||
}
|
||||
|
||||
fun getAllDeviceFriendRequestStatuses(context: Context, hexEncodedPublicKey: String): Promise<Map<String, LokiThreadFriendRequestStatus>, Exception> {
|
||||
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
return LokiDeviceLinkUtilities.getAllLinkedDeviceHexEncodedPublicKeys(hexEncodedPublicKey).map { keys ->
|
||||
|
||||
@@ -194,7 +194,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
|
||||
private fun openConversation(thread: ThreadRecord) {
|
||||
val intent = Intent(this, ConversationActivity::class.java)
|
||||
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, thread.recipient.getAddress())
|
||||
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, thread.recipient.address)
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, thread.threadId)
|
||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, thread.distributionType)
|
||||
intent.putExtra(ConversationActivity.TIMING_EXTRA, System.currentTimeMillis())
|
||||
@@ -255,9 +255,9 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
val dialog = AlertDialog.Builder(activity)
|
||||
dialog.setMessage(dialogMessage)
|
||||
dialog.setPositiveButton(R.string.yes) { _, _ ->
|
||||
val isGroup = recipient.isGroupRecipient
|
||||
val isClosedGroup = recipient.address.isSignalGroup
|
||||
// Send a leave group message if this is an active closed group
|
||||
if (isGroup && DatabaseFactory.getGroupDatabase(activity).isActive(recipient.address.toGroupString())) {
|
||||
if (isClosedGroup && DatabaseFactory.getGroupDatabase(activity).isActive(recipient.address.toGroupString())) {
|
||||
if (!GroupUtil.leaveGroup(activity, recipient)) {
|
||||
Toast.makeText(activity, "Couldn't leave group", Toast.LENGTH_LONG).show()
|
||||
clearView(activity.recyclerView, viewHolder)
|
||||
@@ -267,10 +267,11 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
// Archive the conversation and then delete it after 10 seconds (the case where the
|
||||
// app was closed before the conversation could be deleted is handled in onCreate)
|
||||
threadDatabase.archiveConversation(threadID)
|
||||
val delay = if (isClosedGroup) 10000L else 1000L
|
||||
val handler = Handler()
|
||||
handler.postDelayed(deleteThread, 10000)
|
||||
handler.postDelayed(deleteThread, delay)
|
||||
// Notify the user
|
||||
val toastMessage = if (isGroup) R.string.MessageRecord_left_group else R.string.activity_home_conversation_deleted_message
|
||||
val toastMessage = if (recipient.isGroupRecipient) R.string.MessageRecord_left_group else R.string.activity_home_conversation_deleted_message
|
||||
Toast.makeText(activity, toastMessage, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
dialog.setNegativeButton(R.string.no) { _, _ ->
|
||||
|
||||
@@ -16,14 +16,12 @@ import kotlinx.android.synthetic.main.fragment_enter_chat_url.*
|
||||
import network.loki.messenger.R
|
||||
import nl.komponents.kovenant.ui.failUi
|
||||
import nl.komponents.kovenant.ui.successUi
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.OpenGroupUtilities
|
||||
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragment
|
||||
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragmentDelegate
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.sms.MessageSender
|
||||
|
||||
class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
|
||||
private val adapter = JoinPublicChatActivityAdapter(this)
|
||||
@@ -68,19 +66,11 @@ class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCode
|
||||
return Toast.makeText(this, "Invalid URL", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
showLoader()
|
||||
val application = ApplicationContext.getInstance(this)
|
||||
|
||||
val channel: Long = 1
|
||||
val displayName = TextSecurePreferences.getProfileName(this)
|
||||
val lokiPublicChatAPI = application.lokiPublicChatAPI!!
|
||||
application.lokiPublicChatManager.addChat(url, channel).successUi {
|
||||
DatabaseFactory.getLokiAPIDatabase(this).removeLastMessageServerID(channel, url)
|
||||
DatabaseFactory.getLokiAPIDatabase(this).removeLastDeletionServerID(channel, url)
|
||||
lokiPublicChatAPI.getMessages(channel, url)
|
||||
lokiPublicChatAPI.setDisplayName(displayName, url)
|
||||
lokiPublicChatAPI.join(channel, url)
|
||||
val profileKey: ByteArray = ProfileKeyUtil.getProfileKey(this)
|
||||
val profileUrl: String? = TextSecurePreferences.getProfileAvatarUrl(this)
|
||||
lokiPublicChatAPI.setProfilePicture(url, profileKey, profileUrl)
|
||||
OpenGroupUtilities.addGroup(this, url, channel).success {
|
||||
MessageSender.syncAllOpenGroups(this)
|
||||
}.successUi {
|
||||
finish()
|
||||
}.failUi {
|
||||
hideLoader()
|
||||
|
||||
@@ -114,7 +114,6 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
||||
}
|
||||
|
||||
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
||||
LokiFileServerAPI.shared.addDeviceLink(deviceLink)
|
||||
TextSecurePreferences.setMasterHexEncodedPublicKey(this, deviceLink.masterHexEncodedPublicKey)
|
||||
val intent = Intent(this, HomeActivity::class.java)
|
||||
show(intent)
|
||||
|
||||
@@ -12,6 +12,7 @@ import android.view.View
|
||||
import android.widget.Toast
|
||||
import kotlinx.android.synthetic.main.activity_linked_devices.*
|
||||
import network.loki.messenger.R
|
||||
import nl.komponents.kovenant.functional.bind
|
||||
import nl.komponents.kovenant.ui.failUi
|
||||
import nl.komponents.kovenant.ui.successUi
|
||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||
@@ -23,6 +24,7 @@ import org.thoughtcrime.securesms.loki.signAndSendDeviceLinkMessage
|
||||
import org.thoughtcrime.securesms.sms.MessageSender
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.loki.api.DeviceLink
|
||||
import org.whispersystems.signalservice.loki.api.LokiAPI
|
||||
import org.whispersystems.signalservice.loki.api.LokiFileServerAPI
|
||||
import java.util.*
|
||||
import kotlin.concurrent.schedule
|
||||
@@ -143,23 +145,21 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager
|
||||
}
|
||||
|
||||
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
||||
LokiFileServerAPI.shared.addDeviceLink(deviceLink).success {
|
||||
signAndSendDeviceLinkMessage(this, deviceLink).successUi {
|
||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||
}.success {
|
||||
TextSecurePreferences.setMultiDevice(this, true)
|
||||
Timer().schedule(4000) {
|
||||
MessageSender.syncAllGroups(this@LinkedDevicesActivity)
|
||||
MessageSender.syncAllContacts(this@LinkedDevicesActivity, Address.fromSerialized(deviceLink.slaveHexEncodedPublicKey))
|
||||
}
|
||||
}.failUi {
|
||||
Toast.makeText(this, "Couldn't link device", Toast.LENGTH_LONG).show()
|
||||
}.fail {
|
||||
LokiFileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey)
|
||||
LokiFileServerAPI.shared.addDeviceLink(deviceLink).bind(LokiAPI.sharedWorkContext) {
|
||||
signAndSendDeviceLinkMessage(this, deviceLink)
|
||||
}.successUi {
|
||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||
}.success {
|
||||
TextSecurePreferences.setMultiDevice(this, true)
|
||||
Timer().schedule(4000) {
|
||||
MessageSender.syncAllGroups(this@LinkedDevicesActivity)
|
||||
MessageSender.syncAllContacts(this@LinkedDevicesActivity, Address.fromSerialized(deviceLink.slaveHexEncodedPublicKey))
|
||||
MessageSender.syncAllOpenGroups(this@LinkedDevicesActivity)
|
||||
}
|
||||
}.failUi {
|
||||
}.fail {
|
||||
LokiFileServerAPI.shared.removeDeviceLink(deviceLink) // If this fails we have a problem
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey)
|
||||
}.failUi {
|
||||
Toast.makeText(this, "Couldn't link device", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.utilities
|
||||
|
||||
import android.content.Context
|
||||
import nl.komponents.kovenant.Promise
|
||||
import nl.komponents.kovenant.then
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.loki.api.LokiPublicChat
|
||||
|
||||
object OpenGroupUtilities {
|
||||
|
||||
@JvmStatic fun addGroup(context: Context, url: String, channel: Long): Promise<LokiPublicChat, Exception> {
|
||||
// Check for an existing group
|
||||
val groupID = LokiPublicChat.getId(channel, url)
|
||||
val threadID = GroupManager.getPublicChatThreadId(groupID, context)
|
||||
val openGroup = DatabaseFactory.getLokiThreadDatabase(context).getPublicChat(threadID)
|
||||
if (openGroup != null) { return Promise.of(openGroup) }
|
||||
// Add the new group
|
||||
val application = ApplicationContext.getInstance(context)
|
||||
val displayName = TextSecurePreferences.getProfileName(context)
|
||||
val lokiPublicChatAPI = application.lokiPublicChatAPI ?: throw Error("LokiPublicChatAPI is not initialized.")
|
||||
return application.lokiPublicChatManager.addChat(url, channel).then { group ->
|
||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastMessageServerID(channel, url)
|
||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(channel, url)
|
||||
lokiPublicChatAPI.getMessages(channel, url)
|
||||
lokiPublicChatAPI.setDisplayName(displayName, url)
|
||||
lokiPublicChatAPI.join(channel, url)
|
||||
val profileKey: ByteArray = ProfileKeyUtil.getProfileKey(context)
|
||||
val profileUrl: String? = TextSecurePreferences.getProfileAvatarUrl(context)
|
||||
lokiPublicChatAPI.setProfilePicture(url, profileKey, profileUrl)
|
||||
group
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user