feat: update protos and add a way to do toasts from DI

This commit is contained in:
0x330a 2023-11-22 12:16:21 +11:00
parent d9b70d45ec
commit 896907dadb
9 changed files with 1010 additions and 757 deletions

View File

@ -98,6 +98,7 @@ import org.thoughtcrime.securesms.database.model.ReactionRecord
import org.thoughtcrime.securesms.dependencies.ConfigFactory import org.thoughtcrime.securesms.dependencies.ConfigFactory
import org.thoughtcrime.securesms.dependencies.DatabaseComponent import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.dependencies.PollerFactory import org.thoughtcrime.securesms.dependencies.PollerFactory
import org.thoughtcrime.securesms.dependencies.Toaster
import org.thoughtcrime.securesms.groups.ClosedGroupManager import org.thoughtcrime.securesms.groups.ClosedGroupManager
import org.thoughtcrime.securesms.groups.GroupManager import org.thoughtcrime.securesms.groups.GroupManager
import org.thoughtcrime.securesms.groups.OpenGroupManager import org.thoughtcrime.securesms.groups.OpenGroupManager
@ -112,7 +113,8 @@ open class Storage(
context: Context, context: Context,
helper: SQLCipherOpenHelper, helper: SQLCipherOpenHelper,
private val configFactory: ConfigFactory, private val configFactory: ConfigFactory,
private val pollerFactory: PollerFactory private val pollerFactory: PollerFactory,
private val toaster: Toaster,
) : Database(context, helper), StorageProtocol, ) : Database(context, helper), StorageProtocol,
ThreadDatabase.ConversationThreadUpdateListener { ThreadDatabase.ConversationThreadUpdateListener {

View File

@ -1,14 +1,20 @@
package org.thoughtcrime.securesms.dependencies package org.thoughtcrime.securesms.dependencies
import android.content.Context
import android.widget.Toast
import androidx.annotation.StringRes
import dagger.Binds import dagger.Binds
import dagger.Module import dagger.Module
import dagger.Provides
import dagger.hilt.EntryPoint import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent import dagger.hilt.components.SingletonComponent
import org.session.libsession.utilities.AppTextSecurePreferences import org.session.libsession.utilities.AppTextSecurePreferences
import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.repository.ConversationRepository import org.thoughtcrime.securesms.repository.ConversationRepository
import org.thoughtcrime.securesms.repository.DefaultConversationRepository import org.thoughtcrime.securesms.repository.DefaultConversationRepository
import javax.inject.Singleton
@Module @Module
@InstallIn(SingletonComponent::class) @InstallIn(SingletonComponent::class)
@ -22,8 +28,23 @@ abstract class AppModule {
} }
@Module
@InstallIn(SingletonComponent::class)
class ToasterModule {
@Provides
@Singleton
fun provideToaster(@ApplicationContext context: Context) = Toaster { stringRes, toastLength, parameters ->
val string = context.getString(stringRes, parameters)
Toast.makeText(context, string, toastLength).show()
}
}
@EntryPoint @EntryPoint
@InstallIn(SingletonComponent::class) @InstallIn(SingletonComponent::class)
interface AppComponent { interface AppComponent {
fun getPrefs(): TextSecurePreferences fun getPrefs(): TextSecurePreferences
}
fun interface Toaster {
fun toast(@StringRes stringRes: Int, toastLength: Int, vararg parameters: Any)
} }

View File

@ -135,8 +135,9 @@ object DatabaseModule {
openHelper: SQLCipherOpenHelper, openHelper: SQLCipherOpenHelper,
configFactory: ConfigFactory, configFactory: ConfigFactory,
threadDatabase: ThreadDatabase, threadDatabase: ThreadDatabase,
pollerFactory: PollerFactory): Storage { pollerFactory: PollerFactory,
val storage = Storage(context, openHelper, configFactory, pollerFactory) toaster: Toaster): Storage {
val storage = Storage(context, openHelper, configFactory, pollerFactory, toaster)
threadDatabase.setUpdateListener(storage) threadDatabase.setUpdateListener(storage)
return storage return storage
} }

View File

