Commit 38893736 authored by Filipe de Lima Brito's avatar Filipe de Lima Brito

Configure Jitsi view.

parent 619af264
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" /> android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
<activity <activity
android:name=".videoconferencing.ui.VideoConferencingActivity" android:name=".videoconference.ui.VideoConferenceActivity"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" /> android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
......
...@@ -46,8 +46,7 @@ class ChatDetailsPresenter @Inject constructor( ...@@ -46,8 +46,7 @@ class ChatDetailsPresenter @Inject constructor(
} }
} }
// TODO fun toVideoConference(roomId: String) = navigator.toVideoConference(roomId)
fun startVideoCall() {}
fun getDetails(chatRoomId: String, chatRoomType: String) { fun getDetails(chatRoomId: String, chatRoomType: String) {
launchUI(strategy) { launchUI(strategy) {
......
...@@ -5,7 +5,6 @@ import android.view.MenuItem ...@@ -5,7 +5,6 @@ import android.view.MenuItem
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.server.domain.isJitsiEnabled import chat.rocket.android.server.domain.isJitsiEnabled
import chat.rocket.android.server.domain.isJitsiEnabledForChannels import chat.rocket.android.server.domain.isJitsiEnabledForChannels
import chat.rocket.android.videoconferencing.ui.videoConferencingIntent
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf import chat.rocket.common.model.roomTypeOf
...@@ -48,6 +47,6 @@ internal fun ChatDetailsFragment.setOnMenuItemClickListener(item: MenuItem) { ...@@ -48,6 +47,6 @@ internal fun ChatDetailsFragment.setOnMenuItemClickListener(item: MenuItem) {
if (item.itemId == MENU_ACTION_FAVORITE_REMOVE_FAVORITE) { if (item.itemId == MENU_ACTION_FAVORITE_REMOVE_FAVORITE) {
presenter.toggleFavoriteChatRoom(chatRoomId, isFavorite) presenter.toggleFavoriteChatRoom(chatRoomId, isFavorite)
} else if (item.itemId == MENU_ACTION_VIDEO_CALL) { } else if (item.itemId == MENU_ACTION_VIDEO_CALL) {
startActivity(activity?.videoConferencingIntent(chatRoomId)) presenter.toVideoConference(chatRoomId)
} }
} }
...@@ -41,7 +41,7 @@ class ChatRoomAdapter( ...@@ -41,7 +41,7 @@ class ChatRoomAdapter(
actionsListener, actionsListener,
reactionListener, reactionListener,
{ userId -> navigator?.toUserDetails(userId) }, { userId -> navigator?.toUserDetails(userId) },
{ roomId?.let { navigator?.toVideoConferencing(it) } } { roomId?.let { navigator?.toVideoConference(it) } }
) )
} }
BaseUiModel.ViewType.URL_PREVIEW -> { BaseUiModel.ViewType.URL_PREVIEW -> {
......
...@@ -13,7 +13,7 @@ import chat.rocket.android.pinnedmessages.ui.TAG_PINNED_MESSAGES_FRAGMENT ...@@ -13,7 +13,7 @@ import chat.rocket.android.pinnedmessages.ui.TAG_PINNED_MESSAGES_FRAGMENT
import chat.rocket.android.server.ui.changeServerIntent import chat.rocket.android.server.ui.changeServerIntent
import chat.rocket.android.userdetails.ui.TAG_USER_DETAILS_FRAGMENT import chat.rocket.android.userdetails.ui.TAG_USER_DETAILS_FRAGMENT
import chat.rocket.android.util.extensions.addFragmentBackStack import chat.rocket.android.util.extensions.addFragmentBackStack
import chat.rocket.android.videoconferencing.ui.videoConferencingIntent import chat.rocket.android.videoconference.ui.videoConferenceIntent
class ChatRoomNavigator(internal val activity: ChatRoomActivity) { class ChatRoomNavigator(internal val activity: ChatRoomActivity) {
...@@ -23,8 +23,8 @@ class ChatRoomNavigator(internal val activity: ChatRoomActivity) { ...@@ -23,8 +23,8 @@ class ChatRoomNavigator(internal val activity: ChatRoomActivity) {
} }
} }
fun toVideoConferencing(chatRoomId: String) { fun toVideoConference(chatRoomId: String) {
activity.startActivity(activity.videoConferencingIntent(chatRoomId)) activity.startActivity(activity.videoConferenceIntent(chatRoomId))
} }
fun toChatRoom( fun toChatRoom(
......
...@@ -37,8 +37,8 @@ import chat.rocket.android.settings.di.SettingsFragmentProvider ...@@ -37,8 +37,8 @@ import chat.rocket.android.settings.di.SettingsFragmentProvider
import chat.rocket.android.settings.password.di.PasswordFragmentProvider import chat.rocket.android.settings.password.di.PasswordFragmentProvider
import chat.rocket.android.settings.password.ui.PasswordActivity import chat.rocket.android.settings.password.ui.PasswordActivity
import chat.rocket.android.userdetails.di.UserDetailsFragmentProvider import chat.rocket.android.userdetails.di.UserDetailsFragmentProvider
import chat.rocket.android.videoconferencing.di.VideoConferencingModule import chat.rocket.android.videoconference.di.VideoConferenceModule
import chat.rocket.android.videoconferencing.ui.VideoConferencingActivity import chat.rocket.android.videoconference.ui.VideoConferenceActivity
import chat.rocket.android.webview.adminpanel.di.AdminPanelWebViewFragmentProvider import chat.rocket.android.webview.adminpanel.di.AdminPanelWebViewFragmentProvider
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
...@@ -107,6 +107,6 @@ abstract class ActivityBuilder { ...@@ -107,6 +107,6 @@ abstract class ActivityBuilder {
abstract fun bindDrawingActivity(): DrawingActivity abstract fun bindDrawingActivity(): DrawingActivity
@PerActivity @PerActivity
@ContributesAndroidInjector(modules = [VideoConferencingModule::class]) @ContributesAndroidInjector(modules = [VideoConferenceModule::class])
abstract fun bindVideoConferencingActivity(): VideoConferencingActivity abstract fun bindVideoConferenceActivity(): VideoConferenceActivity
} }
package chat.rocket.android.helper package chat.rocket.android.helper
import java.net.URL
object JitsiHelper { object JitsiHelper {
/** /**
* Returns the [URL] for the Jitsi video conferencing. * Returns the for the Jitsi video conferencing URL.
* *
* @param isSecureProtocol True if using SSL, false otherwise - from the public settings. * @param isSecureProtocol True if using SSL, false otherwise - from the public settings.
* @param domain The Jitsi domain - from public settings. * @param domain The Jitsi domain - from public settings.
...@@ -19,15 +17,13 @@ object JitsiHelper { ...@@ -19,15 +17,13 @@ object JitsiHelper {
prefix: String?, prefix: String?,
uniqueIdentifier: String?, uniqueIdentifier: String?,
chatRoomId: String? chatRoomId: String?
): URL = ): String =
URL(
getJitsiProtocol(isSecureProtocol) + getJitsiProtocol(isSecureProtocol) +
domain + domain +
"/" + "/" +
prefix + prefix +
uniqueIdentifier + uniqueIdentifier +
chatRoomId chatRoomId
)
private fun getJitsiProtocol(isSecureProtocol: Boolean) = private fun getJitsiProtocol(isSecureProtocol: Boolean) =
if (isSecureProtocol) "https://" else "http://" if (isSecureProtocol) "https://" else "http://"
......
...@@ -124,14 +124,14 @@ class UserDetailsPresenter @Inject constructor( ...@@ -124,14 +124,14 @@ class UserDetailsPresenter @Inject constructor(
} }
} }
fun toVideoConferencing(username: String) { fun toVideoConference(username: String) {
launchUI(strategy) { launchUI(strategy) {
try { try {
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
val directMessage = retryIO("createDirectMessage($username") { val directMessage = retryIO("createDirectMessage($username") {
client.createDirectMessage(username) client.createDirectMessage(username)
} }
navigator.toVideoConferencing(directMessage.id) navigator.toVideoConference(directMessage.id)
} }
} catch (ex: Exception) { } catch (ex: Exception) {
Timber.e(ex) Timber.e(ex)
......
...@@ -104,7 +104,7 @@ class UserDetailsFragment : Fragment(), UserDetailsView { ...@@ -104,7 +104,7 @@ class UserDetailsFragment : Fragment(), UserDetailsView {
if (isVideoCallAllowed) { if (isVideoCallAllowed) {
text_video_call.isVisible = true text_video_call.isVisible = true
text_video_call.setOnClickListener { presenter.toVideoConferencing(username) } text_video_call.setOnClickListener { presenter.toVideoConference(username) }
} else { } else {
text_video_call.isVisible = false text_video_call.isVisible = false
} }
......
package chat.rocket.android.videoconferencing.di package chat.rocket.android.videoconference.di
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerActivity import chat.rocket.android.dagger.scope.PerActivity
import chat.rocket.android.videoconferencing.presenter.VideoConferencingView import chat.rocket.android.videoconference.presenter.JitsiVideoConferenceView
import chat.rocket.android.videoconferencing.ui.VideoConferencingActivity import chat.rocket.android.videoconference.ui.VideoConferenceActivity
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@Module @Module
class VideoConferencingModule { class VideoConferenceModule {
@Provides @Provides
@PerActivity @PerActivity
fun provideVideoConferencingView(activity: VideoConferencingActivity): VideoConferencingView { fun provideVideoConferenceView(activity: VideoConferenceActivity): JitsiVideoConferenceView {
return activity return activity
} }
...@@ -24,7 +24,7 @@ class VideoConferencingModule { ...@@ -24,7 +24,7 @@ class VideoConferencingModule {
@Provides @Provides
@PerActivity @PerActivity
fun provideLifecycleOwner(activity: VideoConferencingActivity): LifecycleOwner = activity fun provideLifecycleOwner(activity: VideoConferenceActivity): LifecycleOwner = activity
@Provides @Provides
@PerActivity @PerActivity
......
package chat.rocket.android.videoconference.presenter
interface JitsiVideoConferenceView {
/**
* Starts the Jitsi video conference.
*
* @param url The video conference URL to be loaded.
* @param name The user name to be show on the video conference.
*/
fun startJitsiVideoConference(url: String, name: String?)
/**
* Closes the Jitsi video conference.
*/
fun closeJitsiVideoConference()
/**
* Logs the state of the Jitsi Meet conference displayed in a JitsiMeetView.
*
* @param message The message to log.
* @param map the map information by Jitsi
*/
fun logJitsiMeetViewState(message: String, map: MutableMap<String, Any>?)
}
\ No newline at end of file
package chat.rocket.android.videoconferencing.presenter package chat.rocket.android.videoconference.presenter
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.helper.JitsiHelper import chat.rocket.android.helper.JitsiHelper
import chat.rocket.android.helper.UserHelper
import chat.rocket.android.server.domain.* import chat.rocket.android.server.domain.*
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.core.RocketChatClient import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.realtime.updateJitsiTimeout import chat.rocket.core.internal.rest.updateJitsiTimeout
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
import kotlin.concurrent.timer import kotlin.concurrent.timer
class VideoConferencingPresenter @Inject constructor( class VideoConferencePresenter @Inject constructor(
private val view: VideoConferencingView, private val view: JitsiVideoConferenceView,
private val strategy: CancelStrategy, private val strategy: CancelStrategy,
private val currentServerRepository: CurrentServerRepository, private val currentServerRepository: CurrentServerRepository,
private val connectionManagerFactory: ConnectionManagerFactory, private val connectionManagerFactory: ConnectionManagerFactory,
private val settings: GetSettingsInteractor private val settings: GetSettingsInteractor,
private val userHelp: UserHelper
) { ) {
private lateinit var client: RocketChatClient private lateinit var client: RocketChatClient
private lateinit var publicSettings: PublicSettings private lateinit var publicSettings: PublicSettings
...@@ -34,22 +37,31 @@ class VideoConferencingPresenter @Inject constructor( ...@@ -34,22 +37,31 @@ class VideoConferencingPresenter @Inject constructor(
this.chatRoomId = chatRoomId this.chatRoomId = chatRoomId
} }
fun setupVideoConferencing() { fun initVideoConference() {
launchUI(strategy) { launchUI(strategy) {
try {
with(publicSettings) { with(publicSettings) {
view.startVideoConferencing( view.startJitsiVideoConference(
JitsiHelper.getJitsiUrl( JitsiHelper.getJitsiUrl(
isJitsiSSL(), isJitsiSSL(),
jitsiDomain(), jitsiDomain(),
jitsiPrefix(), jitsiPrefix(),
uniqueIdentifier(), uniqueIdentifier(),
chatRoomId chatRoomId
),
userHelp.user()?.username
) )
)
updateJitsiTimeout() updateJitsiTimeout()
} }
} catch (ex: Exception) {
Timber.e(ex)
view.closeJitsiVideoConference()
} }
} }
}
fun invalidateTimer() = timer.cancel()
// Jitsi update call needs to be called every 10 seconds to make sure call is not ended and is available to web users. // Jitsi update call needs to be called every 10 seconds to make sure call is not ended and is available to web users.
private fun updateJitsiTimeout() { private fun updateJitsiTimeout() {
...@@ -59,6 +71,5 @@ class VideoConferencingPresenter @Inject constructor( ...@@ -59,6 +71,5 @@ class VideoConferencingPresenter @Inject constructor(
} }
} }
} }
fun invalidateTimer() = timer.cancel()
} }
package chat.rocket.android.videoconference.ui
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.core.os.bundleOf
import chat.rocket.android.videoconference.presenter.JitsiVideoConferenceView
import chat.rocket.android.videoconference.presenter.VideoConferencePresenter
import dagger.android.AndroidInjection
import org.jitsi.meet.sdk.JitsiMeetActivity
import org.jitsi.meet.sdk.JitsiMeetView
import org.jitsi.meet.sdk.JitsiMeetViewListener
import timber.log.Timber
import javax.inject.Inject
fun Context.videoConferenceIntent(chatRoomId: String): Intent =
Intent(this, VideoConferenceActivity::class.java).putExtra(INTENT_CHAT_ROOM_ID, chatRoomId)
private const val INTENT_CHAT_ROOM_ID = "chat_room_id"
class VideoConferenceActivity : JitsiMeetActivity(), JitsiVideoConferenceView,
JitsiMeetViewListener {
@Inject
lateinit var presenter: VideoConferencePresenter
private lateinit var chatRoomId: String
private var view: JitsiMeetView? = null
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
chatRoomId = intent.getStringExtra(INTENT_CHAT_ROOM_ID)
requireNotNull(chatRoomId) { "no chat_room_id provided in Intent extras" }
view = JitsiMeetView(this)
view?.listener = this
setContentView(view)
presenter.setup(chatRoomId)
presenter.initVideoConference()
}
override fun onDestroy() {
super.onDestroy()
presenter.invalidateTimer()
view?.dispose()
view = null
}
override fun onConferenceWillJoin(map: MutableMap<String, Any>?) =
logJitsiMeetViewState("Joining video conferencing", map)
override fun onConferenceJoined(map: MutableMap<String, Any>?) =
logJitsiMeetViewState("Joined video conferencing", map)
override fun onConferenceWillLeave(map: MutableMap<String, Any>?) =
logJitsiMeetViewState("Leaving video conferencing", map)
override fun onConferenceLeft(map: MutableMap<String, Any>?) {
logJitsiMeetViewState("Left video conferencing", map)
closeJitsiVideoConference()
}
override fun onLoadConfigError(map: MutableMap<String, Any>?) =
logJitsiMeetViewState("Error loading video conference config", map)
override fun onConferenceFailed(map: MutableMap<String, Any>?) =
logJitsiMeetViewState("Video conference failed", map)
override fun startJitsiVideoConference(url: String, name: String?) {
view?.loadURLObject(
bundleOf(
"config" to bundleOf(
"startWithAudioMuted" to true,
"startWithVideoMuted" to true
),
"context" to bundleOf(
"user" to bundleOf("name" to name),
"iss" to "rocketchat-android"
),
"url" to url
)
)
}
override fun closeJitsiVideoConference() = finish()
override fun logJitsiMeetViewState(message: String, map: MutableMap<String, Any>?) =
Timber.i("$message: $map")
}
package chat.rocket.android.videoconferencing.presenter
import java.net.URL
interface VideoConferencingView {
/**
* Starts the video conferencing.
*
* @param url The video conferencing URL to be loaded.
*/
fun startVideoConferencing(url: URL)
}
\ No newline at end of file
package chat.rocket.android.videoconferencing.ui
import android.content.Context
import android.content.Intent
import android.os.Bundle
import chat.rocket.android.videoconferencing.presenter.VideoConferencingPresenter
import chat.rocket.android.videoconferencing.presenter.VideoConferencingView
import dagger.android.AndroidInjection
import org.jitsi.meet.sdk.JitsiMeetActivity
import java.net.URL
import javax.inject.Inject
fun Context.videoConferencingIntent(chatRoomId: String): Intent =
Intent(this, VideoConferencingActivity::class.java).putExtra(INTENT_CHAT_ROOM_ID, chatRoomId)
private const val INTENT_CHAT_ROOM_ID = "chat_room_id"
class VideoConferencingActivity : JitsiMeetActivity(), VideoConferencingView {
@Inject
lateinit var presenter: VideoConferencingPresenter
private lateinit var chatRoomId: String
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
chatRoomId = intent.getStringExtra(INTENT_CHAT_ROOM_ID)
requireNotNull(chatRoomId) { "no chat_room_id provided in Intent extras" }
presenter.setup(chatRoomId)
presenter.setupVideoConferencing()
}
override fun onDestroy() {
super.onDestroy()
presenter.invalidateTimer()
}
override fun startVideoConferencing(url: URL) = loadURL(url)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment