Integrate Element Call with widget API (#1581)
* Integrate Element Call with widget API. - Add `appconfig` module and extract constants that can be overridden in forks there. - Add an Element Call feature flag, disabled by default. - Refactor the whole `ElementCallActivity`, move most logic out of it. - Integrate with the Rust Widget Driver API (note the Rust SDK version used in this PR lacks some needed changes to make the calls actually work). - Handle calls differently based on `CallType`. - Add UI to create/join a call. --------- Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
parent
a814c4a95a
commit
46f78ef700
102 changed files with 2202 additions and 166 deletions
|
|
@ -34,6 +34,7 @@ anvil {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.appconfig)
|
||||
implementation(projects.libraries.di)
|
||||
implementation(libs.dagger)
|
||||
implementation(projects.libraries.core)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
package io.element.android.libraries.matrix.api.permalink
|
||||
|
||||
import android.net.Uri
|
||||
import io.element.android.libraries.matrix.api.config.MatrixConfiguration
|
||||
import io.element.android.appconfig.MatrixConfiguration
|
||||
|
||||
/**
|
||||
* Mapping of an input URI to a matrix.to compliant URI.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.permalink
|
||||
|
||||
import io.element.android.libraries.matrix.api.config.MatrixConfiguration
|
||||
import io.element.android.appconfig.MatrixConfiguration
|
||||
import io.element.android.libraries.matrix.api.core.MatrixPatterns
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import io.element.android.libraries.matrix.api.media.VideoInfo
|
|||
import io.element.android.libraries.matrix.api.poll.PollKind
|
||||
import io.element.android.libraries.matrix.api.room.location.AssetType
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import java.io.Closeable
|
||||
import java.io.File
|
||||
|
|
@ -192,5 +194,27 @@ interface MatrixRoom : Closeable {
|
|||
progressCallback: ProgressCallback?
|
||||
): Result<MediaUploadHandler>
|
||||
|
||||
/**
|
||||
* Generates a Widget url to display in a [android.webkit.WebView] given the provided parameters.
|
||||
* @param widgetSettings The widget settings to use.
|
||||
* @param clientId The client id to use. It should be unique per app install.
|
||||
* @param languageTag The language tag to use. If null, the default language will be used.
|
||||
* @param theme The theme to use. If null, the default theme will be used.
|
||||
* @return The resulting url, or a failure.
|
||||
*/
|
||||
suspend fun generateWidgetWebViewUrl(
|
||||
widgetSettings: MatrixWidgetSettings,
|
||||
clientId: String,
|
||||
languageTag: String? = null,
|
||||
theme: String? = null,
|
||||
): Result<String>
|
||||
|
||||
/**
|
||||
* Get a [MatrixWidgetDriver] for the provided [widgetSettings].
|
||||
* @param widgetSettings The widget settings to use.
|
||||
* @return The resulting [MatrixWidgetDriver], or a failure.
|
||||
*/
|
||||
fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result<MatrixWidgetDriver>
|
||||
|
||||
override fun close() = destroy()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,13 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.api.config
|
||||
package io.element.android.libraries.matrix.api.widget
|
||||
|
||||
object MatrixConfiguration {
|
||||
const val matrixToPermalinkBaseUrl: String = "https://matrix.to/#/"
|
||||
val clientPermalinkBaseUrl: String? = null
|
||||
import java.util.UUID
|
||||
|
||||
interface CallWidgetSettingsProvider {
|
||||
fun provide(
|
||||
baseUrl: String,
|
||||
widgetId: String = UUID.randomUUID().toString()
|
||||
): MatrixWidgetSettings
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.api.widget
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface MatrixWidgetDriver : AutoCloseable {
|
||||
val id: String
|
||||
val incomingMessages: Flow<String>
|
||||
|
||||
suspend fun run()
|
||||
suspend fun send(message: String)
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.api.widget
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
class MatrixWidgetSettings(
|
||||
val id: String,
|
||||
val initAfterContentLoad: Boolean,
|
||||
val rawUrl: String,
|
||||
) : Parcelable {
|
||||
companion object
|
||||
}
|
||||
|
|
@ -40,6 +40,8 @@ import io.element.android.libraries.matrix.api.room.location.AssetType
|
|||
import io.element.android.libraries.matrix.api.room.roomMembers
|
||||
import io.element.android.libraries.matrix.api.room.roomNotificationSettings
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||
import io.element.android.libraries.matrix.impl.core.toProgressWatcher
|
||||
import io.element.android.libraries.matrix.impl.media.MediaUploadHandlerImpl
|
||||
import io.element.android.libraries.matrix.impl.media.map
|
||||
|
|
@ -48,6 +50,8 @@ import io.element.android.libraries.matrix.impl.poll.toInner
|
|||
import io.element.android.libraries.matrix.impl.room.location.toInner
|
||||
import io.element.android.libraries.matrix.impl.timeline.RustMatrixTimeline
|
||||
import io.element.android.libraries.matrix.impl.util.destroyAll
|
||||
import io.element.android.libraries.matrix.impl.widget.RustWidgetDriver
|
||||
import io.element.android.libraries.matrix.impl.widget.generateWidgetWebViewUrl
|
||||
import io.element.android.libraries.sessionstorage.api.SessionData
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import kotlinx.coroutines.CancellationException
|
||||
|
|
@ -65,6 +69,8 @@ import org.matrix.rustcomponents.sdk.RoomListItem
|
|||
import org.matrix.rustcomponents.sdk.RoomMember
|
||||
import org.matrix.rustcomponents.sdk.RoomMessageEventContentWithoutRelation
|
||||
import org.matrix.rustcomponents.sdk.SendAttachmentJoinHandle
|
||||
import org.matrix.rustcomponents.sdk.WidgetPermissions
|
||||
import org.matrix.rustcomponents.sdk.WidgetPermissionsProvider
|
||||
import org.matrix.rustcomponents.sdk.messageEventContentFromHtml
|
||||
import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdown
|
||||
import timber.log.Timber
|
||||
|
|
@ -478,6 +484,27 @@ class RustMatrixRoom(
|
|||
)
|
||||
}
|
||||
|
||||
override suspend fun generateWidgetWebViewUrl(
|
||||
widgetSettings: MatrixWidgetSettings,
|
||||
clientId: String,
|
||||
languageTag: String?,
|
||||
theme: String?,
|
||||
) = runCatching {
|
||||
widgetSettings.generateWidgetWebViewUrl(innerRoom, clientId, languageTag, theme)
|
||||
}
|
||||
|
||||
override fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result<MatrixWidgetDriver> = runCatching {
|
||||
RustWidgetDriver(
|
||||
widgetSettings = widgetSettings,
|
||||
room = innerRoom,
|
||||
widgetPermissionsProvider = object : WidgetPermissionsProvider {
|
||||
override fun acquirePermissions(permissions: WidgetPermissions): WidgetPermissions {
|
||||
return permissions
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun sendAttachment(files: List<File>, handle: () -> SendAttachmentJoinHandle): Result<MediaUploadHandler> {
|
||||
return runCatching {
|
||||
MediaUploadHandlerImpl(files, handle())
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.widget
|
||||
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.widget.CallWidgetSettingsProvider
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||
import org.matrix.rustcomponents.sdk.VirtualElementCallWidgetOptions
|
||||
import org.matrix.rustcomponents.sdk.newVirtualElementCallWidget
|
||||
import javax.inject.Inject
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultCallWidgetSettingsProvider @Inject constructor() : CallWidgetSettingsProvider {
|
||||
override fun provide(baseUrl: String, widgetId: String): MatrixWidgetSettings {
|
||||
val options = VirtualElementCallWidgetOptions(
|
||||
elementCallUrl = baseUrl,
|
||||
widgetId = widgetId,
|
||||
parentUrl = null,
|
||||
hideHeader = null,
|
||||
preload = null,
|
||||
fontScale = null,
|
||||
appPrompt = false,
|
||||
skipLobby = true,
|
||||
confineToRoom = true,
|
||||
fonts = null,
|
||||
analyticsId = null
|
||||
)
|
||||
val rustWidgetSettings = newVirtualElementCallWidget(options)
|
||||
return MatrixWidgetSettings.fromRustWidgetSettings(rustWidgetSettings)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.widget
|
||||
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||
import org.matrix.rustcomponents.sdk.ClientProperties
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.WidgetSettings
|
||||
import org.matrix.rustcomponents.sdk.generateWebviewUrl
|
||||
|
||||
fun MatrixWidgetSettings.toRustWidgetSettings() = WidgetSettings(
|
||||
id = this.id,
|
||||
initAfterContentLoad = this.initAfterContentLoad,
|
||||
rawUrl = this.rawUrl,
|
||||
)
|
||||
|
||||
fun MatrixWidgetSettings.Companion.fromRustWidgetSettings(widgetSettings: WidgetSettings) = MatrixWidgetSettings(
|
||||
id = widgetSettings.id,
|
||||
initAfterContentLoad = widgetSettings.initAfterContentLoad,
|
||||
rawUrl = widgetSettings.rawUrl,
|
||||
)
|
||||
|
||||
suspend fun MatrixWidgetSettings.generateWidgetWebViewUrl(
|
||||
room: Room,
|
||||
clientId: String,
|
||||
languageTag: String? = null,
|
||||
theme: String? = null
|
||||
) = generateWebviewUrl(
|
||||
widgetSettings = this.toRustWidgetSettings(),
|
||||
room = room,
|
||||
props = ClientProperties(
|
||||
clientId = clientId,
|
||||
languageTag = languageTag,
|
||||
theme = theme,
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.widget
|
||||
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.WidgetPermissionsProvider
|
||||
import org.matrix.rustcomponents.sdk.makeWidgetDriver
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
class RustWidgetDriver(
|
||||
widgetSettings: MatrixWidgetSettings,
|
||||
private val room: Room,
|
||||
private val widgetPermissionsProvider: WidgetPermissionsProvider,
|
||||
): MatrixWidgetDriver {
|
||||
|
||||
override val incomingMessages = MutableSharedFlow<String>()
|
||||
|
||||
private val driverAndHandle = makeWidgetDriver(widgetSettings.toRustWidgetSettings())
|
||||
private var receiveMessageJob: Job? = null
|
||||
|
||||
private var isRunning = AtomicBoolean(false)
|
||||
|
||||
override val id: String = widgetSettings.id
|
||||
|
||||
override suspend fun run() {
|
||||
// Don't run the driver if it's already running
|
||||
if (!isRunning.compareAndSet(false, true)) {
|
||||
return
|
||||
}
|
||||
|
||||
val coroutineScope = CoroutineScope(coroutineContext)
|
||||
coroutineScope.launch {
|
||||
// This call will suspend the coroutine while the driver is running, so it needs to be launched separately
|
||||
driverAndHandle.driver.run(room, widgetPermissionsProvider)
|
||||
}
|
||||
receiveMessageJob = coroutineScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
while (isActive) {
|
||||
driverAndHandle.handle.recv()?.let { incomingMessages.emit(it) }
|
||||
}
|
||||
} finally {
|
||||
driverAndHandle.handle.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun send(message: String) {
|
||||
driverAndHandle.handle.send(message)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
receiveMessageJob?.cancel()
|
||||
driverAndHandle.driver.close()
|
||||
}
|
||||
}
|
||||
|
|
@ -208,8 +208,12 @@ class FakeMatrixClient(
|
|||
findDmResult = result
|
||||
}
|
||||
|
||||
fun givenGetRoomResult(roomId: RoomId, result: MatrixRoom) {
|
||||
getRoomResults[roomId] = result
|
||||
fun givenGetRoomResult(roomId: RoomId, result: MatrixRoom?) {
|
||||
if (result == null) {
|
||||
getRoomResults.remove(roomId)
|
||||
} else {
|
||||
getRoomResults[roomId] = result
|
||||
}
|
||||
}
|
||||
|
||||
fun givenSearchUsersResult(searchTerm: String, result: Result<MatrixSearchUserResults>) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.test
|
||||
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
|
||||
class FakeMatrixClientProvider(
|
||||
private val getClient: (SessionId) -> Result<MatrixClient> = { Result.success(FakeMatrixClient()) }
|
||||
) : MatrixClientProvider {
|
||||
override suspend fun getOrRestore(sessionId: SessionId): Result<MatrixClient> = getClient(sessionId)
|
||||
}
|
||||
|
|
@ -36,11 +36,14 @@ import io.element.android.libraries.matrix.api.room.MessageEventType
|
|||
import io.element.android.libraries.matrix.api.room.StateEventType
|
||||
import io.element.android.libraries.matrix.api.room.location.AssetType
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler
|
||||
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
|
||||
import io.element.android.libraries.matrix.test.timeline.FakeMatrixTimeline
|
||||
import io.element.android.libraries.matrix.test.widget.FakeWidgetDriver
|
||||
import io.element.android.tests.testutils.simulateLongTask
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -92,6 +95,8 @@ class FakeMatrixRoom(
|
|||
private var sendPollResponseResult = Result.success(Unit)
|
||||
private var endPollResult = Result.success(Unit)
|
||||
private var progressCallbackValues = emptyList<Pair<Long, Long>>()
|
||||
private var generateWidgetWebViewUrlResult = Result.success("https://call.element.io")
|
||||
private var getWidgetDriverResult: Result<MatrixWidgetDriver> = Result.success(FakeWidgetDriver())
|
||||
val editMessageCalls = mutableListOf<Pair<String, String?>>()
|
||||
|
||||
var sendMediaCount = 0
|
||||
|
|
@ -368,6 +373,15 @@ class FakeMatrixRoom(
|
|||
progressCallback: ProgressCallback?
|
||||
): Result<MediaUploadHandler> = fakeSendMedia(progressCallback)
|
||||
|
||||
override suspend fun generateWidgetWebViewUrl(
|
||||
widgetSettings: MatrixWidgetSettings,
|
||||
clientId: String,
|
||||
languageTag: String?,
|
||||
theme: String?,
|
||||
): Result<String> = generateWidgetWebViewUrlResult
|
||||
|
||||
override fun getWidgetDriver(widgetSettings: MatrixWidgetSettings): Result<MatrixWidgetDriver> = getWidgetDriverResult
|
||||
|
||||
fun givenLeaveRoomError(throwable: Throwable?) {
|
||||
this.leaveRoomError = throwable
|
||||
}
|
||||
|
|
@ -475,6 +489,14 @@ class FakeMatrixRoom(
|
|||
fun givenProgressCallbackValues(values: List<Pair<Long, Long>>) {
|
||||
progressCallbackValues = values
|
||||
}
|
||||
|
||||
fun givenGenerateWidgetWebViewUrlResult(result: Result<String>) {
|
||||
generateWidgetWebViewUrlResult = result
|
||||
}
|
||||
|
||||
fun givenGetWidgetDriverResult(result: Result<MatrixWidgetDriver>) {
|
||||
getWidgetDriverResult = result
|
||||
}
|
||||
}
|
||||
|
||||
data class SendLocationInvocation(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.test.widget
|
||||
|
||||
import io.element.android.libraries.matrix.api.widget.CallWidgetSettingsProvider
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||
|
||||
class FakeCallWidgetSettingsProvider(
|
||||
private val provideFn: (String, String) -> MatrixWidgetSettings = { _, _ -> MatrixWidgetSettings("id", true, "url") }
|
||||
) : CallWidgetSettingsProvider {
|
||||
|
||||
val providedBaseUrls = mutableListOf<String>()
|
||||
|
||||
override fun provide(baseUrl: String, widgetId: String): MatrixWidgetSettings {
|
||||
providedBaseUrls += baseUrl
|
||||
return provideFn(baseUrl, widgetId)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.test.widget
|
||||
|
||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import java.util.UUID
|
||||
|
||||
class FakeWidgetDriver(
|
||||
override val id: String = UUID.randomUUID().toString(),
|
||||
) : MatrixWidgetDriver {
|
||||
|
||||
private val _sentMessages = mutableListOf<String>()
|
||||
val sentMessages: List<String> = _sentMessages
|
||||
|
||||
var runCalledCount = 0
|
||||
private set
|
||||
var closeCalledCount = 0
|
||||
private set
|
||||
|
||||
override val incomingMessages = MutableSharedFlow<String>(extraBufferCapacity = 1)
|
||||
|
||||
override suspend fun run() {
|
||||
runCalledCount++
|
||||
}
|
||||
|
||||
override suspend fun send(message: String) {
|
||||
_sentMessages.add(message)
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
closeCalledCount++
|
||||
}
|
||||
|
||||
fun givenIncomingMessage(message: String) {
|
||||
incomingMessages.tryEmit(message)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue