Show conference edit button in schedule list for organizer + allow to edit conference + sort conferences by date when notified of a new conference schedule by callback while in conferences list view
This commit is contained in:
parent
aff768548a
commit
f4c89fbb2c
8 changed files with 106 additions and 31 deletions
|
@ -50,6 +50,10 @@ class ScheduledConferencesAdapter(
|
|||
MutableLiveData<Event<Pair<String, String?>>>()
|
||||
}
|
||||
|
||||
val editConferenceEvent: MutableLiveData<Event<String>> by lazy {
|
||||
MutableLiveData<Event<String>>()
|
||||
}
|
||||
|
||||
val deleteConferenceInfoEvent: MutableLiveData<Event<ScheduledConferenceData>> by lazy {
|
||||
MutableLiveData<Event<ScheduledConferenceData>>()
|
||||
}
|
||||
|
@ -117,6 +121,13 @@ class ScheduledConferencesAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
setEditConferenceClickListener {
|
||||
val address = conferenceData.conferenceInfo.uri
|
||||
if (address != null) {
|
||||
editConferenceEvent.value = Event(address.asStringUriOnly())
|
||||
}
|
||||
}
|
||||
|
||||
setDeleteConferenceClickListener {
|
||||
deleteConferenceInfoEvent.value = Event(conferenceData)
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ class ScheduledConferenceData(val conferenceInfo: ConferenceInfo) {
|
|||
val date = MutableLiveData<String>()
|
||||
val duration = MutableLiveData<String>()
|
||||
val organizer = MutableLiveData<String>()
|
||||
val canEdit = MutableLiveData<Boolean>()
|
||||
val participantsShort = MutableLiveData<String>()
|
||||
val participantsExpanded = MutableLiveData<String>()
|
||||
val showDuration = MutableLiveData<Boolean>()
|
||||
|
@ -59,12 +60,19 @@ class ScheduledConferenceData(val conferenceInfo: ConferenceInfo) {
|
|||
|
||||
val organizerAddress = conferenceInfo.organizer
|
||||
if (organizerAddress != null) {
|
||||
val localAccount = coreContext.core.accountList.find { account ->
|
||||
val address = account.params.identityAddress
|
||||
address != null && organizerAddress.weakEqual(address)
|
||||
}
|
||||
canEdit.value = localAccount != null
|
||||
|
||||
val contact = coreContext.contactsManager.findContactByAddress(organizerAddress)
|
||||
organizer.value = if (contact != null)
|
||||
contact.fullName
|
||||
else
|
||||
LinphoneUtils.getDisplayName(conferenceInfo.organizer)
|
||||
} else {
|
||||
canEdit.value = false
|
||||
Log.e("[Scheduled Conference] No organizer SIP URI found for: ${conferenceInfo.uri?.asStringUriOnly()}")
|
||||
}
|
||||
|
||||
|
|
|
@ -22,20 +22,26 @@ package org.linphone.activities.main.conference.fragments
|
|||
import android.os.Bundle
|
||||
import android.text.format.DateFormat.is24HourFormat
|
||||
import android.view.View
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.navGraphViewModels
|
||||
import com.google.android.material.datepicker.CalendarConstraints
|
||||
import com.google.android.material.datepicker.DateValidatorPointForward
|
||||
import com.google.android.material.datepicker.MaterialDatePicker
|
||||
import com.google.android.material.timepicker.MaterialTimePicker
|
||||
import com.google.android.material.timepicker.TimeFormat
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
import org.linphone.activities.main.conference.viewmodels.ConferenceSchedulingViewModel
|
||||
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||
import org.linphone.activities.navigateToParticipantsList
|
||||
import org.linphone.core.Factory
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.ConferenceSchedulingFragmentBinding
|
||||
|
||||
class ConferenceSchedulingFragment : GenericFragment<ConferenceSchedulingFragmentBinding>() {
|
||||
private val viewModel: ConferenceSchedulingViewModel by navGraphViewModels(R.id.conference_scheduling_nav_graph)
|
||||
private lateinit var sharedViewModel: SharedMainViewModel
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.conference_scheduling_fragment
|
||||
|
||||
|
@ -46,6 +52,29 @@ class ConferenceSchedulingFragment : GenericFragment<ConferenceSchedulingFragmen
|
|||
|
||||
binding.viewModel = viewModel
|
||||
|
||||
sharedViewModel = requireActivity().run {
|
||||
ViewModelProvider(this)[SharedMainViewModel::class.java]
|
||||
}
|
||||
|
||||
sharedViewModel.conferenceInfoToEdit.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume { address ->
|
||||
val conferenceAddress = Factory.instance().createAddress(address)
|
||||
if (conferenceAddress != null) {
|
||||
Log.i("[Conference Scheduling] Trying to edit conference info using address: $address")
|
||||
val conferenceInfo = coreContext.core.findConferenceInformationFromUri(conferenceAddress)
|
||||
if (conferenceInfo != null) {
|
||||
viewModel.populateFromConferenceInfo(conferenceInfo)
|
||||
} else {
|
||||
Log.e("[Conference Scheduling] Failed to find ConferenceInfo matching address: $address")
|
||||
}
|
||||
} else {
|
||||
Log.e("[Conference Scheduling] Failed to parse conference address: $address")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.setBackClickListener {
|
||||
goBack()
|
||||
}
|
||||
|
|
|
@ -33,16 +33,19 @@ import org.linphone.activities.main.MainActivity
|
|||
import org.linphone.activities.main.conference.adapters.ScheduledConferencesAdapter
|
||||
import org.linphone.activities.main.conference.viewmodels.ScheduledConferencesViewModel
|
||||
import org.linphone.activities.main.viewmodels.DialogViewModel
|
||||
import org.linphone.activities.main.viewmodels.SharedMainViewModel
|
||||
import org.linphone.activities.navigateToConferenceScheduling
|
||||
import org.linphone.activities.navigateToConferenceWaitingRoom
|
||||
import org.linphone.databinding.ConferencesScheduledFragmentBinding
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.RecyclerViewHeaderDecoration
|
||||
|
||||
class ScheduledConferencesFragment : GenericFragment<ConferencesScheduledFragmentBinding>() {
|
||||
private lateinit var viewModel: ScheduledConferencesViewModel
|
||||
private lateinit var adapter: ScheduledConferencesAdapter
|
||||
private lateinit var sharedViewModel: SharedMainViewModel
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.conferences_scheduled_fragment
|
||||
|
||||
|
@ -63,6 +66,10 @@ class ScheduledConferencesFragment : GenericFragment<ConferencesScheduledFragmen
|
|||
)
|
||||
binding.conferenceInfoList.adapter = adapter
|
||||
|
||||
sharedViewModel = requireActivity().run {
|
||||
ViewModelProvider(this)[SharedMainViewModel::class.java]
|
||||
}
|
||||
|
||||
val layoutManager = LinearLayoutManager(activity)
|
||||
binding.conferenceInfoList.layoutManager = layoutManager
|
||||
|
||||
|
@ -97,6 +104,15 @@ class ScheduledConferencesFragment : GenericFragment<ConferencesScheduledFragmen
|
|||
}
|
||||
}
|
||||
|
||||
adapter.editConferenceEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume { address ->
|
||||
sharedViewModel.conferenceInfoToEdit.value = Event(address)
|
||||
navigateToConferenceScheduling()
|
||||
}
|
||||
}
|
||||
|
||||
adapter.deleteConferenceInfoEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
|
|
|
@ -69,20 +69,9 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
|||
var hour: Int = 0
|
||||
var minutes: Int = 0
|
||||
|
||||
private var confInfo: ConferenceInfo? = null
|
||||
private val conferenceScheduler = coreContext.core.createConferenceScheduler()
|
||||
|
||||
private val chatRoomListener = object : ChatRoomListenerStub() {
|
||||
override fun onStateChanged(room: ChatRoom, state: ChatRoom.State) {
|
||||
if (state == ChatRoom.State.Created) {
|
||||
Log.i("[Conference Creation] Chat room created")
|
||||
room.removeListener(this)
|
||||
} else if (state == ChatRoom.State.CreationFailed) {
|
||||
Log.e("[Conference Creation] Group chat room creation has failed !")
|
||||
room.removeListener(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val listener = object : ConferenceSchedulerListenerStub() {
|
||||
override fun onStateChanged(
|
||||
conferenceScheduler: ConferenceScheduler,
|
||||
|
@ -179,6 +168,30 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
|||
super.onCleared()
|
||||
}
|
||||
|
||||
fun populateFromConferenceInfo(conferenceInfo: ConferenceInfo) {
|
||||
confInfo = conferenceInfo
|
||||
address.value = conferenceInfo.uri
|
||||
subject.value = conferenceInfo.subject
|
||||
description.value = conferenceInfo.description
|
||||
|
||||
val dateTime = conferenceInfo.dateTime
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = dateTime * 1000
|
||||
setDate(calendar.timeInMillis)
|
||||
setTime(calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE))
|
||||
|
||||
val conferenceDuration = conferenceInfo.duration
|
||||
duration.value = durationList.find { it.value == conferenceDuration }
|
||||
scheduleForLater.value = conferenceDuration > 0
|
||||
|
||||
val participantsList = arrayListOf<Address>()
|
||||
for (participant in conferenceInfo.participants) {
|
||||
participantsList.add(participant)
|
||||
}
|
||||
selectedAddresses.value = participantsList
|
||||
computeParticipantsData()
|
||||
}
|
||||
|
||||
fun toggleSchedule() {
|
||||
scheduleForLater.value = scheduleForLater.value == false
|
||||
}
|
||||
|
@ -221,23 +234,10 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
|||
val core = coreContext.core
|
||||
val participants = arrayOfNulls<Address>(selectedAddresses.value.orEmpty().size)
|
||||
selectedAddresses.value?.toArray(participants)
|
||||
val localAddress = core.defaultAccount?.params?.identityAddress
|
||||
val localAccount = core.defaultAccount
|
||||
val localAddress = localAccount?.params?.identityAddress
|
||||
|
||||
// TODO: Temporary workaround for chat room, to be removed once we can get matching chat room from conference
|
||||
/*val chatRoomParams = core.createDefaultChatRoomParams()
|
||||
chatRoomParams.backend = ChatRoomBackend.FlexisipChat
|
||||
chatRoomParams.enableGroup(true)
|
||||
chatRoomParams.subject = subject.value
|
||||
val chatRoom = core.createChatRoom(chatRoomParams, localAddress, participants)
|
||||
if (chatRoom == null) {
|
||||
Log.e("[Conference Creation] Failed to create a chat room with same subject & participants as for conference")
|
||||
} else {
|
||||
Log.i("[Conference Creation] Creating chat room with same subject [${subject.value}] & participants as for conference")
|
||||
chatRoom.addListener(chatRoomListener)
|
||||
}*/
|
||||
// END OF TODO
|
||||
|
||||
val conferenceInfo = Factory.instance().createConferenceInfo()
|
||||
val conferenceInfo = confInfo ?: Factory.instance().createConferenceInfo()
|
||||
conferenceInfo.organizer = localAddress
|
||||
conferenceInfo.subject = subject.value
|
||||
conferenceInfo.description = description.value
|
||||
|
@ -248,7 +248,10 @@ class ConferenceSchedulingViewModel : ContactsSelectionViewModel() {
|
|||
val duration = duration.value?.value ?: 0
|
||||
conferenceInfo.duration = duration
|
||||
}
|
||||
conferenceScheduler.info = conferenceInfo // Will trigger the conference creation automatically
|
||||
confInfo = conferenceInfo
|
||||
conferenceScheduler.account = localAccount
|
||||
// Will trigger the conference creation/update automatically
|
||||
conferenceScheduler.info = conferenceInfo
|
||||
}
|
||||
|
||||
private fun computeTimeZonesList(): List<TimeZoneData> {
|
||||
|
|
|
@ -38,6 +38,7 @@ class ScheduledConferencesViewModel : ViewModel() {
|
|||
conferencesList.addAll(conferences.value.orEmpty())
|
||||
val data = ScheduledConferenceData(conferenceInfo)
|
||||
conferencesList.add(data)
|
||||
conferencesList.sortBy { it.conferenceInfo.dateTime }
|
||||
conferences.value = conferencesList
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,12 @@ class SharedMainViewModel : ViewModel() {
|
|||
|
||||
var pendingCallTransfer: Boolean = false
|
||||
|
||||
/* Conference */
|
||||
|
||||
val conferenceInfoToEdit: MutableLiveData<Event<String>> by lazy {
|
||||
MutableLiveData<Event<String>>()
|
||||
}
|
||||
|
||||
/* Dialer */
|
||||
|
||||
var dialerUri: String = ""
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
android:visibility="@{data.expanded ? View.GONE : View.VISIBLE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
|
@ -125,6 +125,7 @@
|
|||
android:visibility="@{data.expanded ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginEnd="5dp">
|
||||
|
||||
|
@ -255,7 +256,7 @@
|
|||
|
||||
<ImageView
|
||||
android:onClick="@{editConferenceClickListener}"
|
||||
android:visibility="gone"
|
||||
android:visibility="@{data.canEdit ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="center"
|
||||
|
|
Loading…
Reference in a new issue