kopia lustrzana https://github.com/ryukoposting/Signal-Android
211 wiersze
7.5 KiB
Kotlin
211 wiersze
7.5 KiB
Kotlin
package org.thoughtcrime.securesms.components.settings.conversation
|
|
|
|
import android.content.Context
|
|
import android.database.Cursor
|
|
import androidx.annotation.WorkerThread
|
|
import androidx.lifecycle.LiveData
|
|
import io.reactivex.rxjava3.core.Observable
|
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
|
import org.signal.core.util.concurrent.SignalExecutors
|
|
import org.signal.core.util.logging.Log
|
|
import org.signal.storageservice.protos.groups.local.DecryptedGroup
|
|
import org.signal.storageservice.protos.groups.local.DecryptedPendingMember
|
|
import org.thoughtcrime.securesms.contacts.sync.ContactDiscovery
|
|
import org.thoughtcrime.securesms.database.GroupTable
|
|
import org.thoughtcrime.securesms.database.MediaTable
|
|
import org.thoughtcrime.securesms.database.SignalDatabase
|
|
import org.thoughtcrime.securesms.database.model.IdentityRecord
|
|
import org.thoughtcrime.securesms.database.model.StoryViewState
|
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
|
import org.thoughtcrime.securesms.groups.GroupId
|
|
import org.thoughtcrime.securesms.groups.GroupProtoUtil
|
|
import org.thoughtcrime.securesms.groups.LiveGroup
|
|
import org.thoughtcrime.securesms.groups.v2.GroupAddMembersResult
|
|
import org.thoughtcrime.securesms.groups.v2.GroupManagementRepository
|
|
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
|
import org.thoughtcrime.securesms.recipients.Recipient
|
|
import org.thoughtcrime.securesms.recipients.RecipientId
|
|
import org.thoughtcrime.securesms.recipients.RecipientUtil
|
|
import org.thoughtcrime.securesms.util.FeatureFlags
|
|
import java.io.IOException
|
|
import java.util.Optional
|
|
|
|
private val TAG = Log.tag(ConversationSettingsRepository::class.java)
|
|
|
|
class ConversationSettingsRepository(
|
|
private val context: Context,
|
|
private val groupManagementRepository: GroupManagementRepository = GroupManagementRepository(context)
|
|
) {
|
|
|
|
@WorkerThread
|
|
fun getThreadMedia(threadId: Long): Optional<Cursor> {
|
|
return if (threadId <= 0) {
|
|
Optional.empty()
|
|
} else {
|
|
Optional.of(SignalDatabase.media.getGalleryMediaForThread(threadId, MediaTable.Sorting.Newest))
|
|
}
|
|
}
|
|
|
|
fun getStoryViewState(groupId: GroupId): Observable<StoryViewState> {
|
|
return Observable.fromCallable {
|
|
SignalDatabase.recipients.getByGroupId(groupId)
|
|
}.flatMap {
|
|
StoryViewState.getForRecipientId(it.get())
|
|
}.observeOn(Schedulers.io())
|
|
}
|
|
|
|
fun getThreadId(recipientId: RecipientId, consumer: (Long) -> Unit) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
consumer(SignalDatabase.threads.getThreadIdIfExistsFor(recipientId))
|
|
}
|
|
}
|
|
|
|
fun getThreadId(groupId: GroupId, consumer: (Long) -> Unit) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
val recipientId = Recipient.externalGroupExact(groupId).id
|
|
consumer(SignalDatabase.threads.getThreadIdIfExistsFor(recipientId))
|
|
}
|
|
}
|
|
|
|
fun isInternalRecipientDetailsEnabled(): Boolean = SignalStore.internalValues().recipientDetails()
|
|
|
|
fun hasGroups(consumer: (Boolean) -> Unit) {
|
|
SignalExecutors.BOUNDED.execute { consumer(SignalDatabase.groups.activeGroupCount > 0) }
|
|
}
|
|
|
|
fun getIdentity(recipientId: RecipientId, consumer: (IdentityRecord?) -> Unit) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
if (SignalStore.account().aci != null && SignalStore.account().pni != null) {
|
|
consumer(ApplicationDependencies.getProtocolStore().aci().identities().getIdentityRecord(recipientId).orElse(null))
|
|
} else {
|
|
consumer(null)
|
|
}
|
|
}
|
|
}
|
|
|
|
fun getGroupsInCommon(recipientId: RecipientId, consumer: (List<Recipient>) -> Unit) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
consumer(
|
|
SignalDatabase
|
|
.groups
|
|
.getPushGroupsContainingMember(recipientId)
|
|
.asSequence()
|
|
.filter { it.members.contains(Recipient.self().id) }
|
|
.map(GroupTable.GroupRecord::getRecipientId)
|
|
.map(Recipient::resolved)
|
|
.sortedBy { gr -> gr.getDisplayName(context) }
|
|
.toList()
|
|
)
|
|
}
|
|
}
|
|
|
|
fun getGroupMembership(recipientId: RecipientId, consumer: (List<RecipientId>) -> Unit) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
val groupDatabase = SignalDatabase.groups
|
|
val groupRecords = groupDatabase.getPushGroupsContainingMember(recipientId)
|
|
val groupRecipients = ArrayList<RecipientId>(groupRecords.size)
|
|
for (groupRecord in groupRecords) {
|
|
groupRecipients.add(groupRecord.recipientId)
|
|
}
|
|
consumer(groupRecipients)
|
|
}
|
|
}
|
|
|
|
fun refreshRecipient(recipientId: RecipientId) {
|
|
SignalExecutors.UNBOUNDED.execute {
|
|
try {
|
|
ContactDiscovery.refresh(context, Recipient.resolved(recipientId), false)
|
|
} catch (e: IOException) {
|
|
Log.w(TAG, "Failed to refresh user after adding to contacts.")
|
|
}
|
|
}
|
|
}
|
|
|
|
fun setMuteUntil(recipientId: RecipientId, until: Long) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
SignalDatabase.recipients.setMuted(recipientId, until)
|
|
}
|
|
}
|
|
|
|
fun getGroupCapacity(groupId: GroupId, consumer: (GroupCapacityResult) -> Unit) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
val groupRecord: GroupTable.GroupRecord = SignalDatabase.groups.getGroup(groupId).get()
|
|
consumer(
|
|
if (groupRecord.isV2Group) {
|
|
val decryptedGroup: DecryptedGroup = groupRecord.requireV2GroupProperties().decryptedGroup
|
|
val pendingMembers: List<RecipientId> = decryptedGroup.pendingMembersList
|
|
.map(DecryptedPendingMember::getUuid)
|
|
.map(GroupProtoUtil::uuidByteStringToRecipientId)
|
|
|
|
val members = mutableListOf<RecipientId>()
|
|
|
|
members.addAll(groupRecord.members)
|
|
members.addAll(pendingMembers)
|
|
|
|
GroupCapacityResult(Recipient.self().id, members, FeatureFlags.groupLimits(), groupRecord.isAnnouncementGroup)
|
|
} else {
|
|
GroupCapacityResult(Recipient.self().id, groupRecord.members, FeatureFlags.groupLimits(), false)
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
fun addMembers(groupId: GroupId, selected: List<RecipientId>, consumer: (GroupAddMembersResult) -> Unit) {
|
|
groupManagementRepository.addMembers(groupId, selected, consumer)
|
|
}
|
|
|
|
fun setMuteUntil(groupId: GroupId, until: Long) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
val recipientId = Recipient.externalGroupExact(groupId).id
|
|
SignalDatabase.recipients.setMuted(recipientId, until)
|
|
}
|
|
}
|
|
|
|
fun block(recipientId: RecipientId) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
val recipient = Recipient.resolved(recipientId)
|
|
if (recipient.isGroup) {
|
|
RecipientUtil.block(context, recipient)
|
|
} else {
|
|
RecipientUtil.blockNonGroup(context, recipient)
|
|
}
|
|
}
|
|
}
|
|
|
|
fun unblock(recipientId: RecipientId) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
val recipient = Recipient.resolved(recipientId)
|
|
RecipientUtil.unblock(recipient)
|
|
}
|
|
}
|
|
|
|
fun block(groupId: GroupId) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
val recipient = Recipient.externalGroupExact(groupId)
|
|
RecipientUtil.block(context, recipient)
|
|
}
|
|
}
|
|
|
|
fun unblock(groupId: GroupId) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
val recipient = Recipient.externalGroupExact(groupId)
|
|
RecipientUtil.unblock(recipient)
|
|
}
|
|
}
|
|
|
|
@WorkerThread
|
|
fun isMessageRequestAccepted(recipient: Recipient): Boolean {
|
|
return RecipientUtil.isMessageRequestAccepted(context, recipient)
|
|
}
|
|
|
|
fun getMembershipCountDescription(liveGroup: LiveGroup): LiveData<String> {
|
|
return liveGroup.getMembershipCountDescription(context.resources)
|
|
}
|
|
|
|
fun getExternalPossiblyMigratedGroupRecipientId(groupId: GroupId, consumer: (RecipientId) -> Unit) {
|
|
SignalExecutors.BOUNDED.execute {
|
|
consumer(Recipient.externalPossiblyMigratedGroup(groupId).id)
|
|
}
|
|
}
|
|
}
|