Skip to content

Commit 016f699

Browse files
Optimizing community joining process (#1968)
1 parent ddad4f0 commit 016f699

File tree

5 files changed

+104
-43
lines changed

5 files changed

+104
-43
lines changed

app/src/main/java/org/session/libsession/database/StorageProtocol.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ interface StorageProtocol {
5959
fun getServerCapabilities(server: String): List<String>?
6060
fun clearServerCapabilities(server: String)
6161

62-
// Open Groups
63-
suspend fun addOpenGroup(urlAsString: String)
6462
fun setOpenGroupServerMessageID(messageID: MessageId, serverID: Long, threadID: Long)
6563

6664
// Open Group Public Keys

app/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupApi.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,24 @@ object OpenGroupApi {
100100
@SerialName("default_upload")
101101
val defaultUpload: Boolean = false,
102102
val details: RoomInfoDetails = RoomInfoDetails()
103-
)
103+
) {
104+
constructor(details: RoomInfoDetails): this(
105+
token = details.token,
106+
activeUsers = details.activeUsers,
107+
admin = details.admin,
108+
globalAdmin = details.globalAdmin,
109+
moderator = details.moderator,
110+
globalModerator = details.globalModerator,
111+
read = details.read,
112+
defaultRead = details.defaultRead,
113+
defaultAccessible = details.defaultAccessible,
114+
write = details.write,
115+
defaultWrite = details.defaultWrite,
116+
upload = details.upload,
117+
defaultUpload = details.defaultUpload,
118+
details = details
119+
)
120+
}
104121

105122
@Serializable
106123
data class DirectMessage(
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.session.libsession.messaging.open_groups.api
2+
3+
import dagger.assisted.Assisted
4+
import dagger.assisted.AssistedFactory
5+
import dagger.assisted.AssistedInject
6+
import kotlinx.serialization.json.JsonObject
7+
import kotlinx.serialization.json.decodeFromStream
8+
import org.session.libsession.messaging.open_groups.OpenGroupApi
9+
import org.thoughtcrime.securesms.api.ApiExecutorContext
10+
import org.thoughtcrime.securesms.api.http.HttpResponse
11+
12+
class GetRoomDetailsApi @AssistedInject constructor(
13+
deps: CommunityApiDependencies,
14+
@Assisted override val room: String,
15+
) : CommunityApi<OpenGroupApi.RoomInfoDetails>(deps) {
16+
override val requiresSigning: Boolean
17+
get() = false
18+
19+
override val httpMethod: String
20+
get() = "GET"
21+
22+
override val httpEndpoint: String
23+
get() = "/room/${room}"
24+
25+
override suspend fun handleSuccessResponse(
26+
executorContext: ApiExecutorContext,
27+
baseUrl: String,
28+
response: HttpResponse
29+
): OpenGroupApi.RoomInfoDetails {
30+
@Suppress("OPT_IN_USAGE")
31+
return response.body.asInputStream().use(json::decodeFromStream)
32+
}
33+
34+
@AssistedFactory
35+
interface Factory {
36+
fun create(room: String): GetRoomDetailsApi
37+
}
38+
}

app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -871,10 +871,6 @@ open class Storage @Inject constructor(
871871
return groupDatabase.getAllGroups(includeInactive)
872872
}
873873

874-
override suspend fun addOpenGroup(urlAsString: String) {
875-
return openGroupManager.get().addOpenGroup(urlAsString)
876-
}
877-
878874
override fun getOrCreateThreadIdFor(address: Address): Long {
879875
return threadDatabase.getOrCreateThreadIdFor(address)
880876
}
Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
package org.thoughtcrime.securesms.groups
22

3-
import kotlinx.coroutines.flow.first
4-
import kotlinx.coroutines.flow.mapNotNull
5-
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
6-
import org.session.libsession.messaging.open_groups.OpenGroup
3+
import kotlinx.coroutines.async
4+
import kotlinx.coroutines.supervisorScope
5+
import kotlinx.serialization.json.Json
76
import org.session.libsession.messaging.open_groups.OpenGroupApi
87
import org.session.libsession.messaging.open_groups.api.CommunityApiExecutor
98
import org.session.libsession.messaging.open_groups.api.CommunityApiRequest
109
import org.session.libsession.messaging.open_groups.api.GetCapsApi
10+
import org.session.libsession.messaging.open_groups.api.GetRoomDetailsApi
1111
import org.session.libsession.messaging.open_groups.api.execute
12-
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPollerManager
12+
import org.session.libsession.utilities.Address
1313
import org.session.libsession.utilities.ConfigFactoryProtocol
1414
import org.session.libsession.utilities.withMutableUserConfigs
15+
import org.session.libsession.utilities.withUserConfigs
1516
import org.session.libsignal.utilities.Log
17+
import org.thoughtcrime.securesms.database.CommunityDatabase
1618
import org.thoughtcrime.securesms.database.LokiAPIDatabase
1719
import javax.inject.Inject
1820
import javax.inject.Provider
@@ -26,25 +28,53 @@ private const val TAG = "OpenGroupManager"
2628
@Singleton
2729
class OpenGroupManager @Inject constructor(
2830
private val configFactory: ConfigFactoryProtocol,
29-
private val pollerManager: OpenGroupPollerManager,
3031
private val lokiAPIDatabase: LokiAPIDatabase,
3132
private val communityApiExecutor: CommunityApiExecutor,
3233
private val getCapsApi: Provider<GetCapsApi>,
34+
private val getRoomDetailsApiFactory: GetRoomDetailsApi.Factory,
35+
private val communityDatabase: CommunityDatabase,
36+
private val json: Json,
3337
) {
34-
suspend fun add(server: String, room: String, publicKey: String) {
38+
suspend fun add(server: String, room: String, publicKey: String): Unit = supervisorScope {
39+
// Check if the community is already added, if so, we can skip the rest of the process
40+
val alreadyJoined = configFactory.withUserConfigs {
41+
it.userGroups.getCommunityInfo(server, room)
42+
} != null
43+
44+
if (alreadyJoined) {
45+
Log.d("OpenGroupManager", "Community $server is already added, skipping add process")
46+
return@supervisorScope
47+
}
48+
3549
// Fetch the server's capabilities upfront to see if this server is actually running
36-
// Note: this process is not essential to adding a community, just a nice to have test
37-
// for the user to see if the server they are adding is reachable.
38-
// The addition of the community to the config later will always succeed and the poller
39-
// will be started regardless of the server's status.
40-
val caps = communityApiExecutor.execute(
41-
CommunityApiRequest(
42-
serverBaseUrl = server,
43-
serverPubKey = publicKey,
44-
api = getCapsApi.get()
50+
val getCaps = async {
51+
communityApiExecutor.execute(
52+
CommunityApiRequest(
53+
serverBaseUrl = server,
54+
serverPubKey = publicKey,
55+
api = getCapsApi.get()
56+
)
57+
)
58+
}
59+
60+
// Fetch room details at the same time also
61+
val getRoomDetails = async {
62+
communityApiExecutor.execute(
63+
CommunityApiRequest(
64+
serverBaseUrl = server,
65+
serverPubKey = publicKey,
66+
api = getRoomDetailsApiFactory.create(room)
67+
)
4568
)
46-
)
47-
lokiAPIDatabase.setServerCapabilities(server, caps.capabilities)
69+
}
70+
71+
val caps = getCaps.await().capabilities
72+
val roomDetails = getRoomDetails.await()
73+
74+
lokiAPIDatabase.setServerCapabilities(server, caps)
75+
communityDatabase.patchRoomInfo(Address.Community(server, room),
76+
json.encodeToString(OpenGroupApi.RoomInfo(roomDetails)))
77+
4878

4979
// We should be good, now go ahead and add the community to the config
5080
configFactory.withMutableUserConfigs { configs ->
@@ -56,15 +86,6 @@ class OpenGroupManager @Inject constructor(
5686

5787
configs.userGroups.set(community)
5888
}
59-
60-
Log.d(TAG, "Waiting for poller for server $server to be started.")
61-
62-
// Wait until we have a poller for the server, and then request one poll
63-
pollerManager.pollers
64-
.mapNotNull { it[server] }
65-
.first()
66-
.poller
67-
.manualPollOnce()
6889
}
6990

7091
fun delete(server: String, room: String) {
@@ -73,13 +94,4 @@ class OpenGroupManager @Inject constructor(
7394
configs.convoInfoVolatile.eraseCommunity(server, room)
7495
}
7596
}
76-
77-
suspend fun addOpenGroup(urlAsString: String) {
78-
val url = urlAsString.toHttpUrlOrNull() ?: return
79-
val server = OpenGroup.getServer(urlAsString)
80-
val room = url.pathSegments.firstOrNull() ?: return
81-
val publicKey = url.queryParameter("public_key") ?: return
82-
83-
add(server.toString().removeSuffix("/"), room, publicKey) // assume migrated from calling function
84-
}
8597
}

0 commit comments

Comments
 (0)