Skip to content

Commit

Permalink
Merge pull request #522 from 100mslive/dev
Browse files Browse the repository at this point in the history
Dev to release
  • Loading branch information
AniketSK authored Nov 6, 2023
2 parents 8832478 + e105db5 commit 864b1ea
Show file tree
Hide file tree
Showing 35 changed files with 993 additions and 387 deletions.
8 changes: 4 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ android {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.10.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

//100ms.live prebuilt lib
implementation "live.100ms:room-kit:1.1.1"
implementation "live.100ms:room-kit:1.1.2"

// Navigation
implementation "androidx.navigation:navigation-fragment-ktx:2.4.0"
Expand Down
12 changes: 3 additions & 9 deletions app/src/main/java/live/hms/app2/ui/home/HomeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,9 @@ class HomeFragment : Fragment() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_settings -> {
val args = Bundle().apply {
putSerializable("mode", SettingsMode.HOME)
}
parentFragmentManager
.beginTransaction()
.replace(R.id.nav_host_fragment, SettingsFragment().apply { arguments = args },
SETTINGS_FRAGMENT_TAG)
.addToBackStack(null)
.commit()
findNavController().navigate(
HomeFragmentDirections.actionHomeFragmentToSettingsFragment(SettingsMode.HOME)
)

}
R.id.action_email_logs -> {
Expand Down
18 changes: 18 additions & 0 deletions app/src/main/res/navigation/home_nav_graph.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,24 @@
android:label="@string/home_fragment"
tools:layout="@layout/fragment_home">

<action
android:id="@+id/action_HomeFragment_to_SettingsFragment"
app:destination="@id/SettingsFragment" />

</fragment>

<fragment
android:id="@+id/SettingsFragment"
android:name="live.hms.roomkit.ui.settings.SettingsFragment"
android:label="@string/settings_fragment"
tools:layout="@layout/fragment_settings">

<argument
android:name="mode"
app:argType="live.hms.roomkit.ui.settings.SettingsMode"
app:nullable="false" />

</fragment>


</navigation>
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ kotlin.code.style=official
100MS_APP_VERSION_CODE=643
100MS_APP_VERSION_NAME=5.8.872
hmsRoomKitGroup=live.100ms
HMS_ROOM_KIT_VERSION=1.1.1
HMS_ROOM_KIT_VERSION=1.1.2
android.suppressUnsupportedCompileSdk=33
2 changes: 1 addition & 1 deletion room-kit/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.percentlayout:percentlayout:1.0.0'

def hmsVersion = "2.7.8"
def hmsVersion = "2.8.0"
// To add dependencies of specific module
implementation "live.100ms:android-sdk:$hmsVersion"
implementation "live.100ms:video-view:$hmsVersion"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -666,14 +666,6 @@ class MeetingFragment : Fragment() {

}

// private fun showPollStart(poll: HmsPoll) {
// val pollId = poll.pollId
// if (!showedPolls.contains(pollId)) {
// showedPolls.add(pollId)
// meetingViewModel.triggerPollsNotification(poll)
// }
// }

private val pipReceiver by lazy {
PipBroadcastReceiver(
toogleLocalAudio = meetingViewModel::toggleLocalAudio,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class MeetingViewModel(
HMSAudioTrackSettings.Builder()
.setUseHardwareAcousticEchoCanceler(settings.enableHardwareAEC)
.initialState(getAudioTrackState())
.setDisableInternalAudioManager(settings.detectDominantSpeaker.not())
.setPhoneCallMuteState(if (settings.muteLocalAudioOnPhoneRing) PhoneCallState.ENABLE_MUTE_ON_PHONE_CALL_RING else PhoneCallState.DISABLE_MUTE_ON_VOIP_PHONE_CALL_RING)
.build()
)
Expand Down Expand Up @@ -1912,6 +1913,16 @@ class MeetingViewModel(
}
fun permissionGranted() = hmsSDK.setPermissionsAccepted()

fun endPoll(hmsPoll: HmsPoll) = localHmsInteractivityCenter.stop(hmsPoll, object : HMSActionResultListener {
override fun onError(error: HMSException) {
Log.e("EndPoll","Error ending poll")
}

override fun onSuccess() {
Log.d("EndPoll","Poll ended")
}

})
fun startPoll(currentList: List<QuestionUi>, pollCreationInfo: PollCreationInfo) {
// To start a poll

Expand All @@ -1927,28 +1938,29 @@ class MeetingViewModel(
Log.d("Polls","Processing $questionUi")

when(questionUi) {
is QuestionUi.LongAnswer -> hmsPollBuilder.addLongAnswerQuestion(questionUi.text)
// is QuestionUi.LongAnswer -> hmsPollBuilder.addLongAnswerQuestion(questionUi.text)
is QuestionUi.MultiChoiceQuestion -> {
val multiChoice = HMSPollQuestionBuilder.Builder(HMSPollQuestionType.multiChoice)
.withTitle(questionUi.withTitle)
questionUi.options.forEachIndexed { index : Int, option : String ->
multiChoice.addQuizOption(option, questionUi.correctOptionIndex?.contains(index) == true)
multiChoice.addQuizOption(option, questionUi.selections.contains(index))
}
hmsPollBuilder
.addQuestion(multiChoice.build())
}
QuestionUi.QuestionCreator,
QuestionUi.AddAnotherItemView -> { /*Nothing to do here*/}
is QuestionUi.ShortAnswer -> hmsPollBuilder.addShortAnswerQuestion(questionUi.text)
// is QuestionUi.ShortAnswer -> hmsPollBuilder.addShortAnswerQuestion(questionUi.text)
is QuestionUi.SingleChoiceQuestion -> {
val singleChoiceQuestionBuilder = HMSPollQuestionBuilder.Builder(HMSPollQuestionType.singleChoice)
.withTitle(questionUi.withTitle)
questionUi.options.forEachIndexed { index : Int, option : String ->
singleChoiceQuestionBuilder.addQuizOption(option, questionUi.correctOptionIndex == index)
singleChoiceQuestionBuilder.addQuizOption(option, isCorrect = questionUi.selections.contains(index))
}
hmsPollBuilder
.addQuestion(singleChoiceQuestionBuilder.build())
}
is QuestionUi.QuestionCreator,
is QuestionUi.LaunchButton,
QuestionUi.AddAnotherItemView, -> { /*Nothing to do here*/}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package live.hms.roomkit.ui.polls

import android.view.View
import com.xwray.groupie.viewbinding.BindableItem
import live.hms.roomkit.R
import live.hms.roomkit.databinding.LayoutMultiChoiceQuestionOptionItemBinding
import live.hms.roomkit.ui.theme.applyTheme

class MultiChoiceQuestionOptionItem(
question: QuestionUi.ChoiceQuestions,
val option: String
) : BindableItem<LayoutMultiChoiceQuestionOptionItemBinding>(question.getItemId()) {
override fun bind(viewBinding: LayoutMultiChoiceQuestionOptionItemBinding, position: Int) {
with(viewBinding) {
applyTheme()
optionText.text = option
}
// We need a divider of spacing 1
}

override fun getLayout(): Int = R.layout.layout_multi_choice_question_option_item

override fun initializeViewBinding(view: View): LayoutMultiChoiceQuestionOptionItemBinding =
LayoutMultiChoiceQuestionOptionItemBinding.bind(view)

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,47 @@ import androidx.core.widget.doOnTextChanged
import androidx.recyclerview.widget.RecyclerView.NO_POSITION
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import live.hms.roomkit.databinding.LayoutPollQuizOptionsItemBinding
import live.hms.roomkit.setOnSingleClickListener

class OptionViewHolder(val binding : LayoutPollQuizOptionsItemBinding,
getItem: (position : Int) -> Option,
selectOnlyCurrentPosition : (Int) -> Unit,
refreshSubmitButton : () -> Unit) : ViewHolder(binding.root) {
selectRadioOption : (Int) -> Unit,
selectCheckboxOption : (Int, Boolean) -> Unit,
deleteThisOption : (position : Int) -> Unit,
) : ViewHolder(binding.root) {
private var skipCheckChange = false
init {
if(bindingAdapterPosition != NO_POSITION) {
binding.text.setText(getItem(bindingAdapterPosition).text)
}
binding.deleteOptionTrashButton.setOnSingleClickListener {
// Avoid edittext crash
binding.root.requestFocus()
deleteThisOption(bindingAdapterPosition)
}
binding.text.doOnTextChanged { text, _, _, _ ->
getItem(bindingAdapterPosition).text = text.toString()
}
// Both set the same property, only one will be used.
binding.radioButton.setOnCheckedChangeListener { _, isChecked ->
// Radio buttons reset all others when selected
if(skipCheckChange)
return@setOnCheckedChangeListener
if(isChecked)
selectOnlyCurrentPosition(bindingAdapterPosition)
refreshSubmitButton()
selectRadioOption(bindingAdapterPosition)
}
binding.checkbox.setOnCheckedChangeListener { _, isChecked ->
getItem(bindingAdapterPosition).isChecked = isChecked
refreshSubmitButton()
if(skipCheckChange)
return@setOnCheckedChangeListener
selectCheckboxOption(bindingAdapterPosition, isChecked)
}
}

fun bind(option : Option) {
skipCheckChange = true
binding.radioButton.isChecked = option.isChecked
binding.checkbox.isChecked = option.isChecked
skipCheckChange = false
when(option.showCheckbox) {
true -> {
binding.checkbox.visibility = View.VISIBLE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.widget.addTextChangedListener
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import live.hms.roomkit.databinding.LayoutPollQuizOptionsItemBinding
import live.hms.roomkit.databinding.LayoutPollQuizOptionsItemMultiChoiceBinding
import live.hms.roomkit.ui.theme.setTheme
import java.util.*

Expand All @@ -19,6 +17,11 @@ data class Option(var text : String,

class OptionsListAdapter : ListAdapter<Option, OptionViewHolder>(DIFFUTIL_CALLBACK) {
lateinit var refreshSubmitButton :() -> Unit
lateinit var onOptionTextChanged : (optionIndex : Int, text : String) -> Unit
lateinit var onSingleOptionSelected : (optionIndex : Int) -> Unit
lateinit var onMultipleOptionSelected : (optionIndex : Int, selected : Boolean) -> Unit
lateinit var deleteOption : (optionIndex : Int) -> Unit


companion object {
val DIFFUTIL_CALLBACK = object : DiffUtil.ItemCallback<Option>() {
Expand All @@ -34,22 +37,31 @@ class OptionsListAdapter : ListAdapter<Option, OptionViewHolder>(DIFFUTIL_CALLBA

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionViewHolder {
val binding = LayoutPollQuizOptionsItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return OptionViewHolder(binding,::getItem, ::selectOnlyCurrentOption, refreshSubmitButton)
return OptionViewHolder(binding,
::getItem,
::selectRadioOption,
::selectCheckboxOption,
deleteOption
)
}

override fun onBindViewHolder(holder: OptionViewHolder, position: Int) {
holder.bind(getItem(position))
holder.binding.setTheme()
// Put the cursor in the edittext as it's created.
holder.binding.text.requestFocus()
// holder.binding.text.requestFocus() // TODO maybe required but it's not quite right anyway
holder.binding.text.hint = "Option ${position+1}"
holder.binding.text.addTextChangedListener(object : TextWatcher {
holder.binding.text.addTextChangedListener(
object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

}

override fun onTextChanged(text: CharSequence?, p1: Int, p2: Int, p3: Int) {
getItem(holder.bindingAdapterPosition).text = text.toString()
val text = text.toString()
onOptionTextChanged(holder.bindingAdapterPosition, text)
// Maybe this is not required? Might be too big to refresh.
getItem(holder.bindingAdapterPosition).text = text
}

override fun afterTextChanged(p0: Editable?) {
Expand All @@ -67,11 +79,19 @@ class OptionsListAdapter : ListAdapter<Option, OptionViewHolder>(DIFFUTIL_CALLBA
refreshSubmitButton()
}

private fun selectOnlyCurrentOption(position: Int) {
for ( i in 0 until currentList.size) {
private fun selectRadioOption(position: Int){
onSingleOptionSelected(position)
// TODO this might not be necessary
for (i in 0 until currentList.size) {
getItem(i).isChecked = i == position
if(i != position)
if (i != position)
notifyItemChanged(i)
}
refreshSubmitButton()
}
private fun selectCheckboxOption(position: Int, selected: Boolean) {
onMultipleOptionSelected(position, selected)
getItem(position).isChecked = selected
refreshSubmitButton()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.content.res.AppCompatResources
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView.VERTICAL
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import live.hms.roomkit.R
import live.hms.roomkit.databinding.LayoutPollQuestionCreationBinding
import live.hms.roomkit.ui.meeting.MeetingViewModel
Expand All @@ -26,9 +31,10 @@ import live.hms.roomkit.util.viewLifecycle
*/
class PollQuestionCreation : Fragment() {

val args: PollQuestionCreationArgs by navArgs()
private val pollsViewModel: PollsViewModel by activityViewModels()
private val meetingViewModel: MeetingViewModel by activityViewModels()
private val adapter = PollQuestionCreatorAdapter { pollsViewModel.isPoll() }
private val adapter by lazy { PollQuestionCreatorAdapter(args.isPoll, ::launchPoll) }

private var binding by viewLifecycle<LayoutPollQuestionCreationBinding>()

Expand Down Expand Up @@ -56,30 +62,15 @@ class PollQuestionCreation : Fragment() {
super.onViewCreated(view, savedInstanceState)
initOnBackPress()
with(binding) {
heading.text = "${pollsViewModel.getPollsCreationInfo().pollTitle} ${if(pollsViewModel.isPoll()) "Poll" else "Quiz"}"
backButton.setOnSingleClickListener { findNavController().popBackStack() }
createdQuestionList.adapter = adapter
createdQuestionList.layoutManager = LinearLayoutManager(requireContext())
val divider = DividerItemDecoration(requireContext(), VERTICAL).apply {
setDrawable(binding.root.context.getDrawable(R.drawable.questions_divider)!!)
setDrawable(AppCompatResources.getDrawable(requireContext(), R.drawable.questions_divider)!!)
}
createdQuestionList.addItemDecoration(divider)

adapter.isReady = { isReady ->
launchPollQuiz.isEnabled = isReady
}


launchPollQuiz.setOnSingleClickListener {
// Clear the UI
// start the data
meetingViewModel.startPoll(
adapter.currentList,
pollsViewModel.getPollsCreationInfo()
)
backButton.callOnClick()
}
// Will be enabled later.
launchPollQuiz.isEnabled = false
}
}

Expand All @@ -92,4 +83,14 @@ class PollQuestionCreation : Fragment() {
}
})
}

private fun launchPoll() {
// Launch the poll
meetingViewModel.startPoll(
adapter.currentList,
pollsViewModel.getPollsCreationInfo()
)
// Go back
findNavController().popBackStack()
}
}
Loading

0 comments on commit 864b1ea

Please sign in to comment.