diff --git a/app/src/main/java/live/hms/app2/ui/home/HomeFragment.kt b/app/src/main/java/live/hms/app2/ui/home/HomeFragment.kt
index 19185375d..2ade9a615 100644
--- a/app/src/main/java/live/hms/app2/ui/home/HomeFragment.kt
+++ b/app/src/main/java/live/hms/app2/ui/home/HomeFragment.kt
@@ -11,6 +11,7 @@ import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
+import android.widget.EditText
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
@@ -26,7 +27,6 @@ import live.hms.roomkit.ui.settings.SettingsMode
import live.hms.roomkit.ui.settings.SettingsStore
import live.hms.roomkit.util.EmailUtils
import live.hms.app2.util.*
-import live.hms.roomkit.util.NameUtils.isValidUserName
import live.hms.roomkit.ui.HMSPrebuiltOptions
import live.hms.roomkit.ui.HMSRoomKit
import live.hms.roomkit.ui.meeting.*
@@ -249,6 +249,15 @@ class HomeFragment : Fragment() {
}
}
+ fun isValidUserName(editText: EditText): Boolean {
+ val username = editText.text.toString()
+ if (username.isEmpty()) {
+ return false
+ }
+ return true
+ }
+
+
private fun enableButton() {
binding.btnJoinNow.isEnabled = true
binding.btnJoinNow.background =
diff --git a/common/.gitignore b/common/.gitignore
new file mode 100644
index 000000000..42afabfd2
--- /dev/null
+++ b/common/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/common/build.gradle b/common/build.gradle
new file mode 100644
index 000000000..9cfde5b76
--- /dev/null
+++ b/common/build.gradle
@@ -0,0 +1,121 @@
+plugins {
+ id 'com.android.library'
+ id 'kotlin-android'
+ id 'kotlin-kapt'
+ id 'maven-publish'
+ id 'kotlin-parcelize'
+ id 'signing'
+ id "org.jetbrains.dokka" version "1.5.0"
+}
+
+def getVersionName = { ->
+ return "$HMS_ROOM_KIT_VERSION"
+}
+
+android {
+ namespace 'live.hms.common'
+ compileSdk 33
+
+ defaultConfig {
+ minSdk 21
+ targetSdk 33
+ versionCode 1
+ versionName getVersionName()
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ dataBinding {
+ enabled true
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ publishing {
+ singleVariant('release') {
+ withSourcesJar()
+ }
+ }
+
+}
+
+dependencies {
+ implementation 'androidx.core:core:1.10.1'
+ def hmsVersion = "2.7.7-de"
+ // To add dependencies of specific module
+ implementation "live.100ms:android-sdk:$hmsVersion"
+ implementation "live.100ms:video-view:$hmsVersion"
+ implementation 'com.google.code.gson:gson:2.8.6'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+}
+
+
+task javadocJar(type: Jar, dependsOn: dokkaJavadoc) {
+ archiveFileName = "javadoc.jar"
+ from "build/dokka/javadoc"
+ archiveClassifier.set("javadoc")
+}
+
+afterEvaluate {
+ publishing {
+ publications {
+ // Creates a Maven publication called "release".
+ release(MavenPublication) {
+ from components.release
+ pom {
+ // Only sign the artefacts if this is a maven central build.
+ // This would only halt jitpack builds and/or make our signing keys public.
+ if(rootProject.properties["ossrhUsername"]) {
+ artifact javadocJar
+ signing {
+ sign publishing.publications
+ }
+ }
+ name = "100ms.live Android Room Kit"
+ description = "Room Kit that simplifies setting up videoconferencing in your own app. See more at https://www.100ms.live/docs/android/v2/guides/quickstart"
+ url = "100ms.live"
+ licenses {
+ license {
+ name = 'MIT License'
+ url = 'http://www.opensource.org/licenses/mit-license.php'
+ }
+ }
+ developers {
+ developer {
+ id = '1'
+ name = '100ms'
+ email = 'support@100ms.live'
+ }
+ }
+ scm {
+ connection = 'SCM is private'
+ developerConnection = 'SCM is private'
+ url = 'SCM is private'
+ }
+ }
+ groupId = "live.100ms"
+ artifactId = 'common'
+ version = getVersionName()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/consumer-rules.pro b/common/consumer-rules.pro
new file mode 100644
index 000000000..e69de29bb
diff --git a/common/proguard-rules.pro b/common/proguard-rules.pro
new file mode 100644
index 000000000..481bb4348
--- /dev/null
+++ b/common/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/common/src/androidTest/java/live/hms/common/ExampleInstrumentedTest.kt b/common/src/androidTest/java/live/hms/common/ExampleInstrumentedTest.kt
new file mode 100644
index 000000000..722069bd9
--- /dev/null
+++ b/common/src/androidTest/java/live/hms/common/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package live.hms.common
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("live.hms.common.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/AndroidManifest.xml b/common/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..a5918e68a
--- /dev/null
+++ b/common/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/util/NameUtils.kt b/common/src/main/java/live/hms/common/util/NameUtils.kt
similarity index 97%
rename from room-kit/src/main/java/live/hms/roomkit/util/NameUtils.kt
rename to common/src/main/java/live/hms/common/util/NameUtils.kt
index 7e7dab8d0..4510f14b3 100644
--- a/room-kit/src/main/java/live/hms/roomkit/util/NameUtils.kt
+++ b/common/src/main/java/live/hms/common/util/NameUtils.kt
@@ -1,4 +1,4 @@
-package live.hms.roomkit.util
+package live.hms.common.util
import android.widget.EditText
import java.util.*
diff --git a/room-kit/src/main/java/live/hms/roomkit/util/ViewExt.kt b/common/src/main/java/live/hms/common/util/ViewExt.kt
similarity index 93%
rename from room-kit/src/main/java/live/hms/roomkit/util/ViewExt.kt
rename to common/src/main/java/live/hms/common/util/ViewExt.kt
index d68430458..f8e928294 100644
--- a/room-kit/src/main/java/live/hms/roomkit/util/ViewExt.kt
+++ b/common/src/main/java/live/hms/common/util/ViewExt.kt
@@ -1,4 +1,4 @@
-package live.hms.roomkit.util
+package live.hms.common.util
import android.app.Activity
import android.app.AlertDialog
@@ -12,8 +12,7 @@ import android.view.*
import android.view.accessibility.AccessibilityManager
import androidx.core.content.FileProvider
import androidx.core.view.GestureDetectorCompat
-import live.hms.roomkit.R
-import live.hms.roomkit.helpers.OnSingleClickListener
+import live.hms.common.util.helpers.OnSingleClickListener
import live.hms.video.media.capturers.camera.CameraControl
import live.hms.video.media.settings.HMSSimulcastLayerDefinition
import live.hms.video.media.tracks.HMSLocalVideoTrack
@@ -80,7 +79,7 @@ fun Bitmap.saveCaptureToLocalCache(context: Context) : Uri? {
val imagePath = File(context.cacheDir, "images")
val newFile = File(imagePath, "image.png")
- return FileProvider.getUriForFile(context, "live.hms.roomkit.provider", newFile)
+ return null
}
@@ -98,9 +97,6 @@ fun Activity.openShareIntent(uri: Uri) {
startActivity(Intent.createChooser(shareIntent, "Choose an app"))
}
-fun HMSVideoTrack?.isValid(): Boolean {
- return !(this == null || this.isMute || this.isDegraded)
-}
fun Context.showTileListDialog(
@@ -139,6 +135,8 @@ fun SurfaceViewRenderer.onBitMap(onBitmap: (Bitmap?) -> Unit, scale : Float = 1.
}, scale)
}
+
+
fun Context.showSimulcastDialog(hmsVideoTrack: HMSRemoteVideoTrack?) {
if (hmsVideoTrack == null)
return
@@ -196,17 +194,7 @@ fun Context.showMirrorOptions(surfaceViewRenderer: SurfaceViewRenderer?) {
}
-fun SurfaceViewRenderer.setInit() {
- setTag(R.id.IS_INT,true)
-}
-fun SurfaceViewRenderer.setRelease() {
- setTag(R.id.IS_INT,false)
-}
-
-fun SurfaceViewRenderer.isInit() : Boolean {
- return (getTag(R.id.IS_INT) as? Boolean) == true
-}
fun HMSVideoTrack?.switchCamera() {
(this as? HMSLocalVideoTrack)?.switchCamera()
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/CustomPeerMetadata.kt b/common/src/main/java/live/hms/common/util/helpers/CustomPeerMetadata.kt
similarity index 97%
rename from room-kit/src/main/java/live/hms/roomkit/ui/meeting/CustomPeerMetadata.kt
rename to common/src/main/java/live/hms/common/util/helpers/CustomPeerMetadata.kt
index 2e77c88f1..709e5ab2c 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/CustomPeerMetadata.kt
+++ b/common/src/main/java/live/hms/common/util/helpers/CustomPeerMetadata.kt
@@ -1,4 +1,4 @@
-package live.hms.roomkit.ui.meeting
+package live.hms.common.util.helpers
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
diff --git a/room-kit/src/main/java/live/hms/roomkit/helpers/NetworkQualityHelper.kt b/common/src/main/java/live/hms/common/util/helpers/NetworkQualityHelper.kt
similarity index 93%
rename from room-kit/src/main/java/live/hms/roomkit/helpers/NetworkQualityHelper.kt
rename to common/src/main/java/live/hms/common/util/helpers/NetworkQualityHelper.kt
index b6753fdb0..460b2cced 100644
--- a/room-kit/src/main/java/live/hms/roomkit/helpers/NetworkQualityHelper.kt
+++ b/common/src/main/java/live/hms/common/util/helpers/NetworkQualityHelper.kt
@@ -1,9 +1,9 @@
-package live.hms.roomkit.helpers
+package live.hms.common.util.helpers
import android.content.Context
import android.graphics.drawable.Drawable
import androidx.core.content.ContextCompat
-import live.hms.roomkit.R
+import live.hms.common.R
class NetworkQualityHelper {
diff --git a/room-kit/src/main/java/live/hms/roomkit/helpers/OnSingleClickListener.kt b/common/src/main/java/live/hms/common/util/helpers/OnSingleClickListener.kt
similarity index 96%
rename from room-kit/src/main/java/live/hms/roomkit/helpers/OnSingleClickListener.kt
rename to common/src/main/java/live/hms/common/util/helpers/OnSingleClickListener.kt
index f99c862ca..5c49cb91c 100644
--- a/room-kit/src/main/java/live/hms/roomkit/helpers/OnSingleClickListener.kt
+++ b/common/src/main/java/live/hms/common/util/helpers/OnSingleClickListener.kt
@@ -1,4 +1,4 @@
-package live.hms.roomkit.helpers
+package live.hms.common.util.helpers
import android.view.View
diff --git a/room-kit/src/main/res/drawable/avd_mic_off_to_on.xml b/common/src/main/res/drawable/avd_mic_off_to_on.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/avd_mic_off_to_on.xml
rename to common/src/main/res/drawable/avd_mic_off_to_on.xml
diff --git a/room-kit/src/main/res/drawable/avd_mic_on_to_off.xml b/common/src/main/res/drawable/avd_mic_on_to_off.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/avd_mic_on_to_off.xml
rename to common/src/main/res/drawable/avd_mic_on_to_off.xml
diff --git a/room-kit/src/main/res/drawable/avd_video_off_to_on.xml b/common/src/main/res/drawable/avd_video_off_to_on.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/avd_video_off_to_on.xml
rename to common/src/main/res/drawable/avd_video_off_to_on.xml
diff --git a/room-kit/src/main/res/drawable/avd_video_on_to_off.xml b/common/src/main/res/drawable/avd_video_on_to_off.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/avd_video_on_to_off.xml
rename to common/src/main/res/drawable/avd_video_on_to_off.xml
diff --git a/room-kit/src/main/res/drawable/circle_secondary_24.xml b/common/src/main/res/drawable/circle_secondary_24.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/circle_secondary_24.xml
rename to common/src/main/res/drawable/circle_secondary_24.xml
diff --git a/room-kit/src/main/res/drawable/circle_secondary_80.xml b/common/src/main/res/drawable/circle_secondary_80.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/circle_secondary_80.xml
rename to common/src/main/res/drawable/circle_secondary_80.xml
diff --git a/room-kit/src/main/res/drawable/dot_default_4.xml b/common/src/main/res/drawable/dot_default_4.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/dot_default_4.xml
rename to common/src/main/res/drawable/dot_default_4.xml
diff --git a/app/src/main/res/drawable/dot_selected_4.xml b/common/src/main/res/drawable/dot_selected_4.xml
similarity index 84%
rename from app/src/main/res/drawable/dot_selected_4.xml
rename to common/src/main/res/drawable/dot_selected_4.xml
index aedc1cbaa..1008c36f1 100644
--- a/app/src/main/res/drawable/dot_selected_4.xml
+++ b/common/src/main/res/drawable/dot_selected_4.xml
@@ -6,7 +6,7 @@
android:shape="ring"
android:thickness="4dp"
android:useLevel="false">
-
+
diff --git a/room-kit/src/main/res/drawable/dot_selector_4.xml b/common/src/main/res/drawable/dot_selector_4.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/dot_selector_4.xml
rename to common/src/main/res/drawable/dot_selector_4.xml
diff --git a/room-kit/src/main/res/drawable/ic_baseline_wifi_0.xml b/common/src/main/res/drawable/ic_baseline_wifi_0.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_baseline_wifi_0.xml
rename to common/src/main/res/drawable/ic_baseline_wifi_0.xml
diff --git a/room-kit/src/main/res/drawable/ic_baseline_wifi_1.xml b/common/src/main/res/drawable/ic_baseline_wifi_1.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_baseline_wifi_1.xml
rename to common/src/main/res/drawable/ic_baseline_wifi_1.xml
diff --git a/room-kit/src/main/res/drawable/ic_baseline_wifi_2.xml b/common/src/main/res/drawable/ic_baseline_wifi_2.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_baseline_wifi_2.xml
rename to common/src/main/res/drawable/ic_baseline_wifi_2.xml
diff --git a/room-kit/src/main/res/drawable/ic_baseline_wifi_3.xml b/common/src/main/res/drawable/ic_baseline_wifi_3.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_baseline_wifi_3.xml
rename to common/src/main/res/drawable/ic_baseline_wifi_3.xml
diff --git a/room-kit/src/main/res/drawable/ic_baseline_wifi_4.xml b/common/src/main/res/drawable/ic_baseline_wifi_4.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_baseline_wifi_4.xml
rename to common/src/main/res/drawable/ic_baseline_wifi_4.xml
diff --git a/room-kit/src/main/res/drawable/ic_baseline_wifi_5.xml b/common/src/main/res/drawable/ic_baseline_wifi_5.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_baseline_wifi_5.xml
rename to common/src/main/res/drawable/ic_baseline_wifi_5.xml
diff --git a/room-kit/src/main/res/drawable/ic_brb.xml b/common/src/main/res/drawable/ic_brb.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_brb.xml
rename to common/src/main/res/drawable/ic_brb.xml
diff --git a/room-kit/src/main/res/drawable/ic_degraded.xml b/common/src/main/res/drawable/ic_degraded.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_degraded.xml
rename to common/src/main/res/drawable/ic_degraded.xml
diff --git a/room-kit/src/main/res/drawable/ic_hand_raise.xml b/common/src/main/res/drawable/ic_hand_raise.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_hand_raise.xml
rename to common/src/main/res/drawable/ic_hand_raise.xml
diff --git a/room-kit/src/main/res/drawable/ic_mic_mute.xml b/common/src/main/res/drawable/ic_mic_mute.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_mic_mute.xml
rename to common/src/main/res/drawable/ic_mic_mute.xml
diff --git a/room-kit/src/main/res/drawable/ic_mobile_screen_share_24.xml b/common/src/main/res/drawable/ic_mobile_screen_share_24.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_mobile_screen_share_24.xml
rename to common/src/main/res/drawable/ic_mobile_screen_share_24.xml
diff --git a/room-kit/src/main/res/drawable/ic_share_screen.xml b/common/src/main/res/drawable/ic_share_screen.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_share_screen.xml
rename to common/src/main/res/drawable/ic_share_screen.xml
diff --git a/room-kit/src/main/res/drawable/ic_signal_medium.xml b/common/src/main/res/drawable/ic_signal_medium.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_signal_medium.xml
rename to common/src/main/res/drawable/ic_signal_medium.xml
diff --git a/room-kit/src/main/res/drawable/ic_signal_strong.xml b/common/src/main/res/drawable/ic_signal_strong.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_signal_strong.xml
rename to common/src/main/res/drawable/ic_signal_strong.xml
diff --git a/room-kit/src/main/res/drawable/ic_signal_terrible.xml b/common/src/main/res/drawable/ic_signal_terrible.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_signal_terrible.xml
rename to common/src/main/res/drawable/ic_signal_terrible.xml
diff --git a/room-kit/src/main/res/drawable/ic_signal_weak.xml b/common/src/main/res/drawable/ic_signal_weak.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/ic_signal_weak.xml
rename to common/src/main/res/drawable/ic_signal_weak.xml
diff --git a/room-kit/src/main/res/drawable/icon_maximised.xml b/common/src/main/res/drawable/icon_maximised.xml
similarity index 100%
rename from room-kit/src/main/res/drawable/icon_maximised.xml
rename to common/src/main/res/drawable/icon_maximised.xml
diff --git a/room-kit/src/main/res/font/clan_pro_medium.ttf b/common/src/main/res/font/clan_pro_medium.ttf
similarity index 100%
rename from room-kit/src/main/res/font/clan_pro_medium.ttf
rename to common/src/main/res/font/clan_pro_medium.ttf
diff --git a/room-kit/src/main/res/font/clan_pro_news.TTF b/common/src/main/res/font/clan_pro_news.TTF
similarity index 100%
rename from room-kit/src/main/res/font/clan_pro_news.TTF
rename to common/src/main/res/font/clan_pro_news.TTF
diff --git a/room-kit/src/main/res/font/inter_bold.ttf b/common/src/main/res/font/inter_bold.ttf
similarity index 100%
rename from room-kit/src/main/res/font/inter_bold.ttf
rename to common/src/main/res/font/inter_bold.ttf
diff --git a/room-kit/src/main/res/font/inter_extrabold.ttf b/common/src/main/res/font/inter_extrabold.ttf
similarity index 100%
rename from room-kit/src/main/res/font/inter_extrabold.ttf
rename to common/src/main/res/font/inter_extrabold.ttf
diff --git a/room-kit/src/main/res/font/inter_medium.ttf b/common/src/main/res/font/inter_medium.ttf
similarity index 100%
rename from room-kit/src/main/res/font/inter_medium.ttf
rename to common/src/main/res/font/inter_medium.ttf
diff --git a/room-kit/src/main/res/font/inter_regular.ttf b/common/src/main/res/font/inter_regular.ttf
similarity index 100%
rename from room-kit/src/main/res/font/inter_regular.ttf
rename to common/src/main/res/font/inter_regular.ttf
diff --git a/room-kit/src/main/res/font/inter_semibold.ttf b/common/src/main/res/font/inter_semibold.ttf
similarity index 100%
rename from room-kit/src/main/res/font/inter_semibold.ttf
rename to common/src/main/res/font/inter_semibold.ttf
diff --git a/room-kit/src/main/res/layout/fragment_video_grid_page.xml b/common/src/main/res/layout/fragment_video_grid_page.xml
similarity index 82%
rename from room-kit/src/main/res/layout/fragment_video_grid_page.xml
rename to common/src/main/res/layout/fragment_video_grid_page.xml
index fd0a34dd3..983388387 100644
--- a/room-kit/src/main/res/layout/fragment_video_grid_page.xml
+++ b/common/src/main/res/layout/fragment_video_grid_page.xml
@@ -5,4 +5,4 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="false"
- tools:context=".ui.meeting.videogrid.VideoGridPageFragment" />
+ />
diff --git a/room-kit/src/main/res/values/dimens.xml b/common/src/main/res/values/dimens.xml
similarity index 86%
rename from room-kit/src/main/res/values/dimens.xml
rename to common/src/main/res/values/dimens.xml
index e4cd7e0e1..542fe2b29 100644
--- a/room-kit/src/main/res/values/dimens.xml
+++ b/common/src/main/res/values/dimens.xml
@@ -8,6 +8,8 @@
186dp
16dp
8dp
+ 1dp
+ 4dp
4dp
32dp
\ No newline at end of file
diff --git a/common/src/test/java/live/hms/common/ExampleUnitTest.kt b/common/src/test/java/live/hms/common/ExampleUnitTest.kt
new file mode 100644
index 000000000..74f6a247f
--- /dev/null
+++ b/common/src/test/java/live/hms/common/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package live.hms.common
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/room-kit/build.gradle b/room-kit/build.gradle
index 2baa2dc73..8ea98dd79 100644
--- a/room-kit/build.gradle
+++ b/room-kit/build.gradle
@@ -74,7 +74,10 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.percentlayout:percentlayout:1.0.0'
- def hmsVersion = "2.7.2"
+ implementation "live.100ms:common:0.0.6"
+ implementation "live.100ms:videogrid:0.0.6"
+
+ def hmsVersion = "2.7.7-de"
// To add dependencies of specific module
implementation "live.100ms:android-sdk:$hmsVersion"
implementation "live.100ms:video-view:$hmsVersion"
diff --git a/room-kit/src/main/java/live/hms/roomkit/ViewExt.kt b/room-kit/src/main/java/live/hms/roomkit/ViewExt.kt
index 5fd1b417c..24faf7856 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ViewExt.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ViewExt.kt
@@ -19,7 +19,7 @@ import androidx.core.content.FileProvider
import androidx.core.view.GestureDetectorCompat
import androidx.fragment.app.Fragment
import live.hms.roomkit.R
-import live.hms.roomkit.helpers.OnSingleClickListener
+import live.hms.common.util.helpers.OnSingleClickListener
import live.hms.video.media.capturers.camera.CameraControl
import live.hms.video.media.settings.HMSSimulcastLayerDefinition
import live.hms.video.media.tracks.HMSLocalVideoTrack
@@ -270,72 +270,3 @@ fun SurfaceViewRenderer.isInit() : Boolean {
}
-fun HMSVideoView.setCameraGestureListener(track : HMSVideoTrack?,onImageCapture : (Uri)-> Unit, onLongPress: () -> Unit) {
-
- val cameraControl: CameraControl = (track as? HMSLocalVideoTrack)?.getCameraControl() ?: return
- var lastZoom = cameraControl.getMinZoom()
-
- val gestureDetector = GestureDetectorCompat(context, object : GestureDetector.SimpleOnGestureListener() {
-
- override fun onDown(e: MotionEvent) = true
- override fun onSingleTapUp(event: MotionEvent): Boolean {
- if (cameraControl.isTapToFocusSupported())
- cameraControl.setTapToFocusAt(
- event.x,
- event.y,
- viewWidth = width,
- viewHeight = height
- )
- return true
- }
-
- override fun onDoubleTap(e: MotionEvent): Boolean {
-
- val cachePath = File(context.cacheDir, "images")
- cachePath.mkdirs()
- val imageSavePath = File(cachePath, "image.jpeg")
-
- cameraControl.captureImageAtMaxSupportedResolution(imageSavePath) { it ->
-
- val fileSaveUri = FileProvider.getUriForFile(
- context,
- "live.hms.roomkit.provider",
- imageSavePath
- )
-
- onImageCapture.invoke(fileSaveUri)
- }
- return true
- }
-
- override fun onLongPress(e: MotionEvent) {
- onLongPress.invoke()
- }
-
-
-
- })
-
- val scaleGestureDetector = ScaleGestureDetector(
- context,
- object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
- override fun onScale(detector: ScaleGestureDetector): Boolean {
- if (cameraControl.isZoomSupported()) {
- lastZoom *= detector.scaleFactor
- cameraControl.setZoom(lastZoom)
- return true
- }
- return false
- }
- })
-
- this.setOnTouchListener { _, event ->
- var didConsume = scaleGestureDetector.onTouchEvent(event)
- if (!scaleGestureDetector.isInProgress) {
- didConsume = gestureDetector.onTouchEvent(event)
- }
- didConsume
- }
-
-
-}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/ChangeNameDialogFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/ChangeNameDialogFragment.kt
index 26ec79fb7..9d7f5a176 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/ChangeNameDialogFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/ChangeNameDialogFragment.kt
@@ -9,7 +9,7 @@ import android.widget.EditText
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import live.hms.roomkit.R
-import live.hms.roomkit.util.NameUtils.isValidUserName
+import live.hms.common.util.NameUtils.isValidUserName
class ChangeNameDialogFragment : DialogFragment() {
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/HlsStreamingToggleBottomSheet.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/HlsStreamingToggleBottomSheet.kt
index 8bf909f97..45658da5f 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/HlsStreamingToggleBottomSheet.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/HlsStreamingToggleBottomSheet.kt
@@ -9,7 +9,7 @@ import androidx.fragment.app.activityViewModels
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import live.hms.roomkit.databinding.HlsBottomSheetDialogBinding
import live.hms.roomkit.ui.meeting.participants.meetingToHlsUrl
-import live.hms.roomkit.util.setOnSingleClickListener
+import live.hms.common.util.setOnSingleClickListener
import live.hms.roomkit.util.viewLifecycle
import live.hms.video.sdk.models.HMSHlsRecordingConfig
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingActivity.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingActivity.kt
index f690adf72..558ef9637 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingActivity.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingActivity.kt
@@ -1,7 +1,6 @@
package live.hms.roomkit.ui.meeting
import android.Manifest.permission.BLUETOOTH_CONNECT
-import android.content.pm.PackageManager
import android.os.Bundle
import android.view.View
import android.view.WindowManager
@@ -10,10 +9,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
-import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
-import androidx.core.content.ContextCompat
-import androidx.core.view.WindowInsetsControllerCompat
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.NavHostFragment
import kotlinx.coroutines.launch
@@ -21,6 +17,8 @@ import live.hms.roomkit.R
import live.hms.roomkit.animation.RootViewDeferringInsetsCallback
import live.hms.roomkit.databinding.ActivityMeetingBinding
import live.hms.roomkit.ui.HMSPrebuiltOptions
+import live.hms.videogrid.GridViewModel
+import live.hms.videogrid.GridViewModelFactory
import live.hms.roomkit.ui.settings.SettingsStore
import live.hms.roomkit.util.ROOM_CODE
import live.hms.roomkit.util.ROOM_PREBUILT
@@ -43,6 +41,12 @@ class MeetingActivity : AppCompatActivity() {
)
}
+ private val gridViewModel : live.hms.videogrid.GridViewModel by viewModels {
+ live.hms.videogrid.GridViewModelFactory(
+ application
+ )
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivityMeetingBinding.inflate(layoutInflater)
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingFragment.kt
index 9c8da0460..607e3d454 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingFragment.kt
@@ -59,7 +59,6 @@ import live.hms.roomkit.ui.meeting.broadcastreceiver.PipUtils.muteTogglePipEvent
import live.hms.roomkit.ui.meeting.chat.ChatAdapter
import live.hms.roomkit.ui.meeting.chat.ChatUseCase
import live.hms.roomkit.ui.meeting.chat.ChatViewModel
-import live.hms.roomkit.ui.meeting.commons.VideoGridBaseFragment
import live.hms.roomkit.ui.meeting.participants.RtmpRecordBottomSheet
import live.hms.roomkit.ui.meeting.pinnedvideo.PinnedVideoFragment
import live.hms.roomkit.ui.meeting.videogrid.VideoGridFragment
@@ -706,8 +705,8 @@ class MeetingFragment : Fragment() {
if (settings.showReconnectingProgressBars) {
updateProgressBarUI(state.heading, state.message)
showProgressBar()
- if (currentFragment is VideoGridBaseFragment)
- (currentFragment as VideoGridBaseFragment).unbindViews()
+ if (currentFragment is live.hms.videogrid.VideoGridBaseFragment)
+ (currentFragment as live.hms.videogrid.VideoGridBaseFragment).unbindViews()
}
}
@@ -733,8 +732,8 @@ class MeetingFragment : Fragment() {
}
is MeetingState.Reconnected -> {
hideProgressBar()
- if (currentFragment is VideoGridBaseFragment)
- (currentFragment as VideoGridBaseFragment).bindViews()
+ if (currentFragment is live.hms.videogrid.VideoGridBaseFragment)
+ (currentFragment as live.hms.videogrid.VideoGridBaseFragment).bindViews()
isMeetingOngoing = true
}
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingViewModel.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingViewModel.kt
index 141f4ed1e..ee6809317 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingViewModel.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingViewModel.kt
@@ -13,8 +13,8 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.launch
+import live.hms.common.util.helpers.CustomPeerMetadata
import live.hms.roomkit.ui.HMSPrebuiltOptions
-import live.hms.roomkit.ui.meeting.activespeaker.ActiveSpeakerHandler
import live.hms.roomkit.ui.meeting.chat.ChatMessage
import live.hms.roomkit.ui.meeting.chat.Recipient
import live.hms.roomkit.ui.polls.PollCreationInfo
@@ -335,62 +335,9 @@ class MeetingViewModel(
// Live data containing the current Speaker in the meeting
val speakers = MutableLiveData>()
- private val activeSpeakerHandler = ActiveSpeakerHandler(false) { _tracks }
val updateRowAndColumnSpanForVideoPeerGrid = MutableLiveData>()
- val speakerUpdateLiveData = object : ActiveSpeakerLiveData() {
- private val speakerH = ActiveSpeakerHandler(true,settings.videoGridRows* settings.videoGridColumns
- ) { _tracks }
-
- override fun addSpeakerSource() {
- addSource(speakers) { speakers : Array ->
-
- val excludeLocalTrackIfRemotePeerIsPreset : Array =
- speakers.filter { it.peer?.isLocal == false }.toTypedArray()
-
- val result = speakerH.speakerUpdate(excludeLocalTrackIfRemotePeerIsPreset)
- setValue(result.first)
- }
- }
-
- override fun removeSpeakerSource() {
- removeSource(speakers)
- }
-
- //TODO can't be null
- fun refreshSpeaker() {
- // speakers.postValue(speakers.value)
- }
-
- override fun updateMaxActiveSpeaker(rowCount: Int, columnCount: Int) {
- speakerH.updateMaxActiveSpeaker(rowCount*columnCount)
- refreshSpeaker()
- }
- init {
- addSpeakerSource()
-
- // Add all tracks as they come in.
- addSource(tracks) { meetTracks: List ->
- //if remote peer and local peer is present inset mode
- val excludeLocalTrackIfRemotePeerIsPreset = if (meetTracks.size > 1) {
- meetTracks.filter { !it.isLocal }.toList()
- } else
- meetTracks
-
- val result = speakerH.trackUpdateTrigger(excludeLocalTrackIfRemotePeerIsPreset)
- setValue(result)
- }
-
- }
-
-
-
- }
-
- val activeSpeakers: LiveData, Array>> =
- speakers.map(activeSpeakerHandler::speakerUpdate)
- val activeSpeakersUpdatedTracks = _liveDataTracks.map(activeSpeakerHandler::trackUpdateTrigger)
// We need all the active speakers, but the very first time it should be filled.
// with all the tracks.
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PreviewFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PreviewFragment.kt
index 800b939c7..fdcbda618 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PreviewFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PreviewFragment.kt
@@ -4,7 +4,6 @@ import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
-import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
@@ -22,12 +21,17 @@ import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import com.bumptech.glide.Glide
+import live.hms.common.util.NameUtils
+import live.hms.common.util.openShareIntent
+import live.hms.common.util.setCameraGestureListener
+import live.hms.common.util.setOnSingleClickListener
+import live.hms.common.util.switchCamera
import live.hms.roomkit.R
import live.hms.roomkit.animation.ControlFocusInsetsAnimationCallback
import live.hms.roomkit.animation.TranslateDeferringInsetsAnimationCallback
import live.hms.roomkit.databinding.FragmentPreviewBinding
import live.hms.roomkit.drawableStart
-import live.hms.roomkit.helpers.NetworkQualityHelper
+import live.hms.common.util.helpers.NetworkQualityHelper
import live.hms.roomkit.hideKeyboard
import live.hms.roomkit.setDrawables
import live.hms.roomkit.ui.meeting.participants.ParticipantsAdapter
@@ -37,16 +41,13 @@ import live.hms.roomkit.ui.theme.*
import live.hms.roomkit.ui.theme.applyTheme
import live.hms.roomkit.util.*
import live.hms.video.audio.HMSAudioManager
-import live.hms.video.error.HMSException
import live.hms.video.media.tracks.HMSLocalAudioTrack
import live.hms.video.media.tracks.HMSLocalVideoTrack
import live.hms.video.sdk.models.HMSLocalPeer
import live.hms.video.sdk.models.HMSPeer
import live.hms.video.sdk.models.HMSRoom
import live.hms.video.sdk.models.enums.HMSPeerUpdate
-import live.hms.video.sdk.models.enums.HMSRoomUpdate
import live.hms.video.sdk.models.role.PublishParams
-import live.hms.video.utils.HMSLogger
class PreviewFragment : Fragment() {
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/SettingsBottomSheet.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/SettingsBottomSheet.kt
index 4b7f7edfd..352156696 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/SettingsBottomSheet.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/SettingsBottomSheet.kt
@@ -10,8 +10,8 @@ import androidx.appcompat.widget.AppCompatButton
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import live.hms.roomkit.R
import live.hms.roomkit.databinding.SettingsBottomSheetDialogBinding
+import live.hms.roomkit.setOnSingleClickListener
import live.hms.roomkit.ui.meeting.participants.MusicSelectionSheet
-import live.hms.roomkit.util.setOnSingleClickListener
import live.hms.roomkit.util.viewLifecycle
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/ActiveSpeakerFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/ActiveSpeakerFragment.kt
index 40591f110..29c6de991 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/ActiveSpeakerFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/ActiveSpeakerFragment.kt
@@ -4,24 +4,13 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import live.hms.roomkit.R
import live.hms.roomkit.databinding.FragmentActiveSpeakerBinding
-import live.hms.roomkit.ui.meeting.CustomPeerMetadata
-import live.hms.roomkit.ui.meeting.MeetingTrack
-import live.hms.roomkit.ui.meeting.commons.VideoGridBaseFragment
-import live.hms.roomkit.ui.meeting.pinnedvideo.StatsInterpreter
-import live.hms.roomkit.ui.theme.applyTheme
import live.hms.roomkit.util.*
-import live.hms.video.media.tracks.HMSLocalVideoTrack
-import live.hms.video.media.tracks.HMSRemoteVideoTrack
-import live.hms.video.media.tracks.HMSVideoTrack
-import live.hms.video.sdk.models.enums.HMSPeerUpdate
-import live.hms.video.utils.HMSLogger
-import org.webrtc.RendererCommon
-import org.webrtc.SurfaceViewRenderer
-class ActiveSpeakerFragment : VideoGridBaseFragment() {
+class ActiveSpeakerFragment : Fragment() {
companion object {
private const val TAG = "ActiveSpeakerFragment"
@@ -29,11 +18,6 @@ class ActiveSpeakerFragment : VideoGridBaseFragment() {
private var binding by viewLifecycle()
- private var screenShareTrack: MeetingTrack? = null
- private var wasLastModePip = false
-
- private val mediaPlayerManager by lazy { MediaPlayerManager(lifecycle) }
-
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -44,207 +28,5 @@ class ActiveSpeakerFragment : VideoGridBaseFragment() {
return binding.root
}
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- binding.applyTheme()
- screenShareStats = StatsInterpreter(settings.showStats)
- initViewModels()
- }
-
- private fun unBindScreenShareTrack() {
- screenShareTrack?.let {
- unbindSurfaceView(binding.screenShare, it)
- }
- }
-
- override fun onResume() {
- if (wasLastModePip) {
- //if it's coming back from pip --> full screen i.e [pause --> resume] we wont' bind the screenshare track again since we never removed it in the first place
- super.onResume()
- wasLastModePip = false
- screenShareOverLocalVideoInGrid()
- return
- }
-
- screenShareTrack?.let { meetingTrack ->
- binding.screenShare.raisedHand.alpha =
- visibilityOpacity(CustomPeerMetadata.fromJson(meetingTrack.peer.metadata)?.isHandRaised == true)
- bindSurfaceView(
- binding.screenShare,
- meetingTrack,
- RendererCommon.ScalingType.SCALE_ASPECT_FIT
- )
- binding.screenShare.hmsVideoView.setOnLongClickListener { view ->
- openDialog(
- view as? SurfaceViewRenderer,
- meetingTrack.video,
- meetingTrack.peer.name.orEmpty()
- )
- return@setOnLongClickListener true
- }
- }
- super.onResume()
- }
-
- private fun openDialog(
- surfaceView: SurfaceViewRenderer?,
- videoTrack: HMSVideoTrack?,
- peerName: String
- ) {
-
- if (videoTrack.isValid().not())
- return
- contextSafe { context, activity ->
- context.showTileListDialog (
- isLocalTrack = videoTrack is HMSLocalVideoTrack,
- onScreenCapture = { captureVideoFrame(surfaceView, videoTrack) },
- onSimulcast = { context.showSimulcastDialog(videoTrack as? HMSRemoteVideoTrack) },
- onMirror = { context.showMirrorOptions(surfaceView)}
- )
- }
-
- }
-
- private fun captureVideoFrame(surfaceView: SurfaceViewRenderer?, videoTrack: HMSVideoTrack?) {
-
- //safe check incase video
- if (videoTrack.isValid().not()){
- return
- }
- contextSafe { context, activity -> mediaPlayerManager.startPlay(R.raw.camera_shut, context )}
- surfaceView?.vibrateStrong()
-
- surfaceView?.onBitMap(onBitmap = { bitmap ->
- contextSafe { context, activity ->
- //stores the bitmap in local cache thus avoiding any permission
- val uri = bitmap?.saveCaptureToLocalCache(context)
- //the uri is used to open share intent
- uri?.let { activity.openShareIntent(it) }
- }
- })
- }
-
-
- override fun onPause() {
- if (activity?.isInPictureInPictureMode == true) {
- //when it's pip mode don't unbind views
- wasLastModePip = true
- screenShareOverLocalVideoInGrid()
- } else {
- unBindScreenShareTrack()
- }
-// screenShareStats.close()
- super.onPause()
- }
-
- private fun screenShareOverLocalVideoInGrid() {
- //hide video grid when screen share is shown!
- binding.container.visibility = if (screenShareTrack != null && activity?.isInPictureInPictureMode == true) {
- View.GONE
- } else {
- View.VISIBLE
- }
- }
-
- override fun initViewModels() {
- super.initViewModels()
- meetingViewModel.tracks.observe(viewLifecycleOwner) { tracks ->
- HMSLogger.v(TAG, "tracks update received 🎼 [size=${tracks.size}]")
- updateScreenshareTracks(tracks)
- }
-
- meetingViewModel.activeSpeakersUpdatedTracks.observe(viewLifecycleOwner) { tracks ->
- HMSLogger.v(TAG, "tracks update received 🎼 [size=${tracks.size}]")
- updateVideos(binding.container, tracks, false)
- }
-
- meetingViewModel.activeSpeakers.observe(viewLifecycleOwner) { (videos, speakers) ->
- updateVideos(binding.container, videos, false)
- // Active speaker should be updated via, tracks AND actual active speakers.
- applySpeakerUpdates(speakers)
- }
-
- meetingViewModel.peerMetadataNameUpdate.observe(viewLifecycleOwner) {
- if( screenShareTrack?.peer?.peerID == it.first.peerID) {
- when(it.second) {
- HMSPeerUpdate.METADATA_CHANGED -> {
- HMSLogger.v(TAG,"metadata changed : ${it.second} ")
- }
-
- HMSPeerUpdate.NAME_CHANGED -> {
- binding.screenShare.name.text = it.first.name
- }
- else -> {}
- }
- }
- }
-
- meetingViewModel.trackStatus.observe(viewLifecycleOwner) { statsPair ->
- if (statsPair.second){
- binding.screenShare.statsView.visibility = View.GONE
- }else{
- binding.screenShare.statsView.visibility = View.VISIBLE
- binding.screenShare.statsView.text = statsPair.first
- }
- }
- }
-
- override fun isScreenshare(): Boolean {
- return false
- }
-
- private var screenShareStats : StatsInterpreter? = null
- private fun updateScreenshareTracks(tracks: List) {
-
- // Check if the currently shared screen-share track is removed
- screenShareTrack?.let { screen ->
- if (!tracks.contains(screen)) {
- screenShareTrack?.let { unbindSurfaceView(binding.screenShare, it) }
-// screenShareStats.close()
- screenShareTrack = null
- screenShareOverLocalVideoInGrid()
- }
- }
-
- // Check for screen share
- if (screenShareTrack == null) tracks.find { it.isScreen }?.let { screen ->
- screenShareStats?.initiateStats(
- viewLifecycleOwner,
- meetingViewModel.getStats(),
- screen.video,
- screen.audio, screen.peer.isLocal
- ) { statsString ->
- binding.screenShare.statsView.text = statsString
- }
- meetingViewModel.statsToggleData.observe(viewLifecycleOwner, Observer {
- if (it){
- binding.screenShare.statsView.visibility = View.VISIBLE
- }else{
- binding.screenShare.statsView.visibility = View.GONE
- }
- })
- screenShareTrack = screen
- screenShareOverLocalVideoInGrid()
- if (isFragmentVisible) {
- bindSurfaceView(
- binding.screenShare,
- screen,
- RendererCommon.ScalingType.SCALE_ASPECT_FIT
- )
- }
- bindVideo(binding.screenShare, screen)
- binding.screenShare.apply {
- iconAudioOff.visibility = View.GONE
- iconScreenShare.visibility = View.GONE
- audioLevel.visibility = View.GONE
- raisedHand.alpha = visibilityOpacity(CustomPeerMetadata.fromJson(screen.peer.metadata)?.isHandRaised == true)
- }
- binding.screenShareContainer.visibility = View.VISIBLE
- }
-
- if (screenShareTrack == null && binding.screenShareContainer.visibility != View.GONE) {
- binding.screenShareContainer.visibility = View.GONE
- }
- }
}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/audiomode/AudioItemsAdapter.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/audiomode/AudioItemsAdapter.kt
index c44124103..54f73cecf 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/audiomode/AudioItemsAdapter.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/audiomode/AudioItemsAdapter.kt
@@ -6,7 +6,7 @@ import androidx.annotation.MainThread
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import live.hms.roomkit.databinding.ListItemAudioBinding
-import live.hms.roomkit.util.NameUtils
+import live.hms.common.util.NameUtils
import live.hms.roomkit.util.visibility
class AudioItemsAdapter : RecyclerView.Adapter() {
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantItem.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantItem.kt
index 917ec261f..043234f9c 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantItem.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantItem.kt
@@ -4,16 +4,14 @@ import androidx.appcompat.widget.PopupMenu
import com.xwray.groupie.viewbinding.BindableItem
import live.hms.roomkit.R
import live.hms.roomkit.databinding.ListItemPeerListBinding
-import live.hms.roomkit.helpers.NetworkQualityHelper
-import live.hms.roomkit.ui.meeting.CustomPeerMetadata
+import live.hms.common.util.helpers.NetworkQualityHelper
+import live.hms.common.util.helpers.CustomPeerMetadata
import live.hms.roomkit.ui.theme.HMSPrebuiltTheme
import live.hms.roomkit.ui.theme.getColorOrDefault
import live.hms.video.connection.stats.quality.HMSNetworkQuality
-import live.hms.video.media.tracks.HMSTrack
import live.hms.video.media.tracks.HMSTrackType
import live.hms.video.sdk.models.HMSPeer
import live.hms.video.sdk.models.HMSRemotePeer
-import live.hms.video.sdk.models.role.HMSRole
class ParticipantItem(private val hmsPeer: HMSPeer,
private val toggleTrack: (hmsPeer: HMSRemotePeer, type: HMSTrackType) -> Unit,
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsFragment.kt
index fc277b876..427e61236 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsFragment.kt
@@ -21,7 +21,7 @@ import com.xwray.groupie.GroupieAdapter
import kotlinx.coroutines.launch
import live.hms.roomkit.R
import live.hms.roomkit.databinding.FragmentParticipantsBinding
-import live.hms.roomkit.ui.meeting.CustomPeerMetadata
+import live.hms.common.util.helpers.CustomPeerMetadata
import live.hms.roomkit.ui.meeting.MeetingState
import live.hms.roomkit.ui.meeting.MeetingViewModel
import live.hms.roomkit.ui.meeting.MeetingViewModelFactory
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/pinnedvideo/PinnedVideoFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/pinnedvideo/PinnedVideoFragment.kt
index 163e7583f..b53608da1 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/pinnedvideo/PinnedVideoFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/pinnedvideo/PinnedVideoFragment.kt
@@ -11,8 +11,9 @@ import androidx.core.view.forEach
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.LinearLayoutManager
+import live.hms.common.util.NameUtils
import live.hms.roomkit.databinding.FragmentPinnedVideoBinding
-import live.hms.roomkit.ui.meeting.CustomPeerMetadata
+import live.hms.common.util.helpers.CustomPeerMetadata
import live.hms.roomkit.ui.meeting.MeetingTrack
import live.hms.roomkit.ui.meeting.MeetingViewModel
import live.hms.roomkit.ui.meeting.MeetingViewModelFactory
@@ -231,7 +232,7 @@ class PinnedVideoFragment : Fragment() {
if (newName != null) {
with(binding.pinVideo) {
name.text = newName
- nameInitials.text = NameUtils.getInitials(newName)
+ nameInitials.text = live.hms.common.util.NameUtils.getInitials(newName)
}
}
}
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/pinnedvideo/VideoListAdapter.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/pinnedvideo/VideoListAdapter.kt
index cdbe131ee..b95b5f064 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/pinnedvideo/VideoListAdapter.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/pinnedvideo/VideoListAdapter.kt
@@ -11,12 +11,12 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.flow.Flow
import live.hms.roomkit.databinding.ListItemVideoBinding
-import live.hms.roomkit.helpers.NetworkQualityHelper
-import live.hms.roomkit.ui.meeting.CustomPeerMetadata
+import live.hms.common.util.helpers.NetworkQualityHelper
+import live.hms.common.util.helpers.CustomPeerMetadata
import live.hms.roomkit.ui.meeting.MeetingTrack
import live.hms.roomkit.ui.theme.HMSPrebuiltTheme
import live.hms.roomkit.ui.theme.getColorOrDefault
-import live.hms.roomkit.util.NameUtils
+import live.hms.common.util.NameUtils
import live.hms.roomkit.util.visibility
import live.hms.video.sdk.models.HMSPeer
import live.hms.video.sdk.models.enums.HMSPeerUpdate
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridAdapter.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridAdapter.kt
deleted file mode 100644
index 4c24c19db..000000000
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridAdapter.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package live.hms.roomkit.ui.meeting.videogrid
-
-import androidx.fragment.app.Fragment
-import androidx.recyclerview.widget.DiffUtil
-import androidx.viewpager2.adapter.FragmentStateAdapter
-
-class VideoGridAdapter(parentFragment: Fragment,val isScreenShare: Boolean = false) : FragmentStateAdapter(parentFragment) {
-
- companion object {
- const val TAG = "VideoGridAdapter"
- }
-
- var totalPages = 0
- set(value) {
- val callback = VideoGridPagerDiffUtil(field, value)
- val diff = DiffUtil.calculateDiff(callback)
- field = value
- diff.dispatchUpdatesTo(this)
- }
-
- override fun getItemCount() = totalPages
- override fun createFragment(position: Int) = VideoGridPageFragment.newInstance(position, isScreenShare)
- override fun getItemId(position: Int) = position.toLong()
- override fun containsItem(itemId: Long) = itemId < totalPages
-}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridFragment.kt
index 30f4a9774..711e828b0 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridFragment.kt
@@ -13,16 +13,18 @@ import com.google.android.material.tabs.TabLayoutMediator
import live.hms.roomkit.R
import live.hms.roomkit.databinding.FragmentGridVideoBinding
import live.hms.roomkit.ui.inset.makeInset
-import live.hms.roomkit.ui.meeting.CustomPeerMetadata
+import live.hms.common.util.helpers.CustomPeerMetadata
import live.hms.roomkit.ui.meeting.MeetingViewModel
import live.hms.roomkit.ui.settings.SettingsStore
import live.hms.roomkit.ui.theme.applyTheme
import live.hms.roomkit.ui.theme.setIconDisabled
-import live.hms.roomkit.util.NameUtils
+import live.hms.common.util.NameUtils
import live.hms.roomkit.util.viewLifecycle
import live.hms.video.error.HMSException
import live.hms.video.sdk.HMSActionResultListener
import live.hms.video.sdk.models.enums.HMSPeerUpdate
+import live.hms.videogrid.GridViewModel
+import live.hms.videogrid.VideoGridAdapter
import org.webrtc.RendererCommon
class VideoGridFragment : Fragment() {
@@ -36,6 +38,7 @@ class VideoGridFragment : Fragment() {
private lateinit var clipboard: ClipboardManager
private val meetingViewModel: MeetingViewModel by activityViewModels()
+ private val gridViewModel: GridViewModel by activityViewModels()
private lateinit var peerGridVideoAdapter: VideoGridAdapter
private lateinit var screenShareAdapter: VideoGridAdapter
@@ -54,7 +57,7 @@ class VideoGridFragment : Fragment() {
): View {
binding = FragmentGridVideoBinding.inflate(inflater, container, false)
settings = SettingsStore(requireContext())
-
+ gridViewModel.initHMSSDK(meetingViewModel.hmsSDK)
initVideoGrid()
initViewModels()
return binding.root
@@ -129,7 +132,7 @@ class VideoGridFragment : Fragment() {
}
- meetingViewModel.tracks.observe(viewLifecycleOwner) {
+ gridViewModel.getTrackLiveData().observe(viewLifecycleOwner) {
val localMeeting = it.filter { it.isLocal }.firstOrNull()
//show or hide inset
@@ -178,7 +181,7 @@ class VideoGridFragment : Fragment() {
@SuppressLint("SetTextI18n")
private fun initViewModels() {
- meetingViewModel.tracks.observe(viewLifecycleOwner) { tracks ->
+ gridViewModel.getTrackLiveData().observe(viewLifecycleOwner) { tracks ->
val screenShareTrackList = tracks.filter { it.isScreen }
var newRowCount = 0
@@ -203,7 +206,7 @@ class VideoGridFragment : Fragment() {
binding.localScreenShareContainer.visibility = View.GONE
}
- meetingViewModel.updateRowAndColumnSpanForVideoPeerGrid.value = Pair(newRowCount, newColumnCount)
+ gridViewModel.updateRowAndColumnSpanForVideoPeerGrid.value = Pair(newRowCount, newColumnCount)
val itemsPerPage = newRowCount * newColumnCount
// Without this, the extra inset adds one more tile than they should
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPageViewModel.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPageViewModel.kt
deleted file mode 100644
index 264432ac6..000000000
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPageViewModel.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package live.hms.roomkit.ui.meeting.videogrid
-
-import androidx.lifecycle.ViewModel
-import live.hms.roomkit.ui.meeting.MeetingTrack
-
-class VideoGridPageViewModel : ViewModel() {
- var initialVideos = arrayOf()
- var onVideoItemClick: ((MeetingTrack) -> Unit)? = null
-}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionCreation.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionCreation.kt
index 19e5a9898..b89dd1f84 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionCreation.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionCreation.kt
@@ -13,7 +13,7 @@ import androidx.recyclerview.widget.RecyclerView.VERTICAL
import live.hms.roomkit.R
import live.hms.roomkit.databinding.LayoutPollQuestionCreationBinding
import live.hms.roomkit.ui.meeting.MeetingViewModel
-import live.hms.roomkit.util.setOnSingleClickListener
+import live.hms.common.util.setOnSingleClickListener
import live.hms.roomkit.util.viewLifecycle
/**
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionViewHolder.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionViewHolder.kt
index b5ad97afb..abdcb35fd 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionViewHolder.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionViewHolder.kt
@@ -12,7 +12,7 @@ import live.hms.roomkit.R
import live.hms.roomkit.databinding.LayoutPollQuestionCreationItemBinding
import live.hms.roomkit.databinding.LayoutPollQuizItemShortAnswerBinding
import live.hms.roomkit.databinding.LayoutPollQuizOptionsItemMultiChoiceBinding
-import live.hms.roomkit.util.setOnSingleClickListener
+import live.hms.common.util.setOnSingleClickListener
private var count : Long = 0
sealed class QuestionUi(open val index : Long, open val viewType : Int, open val requiredToAnswer : Boolean){
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollsCreationFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollsCreationFragment.kt
index d81f4329a..9e5a4023a 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollsCreationFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollsCreationFragment.kt
@@ -16,7 +16,7 @@ import live.hms.roomkit.ui.meeting.MeetingFragmentDirections
import live.hms.roomkit.ui.meeting.MeetingViewModel
import live.hms.roomkit.ui.polls.previous.PreviousPollsAdaptor
import live.hms.roomkit.ui.polls.previous.PreviousPollsInfo
-import live.hms.roomkit.util.setOnSingleClickListener
+import live.hms.common.util.setOnSingleClickListener
import live.hms.roomkit.util.viewLifecycle
/**
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayFragment.kt
index 5cf24354a..a9160cbd3 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayFragment.kt
@@ -16,7 +16,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import live.hms.roomkit.databinding.LayoutPollsDisplayBinding
import live.hms.roomkit.ui.meeting.MeetingViewModel
-import live.hms.roomkit.util.setOnSingleClickListener
+import live.hms.common.util.setOnSingleClickListener
import live.hms.roomkit.util.viewLifecycle
import live.hms.video.polls.models.HmsPoll
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayQuestionHolder.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayQuestionHolder.kt
index 42f27312e..d7391feab 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayQuestionHolder.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayQuestionHolder.kt
@@ -10,7 +10,7 @@ import live.hms.roomkit.R
import live.hms.roomkit.databinding.LayoutPollsDisplayChoicesQuesionBinding
import live.hms.roomkit.databinding.LayoutQuizDisplayShortAnswerBinding
import live.hms.roomkit.ui.polls.display.voting.VotingProgressAdapter
-import live.hms.roomkit.util.setOnSingleClickListener
+import live.hms.common.util.setOnSingleClickListener
import live.hms.video.polls.models.HmsPoll
import live.hms.video.polls.models.question.HMSPollQuestion
import live.hms.video.polls.models.question.HMSPollQuestionType
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/theme/ThemeExt.kt b/room-kit/src/main/java/live/hms/roomkit/ui/theme/ThemeExt.kt
index 97a7f3c9d..7ccae0667 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/theme/ThemeExt.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/theme/ThemeExt.kt
@@ -1,13 +1,18 @@
package live.hms.roomkit.ui.theme
import android.content.res.ColorStateList
-import android.graphics.PorterDuff
+import android.graphics.LinearGradient
+import android.graphics.Paint
+import android.graphics.Shader
import android.graphics.drawable.Animatable
import android.graphics.drawable.Drawable
+import android.graphics.drawable.ShapeDrawable
+import android.graphics.drawable.shapes.RectShape
+import android.graphics.drawable.shapes.RoundRectShape
import android.view.View
-import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
+import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.appcompat.widget.AppCompatImageButton
import androidx.cardview.widget.CardView
@@ -103,26 +108,43 @@ fun getColorOrDefault(colorStr: String?, defaultColor: String): Int {
}
}
+fun View.backgroundGradientDrawable(@ColorInt startColor: Int, @ColorInt endColor: Int): Unit {
+ val h = this.height.toFloat()
+ val shapeDrawable = ShapeDrawable(RectShape())
+ shapeDrawable.paint.shader =
+ LinearGradient(0f, 0f, 0f, h, startColor, endColor, Shader.TileMode.REPEAT)
+ this.background = shapeDrawable
+}
+
internal fun ImageView.setIconEnabled(
@DrawableRes enabledIconDrawableRes: Int
) {
this.setBackgroundResource(R.drawable.gray_round_stroked_drawable)
+ this.setBackgroundColor(resources.getColor(android.R.color.transparent))
this.setImageResource(enabledIconDrawableRes)
-
- background.setColorFilter(
- getColorOrDefault(
- HMSPrebuiltTheme.getColours()?.secondaryBright,
- HMSPrebuiltTheme.getDefaults().border_bright
- ), PorterDuff.Mode.DST_OVER
- )
-
drawable.setTint(
getColorOrDefault(
HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
HMSPrebuiltTheme.getDefaults().onsurface_high_emp
)
)
+ val shapedrawable = ShapeDrawable()
+ val mDensity = getResources().getDisplayMetrics().density;
+ val r: Float = 10 * mDensity
+ val radii = floatArrayOf(r, r, r, r, r, r, r, r)
+
+ shapedrawable.shape = RoundRectShape(radii, null, null)
+ shapedrawable.paint.color = getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.secondaryBright,
+ HMSPrebuiltTheme.getDefaults().border_bright
+ )
+ shapedrawable.paint.isAntiAlias = true
+ shapedrawable.paint.strokeWidth = r/3
+ shapedrawable.paint.style = Paint.Style.STROKE
+
+
+ background = shapedrawable
(drawable as? Animatable)?.start()
}
diff --git a/settings.gradle b/settings.gradle
index 970dba65a..4dbdde74e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -2,3 +2,5 @@ include ':lib'
include ':app'
rootProject.name = "Android 100ms"
include ':room-kit'
+include ':videogrid'
+include ':common'
diff --git a/videogrid/.gitignore b/videogrid/.gitignore
new file mode 100644
index 000000000..42afabfd2
--- /dev/null
+++ b/videogrid/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/videogrid/build.gradle b/videogrid/build.gradle
new file mode 100644
index 000000000..83d1d7787
--- /dev/null
+++ b/videogrid/build.gradle
@@ -0,0 +1,130 @@
+plugins {
+ id 'com.android.library'
+ id 'kotlin-android'
+ id 'kotlin-kapt'
+ id 'maven-publish'
+ id 'kotlin-parcelize'
+ id 'signing'
+ id "org.jetbrains.dokka" version "1.5.0"
+}
+
+def getVersionName = { ->
+ return "$HMS_ROOM_KIT_VERSION"
+}
+
+android {
+ namespace 'live.hms.videogrid'
+ compileSdk 33
+
+ defaultConfig {
+ minSdk 21
+ targetSdk 33
+
+ versionCode 1
+ versionName getVersionName()
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ buildFeatures {
+ viewBinding true
+ dataBinding {
+ enabled true
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ publishing {
+ singleVariant('release') {
+ withSourcesJar()
+ }
+ }
+}
+
+dependencies {
+ def hmsVersion = "2.7.7-de"
+ // To add dependencies of specific module
+ implementation "live.100ms:android-sdk:$hmsVersion"
+ implementation "live.100ms:video-view:$hmsVersion"
+
+
+ implementation 'androidx.core:core-ktx:1.8.0'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+ implementation 'androidx.viewpager2:viewpager2:1.0.0'
+ implementation 'androidx.fragment:fragment-ktx:1.3.2'
+
+ // Life Cycle
+ implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0"
+ implementation "androidx.lifecycle:lifecycle-common-java8:2.4.0"
+ implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0'
+ implementation 'com.google.android.material:material:1.5.0'
+
+ implementation "live.100ms:common:0.0.6"
+}
+
+
+task javadocJar(type: Jar, dependsOn: dokkaJavadoc) {
+ archiveFileName = "javadoc.jar"
+ from "build/dokka/javadoc"
+ archiveClassifier.set("javadoc")
+}
+
+afterEvaluate {
+ publishing {
+ publications {
+ // Creates a Maven publication called "release".
+ release(MavenPublication) {
+ from components.release
+ pom {
+ // Only sign the artefacts if this is a maven central build.
+ // This would only halt jitpack builds and/or make our signing keys public.
+ if(rootProject.properties["ossrhUsername"]) {
+ artifact javadocJar
+ signing {
+ sign publishing.publications
+ }
+ }
+ name = "100ms.live Android Room Kit"
+ description = "Room Kit that simplifies setting up videoconferencing in your own app. See more at https://www.100ms.live/docs/android/v2/guides/quickstart"
+ url = "100ms.live"
+ licenses {
+ license {
+ name = 'MIT License'
+ url = 'http://www.opensource.org/licenses/mit-license.php'
+ }
+ }
+ developers {
+ developer {
+ id = '1'
+ name = '100ms'
+ email = 'support@100ms.live'
+ }
+ }
+ scm {
+ connection = 'SCM is private'
+ developerConnection = 'SCM is private'
+ url = 'SCM is private'
+ }
+ }
+ groupId = "live.100ms"
+ artifactId = 'videogrid'
+ version = getVersionName()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/videogrid/consumer-rules.pro b/videogrid/consumer-rules.pro
new file mode 100644
index 000000000..e69de29bb
diff --git a/videogrid/proguard-rules.pro b/videogrid/proguard-rules.pro
new file mode 100644
index 000000000..481bb4348
--- /dev/null
+++ b/videogrid/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/videogrid/src/androidTest/java/live/hms/videogrid/ExampleInstrumentedTest.kt b/videogrid/src/androidTest/java/live/hms/videogrid/ExampleInstrumentedTest.kt
new file mode 100644
index 000000000..666956c9c
--- /dev/null
+++ b/videogrid/src/androidTest/java/live/hms/videogrid/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package live.hms.videogrid
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("live.hms.videogrid.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/videogrid/src/main/AndroidManifest.xml b/videogrid/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..a5918e68a
--- /dev/null
+++ b/videogrid/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/ActiveSpeakerCache.kt b/videogrid/src/main/java/live/hms/videogrid/ActiveSpeakerCache.kt
similarity index 96%
rename from room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/ActiveSpeakerCache.kt
rename to videogrid/src/main/java/live/hms/videogrid/ActiveSpeakerCache.kt
index 7cdf68c86..cd0ea2f13 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/ActiveSpeakerCache.kt
+++ b/videogrid/src/main/java/live/hms/videogrid/ActiveSpeakerCache.kt
@@ -1,4 +1,4 @@
-package live.hms.roomkit.ui.meeting.activespeaker
+package live.hms.videogrid
import java.util.concurrent.ConcurrentLinkedQueue
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/ActiveSpeakerHandler.kt b/videogrid/src/main/java/live/hms/videogrid/ActiveSpeakerHandler.kt
similarity index 83%
rename from room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/ActiveSpeakerHandler.kt
rename to videogrid/src/main/java/live/hms/videogrid/ActiveSpeakerHandler.kt
index c8547ca57..c23c510a9 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/ActiveSpeakerHandler.kt
+++ b/videogrid/src/main/java/live/hms/videogrid/ActiveSpeakerHandler.kt
@@ -1,13 +1,12 @@
-package live.hms.roomkit.ui.meeting.activespeaker
+package live.hms.videogrid
-import live.hms.roomkit.ui.meeting.MeetingTrack
import live.hms.video.sdk.models.HMSSpeaker
import live.hms.video.utils.HMSLogger
-class ActiveSpeakerHandler(private val appendUnsorted : Boolean = false, private val numActiveSpeakerVideos : Int = 4, private val getTracks: () -> List) {
+class ActiveSpeakerHandler(private val appendUnsorted : Boolean = false, private val numActiveSpeakerVideos : Int = 4, private val getTracks: () -> ArrayList) {
private val TAG = ActiveSpeakerHandler::class.java.simpleName
private val speakerCache = ActiveSpeakerCache(numActiveSpeakerVideos, appendUnsorted)
- fun trackUpdateTrigger(tracks: List): List {
+ fun trackUpdateTrigger(tracks: List): List {
synchronized(tracks) {
// Update lru just to keep it as much filled as possible
@@ -28,7 +27,7 @@ class ActiveSpeakerHandler(private val appendUnsorted : Boolean = false, private
}
}
- fun speakerUpdate(speakers: Array): Pair, Array> {
+ fun speakerUpdate(speakers: Array): Pair, Array> {
HMSLogger.v(
TAG,
"speakers update received 🎙 [size=${speakers.size}, names=${speakers.map { it.peer?.name }}] "
@@ -42,7 +41,7 @@ class ActiveSpeakerHandler(private val appendUnsorted : Boolean = false, private
return Pair(update(), speakers)
}
- private fun update(): List {
+ private fun update(): List {
// Update all the videos which aren't screenshares
val order = speakerCache.getAllItems()
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/ActiveSpeakerLiveData.kt b/videogrid/src/main/java/live/hms/videogrid/ActiveSpeakerLiveData.kt
similarity index 91%
rename from room-kit/src/main/java/live/hms/roomkit/ui/meeting/ActiveSpeakerLiveData.kt
rename to videogrid/src/main/java/live/hms/videogrid/ActiveSpeakerLiveData.kt
index 7628ba36c..7f59275a1 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/ActiveSpeakerLiveData.kt
+++ b/videogrid/src/main/java/live/hms/videogrid/ActiveSpeakerLiveData.kt
@@ -1,6 +1,7 @@
-package live.hms.roomkit.ui.meeting
+package live.hms.videogrid
import androidx.lifecycle.MediatorLiveData
+import live.hms.video.sdk.reactive.MeetingTrack
abstract class ActiveSpeakerLiveData : MediatorLiveData>() {
diff --git a/videogrid/src/main/java/live/hms/videogrid/GridViewModel.kt b/videogrid/src/main/java/live/hms/videogrid/GridViewModel.kt
new file mode 100644
index 000000000..07b880360
--- /dev/null
+++ b/videogrid/src/main/java/live/hms/videogrid/GridViewModel.kt
@@ -0,0 +1,105 @@
+package live.hms.videogrid
+
+import android.app.Application
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.asLiveData
+import live.hms.video.sdk.HMSAudioListener
+import live.hms.video.sdk.HMSSDK
+import live.hms.video.sdk.models.HMSSpeaker
+import live.hms.video.sdk.reactive.MeetingTrack
+
+class GridViewModel(
+ application: Application
+) : AndroidViewModel(application) {
+
+ private var hmssdk: HMSSDK? = null
+ val speakersLiveData = MutableLiveData>()
+ val updateRowAndColumnSpanForVideoPeerGrid = MutableLiveData>()
+
+ private val liveData by lazy { hmssdk!!.getMeetingTrackFlow().asLiveData() }
+
+ companion object {
+ const val TAG = "GridViewModel"
+ }
+
+ fun initHMSSDK(hmssdk: HMSSDK) {
+ this.hmssdk = hmssdk
+ }
+
+
+ fun getTrackLiveData(): LiveData> {
+ if (hmssdk == null) throw Exception("HMSSDK not initialized")
+ return liveData
+ }
+
+
+
+
+
+ val speakerUpdateLiveData by lazy {
+ object : ActiveSpeakerLiveData() {
+ private val speakerH = ActiveSpeakerHandler(
+ true, 3 * 2
+ ) { getTrackLiveData().value?: ArrayList() }
+
+
+ init {
+ initSpeakerCallBack()
+ addSpeakerSource()
+
+ // Add all tracks as they come in.
+ addSource(getTrackLiveData()) { meetTracks: List ->
+ //if remote peer and local peer is present inset mode
+ val excludeLocalTrackIfRemotePeerIsPreset = if (meetTracks.size > 1) {
+ meetTracks.filter { !it.isLocal }.toList()
+ } else meetTracks
+
+ val result = speakerH.trackUpdateTrigger(excludeLocalTrackIfRemotePeerIsPreset)
+ setValue(result)
+ }
+
+ }
+
+ private fun initSpeakerCallBack() {
+ hmssdk!!.addAudioObserver(object : HMSAudioListener {
+ override fun onAudioLevelUpdate(speakers: Array) {
+ speakersLiveData.postValue(speakers)
+ }
+ })
+
+ }
+
+
+ override fun addSpeakerSource() {
+ addSource(speakersLiveData) { speakers: Array ->
+
+ val excludeLocalTrackIfRemotePeerIsPreset: Array =
+ speakers.filter { it.peer?.isLocal == false }.toTypedArray()
+
+ val result = speakerH.speakerUpdate(excludeLocalTrackIfRemotePeerIsPreset)
+ setValue(result.first)
+ }
+ }
+
+ override fun removeSpeakerSource() {
+ removeSource(speakersLiveData)
+ }
+
+ //TODO can't be null
+ fun refreshSpeaker() {
+ // speakers.postValue(speakers.value)
+ }
+
+ override fun updateMaxActiveSpeaker(rowCount: Int, columnCount: Int) {
+ speakerH.updateMaxActiveSpeaker(rowCount * columnCount)
+ refreshSpeaker()
+ }
+
+
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/videogrid/src/main/java/live/hms/videogrid/GridViewModelFactory.kt b/videogrid/src/main/java/live/hms/videogrid/GridViewModelFactory.kt
new file mode 100644
index 000000000..53804fc1a
--- /dev/null
+++ b/videogrid/src/main/java/live/hms/videogrid/GridViewModelFactory.kt
@@ -0,0 +1,18 @@
+package live.hms.videogrid
+
+import android.app.Application
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+
+class GridViewModelFactory(
+ private val application: Application
+) : ViewModelProvider.NewInstanceFactory() {
+
+ @Suppress("UNCHECKED_CAST")
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(GridViewModel::class.java)) {
+ return GridViewModel(application) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class $modelClass")
+ }
+}
\ No newline at end of file
diff --git a/videogrid/src/main/java/live/hms/videogrid/VideoGridAdapter.kt b/videogrid/src/main/java/live/hms/videogrid/VideoGridAdapter.kt
new file mode 100644
index 000000000..f92ce06aa
--- /dev/null
+++ b/videogrid/src/main/java/live/hms/videogrid/VideoGridAdapter.kt
@@ -0,0 +1,42 @@
+package live.hms.videogrid
+
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.fragment.app.FragmentManager
+import androidx.lifecycle.Lifecycle
+import androidx.recyclerview.widget.DiffUtil
+import androidx.viewpager2.adapter.FragmentStateAdapter
+
+class VideoGridAdapter(
+ private val fragmentManager: FragmentManager,
+ private val lifeCycle: Lifecycle,
+ private val isScreenShare: Boolean = false
+) : FragmentStateAdapter(fragmentManager, lifeCycle) {
+
+ companion object {
+ const val TAG = "VideoGridAdapter"
+ }
+
+ constructor(
+ activity: FragmentActivity, isScreenShare: Boolean = false
+ ) : this(activity.supportFragmentManager, activity.lifecycle, isScreenShare)
+
+ constructor(
+ parentFragment: Fragment, isScreenShare: Boolean = false
+ ) : this(parentFragment.childFragmentManager, parentFragment.lifecycle, isScreenShare)
+
+ var totalPages = 0
+ set(value) {
+ val callback = VideoGridPagerDiffUtil(field, value)
+ val diff = DiffUtil.calculateDiff(callback)
+ field = value
+ diff.dispatchUpdatesTo(this)
+ }
+
+ override fun getItemCount() = totalPages
+ override fun createFragment(position: Int) =
+ VideoGridPageFragment.newInstance(position, isScreenShare)
+
+ override fun getItemId(position: Int) = position.toLong()
+ override fun containsItem(itemId: Long) = itemId < totalPages
+}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/commons/VideoGridBaseFragment.kt b/videogrid/src/main/java/live/hms/videogrid/VideoGridBaseFragment.kt
similarity index 78%
rename from room-kit/src/main/java/live/hms/roomkit/ui/meeting/commons/VideoGridBaseFragment.kt
rename to videogrid/src/main/java/live/hms/videogrid/VideoGridBaseFragment.kt
index 3832c423c..c26496a6b 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/commons/VideoGridBaseFragment.kt
+++ b/videogrid/src/main/java/live/hms/videogrid/VideoGridBaseFragment.kt
@@ -1,4 +1,4 @@
-package live.hms.roomkit.ui.meeting.commons
+package live.hms.videogrid
import android.content.Context
import android.os.Bundle
@@ -13,25 +13,18 @@ import androidx.core.view.children
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
-import live.hms.roomkit.R
-import live.hms.roomkit.databinding.GridItemVideoBinding
-import live.hms.roomkit.databinding.VideoCardBinding
-import live.hms.roomkit.helpers.NetworkQualityHelper
-import live.hms.roomkit.ui.meeting.CustomPeerMetadata
-import live.hms.roomkit.ui.meeting.MeetingTrack
-import live.hms.roomkit.ui.meeting.MeetingViewModel
-import live.hms.roomkit.ui.meeting.pinnedvideo.StatsInterpreter
-import live.hms.roomkit.ui.settings.SettingsStore
-import live.hms.roomkit.ui.theme.HMSPrebuiltTheme
-import live.hms.roomkit.ui.theme.applyTheme
-import live.hms.roomkit.ui.theme.getColorOrDefault
-import live.hms.roomkit.util.*
-import live.hms.video.media.tracks.HMSLocalVideoTrack
-import live.hms.video.media.tracks.HMSRemoteVideoTrack
+import live.hms.common.util.NameUtils
+import live.hms.common.util.helpers.CustomPeerMetadata
+import live.hms.common.util.helpers.NetworkQualityHelper
+import live.hms.common.util.setCameraGestureListener
import live.hms.video.media.tracks.HMSVideoTrack
import live.hms.video.sdk.models.HMSPeer
import live.hms.video.sdk.models.HMSSpeaker
import live.hms.video.sdk.models.enums.HMSPeerUpdate
+import live.hms.videogrid.databinding.HmsGridItemBinding
+import live.hms.videogrid.databinding.HmsVideoCardBinding
+import live.hms.videogrid.utils.contextSafe
+import live.hms.videogrid.utils.visibilityOpacity
import live.hms.videoview.HMSVideoView
import org.webrtc.RendererCommon
import org.webrtc.SurfaceViewRenderer
@@ -52,8 +45,7 @@ abstract class VideoGridBaseFragment : Fragment() {
private const val TAG = "VideoGridBase"
}
- protected val settings: SettingsStore by lazy { SettingsStore(requireContext()) }
- protected val meetingViewModel by activityViewModels()
+
// Determined using the onResume() and onPause()
var isFragmentVisible = false
@@ -69,13 +61,12 @@ abstract class VideoGridBaseFragment : Fragment() {
private var gridColumnCount = 0
data class RenderedViewPair(
- val binding: GridItemVideoBinding,
- val meetingTrack: MeetingTrack,
- val statsInterpreter: StatsInterpreter?,
+ val binding: HmsGridItemBinding,
+ val meetingTrack: live.hms.video.sdk.reactive.MeetingTrack,
)
protected val renderedViews = ArrayList()
- private val mediaPlayerManager by lazy { MediaPlayerManager(lifecycle) }
+ protected val gridViewModel by activityViewModels()
internal fun shouldUpdateRowOrGrid(rowCount: Int, columnCount: Int) : Boolean{
return !(rowCount == gridRowCount && columnCount == gridColumnCount)
@@ -177,20 +168,21 @@ abstract class VideoGridBaseFragment : Fragment() {
}
- private fun createVideoView(parent: ViewGroup): GridItemVideoBinding {
- val binding = GridItemVideoBinding.inflate(
+ private fun createVideoView(parent: ViewGroup): HmsGridItemBinding {
+ val binding = HmsGridItemBinding.inflate(
LayoutInflater.from(requireContext()),
parent,
false
)
- binding.videoCard.applyTheme()
+ //TODO add
+ //binding.videoCard.applyTheme()
return binding
}
protected fun bindSurfaceView(
- binding: VideoCardBinding,
- item: MeetingTrack,
+ binding: HmsVideoCardBinding,
+ item: live.hms.video.sdk.reactive.MeetingTrack,
scalingType: RendererCommon.ScalingType = RendererCommon.ScalingType.SCALE_ASPECT_BALANCED
) {
Log.d(TAG,"bindSurfaceView for :: ${item.peer.name}")
@@ -201,14 +193,14 @@ abstract class VideoGridBaseFragment : Fragment() {
item.video?.let { track ->
view.setScalingType(scalingType)
view.addTrack(track)
- view.disableAutoSimulcastLayerSelect(meetingViewModel.isAutoSimulcastEnabled())
+// view.disableAutoSimulcastLayerSelect(meetingViewModel.isAutoSimulcastEnabled())
binding.hmsVideoView.visibility = if (item.video?.isDegraded == true ) View.INVISIBLE else View.VISIBLE
binding.hmsVideoView.setOnLongClickListener {
(it as? HMSVideoView)?.let { videoView -> openDialog(videoView, item.video, item.peer.name.orEmpty()) }
true
}
binding.hmsVideoView.setCameraGestureListener(item.video, {
- activity?.openShareIntent(it)
+
},
onLongPress = {(binding.hmsVideoView as? SurfaceViewRenderer)?.let { surfaceView -> openDialog(surfaceView, item.video, item.peer.name.orEmpty()) }})
}
@@ -222,36 +214,18 @@ abstract class VideoGridBaseFragment : Fragment() {
) {
contextSafe { context, activity ->
- context.showTileListDialog (
- isLocalTrack = videoTrack is HMSLocalVideoTrack,
- onScreenCapture = { captureVideoFrame(surfaceView, videoTrack) },
- onSimulcast = { context.showSimulcastDialog(videoTrack as? HMSRemoteVideoTrack) },
- onMirror = { context.showMirrorOptions(surfaceView)}
- )
+// context.showTileListDialog (
+// isLocalTrack = videoTrack is HMSLocalVideoTrack,
+// onScreenCapture = { captureVideoFrame(surfaceView, videoTrack) },
+// onSimulcast = { context.showSimulcastDialog(videoTrack as? HMSRemoteVideoTrack) },
+// onMirror = { context.showMirrorOptions(surfaceView)}
+// )
}
}
- private fun captureVideoFrame(surfaceView: SurfaceViewRenderer?, videoTrack: HMSVideoTrack?) {
-
- //safe check incase video
- if (videoTrack.isValid().not()){
- return
- }
+ private fun captureVideoFrame(surfaceView: SurfaceViewRenderer?, videoTrack: HMSVideoTrack?) {}
- contextSafe { context, activity -> mediaPlayerManager.startPlay(R.raw.camera_shut, context )}
- surfaceView?.vibrateStrong()
-
- surfaceView?.onBitMap(onBitmap = { bitmap ->
- contextSafe { context, activity ->
- //stores the bitmap in local cache thus avoiding any permission
- val uri = bitmap?.saveCaptureToLocalCache(context)
- //the uri is used to open share intent
- uri?.let { activity.openShareIntent(it) }
- }
- })
- }
-
- protected fun bindVideo(binding: VideoCardBinding, item: MeetingTrack) {
+ protected fun bindVideo(binding: HmsVideoCardBinding, item: live.hms.video.sdk.reactive.MeetingTrack) {
// FIXME: Add a shared VM with activity scope to subscribe to events
// binding.container.setOnClickListener { viewModel.onVideoItemClick?.invoke(item) }
//binding.applyTheme()
@@ -291,11 +265,11 @@ abstract class VideoGridBaseFragment : Fragment() {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
- setVideoGridRowsAndColumns(settings.videoGridRows, settings.videoGridColumns)
+ setVideoGridRowsAndColumns(3, 2)
}
protected fun unbindSurfaceView(
- binding: VideoCardBinding,
- item: MeetingTrack,
+ binding: HmsVideoCardBinding,
+ item: live.hms.video.sdk.reactive.MeetingTrack,
metadata: String = ""
) {
Log.d(TAG,"unbindSurfaceView for :: ${item.peer.name}")
@@ -309,7 +283,7 @@ abstract class VideoGridBaseFragment : Fragment() {
protected fun updateVideos(
layout: GridLayout,
- newVideos: List,
+ newVideos: List,
isVideoGrid: Boolean,
isScreenShare: Boolean = false
) {
@@ -348,7 +322,7 @@ abstract class VideoGridBaseFragment : Fragment() {
// VideoTrack was not present, hence had to create an empty tile)
bindSurfaceView(renderedViewPair.binding.videoCard, newVideo, if (isScreenshare()) RendererCommon.ScalingType.SCALE_ASPECT_FIT else RendererCommon.ScalingType.SCALE_ASPECT_BALANCED)
//handling simulcast case since we are updating local reference it thinks it's an update instead of rebinding it
- renderedViewPair.statsInterpreter?.updateVideoTrack(newVideo.video)
+ //renderedViewPair.statsInterpreter?.updateVideoTrack(newVideo.video)
}
val downlinkScore = newVideo.peer.networkQuality?.downlinkQuality
updateNetworkQualityView(downlinkScore ?: -1,requireContext(),renderedViewPair.binding.videoCard.networkQuality)
@@ -363,23 +337,23 @@ abstract class VideoGridBaseFragment : Fragment() {
// Create a new view
val videoBinding = createVideoView(layout)
- var statsInterpreter: StatsInterpreter? = null
+// var statsInterpreter: StatsInterpreter? = null
if (!isVideoGrid) {
- statsInterpreter = StatsInterpreter(settings.showStats)
- meetingViewModel.statsToggleLiveData.observe(this) {
- if (it) {
- videoBinding.videoCard.statsView.visibility = View.VISIBLE
- statsInterpreter.initiateStats(
- viewLifecycleOwner,
- meetingViewModel.getStats(),
- newVideo.video,
- newVideo.audio,
- newVideo.peer.isLocal
- ) { videoBinding.videoCard.statsView.text = it }
- } else {
- videoBinding.videoCard.statsView.visibility = View.GONE
- }
- }
+// statsInterpreter = StatsInterpreter(settings.showStats)
+// meetingViewModel.statsToggleLiveData.observe(this) {
+// if (it) {
+// videoBinding.videoCard.statsView.visibility = View.VISIBLE
+// statsInterpreter.initiateStats(
+// viewLifecycleOwner,
+// meetingViewModel.getStats(),
+// newVideo.video,
+// newVideo.audio,
+// newVideo.peer.isLocal
+// ) { videoBinding.videoCard.statsView.text = it }
+// } else {
+// videoBinding.videoCard.statsView.visibility = View.GONE
+// }
+// }
}
// Bind surfaceView when view is visible to user
@@ -394,7 +368,7 @@ abstract class VideoGridBaseFragment : Fragment() {
visibilityOpacity(CustomPeerMetadata.fromJson(newVideo.peer.metadata)?.isBRBOn == true)
layout.addView(videoBinding.root)
- newRenderedViews.add(RenderedViewPair(videoBinding, newVideo, statsInterpreter))
+ newRenderedViews.add(RenderedViewPair(videoBinding, newVideo))
}
}
}
@@ -451,7 +425,8 @@ abstract class VideoGridBaseFragment : Fragment() {
fun updateNetworkQualityView(downlinkScore : Int,context: Context,imageView: ImageView){
NetworkQualityHelper.getNetworkResource(downlinkScore, context).let { drawable ->
if (downlinkScore == 0) {
- imageView.setColorFilter(getColorOrDefault(HMSPrebuiltTheme.getColours()?.alertErrorDefault, HMSPrebuiltTheme.getDefaults().error_default), android.graphics.PorterDuff.Mode.SRC_IN);
+ //TODO
+ //imageView.setColorFilter(getColorOrDefault(HMSPrebuiltTheme.getColours()?.alertErrorDefault, HMSPrebuiltTheme.getDefaults().error_default), android.graphics.PorterDuff.Mode.SRC_IN);
} else {
imageView.colorFilter = null
}
@@ -480,7 +455,7 @@ abstract class VideoGridBaseFragment : Fragment() {
videoCard.audioLevel.apply {
text = "$level"
}
- if (level >= settings.silenceAudioLevelThreshold) {
+ if (level >= 10) {
hideOrShowGridsForPip(index)
wasLastSpeakingViewIndex = index
}
@@ -488,7 +463,7 @@ abstract class VideoGridBaseFragment : Fragment() {
level >= 70 -> {
container.strokeWidth = 6
}
- 70 > level && level >= settings.silenceAudioLevelThreshold -> {
+ 70 > level && level >= 10 -> {
container.strokeWidth = 4
}
else -> {
@@ -497,7 +472,7 @@ abstract class VideoGridBaseFragment : Fragment() {
}
}
- videoCard.audioLevel.visibility = if (meetingViewModel.isPrebuiltDebugMode()) View.VISIBLE else View.INVISIBLE
+ videoCard.audioLevel.visibility = View.INVISIBLE
}
}
}
@@ -545,20 +520,20 @@ abstract class VideoGridBaseFragment : Fragment() {
renderedViews.forEach { renderedView ->
bindSurfaceView(renderedView.binding.videoCard, renderedView.meetingTrack, if (isScreenshare()) RendererCommon.ScalingType.SCALE_ASPECT_FIT else RendererCommon.ScalingType.SCALE_ASPECT_BALANCED)
- meetingViewModel.statsToggleLiveData.observe(this) {
- if (it) {
- renderedView.binding.videoCard.statsView.visibility = View.VISIBLE
- renderedView.statsInterpreter?.initiateStats(
- viewLifecycleOwner,
- meetingViewModel.getStats(),
- renderedView.meetingTrack.video,
- renderedView.meetingTrack.audio,
- renderedView.meetingTrack.peer.isLocal
- ) { string -> renderedView.binding.videoCard.statsView.text = string }
- } else {
- renderedView.binding.videoCard.statsView.visibility = View.GONE
- }
- }
+// meetingViewModel.statsToggleLiveData.observe(this) {
+// if (it) {
+// renderedView.binding.videoCard.statsView.visibility = View.VISIBLE
+// renderedView.statsInterpreter?.initiateStats(
+// viewLifecycleOwner,
+// meetingViewModel.getStats(),
+// renderedView.meetingTrack.video,
+// renderedView.meetingTrack.audio,
+// renderedView.meetingTrack.peer.isLocal
+// ) { string -> renderedView.binding.videoCard.statsView.text = string }
+// } else {
+// renderedView.binding.videoCard.statsView.visibility = View.GONE
+// }
+// }
}
}
@@ -601,9 +576,10 @@ abstract class VideoGridBaseFragment : Fragment() {
@CallSuper
open fun initViewModels() {
- meetingViewModel.peerMetadataNameUpdate.observe(viewLifecycleOwner) {
- applyMetadataUpdates(it)
- }
+ //TODO add flow from sdk side
+// meetingViewModel.peerMetadataNameUpdate.observe(viewLifecycleOwner) {
+// applyMetadataUpdates(it)
+// }
}
abstract fun isScreenshare(): Boolean
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPageFragment.kt b/videogrid/src/main/java/live/hms/videogrid/VideoGridPageFragment.kt
similarity index 77%
rename from room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPageFragment.kt
rename to videogrid/src/main/java/live/hms/videogrid/VideoGridPageFragment.kt
index ee6c016a6..a1b0fcc3c 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPageFragment.kt
+++ b/videogrid/src/main/java/live/hms/videogrid/VideoGridPageFragment.kt
@@ -1,14 +1,12 @@
-package live.hms.roomkit.ui.meeting.videogrid
+package live.hms.videogrid
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.os.bundleOf
-import live.hms.roomkit.databinding.FragmentVideoGridPageBinding
-import live.hms.roomkit.ui.meeting.MeetingTrack
-import live.hms.roomkit.ui.meeting.commons.VideoGridBaseFragment
-import live.hms.roomkit.util.viewLifecycle
+import live.hms.common.databinding.FragmentVideoGridPageBinding
+import live.hms.videogrid.utils.viewLifecycle
import kotlin.math.min
class VideoGridPageFragment : VideoGridBaseFragment() {
@@ -28,7 +26,6 @@ class VideoGridPageFragment : VideoGridBaseFragment() {
}
}
-
private var binding by viewLifecycle()
private val pageIndex by lazy { requireArguments()[BUNDLE_PAGE_INDEX] as Int }
private val isScreenShare by lazy { requireArguments()[BUNDLE_IS_SCREEN_SHARE] as Boolean }
@@ -47,10 +44,10 @@ class VideoGridPageFragment : VideoGridBaseFragment() {
override fun onResume() {
super.onResume()
// Turn of sorting when we leave the first page
- meetingViewModel.speakerUpdateLiveData.enableSorting(pageIndex == 0)
+ gridViewModel.speakerUpdateLiveData.enableSorting(pageIndex == 0)
}
- private fun getCurrentPageVideos(tracks: List): List {
- val pageVideos = ArrayList()
+ private fun getCurrentPageVideos(tracks: List): List {
+ val pageVideos = ArrayList()
// Range is [fromIndex, toIndex] -- Notice the bounds
val itemsCount = maxItems
@@ -72,7 +69,7 @@ class VideoGridPageFragment : VideoGridBaseFragment() {
//don't update if row and column are same
if (shouldUpdate.not()) return
setVideoGridRowsAndColumns(rowCount, columnCount)
- meetingViewModel.speakerUpdateLiveData.refresh(rowCount, columnCount)
+ gridViewModel.speakerUpdateLiveData.refresh(rowCount, columnCount)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
@@ -84,11 +81,11 @@ class VideoGridPageFragment : VideoGridBaseFragment() {
override fun initViewModels() {
super.initViewModels()
if (isScreenShare.not()) {
- meetingViewModel.speakerUpdateLiveData.observe(viewLifecycleOwner) { videoGridTrack ->
+ gridViewModel.speakerUpdateLiveData.observe(viewLifecycleOwner) { videoGridTrack ->
renderCurrentPage(videoGridTrack)
}
} else {
- meetingViewModel.tracks.observe(viewLifecycleOwner) { track ->
+ gridViewModel.getTrackLiveData().observe(viewLifecycleOwner) { track ->
val screenShareTrack = track.filter { it.isScreen }.toList()
renderCurrentPage(screenShareTrack)
}
@@ -97,7 +94,7 @@ class VideoGridPageFragment : VideoGridBaseFragment() {
//Don't register listener if it's not screen share
if (isScreenShare.not()){
- meetingViewModel.updateRowAndColumnSpanForVideoPeerGrid.observe(viewLifecycleOwner) { (rowCount, columnCount) ->
+ gridViewModel.updateRowAndColumnSpanForVideoPeerGrid.observe(viewLifecycleOwner) { (rowCount, columnCount) ->
refreshGridRowsAndColumns(rowCount, columnCount)
}
}
@@ -109,7 +106,7 @@ class VideoGridPageFragment : VideoGridBaseFragment() {
return isScreenShare
}
- private fun renderCurrentPage(tracks: List) {
+ private fun renderCurrentPage(tracks: List) {
val videos = getCurrentPageVideos(tracks)
updateVideos(binding.container, videos, false)
}
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPageItem.kt b/videogrid/src/main/java/live/hms/videogrid/VideoGridPageItem.kt
similarity index 84%
rename from room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPageItem.kt
rename to videogrid/src/main/java/live/hms/videogrid/VideoGridPageItem.kt
index e4f24d3ef..a94267d23 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPageItem.kt
+++ b/videogrid/src/main/java/live/hms/videogrid/VideoGridPageItem.kt
@@ -1,6 +1,6 @@
-package live.hms.roomkit.ui.meeting.videogrid
+package live.hms.videogrid
-import live.hms.roomkit.ui.meeting.MeetingTrack
+import live.hms.video.sdk.reactive.MeetingTrack
data class VideoGridPageItem(
val id: Long,
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPagerDiffUtil.kt b/videogrid/src/main/java/live/hms/videogrid/VideoGridPagerDiffUtil.kt
similarity index 94%
rename from room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPagerDiffUtil.kt
rename to videogrid/src/main/java/live/hms/videogrid/VideoGridPagerDiffUtil.kt
index 925b96aa8..916ef302a 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/videogrid/VideoGridPagerDiffUtil.kt
+++ b/videogrid/src/main/java/live/hms/videogrid/VideoGridPagerDiffUtil.kt
@@ -1,4 +1,4 @@
-package live.hms.roomkit.ui.meeting.videogrid
+package live.hms.videogrid
import androidx.recyclerview.widget.DiffUtil
diff --git a/videogrid/src/main/java/live/hms/videogrid/utils/Ext.kt b/videogrid/src/main/java/live/hms/videogrid/utils/Ext.kt
new file mode 100644
index 000000000..45c8c7e5d
--- /dev/null
+++ b/videogrid/src/main/java/live/hms/videogrid/utils/Ext.kt
@@ -0,0 +1,64 @@
+package live.hms.videogrid.utils
+
+import android.content.Context
+import android.util.Log
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentActivity
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.viewbinding.ViewBinding
+import live.hms.video.media.tracks.HMSVideoTrack
+import kotlin.properties.ReadWriteProperty
+import kotlin.reflect.KProperty
+
+fun HMSVideoTrack?.isValid(): Boolean {
+ return !(this == null || this.isMute || this.isDegraded)
+}
+
+fun visibilityOpacity(show: Boolean) = if (show) {
+ 1.0f
+} else {
+ 0.0f
+}
+
+
+fun Fragment.viewLifecycle(): ReadWriteProperty =
+ object : ReadWriteProperty, DefaultLifecycleObserver {
+
+ private var binding: T? = null
+
+ override fun onDestroy(owner: LifecycleOwner) {
+ super.onDestroy(owner)
+
+
+ binding = null
+ owner.lifecycle.removeObserver(this)
+ }
+
+ override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
+ return this.binding ?: error("Called before onCreateView or after onDestroyView.")
+ }
+
+ override fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) {
+ if (this.binding != null) {
+ error("ViewBindingLifecycleExtension: binding already initialized to $binding")
+ }
+
+ this.binding = value
+
+ // Observe the view lifecycle of the Fragment.
+ // The view lifecycle owner is null before onCreateView and after onDestroyView.
+ // The observer is automatically removed after the onDestroy event.
+ thisRef.viewLifecycleOwnerLiveData.observe(thisRef.viewLifecycleOwner) {
+ it.lifecycle.addObserver(this)
+ }
+
+ }
+ }
+
+fun Fragment.contextSafe(funCall: (context: Context, activity: FragmentActivity) -> Unit) {
+ if (context != null && activity != null && activity?.isFinishing == false && isAdded) {
+ funCall.invoke(context!!, activity!!)
+ }
+}
+
diff --git a/videogrid/src/main/res/layout/hms_fragment_video_grid.xml b/videogrid/src/main/res/layout/hms_fragment_video_grid.xml
new file mode 100644
index 000000000..fa24034ff
--- /dev/null
+++ b/videogrid/src/main/res/layout/hms_fragment_video_grid.xml
@@ -0,0 +1,277 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/videogrid/src/main/res/layout/hms_grid_item.xml b/videogrid/src/main/res/layout/hms_grid_item.xml
new file mode 100644
index 000000000..3e2509b53
--- /dev/null
+++ b/videogrid/src/main/res/layout/hms_grid_item.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
diff --git a/videogrid/src/main/res/layout/hms_video_card.xml b/videogrid/src/main/res/layout/hms_video_card.xml
new file mode 100644
index 000000000..dafefb44c
--- /dev/null
+++ b/videogrid/src/main/res/layout/hms_video_card.xml
@@ -0,0 +1,180 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/videogrid/src/test/java/live/hms/videogrid/ExampleUnitTest.kt b/videogrid/src/test/java/live/hms/videogrid/ExampleUnitTest.kt
new file mode 100644
index 000000000..733785aab
--- /dev/null
+++ b/videogrid/src/test/java/live/hms/videogrid/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package live.hms.videogrid
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file