diff --git a/buildSrc/src/main/kotlin/io/getstream/video/android/Configuration.kt b/buildSrc/src/main/kotlin/io/getstream/video/android/Configuration.kt
index d425890f2e..39c5a85035 100644
--- a/buildSrc/src/main/kotlin/io/getstream/video/android/Configuration.kt
+++ b/buildSrc/src/main/kotlin/io/getstream/video/android/Configuration.kt
@@ -6,11 +6,11 @@ object Configuration {
const val minSdk = 24
const val majorVersion = 0
const val minorVersion = 5
- const val patchVersion = 5
+ const val patchVersion = 6
const val versionName = "$majorVersion.$minorVersion.$patchVersion"
- const val versionCode = 19
+ const val versionCode = 20
const val snapshotVersionName = "$majorVersion.$minorVersion.${patchVersion + 1}-SNAPSHOT"
const val artifactGroup = "io.getstream"
- const val streamVideoCallGooglePlayVersion = "1.0.7"
+ const val streamVideoCallGooglePlayVersion = "1.0.8"
const val streamWebRtcVersionName = "1.1.1"
}
diff --git a/docusaurus/docs/Android/02-tutorials/01-video-calling.mdx b/docusaurus/docs/Android/02-tutorials/01-video-calling.mdx
index 2df29c2583..f7cf69cb36 100644
--- a/docusaurus/docs/Android/02-tutorials/01-video-calling.mdx
+++ b/docusaurus/docs/Android/02-tutorials/01-video-calling.mdx
@@ -31,7 +31,7 @@ If you're new to android, note that there are 2 `build.gradle` files, you want t
```kotlin
dependencies {
// Stream Video Compose SDK
- implementation("io.getstream:stream-video-android-ui-compose:0.5.5")
+ implementation("io.getstream:stream-video-android-ui-compose:0.5.6")
// Optionally add Jetpack Compose if Android studio didn't automatically include them
implementation(platform("androidx.compose:compose-bom:2023.08.00"))
diff --git a/docusaurus/docs/Android/02-tutorials/02-audio-room.mdx b/docusaurus/docs/Android/02-tutorials/02-audio-room.mdx
index da1bec4a09..cbf1678398 100644
--- a/docusaurus/docs/Android/02-tutorials/02-audio-room.mdx
+++ b/docusaurus/docs/Android/02-tutorials/02-audio-room.mdx
@@ -35,7 +35,7 @@ If you're new to android, note that there are 2 `build.gradle` files, you want t
```groovy
dependencies {
// Stream Video Compose SDK
- implementation("io.getstream:stream-video-android-ui-compose:0.5.5")
+ implementation("io.getstream:stream-video-android-ui-compose:0.5.6")
// Jetpack Compose (optional/ android studio typically adds them when you create a new project)
implementation(platform("androidx.compose:compose-bom:2023.08.00"))
diff --git a/docusaurus/docs/Android/02-tutorials/03-livestream.mdx b/docusaurus/docs/Android/02-tutorials/03-livestream.mdx
index ced73749bb..2fbe9459b4 100644
--- a/docusaurus/docs/Android/02-tutorials/03-livestream.mdx
+++ b/docusaurus/docs/Android/02-tutorials/03-livestream.mdx
@@ -35,7 +35,7 @@ If you're new to android, note that there are 2 `build.gradle` files, you want t
```kotlin
dependencies {
// Stream Video Compose SDK
- implementation("io.getstream:stream-video-android-ui-compose:0.5.5")
+ implementation("io.getstream:stream-video-android-ui-compose:0.5.6")
// Jetpack Compose (optional/ android studio typically adds them when you create a new project)
implementation(platform("androidx.compose:compose-bom:2023.08.00"))
diff --git a/docusaurus/docs/Android/06-advanced/07-chat-with-video.mdx b/docusaurus/docs/Android/06-advanced/07-chat-with-video.mdx
index 98f74a5c72..60440e7a7a 100644
--- a/docusaurus/docs/Android/06-advanced/07-chat-with-video.mdx
+++ b/docusaurus/docs/Android/06-advanced/07-chat-with-video.mdx
@@ -31,7 +31,7 @@ Let the project sync. It should have all the dependencies required for you to fi
```groovy
dependencies {
// Stream Video Compose SDK
- implementation("io.getstream:stream-video-android-ui-compose:0.5.5")
+ implementation("io.getstream:stream-video-android-ui-compose:0.5.6")
// Stream Chat
implementation(libs.stream.chat.compose)
diff --git a/stream-video-android-core/api/stream-video-android-core.api b/stream-video-android-core/api/stream-video-android-core.api
index 4ac8c77f79..7fae4abb09 100644
--- a/stream-video-android-core/api/stream-video-android-core.api
+++ b/stream-video-android-core/api/stream-video-android-core.api
@@ -4116,7 +4116,6 @@ public final class io/getstream/video/android/core/notifications/NotificationCon
public abstract interface class io/getstream/video/android/core/notifications/NotificationHandler : io/getstream/android/push/permissions/NotificationPermissionHandler {
public static final field ACTION_ACCEPT_CALL Ljava/lang/String;
- public static final field ACTION_DISMISS_NOTIFICATION Ljava/lang/String;
public static final field ACTION_INCOMING_CALL Ljava/lang/String;
public static final field ACTION_LEAVE_CALL Ljava/lang/String;
public static final field ACTION_LIVE_CALL Ljava/lang/String;
@@ -4128,8 +4127,6 @@ public abstract interface class io/getstream/video/android/core/notifications/No
public static final field INCOMING_CALL_NOTIFICATION_ID I
public static final field INTENT_EXTRA_CALL_CID Ljava/lang/String;
public static final field INTENT_EXTRA_CALL_DISPLAY_NAME Ljava/lang/String;
- public static final field INTENT_EXTRA_NEXT_ACTION Ljava/lang/String;
- public static final field INTENT_EXTRA_NEXT_ACTION_BUNDLE Ljava/lang/String;
public static final field INTENT_EXTRA_NOTIFICATION_ID Ljava/lang/String;
public abstract fun getOngoingCallNotification (Lio/getstream/video/android/model/StreamCallId;)Landroid/app/Notification;
public abstract fun getRingingCallNotification (Lio/getstream/video/android/core/RingingState;Lio/getstream/video/android/model/StreamCallId;Ljava/lang/String;)Landroid/app/Notification;
@@ -4140,7 +4137,6 @@ public abstract interface class io/getstream/video/android/core/notifications/No
public final class io/getstream/video/android/core/notifications/NotificationHandler$Companion {
public static final field ACTION_ACCEPT_CALL Ljava/lang/String;
- public static final field ACTION_DISMISS_NOTIFICATION Ljava/lang/String;
public static final field ACTION_INCOMING_CALL Ljava/lang/String;
public static final field ACTION_LEAVE_CALL Ljava/lang/String;
public static final field ACTION_LIVE_CALL Ljava/lang/String;
@@ -4151,8 +4147,6 @@ public final class io/getstream/video/android/core/notifications/NotificationHan
public static final field INCOMING_CALL_NOTIFICATION_ID I
public static final field INTENT_EXTRA_CALL_CID Ljava/lang/String;
public static final field INTENT_EXTRA_CALL_DISPLAY_NAME Ljava/lang/String;
- public static final field INTENT_EXTRA_NEXT_ACTION Ljava/lang/String;
- public static final field INTENT_EXTRA_NEXT_ACTION_BUNDLE Ljava/lang/String;
public static final field INTENT_EXTRA_NOTIFICATION_ID Ljava/lang/String;
}
diff --git a/stream-video-android-core/src/main/AndroidManifest.xml b/stream-video-android-core/src/main/AndroidManifest.xml
index cac418ec93..3726bc57d7 100644
--- a/stream-video-android-core/src/main/AndroidManifest.xml
+++ b/stream-video-android-core/src/main/AndroidManifest.xml
@@ -76,13 +76,6 @@
-
-
-
-
-
-
diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt
index d7cc089e4d..a3e148a546 100644
--- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt
+++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/Call.kt
@@ -1015,6 +1015,8 @@ public class Call(
}
suspend fun accept(): Result {
+ clientImpl.state.removeRingingCall()
+ clientImpl.state.maybeStopForegroundService()
return clientImpl.accept(type, id)
}
diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/ClientState.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/ClientState.kt
index 1d8c8516ea..0fe0daf8eb 100644
--- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/ClientState.kt
+++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/ClientState.kt
@@ -127,8 +127,11 @@ class ClientState(client: StreamVideo) {
_ringingCall.value = null
}
- // Internal logic
- private fun maybeStartForegroundService(call: Call, trigger: String) {
+ /**
+ * Start a foreground service that manages the call even when the UI is gone.
+ * This depends on the flag in [StreamVideoBuilder] called `runForegroundServiceForCalls`
+ */
+ internal fun maybeStartForegroundService(call: Call, trigger: String) {
if (clientImpl.runForegroundService) {
val context = clientImpl.context
val serviceIntent = CallService.buildStartIntent(
@@ -140,7 +143,10 @@ class ClientState(client: StreamVideo) {
}
}
- private fun maybeStopForegroundService() {
+ /**
+ * Stop the foreground service that manages the call even when the UI is gone.
+ */
+ internal fun maybeStopForegroundService() {
if (clientImpl.runForegroundService) {
val context = clientImpl.context
val serviceIntent = CallService.buildStopIntent(context)
diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/NotificationHandler.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/NotificationHandler.kt
index 895fa83723..addfd5c2c4 100644
--- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/NotificationHandler.kt
+++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/NotificationHandler.kt
@@ -38,7 +38,6 @@ public interface NotificationHandler : NotificationPermissionHandler {
const val ACTION_INCOMING_CALL = "io.getstream.video.android.action.INCOMING_CALL"
const val ACTION_OUTGOING_CALL = "io.getstream.video.android.action.OUTGOING_CALL"
const val ACTION_ACCEPT_CALL = "io.getstream.video.android.action.ACCEPT_CALL"
- const val ACTION_DISMISS_NOTIFICATION = "io.getstream.video.android.action.DISMISS_NOTIFICATION"
const val ACTION_REJECT_CALL = "io.getstream.video.android.action.REJECT_CALL"
const val ACTION_LEAVE_CALL = "io.getstream.video.android.action.LEAVE_CALL"
const val ACTION_ONGOING_CALL = "io.getstream.video.android.action.ONGOING_CALL"
@@ -47,10 +46,6 @@ public interface NotificationHandler : NotificationPermissionHandler {
const val INTENT_EXTRA_NOTIFICATION_ID: String =
"io.getstream.video.android.intent-extra.notification_id"
- const val INTENT_EXTRA_NEXT_ACTION: String =
- "io.getstream.video.android.intent-extra.next_action"
- const val INTENT_EXTRA_NEXT_ACTION_BUNDLE: String =
- "io.getstream.video.android.intent-extra.next_action_data"
const val INCOMING_CALL_NOTIFICATION_ID = 24756
}
}
diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/DefaultStreamIntentResolver.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/DefaultStreamIntentResolver.kt
index 4cb71b8d4e..12de2ac5ba 100644
--- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/DefaultStreamIntentResolver.kt
+++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/DefaultStreamIntentResolver.kt
@@ -24,11 +24,9 @@ import android.content.pm.ResolveInfo
import io.getstream.log.taggedLogger
import io.getstream.video.android.core.notifications.DefaultNotificationHandler
import io.getstream.video.android.core.notifications.NotificationHandler
-import io.getstream.video.android.core.notifications.NotificationHandler.Companion.ACTION_ACCEPT_CALL
import io.getstream.video.android.core.notifications.NotificationHandler.Companion.ACTION_LIVE_CALL
import io.getstream.video.android.core.notifications.NotificationHandler.Companion.ACTION_ONGOING_CALL
import io.getstream.video.android.core.notifications.NotificationHandler.Companion.ACTION_REJECT_CALL
-import io.getstream.video.android.core.notifications.NotificationHandler.Companion.INCOMING_CALL_NOTIFICATION_ID
import io.getstream.video.android.core.notifications.NotificationHandler.Companion.INTENT_EXTRA_CALL_CID
import io.getstream.video.android.model.StreamCallId
@@ -96,7 +94,7 @@ internal class DefaultStreamIntentResolver(val context: Context) {
notificationId: Int,
): PendingIntent? =
searchActivityPendingIntent(
- Intent(ACTION_LIVE_CALL),
+ Intent(NotificationHandler.ACTION_LIVE_CALL),
callId,
notificationId,
)
@@ -109,32 +107,13 @@ internal class DefaultStreamIntentResolver(val context: Context) {
*/
internal fun searchAcceptCallPendingIntent(
callId: StreamCallId,
- ): PendingIntent? = searchDismissNotificationPendingIntent(
- callId,
+ notificationId: Int = NotificationHandler.INCOMING_CALL_NOTIFICATION_ID,
+ ): PendingIntent? =
searchActivityPendingIntent(
- Intent(ACTION_ACCEPT_CALL),
- callId,
- INCOMING_CALL_NOTIFICATION_ID,
- ),
- )
-
- /**
- * Search for a broadcast that will dismiss a notification and will then proceed to call the [nextIntent].
- *
- * @param callId the callID
- * @param nextIntent the next action intent.
- */
- internal fun searchDismissNotificationPendingIntent(
- callId: StreamCallId,
- nextIntent: PendingIntent? = null,
- ): PendingIntent? {
- val baseIntent = Intent(NotificationHandler.ACTION_DISMISS_NOTIFICATION)
- baseIntent.putExtra(NotificationHandler.INTENT_EXTRA_NEXT_ACTION, nextIntent)
- return searchBroadcastPendingIntent(
- baseIntent,
+ Intent(NotificationHandler.ACTION_ACCEPT_CALL),
callId,
+ notificationId,
)
- }
/**
* Searches for a broadcast receiver that can consume the [ACTION_REJECT_CALL] intent to reject
@@ -267,17 +246,16 @@ internal class DefaultStreamIntentResolver(val context: Context) {
baseIntent: Intent,
resolveInfo: ResolveInfo,
callId: StreamCallId,
- notificationId: Int = INCOMING_CALL_NOTIFICATION_ID,
): Intent {
return Intent(baseIntent).apply {
component = ComponentName(
resolveInfo.activityInfo.applicationInfo.packageName,
resolveInfo.activityInfo.name,
)
- putExtra(INTENT_EXTRA_CALL_CID, callId)
+ putExtra(NotificationHandler.INTENT_EXTRA_CALL_CID, callId)
putExtra(
NotificationHandler.INTENT_EXTRA_NOTIFICATION_ID,
- notificationId,
+ NotificationHandler.INCOMING_CALL_NOTIFICATION_ID,
)
}
}
diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/receivers/DismissNotificationBroadcastReceiver.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/receivers/DismissNotificationBroadcastReceiver.kt
deleted file mode 100644
index fa863a425a..0000000000
--- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/notifications/internal/receivers/DismissNotificationBroadcastReceiver.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2014-2024 Stream.io Inc. All rights reserved.
- *
- * Licensed under the Stream License;
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://github.com/GetStream/stream-video-android/blob/main/LICENSE
- *
- * 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.getstream.video.android.core.notifications.internal.receivers
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.os.Build
-import androidx.core.app.NotificationManagerCompat
-import io.getstream.log.taggedLogger
-import io.getstream.video.android.core.Call
-import io.getstream.video.android.core.notifications.NotificationHandler
-import io.getstream.video.android.core.notifications.NotificationHandler.Companion.INTENT_EXTRA_NEXT_ACTION
-import io.getstream.video.android.core.notifications.NotificationHandler.Companion.INTENT_EXTRA_NOTIFICATION_ID
-
-/**
- * Used to dismiss a notification. Internal to stream.
- */
-internal class DismissNotificationBroadcastReceiver : GenericCallActionBroadcastReceiver() {
-
- val logger by taggedLogger("DismissNotificationBroadcastReceiver")
- override val action = NotificationHandler.ACTION_DISMISS_NOTIFICATION
-
- override fun onReceive(context: Context?, intent: Intent?) {
- // Dismiss notification right away
- val notificationId = intent?.getIntExtra(INTENT_EXTRA_NOTIFICATION_ID, 0)
- if (context != null && notificationId != null) {
- NotificationManagerCompat.from(context).cancel(notificationId)
- }
- // Proceed with processing see GenericCallActionBroadcastReceiver for details
- super.onReceive(context, intent)
- }
-
- override suspend fun onReceive(call: Call, context: Context, intent: Intent) {
- val nextAction: PendingIntent? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- intent.getParcelableExtra(INTENT_EXTRA_NEXT_ACTION, PendingIntent::class.java)
- } else {
- intent.getParcelableExtra(INTENT_EXTRA_NEXT_ACTION)
- }
- if (nextAction == null) {
- logger.w { "You dismissed a notification, but did not proceed further with the actions." }
- } else {
- // Send the pending intent
- nextAction.send()
- }
- }
-}
diff --git a/stream-video-android-ui-compose/api/stream-video-android-ui-compose.api b/stream-video-android-ui-compose/api/stream-video-android-ui-compose.api
index 3cde11ead0..a17726a284 100644
--- a/stream-video-android-ui-compose/api/stream-video-android-ui-compose.api
+++ b/stream-video-android-ui-compose/api/stream-video-android-ui-compose.api
@@ -356,8 +356,12 @@ public final class io/getstream/video/android/compose/theme/VideoThemeKt {
public final class io/getstream/video/android/compose/ui/ComposableSingletons$StreamCallActivityComposeDelegateKt {
public static final field INSTANCE Lio/getstream/video/android/compose/ui/ComposableSingletons$StreamCallActivityComposeDelegateKt;
public static field lambda-1 Lkotlin/jvm/functions/Function2;
+ public static field lambda-2 Lkotlin/jvm/functions/Function2;
+ public static field lambda-3 Lkotlin/jvm/functions/Function2;
public fun ()V
public final fun getLambda-1$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function2;
+ public final fun getLambda-2$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function2;
+ public final fun getLambda-3$stream_video_android_ui_compose_release ()Lkotlin/jvm/functions/Function2;
}
public class io/getstream/video/android/compose/ui/ComposeStreamCallActivity : io/getstream/video/android/ui/common/StreamCallActivity {
@@ -374,8 +378,11 @@ public class io/getstream/video/android/compose/ui/StreamCallActivityComposeDele
public fun DefaultCallContent (Lio/getstream/video/android/ui/common/StreamCallActivity;Lio/getstream/video/android/core/Call;Landroidx/compose/runtime/Composer;I)V
public fun NoAnswerContent (Lio/getstream/video/android/ui/common/StreamCallActivity;Lio/getstream/video/android/core/Call;Landroidx/compose/runtime/Composer;I)V
public fun NoPermissions (Lio/getstream/video/android/ui/common/StreamCallActivity;Ljava/util/List;Ljava/util/List;ZLandroidx/compose/runtime/Composer;II)V
+ public fun OnIncomingCallContent (Landroidx/compose/ui/Modifier;Lio/getstream/video/android/core/Call;ZZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;I)V
+ public fun OnOutgoingCallContent (Landroidx/compose/ui/Modifier;Lio/getstream/video/android/core/Call;ZZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;I)V
public fun RejectedContent (Lio/getstream/video/android/ui/common/StreamCallActivity;Lio/getstream/video/android/core/Call;Landroidx/compose/runtime/Composer;I)V
public fun RootContent (Lio/getstream/video/android/ui/common/StreamCallActivity;Lio/getstream/video/android/core/Call;Landroidx/compose/runtime/Composer;I)V
+ public fun loadingContent (Lio/getstream/video/android/ui/common/StreamCallActivity;)V
public fun setContent (Lio/getstream/video/android/ui/common/StreamCallActivity;Lio/getstream/video/android/core/Call;)V
}
@@ -1584,7 +1591,7 @@ public final class io/getstream/video/android/compose/ui/components/call/ringing
}
public final class io/getstream/video/android/compose/ui/components/call/ringing/RingingCallContentKt {
- public static final fun RingingCallContent (Lio/getstream/video/android/core/Call;Landroidx/compose/ui/Modifier;ZZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;III)V
+ public static final fun RingingCallContent (Lio/getstream/video/android/core/Call;Landroidx/compose/ui/Modifier;ZZLkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function5;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function11;Lkotlin/jvm/functions/Function11;Landroidx/compose/runtime/Composer;III)V
}
public final class io/getstream/video/android/compose/ui/components/call/ringing/incomingcall/ComposableSingletons$IncomingCallContentKt {
diff --git a/stream-video-android-ui-compose/src/main/kotlin/io/getstream/video/android/compose/ui/StreamCallActivityComposeDelegate.kt b/stream-video-android-ui-compose/src/main/kotlin/io/getstream/video/android/compose/ui/StreamCallActivityComposeDelegate.kt
index c1516d7090..28c2316bb4 100644
--- a/stream-video-android-ui-compose/src/main/kotlin/io/getstream/video/android/compose/ui/StreamCallActivityComposeDelegate.kt
+++ b/stream-video-android-ui-compose/src/main/kotlin/io/getstream/video/android/compose/ui/StreamCallActivityComposeDelegate.kt
@@ -22,17 +22,24 @@ import android.net.Uri
import android.provider.Settings
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
+import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -46,12 +53,17 @@ import io.getstream.video.android.compose.ui.components.base.styling.StreamDialo
import io.getstream.video.android.compose.ui.components.base.styling.StyleSize
import io.getstream.video.android.compose.ui.components.call.activecall.CallContent
import io.getstream.video.android.compose.ui.components.call.ringing.RingingCallContent
+import io.getstream.video.android.compose.ui.components.call.ringing.incomingcall.IncomingCallContent
+import io.getstream.video.android.compose.ui.components.call.ringing.outgoingcall.OutgoingCallContent
import io.getstream.video.android.core.Call
+import io.getstream.video.android.core.MemberState
import io.getstream.video.android.core.RealtimeConnection
+import io.getstream.video.android.core.call.state.CallAction
import io.getstream.video.android.core.call.state.DeclineCall
import io.getstream.video.android.core.call.state.LeaveCall
import io.getstream.video.android.ui.common.StreamActivityUiDelegate
import io.getstream.video.android.ui.common.StreamCallActivity
+import io.getstream.video.android.ui.common.util.StreamCallActivityDelicateApi
/**
* A default implementation of the compose delegate for the call activity.
@@ -68,6 +80,26 @@ public open class StreamCallActivityComposeDelegate : StreamActivityUiDelegate Unit)?,
+ detailsContent: @Composable (
+ ColumnScope.(
+ participants: List,
+ topPadding: Dp,
+ ) -> Unit
+ )?,
+ controlsContent: @Composable (BoxScope.() -> Unit)?,
+ onBackPressed: () -> Unit,
+ onCallAction: (CallAction) -> Unit,
+ ->
+ OnOutgoingCallContent(
+ call = call,
+ isVideoType = isVideoType,
+ modifier = modifier,
+ isShowingHeader = isShowingHeader,
+ headerContent = headerContent,
+ detailsContent = detailsContent,
+ controlsContent = controlsContent,
+ onBackPressed = onBackPressed,
+ onCallAction = onCallAction,
+ )
+ },
+ onIncomingContent = { modifier: Modifier,
+ call: Call,
+ isVideoType: Boolean, isShowingHeader: Boolean,
+ headerContent: @Composable (ColumnScope.() -> Unit)?,
+ detailsContent: @Composable (
+ ColumnScope.(
+ participants: List,
+ topPadding: Dp,
+ ) -> Unit
+ )?,
+ controlsContent: @Composable (BoxScope.() -> Unit)?,
+ onBackPressed: () -> Unit,
+ onCallAction: (CallAction) -> Unit,
+ ->
+ OnIncomingCallContent(
+ call = call,
+ isVideoType = isVideoType,
+ modifier = modifier,
+ isShowingHeader = isShowingHeader,
+ headerContent = headerContent,
+ detailsContent = detailsContent,
+ controlsContent = controlsContent,
+ onBackPressed = onBackPressed,
+ onCallAction = onCallAction,
+ )
+ },
onAcceptedContent = {
if (isVideoCall(call)) {
DefaultCallContent(call = call)
@@ -154,6 +240,66 @@ public open class StreamCallActivityComposeDelegate : StreamActivityUiDelegate Unit)?,
+ detailsContent: (
+ @Composable ColumnScope.(
+ participants: List,
+ topPadding: Dp,
+ ) -> Unit
+ )?,
+ controlsContent: (@Composable BoxScope.() -> Unit)?,
+ onBackPressed: () -> Unit,
+ onCallAction: (CallAction) -> Unit,
+ ) {
+ OutgoingCallContent(
+ call = call,
+ isVideoType = isVideoType,
+ modifier = modifier,
+ isShowingHeader = isShowingHeader,
+ headerContent = headerContent,
+ detailsContent = detailsContent,
+ controlsContent = controlsContent,
+ onBackPressed = onBackPressed,
+ onCallAction = onCallAction,
+ )
+ }
+
+ @Composable
+ public open fun OnIncomingCallContent(
+ modifier: Modifier,
+ call: Call,
+ isVideoType: Boolean,
+ isShowingHeader: Boolean,
+ headerContent: (@Composable ColumnScope.() -> Unit)?,
+ detailsContent: (
+ @Composable ColumnScope.(
+ participants: List,
+ topPadding: Dp,
+ ) -> Unit
+ )?,
+ controlsContent: (@Composable BoxScope.() -> Unit)?,
+ onBackPressed: () -> Unit,
+ onCallAction: (CallAction) -> Unit,
+ ) {
+ IncomingCallContent(
+ call = call,
+ isVideoType = isVideoType,
+ modifier = modifier,
+ isShowingHeader = isShowingHeader,
+ headerContent = headerContent,
+ detailsContent = detailsContent,
+ controlsContent = controlsContent,
+ onBackPressed = onBackPressed,
+ onCallAction = onCallAction,
+ )
+ }
+
/**
* Content when the call is not answered.
*
@@ -193,7 +339,8 @@ public open class StreamCallActivityComposeDelegate : StreamActivityUiDelegate Unit,
onRejectedContent: @Composable () -> Unit = {},
onNoAnswerContent: @Composable () -> Unit = {},
+ onIncomingContent: (
+ @Composable (
+ modifier: Modifier,
+ call: Call,
+ isVideoType: Boolean,
+ isShowingHeader: Boolean,
+ headerContent: (@Composable ColumnScope.() -> Unit)?,
+ detailsContent: (
+ @Composable ColumnScope.(
+ participants: List,
+ topPadding: Dp,
+ ) -> Unit
+ )?,
+ controlsContent: (@Composable BoxScope.() -> Unit)?,
+ onBackPressed: () -> Unit,
+ onCallAction: (CallAction) -> Unit,
+ ) -> Unit
+ )? = null,
+ onOutgoingContent: (
+ @Composable (
+ modifier: Modifier,
+ call: Call,
+ isVideoType: Boolean,
+ isShowingHeader: Boolean,
+ headerContent: (@Composable ColumnScope.() -> Unit)?,
+ detailsContent: (
+ @Composable ColumnScope.(
+ participants: List,
+ topPadding: Dp,
+ ) -> Unit
+ )?,
+ controlsContent: (@Composable BoxScope.() -> Unit)?,
+ onBackPressed: () -> Unit,
+ onCallAction: (CallAction) -> Unit,
+ ) -> Unit
+ )? = null,
) {
val ringingState by call.state.ringingState.collectAsStateWithLifecycle()
when (ringingState) {
is RingingState.Incoming -> {
- IncomingCallContent(
+ onIncomingContent?.invoke(
+ modifier,
+ call,
+ isVideoType,
+ isShowingHeader,
+ headerContent,
+ detailsContent,
+ controlsContent,
+ onBackPressed,
+ onCallAction,
+ ) ?: IncomingCallContent(
call = call,
isVideoType = isVideoType,
modifier = modifier,
@@ -93,7 +139,17 @@ public fun RingingCallContent(
}
is RingingState.Outgoing -> {
- OutgoingCallContent(
+ onOutgoingContent?.invoke(
+ modifier,
+ call,
+ isVideoType,
+ isShowingHeader,
+ headerContent,
+ detailsContent,
+ controlsContent,
+ onBackPressed,
+ onCallAction,
+ ) ?: OutgoingCallContent(
call = call,
isVideoType = isVideoType,
modifier = modifier,
diff --git a/stream-video-android-ui-compose/src/main/kotlin/io/getstream/video/android/compose/ui/components/call/ringing/outgoingcall/OutgoingCallContent.kt b/stream-video-android-ui-compose/src/main/kotlin/io/getstream/video/android/compose/ui/components/call/ringing/outgoingcall/OutgoingCallContent.kt
index b50a7b04fe..ced2713ad8 100644
--- a/stream-video-android-ui-compose/src/main/kotlin/io/getstream/video/android/compose/ui/components/call/ringing/outgoingcall/OutgoingCallContent.kt
+++ b/stream-video-android-ui-compose/src/main/kotlin/io/getstream/video/android/compose/ui/components/call/ringing/outgoingcall/OutgoingCallContent.kt
@@ -156,6 +156,7 @@ public fun OutgoingCallContent(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = VideoTheme.dimens.componentHeightM),
+ isVideoCall = isVideoType,
isCameraEnabled = isCameraEnabled,
isMicrophoneEnabled = isMicrophoneEnabled,
onCallAction = onCallAction,
diff --git a/stream-video-android-ui-core/api/stream-video-android-ui-core.api b/stream-video-android-ui-core/api/stream-video-android-ui-core.api
index 940e34bfbc..62566f372d 100644
--- a/stream-video-android-ui-core/api/stream-video-android-ui-core.api
+++ b/stream-video-android-ui-core/api/stream-video-android-ui-core.api
@@ -20,6 +20,7 @@ public final class io/getstream/video/android/ui/common/AbstractCallActivity$Com
}
public abstract interface class io/getstream/video/android/ui/common/StreamActivityUiDelegate {
+ public abstract fun loadingContent (Lio/getstream/video/android/ui/common/StreamCallActivity;)V
public abstract fun setContent (Lio/getstream/video/android/ui/common/StreamCallActivity;Lio/getstream/video/android/core/Call;)V
}
diff --git a/stream-video-android-ui-core/src/main/kotlin/io/getstream/video/android/ui/common/StreamActivityUiDelegate.kt b/stream-video-android-ui-core/src/main/kotlin/io/getstream/video/android/ui/common/StreamActivityUiDelegate.kt
index fb42d7681a..bb89753011 100644
--- a/stream-video-android-ui-core/src/main/kotlin/io/getstream/video/android/ui/common/StreamActivityUiDelegate.kt
+++ b/stream-video-android-ui-core/src/main/kotlin/io/getstream/video/android/ui/common/StreamActivityUiDelegate.kt
@@ -20,6 +20,12 @@ import io.getstream.video.android.core.Call
public interface StreamActivityUiDelegate {
+ /**
+ * Called when the [setContent] cannot yet be invoked (missing [Call] for e.g.).
+ * Used to show some UI in the activity if the call is not yet loaded.
+ */
+ public fun loadingContent(activity: T)
+
/**
* Set the content for the activity,
*
diff --git a/stream-video-android-ui-core/src/main/kotlin/io/getstream/video/android/ui/common/StreamCallActivity.kt b/stream-video-android-ui-core/src/main/kotlin/io/getstream/video/android/ui/common/StreamCallActivity.kt
index f2680fb702..97b29921f6 100644
--- a/stream-video-android-ui-core/src/main/kotlin/io/getstream/video/android/ui/common/StreamCallActivity.kt
+++ b/stream-video-android-ui-core/src/main/kotlin/io/getstream/video/android/ui/common/StreamCallActivity.kt
@@ -121,6 +121,8 @@ public abstract class StreamCallActivity : ComponentActivity() {
// Platform restriction
public final override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ val uiDelegate = uiDelegate()
+ uiDelegate.loadingContent(this)
onPreCreate(savedInstanceState, null)
logger.d { "Entered [onCreate(Bundle?)" }
initializeCallOrFail(
@@ -145,6 +147,8 @@ public abstract class StreamCallActivity : ComponentActivity() {
persistentState: PersistableBundle?,
) {
super.onCreate(savedInstanceState)
+ val uiDelegate = uiDelegate()
+ uiDelegate.loadingContent(this)
onPreCreate(savedInstanceState, persistentState)
logger.d { "Entered [onCreate(Bundle, PersistableBundle?)" }
initializeCallOrFail(