@ -34,7 +34,7 @@ class EditClosedGroupActivity: PassphraseRequiredActionBarActivity() {
navGraph = NavGraphs.editGroup, navGraph = NavGraphs.editGroup,
dependenciesContainerBuilder = { dependenciesContainerBuilder = {
dependency(NavGraphs.editGroup) { dependency(NavGraphs.editGroup) {
editFactory.create(intent.getStringExtra(groupIDKey)!!) editFactory.create(intent.getStringExtra(groupIDKey)!!, contentResolver)
} }
dependency(NavGraphs.editGroup) { dependency(NavGraphs.editGroup) {
inviteFactory.create(intent.getStringExtra(groupIDKey)!!) inviteFactory.create(intent.getStringExtra(groupIDKey)!!)

View File

@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.groups.compose package org.thoughtcrime.securesms.groups.compose
import android.content.ContentResolver
import android.content.Context import android.content.Context
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
@ -14,6 +15,7 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.Icon import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedButton
import androidx.compose.material.Scaffold import androidx.compose.material.Scaffold
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.rememberScaffoldState import androidx.compose.material.rememberScaffoldState
@ -48,6 +50,8 @@ import network.loki.messenger.R
import network.loki.messenger.libsession_util.util.GroupMember import network.loki.messenger.libsession_util.util.GroupMember
import org.session.libsession.database.StorageProtocol import org.session.libsession.database.StorageProtocol
import org.session.libsession.messaging.contacts.Contact import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.jobs.InviteContactsJob
import org.session.libsession.messaging.jobs.JobQueue
import org.thoughtcrime.securesms.groups.ContactList import org.thoughtcrime.securesms.groups.ContactList
import org.thoughtcrime.securesms.groups.destinations.EditClosedGroupInviteScreenDestination import org.thoughtcrime.securesms.groups.destinations.EditClosedGroupInviteScreenDestination
import org.thoughtcrime.securesms.ui.CellWithPaddingAndMargin import org.thoughtcrime.securesms.ui.CellWithPaddingAndMargin
@ -81,6 +85,9 @@ fun EditClosedGroupScreen(
onInvite = { onInvite = {
navigator.navigate(EditClosedGroupInviteScreenDestination) navigator.navigate(EditClosedGroupInviteScreenDestination)
}, },
onReinvite = { contact ->
eventSink(EditGroupEvent.ReInviteContact(contact))
},
viewState = viewState viewState = viewState
) )
} }
@ -111,6 +118,7 @@ fun EditClosedGroupInviteScreen(
class EditGroupViewModel @AssistedInject constructor( class EditGroupViewModel @AssistedInject constructor(
@Assisted private val groupSessionId: String, @Assisted private val groupSessionId: String,
@Assisted private val contentResolver: ContentResolver,
private val storage: StorageProtocol, private val storage: StorageProtocol,
): ViewModel() { ): ViewModel() {
@ -120,6 +128,10 @@ class EditGroupViewModel @AssistedInject constructor(
storage.getUserPublicKey()!! storage.getUserPublicKey()!!
} }
// val closedGroupRecipient by contentResolver
// .observeQuery(DatabaseContentProviders.ConversationList.CONTENT_URI)
// .collectAsState(initial = null)
val closedGroupInfo = remember { val closedGroupInfo = remember {
storage.getLibSessionClosedGroup(groupSessionId)!! storage.getLibSessionClosedGroup(groupSessionId)!!
} }
@ -163,13 +175,16 @@ class EditGroupViewModel @AssistedInject constructor(
Toast.LENGTH_LONG Toast.LENGTH_LONG
).show() ).show()
} }
is EditGroupEvent.ReInviteContact -> {
JobQueue.shared.add(InviteContactsJob(groupSessionId, arrayOf(event.contactSessionId)))
}
} }
} }
} }
@AssistedFactory @AssistedFactory
interface Factory { interface Factory {
fun create(groupSessionId: String): EditGroupViewModel fun create(groupSessionId: String, contentResolver: ContentResolver): EditGroupViewModel
} }
} }
@ -216,6 +231,7 @@ class EditGroupInviteViewModel @AssistedInject constructor(
fun EditGroupView( fun EditGroupView(
onBack: ()->Unit, onBack: ()->Unit,
onInvite: ()->Unit, onInvite: ()->Unit,
onReinvite: (String)->Unit,
viewState: EditGroupViewState, viewState: EditGroupViewState,
) { ) {
val scaffoldState = rememberScaffoldState() val scaffoldState = rememberScaffoldState()
@ -296,6 +312,14 @@ fun EditGroupView(
) )
} }
} }
// Resend button
if (viewState.admin && member.memberState == MemberState.InviteFailed) {
OutlinedButton(onClick = {
onReinvite(member.memberSessionId)
},) {
Text("Re-send")
}
}
} }
} }
@ -332,10 +356,10 @@ enum class MemberState {
} }
fun memberStateOf(member: GroupMember): MemberState = when { fun memberStateOf(member: GroupMember): MemberState = when {
member.invitePending -> MemberState.InviteSent
member.inviteFailed -> MemberState.InviteFailed member.inviteFailed -> MemberState.InviteFailed
member.promotionPending -> MemberState.PromotionSent member.invitePending -> MemberState.InviteSent
member.promotionFailed -> MemberState.PromotionFailed member.promotionFailed -> MemberState.PromotionFailed
member.promotionPending -> MemberState.PromotionSent
member.admin -> MemberState.Admin member.admin -> MemberState.Admin
else -> MemberState.Member else -> MemberState.Member
} }
@ -350,6 +374,7 @@ data class EditGroupViewState(
sealed class EditGroupEvent { sealed class EditGroupEvent {
data class InviteContacts(val context: Context, data class InviteContacts(val context: Context,
val contacts: ContactList): EditGroupEvent() val contacts: ContactList): EditGroupEvent()
data class ReInviteContact(val contactSessionId: String): EditGroupEvent()
} }
data class EditGroupInviteViewState( data class EditGroupInviteViewState(
@ -367,11 +392,17 @@ fun PreviewList() {
MemberState.InviteSent, MemberState.InviteSent,
false false
) )
val twoMember = MemberViewModel(
"Test User",
"05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1235",
MemberState.InviteFailed,
false
)
val viewState = EditGroupViewState( val viewState = EditGroupViewState(
"Preview", "Preview",
"This is a preview description", "This is a preview description",
listOf(oneMember), listOf(oneMember, twoMember),
true true
) )
@ -379,6 +410,7 @@ fun PreviewList() {
EditGroupView( EditGroupView(
onBack = {}, onBack = {},
onInvite = {}, onInvite = {},
onReinvite = {},
viewState = viewState viewState = viewState
) )
} }

View File

@ -66,6 +66,8 @@ class InviteContactsJob(val groupSessionId: String, val memberSessionIds: Array<
) )
} }
members.set(member.copy(invitePending = true, inviteFailed = false)) members.set(member.copy(invitePending = true, inviteFailed = false))
configs.saveGroupConfigs(keys, info, members)
val subAccount = keys.makeSubAccount(SessionId.from(memberSessionId)) val subAccount = keys.makeSubAccount(SessionId.from(memberSessionId))
val timestamp = SnodeAPI.nowWithOffset val timestamp = SnodeAPI.nowWithOffset
@ -93,6 +95,7 @@ class InviteContactsJob(val groupSessionId: String, val memberSessionIds: Array<
sentTimestamp = timestamp sentTimestamp = timestamp
} }
try { try {
//throw Exception("Just for testing")
MessageSender.send(update, Destination.Contact(memberSessionId), false) MessageSender.send(update, Destination.Contact(memberSessionId), false)
.get() .get()
InviteResult.success(memberSessionId) InviteResult.success(memberSessionId)
@ -119,6 +122,10 @@ class InviteContactsJob(val groupSessionId: String, val memberSessionIds: Array<
members.set(toSet) members.set(toSet)
} }
} }
configs.saveGroupConfigs(keys, info, members)
keys.free()
info.free()
members.free()
} }
} }

View File

@ -170,7 +170,6 @@ class JobQueue : JobDelegate {
} }
companion object { companion object {
@JvmStatic @JvmStatic
val shared: JobQueue by lazy { JobQueue() } val shared: JobQueue by lazy { JobQueue() }
} }

View File

@ -140,18 +140,14 @@ message DataMessage {
required string name = 2; required string name = 2;
// @required // @required
required bytes memberAuthData = 3; required bytes memberAuthData = 3;
optional bytes profileKey = 4;
optional LokiProfile profile = 5;
// @required // @required
required bytes adminSignature = 6; required bytes adminSignature = 4;
} }
message GroupUpdateDeleteMessage { message GroupUpdateDeleteMessage {
repeated string memberSessionIds = 1;
// @required // @required
required string groupSessionId = 1; // The `groupIdentityPublicKey` with a `03` prefix // signature of "DELETE" || timestamp || sessionId[0] || ... || sessionId[n]
// @required
// signature of "DELETE" || sessionId || timestamp
// sessionId is the sessionId of the person being removed
required bytes adminSignature = 2; required bytes adminSignature = 2;
} }
@ -171,6 +167,9 @@ message DataMessage {
required Type type = 1; required Type type = 1;
optional string updatedName = 2; optional string updatedName = 2;
optional uint32 updatedExpiration = 3; optional uint32 updatedExpiration = 3;
// @required
// "INFO_CHANGE" || type || timestamp
required bytes adminSignature = 4;
} }
message GroupUpdateMemberChangeMessage { message GroupUpdateMemberChangeMessage {
@ -182,7 +181,10 @@ message DataMessage {
// @required // @required
required Type type = 1; required Type type = 1;
repeated bytes memberPublicKeys = 2; repeated string memberSessionIds = 2;
// @required
// "MEMBER_CHANGE" || type || timestamp
required bytes adminSignature = 3;
} }
message GroupUpdateMemberLeftMessage { message GroupUpdateMemberLeftMessage {
@ -195,9 +197,10 @@ message DataMessage {
} }
message GroupUpdateDeleteMemberContentMessage { message GroupUpdateDeleteMemberContentMessage {
repeated bytes memberPublicKeys = 1; repeated string memberSessionIds = 1;
repeated string messageHashes = 2;
// @required // @required
required bytes adminSignature = 2; optional bytes adminSignature = 3;
} }