From f7461e66648c7ac68f05b3fb933d6cacc024cac1 Mon Sep 17 00:00:00 2001 From: Aleksandar Apostolov Date: Mon, 18 May 2026 16:43:06 +0200 Subject: [PATCH] feat(core): add CallType.AudioRoom for the audio_room server call type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds CallType.AudioRoom (name = "audio_room") to mirror the same-named call type used by React and iOS. Overrides sortPreset to LivestreamOrAudioRoom so group audio chats self-sort with role-aware ordering out of the box. Distinct from CallType.AudioCall (Android-specific 1:1 voice call). AudioCall keeps SortPreset.Default — role-based sort doesn't apply to a two-participant call. Updates CallType.fromName to include AudioRoom in the lookup list. Tests: extends CallTypeSortPresetTest with assertions for AudioRoom.sortPreset and the fromName("audio_room") resolution path. apiCheck vs develop: additive only. --- .../api/stream-video-android-core.api | 5 +++++ .../video/android/core/call/CallType.kt | 17 ++++++++++++++++- .../core/sorting/CallTypeSortPresetTest.kt | 19 ++++++++++++++++--- 3 files changed, 37 insertions(+), 4 deletions(-) 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 781e6b618c..4bde2d0825 100644 --- a/stream-video-android-core/api/stream-video-android-core.api +++ b/stream-video-android-core/api/stream-video-android-core.api @@ -9648,6 +9648,11 @@ public final class io/getstream/video/android/core/call/CallType$AudioCall : io/ public static final field INSTANCE Lio/getstream/video/android/core/call/CallType$AudioCall; } +public final class io/getstream/video/android/core/call/CallType$AudioRoom : io/getstream/video/android/core/call/CallType { + public static final field INSTANCE Lio/getstream/video/android/core/call/CallType$AudioRoom; + public fun getSortPreset ()Lio/getstream/video/android/core/sorting/SortPreset; +} + public final class io/getstream/video/android/core/call/CallType$Companion { public final fun fromName (Ljava/lang/String;)Lio/getstream/video/android/core/call/CallType; } diff --git a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/call/CallType.kt b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/call/CallType.kt index de1d6dda4f..79c8e23daa 100644 --- a/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/call/CallType.kt +++ b/stream-video-android-core/src/main/kotlin/io/getstream/video/android/core/call/CallType.kt @@ -30,6 +30,15 @@ sealed class CallType(val name: String) { object Livestream : CallType("livestream") { override val sortPreset: SortPreset get() = SortPreset.LivestreamOrAudioRoom } + + /** + * Group audio chat (mirrors React's `audio_room` and iOS's `audio_room` call type). + * Distinct from [AudioCall], which is the Android-specific 1:1 voice call type. + */ + object AudioRoom : CallType("audio_room") { + override val sortPreset: SortPreset get() = SortPreset.LivestreamOrAudioRoom + } + object AudioCall : CallType("audio_call") object Default : CallType("default") object AnyMarker : CallType("ALL_CALL_TYPES") @@ -43,7 +52,13 @@ sealed class CallType(val name: String) { companion object { fun fromName(name: String): CallType? { - return listOf(Livestream, AudioCall, Default, AnyMarker).find { it.name == name } + return listOf( + Livestream, + AudioRoom, + AudioCall, + Default, + AnyMarker, + ).find { it.name == name } } } } diff --git a/stream-video-android-core/src/test/kotlin/io/getstream/video/android/core/sorting/CallTypeSortPresetTest.kt b/stream-video-android-core/src/test/kotlin/io/getstream/video/android/core/sorting/CallTypeSortPresetTest.kt index 6043900179..2862bbedb0 100644 --- a/stream-video-android-core/src/test/kotlin/io/getstream/video/android/core/sorting/CallTypeSortPresetTest.kt +++ b/stream-video-android-core/src/test/kotlin/io/getstream/video/android/core/sorting/CallTypeSortPresetTest.kt @@ -37,14 +37,27 @@ class CallTypeSortPresetTest { assertThat(CallType.Livestream.sortPreset).isEqualTo(SortPreset.LivestreamOrAudioRoom) } + @Test + fun `AudioRoom call type uses SortPreset LivestreamOrAudioRoom`() { + // CallType.AudioRoom mirrors the "audio_room" server type used by React and iOS. + // It applies the same livestream-style sort (activity + roles). + assertThat(CallType.AudioRoom.sortPreset).isEqualTo(SortPreset.LivestreamOrAudioRoom) + } + @Test fun `AudioCall call type falls back to SortPreset Default (1to1 audio is not livestream-like)`() { - // CallType.AudioCall represents a 1:1 audio call, not the React/iOS audio_room - // concept. Auto-applying LivestreamOrAudioRoom there would mis-sort the two - // participants. Stays on Default until a dedicated AudioRoom call type lands. + // CallType.AudioCall represents a 1:1 audio call, distinct from AudioRoom (group + // audio). Auto-applying LivestreamOrAudioRoom there would mis-sort the two + // participants. AudioCall stays on Default. assertThat(CallType.AudioCall.sortPreset).isEqualTo(SortPreset.Default) } + @Test + fun `fromName audio_room resolves to AudioRoom call type with LivestreamOrAudioRoom preset`() { + val resolved = CallType.fromName("audio_room")?.sortPreset ?: SortPreset.Default + assertThat(resolved).isEqualTo(SortPreset.LivestreamOrAudioRoom) + } + @Test fun `Custom call types default to SortPreset Default`() { val custom = CallType.CustomCallType("my_custom_type")