mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-04-24 21:18:31 +00:00
Improved app fluidity
This commit is contained in:
parent
41de644945
commit
00b92a61b4
13 changed files with 218 additions and 72 deletions
|
|
@ -34,7 +34,7 @@ class ZrtpSasConfirmationDialogModel @UiThread constructor(
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "[ZRTP SAS Confirmation Dialog]"
|
private const val TAG = "[ZRTP SAS Confirmation Dialog]"
|
||||||
private const val alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
private const val ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
}
|
}
|
||||||
|
|
||||||
val message = MutableLiveData<String>()
|
val message = MutableLiveData<String>()
|
||||||
|
|
@ -55,24 +55,24 @@ class ZrtpSasConfirmationDialogModel @UiThread constructor(
|
||||||
|
|
||||||
// TODO: improve algo?
|
// TODO: improve algo?
|
||||||
val rnd = Random()
|
val rnd = Random()
|
||||||
val randomLetters1 = "${alphabet[rnd.nextInt(alphabet.length)]}${alphabet[
|
val randomLetters1 = "${ALPHABET[rnd.nextInt(ALPHABET.length)]}${ALPHABET[
|
||||||
rnd.nextInt(
|
rnd.nextInt(
|
||||||
alphabet.length
|
ALPHABET.length
|
||||||
)
|
)
|
||||||
]}"
|
]}"
|
||||||
val randomLetters2 = "${alphabet[rnd.nextInt(alphabet.length)]}${alphabet[
|
val randomLetters2 = "${ALPHABET[rnd.nextInt(ALPHABET.length)]}${ALPHABET[
|
||||||
rnd.nextInt(
|
rnd.nextInt(
|
||||||
alphabet.length
|
ALPHABET.length
|
||||||
)
|
)
|
||||||
]}"
|
]}"
|
||||||
val randomLetters3 = "${alphabet[rnd.nextInt(alphabet.length)]}${alphabet[
|
val randomLetters3 = "${ALPHABET[rnd.nextInt(ALPHABET.length)]}${ALPHABET[
|
||||||
rnd.nextInt(
|
rnd.nextInt(
|
||||||
alphabet.length
|
ALPHABET.length
|
||||||
)
|
)
|
||||||
]}"
|
]}"
|
||||||
val randomLetters4 = "${alphabet[rnd.nextInt(alphabet.length)]}${alphabet[
|
val randomLetters4 = "${ALPHABET[rnd.nextInt(ALPHABET.length)]}${ALPHABET[
|
||||||
rnd.nextInt(
|
rnd.nextInt(
|
||||||
alphabet.length
|
ALPHABET.length
|
||||||
)
|
)
|
||||||
]}"
|
]}"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.participants.observe(viewLifecycleOwner) { items ->
|
viewModel.participants.observe(viewLifecycleOwner) { items ->
|
||||||
adapter.submitList(items)
|
adapter.submitList(items)
|
||||||
Log.i("$TAG Participants list updated with [${items.size}] items")
|
Log.i("$TAG Participants list updated with [${items.size}] items")
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@
|
||||||
package org.linphone.ui.main.fragment
|
package org.linphone.ui.main.fragment
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.IdRes
|
import androidx.annotation.IdRes
|
||||||
import androidx.annotation.UiThread
|
import androidx.annotation.UiThread
|
||||||
import androidx.core.view.doOnPreDraw
|
import androidx.core.view.doOnPreDraw
|
||||||
|
|
@ -53,7 +55,16 @@ abstract class AbstractMainFragment : GenericFragment() {
|
||||||
|
|
||||||
abstract fun onDefaultAccountChanged()
|
abstract fun onDefaultAccountChanged()
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
postponeEnterTransition()
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
fun setViewModel(abstractMainViewModel: AbstractMainViewModel) {
|
fun setViewModel(abstractMainViewModel: AbstractMainViewModel) {
|
||||||
|
(view?.parent as? ViewGroup)?.doOnPreDraw {
|
||||||
|
startPostponedEnterTransition()
|
||||||
|
}
|
||||||
|
|
||||||
viewModel = abstractMainViewModel
|
viewModel = abstractMainViewModel
|
||||||
|
|
||||||
viewModel.openDrawerMenuEvent.observe(viewLifecycleOwner) {
|
viewModel.openDrawerMenuEvent.observe(viewLifecycleOwner) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||||
|
*
|
||||||
|
* This file is part of linphone-android
|
||||||
|
* (see https://www.linphone.org).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.linphone.ui.main.meetings.adapter
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.annotation.UiThread
|
||||||
|
import androidx.databinding.DataBindingUtil
|
||||||
|
import androidx.lifecycle.findViewTreeLifecycleOwner
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import org.linphone.R
|
||||||
|
import org.linphone.databinding.MeetingParticipantListCellBinding
|
||||||
|
import org.linphone.ui.main.meetings.model.ParticipantModel
|
||||||
|
|
||||||
|
class MeetingParticipantsAdapter : ListAdapter<ParticipantModel, RecyclerView.ViewHolder>(
|
||||||
|
MeetingParticipantDiffCallback()
|
||||||
|
) {
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
|
val binding: MeetingParticipantListCellBinding = DataBindingUtil.inflate(
|
||||||
|
LayoutInflater.from(parent.context),
|
||||||
|
R.layout.meeting_participant_list_cell,
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
binding.lifecycleOwner = parent.findViewTreeLifecycleOwner()
|
||||||
|
return ViewHolder(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
|
(holder as ViewHolder).bind(getItem(position))
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ViewHolder(
|
||||||
|
val binding: MeetingParticipantListCellBinding
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
@UiThread
|
||||||
|
fun bind(participantModel: ParticipantModel) {
|
||||||
|
with(binding) {
|
||||||
|
model = participantModel
|
||||||
|
executePendingBindings()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MeetingParticipantDiffCallback : DiffUtil.ItemCallback<ParticipantModel>() {
|
||||||
|
override fun areItemsTheSame(oldItem: ParticipantModel, newItem: ParticipantModel): Boolean {
|
||||||
|
return oldItem.sipUri == newItem.sipUri
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: ParticipantModel, newItem: ParticipantModel): Boolean {
|
||||||
|
return oldItem.avatarModel.id == newItem.avatarModel.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -76,7 +76,8 @@ class EditMeetingFragment : SlidingPaneChildFragment() {
|
||||||
|
|
||||||
val conferenceUri = args.conferenceUri
|
val conferenceUri = args.conferenceUri
|
||||||
Log.i("$TAG Found conference URI [$conferenceUri] in arguments")
|
Log.i("$TAG Found conference URI [$conferenceUri] in arguments")
|
||||||
viewModel.loadExistingConferenceInfoFromUri(conferenceUri)
|
val conferenceInfo = sharedViewModel.displayedMeeting
|
||||||
|
viewModel.findConferenceInfo(conferenceInfo, conferenceUri)
|
||||||
|
|
||||||
binding.setBackClickListener {
|
binding.setBackClickListener {
|
||||||
goBack()
|
goBack()
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import androidx.databinding.DataBindingUtil
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.databinding.MeetingFragmentBinding
|
import org.linphone.databinding.MeetingFragmentBinding
|
||||||
|
|
@ -44,6 +45,7 @@ import org.linphone.databinding.MeetingPopupMenuBinding
|
||||||
import org.linphone.ui.GenericActivity
|
import org.linphone.ui.GenericActivity
|
||||||
import org.linphone.ui.main.fragment.SlidingPaneChildFragment
|
import org.linphone.ui.main.fragment.SlidingPaneChildFragment
|
||||||
import org.linphone.ui.main.history.model.ConfirmationDialogModel
|
import org.linphone.ui.main.history.model.ConfirmationDialogModel
|
||||||
|
import org.linphone.ui.main.meetings.adapter.MeetingParticipantsAdapter
|
||||||
import org.linphone.ui.main.meetings.viewmodel.MeetingViewModel
|
import org.linphone.ui.main.meetings.viewmodel.MeetingViewModel
|
||||||
import org.linphone.utils.DialogUtils
|
import org.linphone.utils.DialogUtils
|
||||||
import org.linphone.utils.Event
|
import org.linphone.utils.Event
|
||||||
|
|
@ -56,10 +58,18 @@ class MeetingFragment : SlidingPaneChildFragment() {
|
||||||
|
|
||||||
private lateinit var binding: MeetingFragmentBinding
|
private lateinit var binding: MeetingFragmentBinding
|
||||||
|
|
||||||
|
private lateinit var adapter: MeetingParticipantsAdapter
|
||||||
|
|
||||||
private lateinit var viewModel: MeetingViewModel
|
private lateinit var viewModel: MeetingViewModel
|
||||||
|
|
||||||
private val args: MeetingFragmentArgs by navArgs()
|
private val args: MeetingFragmentArgs by navArgs()
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
adapter = MeetingParticipantsAdapter()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
|
@ -91,7 +101,16 @@ class MeetingFragment : SlidingPaneChildFragment() {
|
||||||
Log.i(
|
Log.i(
|
||||||
"$TAG Looking up for conference with SIP URI [$uri]"
|
"$TAG Looking up for conference with SIP URI [$uri]"
|
||||||
)
|
)
|
||||||
viewModel.findConferenceInfo(uri)
|
val conferenceInfo = sharedViewModel.displayedMeeting
|
||||||
|
viewModel.findConferenceInfo(conferenceInfo, uri)
|
||||||
|
|
||||||
|
binding.participants.isNestedScrollingEnabled = false
|
||||||
|
binding.participants.setHasFixedSize(false)
|
||||||
|
binding.participants.layoutManager = LinearLayoutManager(requireContext())
|
||||||
|
|
||||||
|
if (binding.participants.adapter != adapter) {
|
||||||
|
binding.participants.adapter = adapter
|
||||||
|
}
|
||||||
|
|
||||||
binding.setBackClickListener {
|
binding.setBackClickListener {
|
||||||
goBack()
|
goBack()
|
||||||
|
|
@ -144,6 +163,11 @@ class MeetingFragment : SlidingPaneChildFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.participants.observe(viewLifecycleOwner) { items ->
|
||||||
|
adapter.submitList(items)
|
||||||
|
Log.i("$TAG Participants list updated with [${items.size}] items")
|
||||||
|
}
|
||||||
|
|
||||||
viewModel.conferenceInfoDeletedEvent.observe(viewLifecycleOwner) {
|
viewModel.conferenceInfoDeletedEvent.observe(viewLifecycleOwner) {
|
||||||
it.consume {
|
it.consume {
|
||||||
Log.i("$TAG Meeting info has been deleted successfully")
|
Log.i("$TAG Meeting info has been deleted successfully")
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,7 @@ class MeetingsListFragment : AbstractMainFragment() {
|
||||||
adapter.meetingClickedEvent.observe(viewLifecycleOwner) {
|
adapter.meetingClickedEvent.observe(viewLifecycleOwner) {
|
||||||
it.consume { model ->
|
it.consume { model ->
|
||||||
Log.i("$TAG Show conversation with ID [${model.id}]")
|
Log.i("$TAG Show conversation with ID [${model.id}]")
|
||||||
|
sharedViewModel.displayedMeeting = model.conferenceInfo
|
||||||
val action = MeetingFragmentDirections.actionGlobalMeetingFragment(model.id)
|
val action = MeetingFragmentDirections.actionGlobalMeetingFragment(model.id)
|
||||||
binding.meetingsNavContainer.findNavController().navigate(action)
|
binding.meetingsNavContainer.findNavController().navigate(action)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import org.linphone.core.Participant
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.utils.TimestampUtils
|
import org.linphone.utils.TimestampUtils
|
||||||
|
|
||||||
class MeetingModel @WorkerThread constructor(private val conferenceInfo: ConferenceInfo) {
|
class MeetingModel @WorkerThread constructor(val conferenceInfo: ConferenceInfo) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "[Meeting Model]"
|
private const val TAG = "[Meeting Model]"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,16 +20,11 @@
|
||||||
package org.linphone.ui.main.meetings.model
|
package org.linphone.ui.main.meetings.model
|
||||||
|
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
import org.linphone.core.Address
|
import org.linphone.core.Address
|
||||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
|
||||||
|
|
||||||
class ParticipantModel @WorkerThread constructor(address: Address, val isOrganizer: Boolean) {
|
class ParticipantModel @WorkerThread constructor(address: Address, val isOrganizer: Boolean) {
|
||||||
val avatarModel = MutableLiveData<ContactAvatarModel>()
|
val sipUri = address.asStringUriOnly()
|
||||||
|
|
||||||
init {
|
val avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(address)
|
||||||
val avatar = coreContext.contactsManager.getContactAvatarModelForAddress(address)
|
|
||||||
avatarModel.postValue(avatar)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -130,9 +130,26 @@ class MeetingViewModel @UiThread constructor() : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
fun findConferenceInfo(uri: String) {
|
fun findConferenceInfo(meeting: ConferenceInfo?, uri: String) {
|
||||||
coreContext.postOnCoreThread { core ->
|
coreContext.postOnCoreThread { core ->
|
||||||
|
if (meeting != null && ::conferenceInfo.isInitialized && meeting == conferenceInfo) {
|
||||||
|
Log.i("$TAG ConferenceInfo object already in memory, skipping")
|
||||||
|
conferenceInfoFoundEvent.postValue(Event(true))
|
||||||
|
return@postOnCoreThread
|
||||||
|
}
|
||||||
|
|
||||||
val address = Factory.instance().createAddress(uri)
|
val address = Factory.instance().createAddress(uri)
|
||||||
|
|
||||||
|
if (meeting != null && (!::conferenceInfo.isInitialized || conferenceInfo != meeting)) {
|
||||||
|
if (address != null && meeting.uri?.equal(address) == true) {
|
||||||
|
Log.i("$TAG ConferenceInfo object available in sharedViewModel, using it")
|
||||||
|
conferenceInfo = meeting
|
||||||
|
configureConferenceInfo()
|
||||||
|
conferenceInfoFoundEvent.postValue(Event(true))
|
||||||
|
return@postOnCoreThread
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
val found = core.findConferenceInformationFromUri(address)
|
val found = core.findConferenceInformationFromUri(address)
|
||||||
if (found != null) {
|
if (found != null) {
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ class ScheduleMeetingViewModel @UiThread constructor() : ViewModel() {
|
||||||
|
|
||||||
private lateinit var conferenceScheduler: ConferenceScheduler
|
private lateinit var conferenceScheduler: ConferenceScheduler
|
||||||
|
|
||||||
private lateinit var conferenceInfoToEdit: ConferenceInfo
|
private lateinit var conferenceInfo: ConferenceInfo
|
||||||
|
|
||||||
private val conferenceSchedulerListener = object : ConferenceSchedulerListenerStub() {
|
private val conferenceSchedulerListener = object : ConferenceSchedulerListenerStub() {
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
|
|
@ -106,9 +106,9 @@ class ScheduleMeetingViewModel @UiThread constructor() : ViewModel() {
|
||||||
}
|
}
|
||||||
ConferenceScheduler.State.Ready -> {
|
ConferenceScheduler.State.Ready -> {
|
||||||
val conferenceAddress = conferenceScheduler.info?.uri
|
val conferenceAddress = conferenceScheduler.info?.uri
|
||||||
if (::conferenceInfoToEdit.isInitialized) {
|
if (::conferenceInfo.isInitialized) {
|
||||||
Log.i(
|
Log.i(
|
||||||
"$TAG Conference info [${conferenceInfoToEdit.uri?.asStringUriOnly()}] has been updated"
|
"$TAG Conference info [${conferenceInfo.uri?.asStringUriOnly()}] has been updated"
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Log.i(
|
Log.i(
|
||||||
|
|
@ -210,61 +210,42 @@ class ScheduleMeetingViewModel @UiThread constructor() : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
fun loadExistingConferenceInfoFromUri(conferenceUri: String) {
|
fun findConferenceInfo(meeting: ConferenceInfo?, uri: String) {
|
||||||
coreContext.postOnCoreThread { core ->
|
coreContext.postOnCoreThread { core ->
|
||||||
val conferenceAddress = core.interpretUrl(conferenceUri, false)
|
if (meeting != null && ::conferenceInfo.isInitialized && meeting == conferenceInfo) {
|
||||||
if (conferenceAddress == null) {
|
Log.i("$TAG ConferenceInfo object already in memory, skipping")
|
||||||
Log.e("$TAG Failed to parse conference URI [$conferenceUri], abort")
|
configureConferenceInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
val address = Factory.instance().createAddress(uri)
|
||||||
|
|
||||||
|
if (meeting != null && (!::conferenceInfo.isInitialized || conferenceInfo != meeting)) {
|
||||||
|
if (address != null && meeting.uri?.equal(address) == true) {
|
||||||
|
Log.i("$TAG ConferenceInfo object available in sharedViewModel, using it")
|
||||||
|
conferenceInfo = meeting
|
||||||
|
configureConferenceInfo()
|
||||||
|
return@postOnCoreThread
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (address == null) {
|
||||||
|
Log.e("$TAG Failed to parse conference URI [$address], abort")
|
||||||
return@postOnCoreThread
|
return@postOnCoreThread
|
||||||
}
|
}
|
||||||
|
|
||||||
val conferenceInfo = core.findConferenceInformationFromUri(conferenceAddress)
|
val conferenceInfo = core.findConferenceInformationFromUri(address)
|
||||||
if (conferenceInfo == null) {
|
if (conferenceInfo == null) {
|
||||||
Log.e(
|
Log.e(
|
||||||
"$TAG Failed to find a conference info matching URI [${conferenceAddress.asString()}], abort"
|
"$TAG Failed to find a conference info matching URI [${address.asString()}], abort"
|
||||||
)
|
)
|
||||||
return@postOnCoreThread
|
return@postOnCoreThread
|
||||||
}
|
}
|
||||||
|
this.conferenceInfo = conferenceInfo
|
||||||
conferenceInfoToEdit = conferenceInfo
|
|
||||||
Log.i(
|
Log.i(
|
||||||
"$TAG Found conference info matching URI [${conferenceInfo.uri?.asString()}] with subject [${conferenceInfo.subject}]"
|
"$TAG Found conference info matching URI [${conferenceInfo.uri?.asString()}] with subject [${conferenceInfo.subject}]"
|
||||||
)
|
)
|
||||||
subject.postValue(conferenceInfo.subject)
|
|
||||||
description.postValue(conferenceInfo.description)
|
|
||||||
|
|
||||||
isBroadcastSelected.postValue(false) // TODO FIXME: not implemented yet
|
configureConferenceInfo()
|
||||||
|
|
||||||
startHour = 0
|
|
||||||
startMinutes = 0
|
|
||||||
endHour = 0
|
|
||||||
endMinutes = 0
|
|
||||||
startTimestamp = conferenceInfo.dateTime * 1000 /* Linphone timestamps are in seconds */
|
|
||||||
endTimestamp = (conferenceInfo.dateTime + conferenceInfo.duration) * 1000 /* Linphone timestamps are in seconds */
|
|
||||||
Log.i(
|
|
||||||
"$TAG Loaded start date is [$startTimestamp], loaded end date is [$endTimestamp]"
|
|
||||||
)
|
|
||||||
computeDateLabels()
|
|
||||||
computeTimeLabels()
|
|
||||||
updateTimezone()
|
|
||||||
|
|
||||||
val list = arrayListOf<SelectedAddressModel>()
|
|
||||||
for (participant in conferenceInfo.participantInfos) {
|
|
||||||
val address = participant.address
|
|
||||||
val avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(
|
|
||||||
address
|
|
||||||
)
|
|
||||||
val model = SelectedAddressModel(address, avatarModel) { model ->
|
|
||||||
// onRemoveFromSelection
|
|
||||||
removeModelFromSelection(model)
|
|
||||||
}
|
|
||||||
list.add(model)
|
|
||||||
Log.i("$TAG Loaded participant [${address.asStringUriOnly()}]")
|
|
||||||
}
|
|
||||||
Log.i(
|
|
||||||
"$TAG [${list.size}] participants loaded from found conference info"
|
|
||||||
)
|
|
||||||
participants.postValue(list)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -433,14 +414,13 @@ class ScheduleMeetingViewModel @UiThread constructor() : ViewModel() {
|
||||||
Log.i(
|
Log.i(
|
||||||
"$TAG Updating ${if (isBroadcastSelected.value == true) "broadcast" else "meeting"}"
|
"$TAG Updating ${if (isBroadcastSelected.value == true) "broadcast" else "meeting"}"
|
||||||
)
|
)
|
||||||
if (!::conferenceInfoToEdit.isInitialized) {
|
if (!::conferenceInfo.isInitialized) {
|
||||||
Log.e("No conference info to edit found!")
|
Log.e("No conference info to edit found!")
|
||||||
return@postOnCoreThread
|
return@postOnCoreThread
|
||||||
}
|
}
|
||||||
|
|
||||||
operationInProgress.postValue(true)
|
operationInProgress.postValue(true)
|
||||||
|
|
||||||
val conferenceInfo = conferenceInfoToEdit
|
|
||||||
conferenceInfo.subject = subject.value
|
conferenceInfo.subject = subject.value
|
||||||
conferenceInfo.description = description.value
|
conferenceInfo.description = description.value
|
||||||
|
|
||||||
|
|
@ -479,6 +459,48 @@ class ScheduleMeetingViewModel @UiThread constructor() : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
private fun configureConferenceInfo() {
|
||||||
|
if (::conferenceInfo.isInitialized) {
|
||||||
|
subject.postValue(conferenceInfo.subject)
|
||||||
|
description.postValue(conferenceInfo.description)
|
||||||
|
|
||||||
|
isBroadcastSelected.postValue(false) // TODO FIXME: not implemented yet
|
||||||
|
|
||||||
|
startHour = 0
|
||||||
|
startMinutes = 0
|
||||||
|
endHour = 0
|
||||||
|
endMinutes = 0
|
||||||
|
startTimestamp = conferenceInfo.dateTime * 1000 /* Linphone timestamps are in seconds */
|
||||||
|
endTimestamp =
|
||||||
|
(conferenceInfo.dateTime + conferenceInfo.duration) * 1000 /* Linphone timestamps are in seconds */
|
||||||
|
Log.i(
|
||||||
|
"$TAG Loaded start date is [$startTimestamp], loaded end date is [$endTimestamp]"
|
||||||
|
)
|
||||||
|
computeDateLabels()
|
||||||
|
computeTimeLabels()
|
||||||
|
updateTimezone()
|
||||||
|
|
||||||
|
val list = arrayListOf<SelectedAddressModel>()
|
||||||
|
for (participant in conferenceInfo.participantInfos) {
|
||||||
|
val address = participant.address
|
||||||
|
val avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(
|
||||||
|
address
|
||||||
|
)
|
||||||
|
val model = SelectedAddressModel(address, avatarModel) { model ->
|
||||||
|
// onRemoveFromSelection
|
||||||
|
removeModelFromSelection(model)
|
||||||
|
}
|
||||||
|
list.add(model)
|
||||||
|
Log.i("$TAG Loaded participant [${address.asStringUriOnly()}]")
|
||||||
|
}
|
||||||
|
Log.i(
|
||||||
|
"$TAG [${list.size}] participants loaded from found conference info"
|
||||||
|
)
|
||||||
|
participants.postValue(list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
private fun removeModelFromSelection(model: SelectedAddressModel) {
|
private fun removeModelFromSelection(model: SelectedAddressModel) {
|
||||||
val newList = arrayListOf<SelectedAddressModel>()
|
val newList = arrayListOf<SelectedAddressModel>()
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import androidx.annotation.UiThread
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import org.linphone.core.ChatRoom
|
import org.linphone.core.ChatRoom
|
||||||
|
import org.linphone.core.ConferenceInfo
|
||||||
import org.linphone.core.Friend
|
import org.linphone.core.Friend
|
||||||
import org.linphone.ui.main.chat.model.MessageModel
|
import org.linphone.ui.main.chat.model.MessageModel
|
||||||
import org.linphone.utils.Event
|
import org.linphone.utils.Event
|
||||||
|
|
@ -137,6 +138,8 @@ class SharedMainViewModel @UiThread constructor() : ViewModel() {
|
||||||
|
|
||||||
/* Meetings related */
|
/* Meetings related */
|
||||||
|
|
||||||
|
var displayedMeeting: ConferenceInfo? = null // Prevents the need to go look for the conference info
|
||||||
|
|
||||||
val forceRefreshMeetingsListEvent: MutableLiveData<Event<Boolean>> by lazy {
|
val forceRefreshMeetingsListEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||||
MutableLiveData<Event<Boolean>>()
|
MutableLiveData<Event<Boolean>>()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -305,16 +305,14 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:tint="?attr/color_main2_600"/>
|
app:tint="?attr/color_main2_600"/>
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/participants"
|
android:id="@+id/participants"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:orientation="vertical"
|
android:nestedScrollingEnabled="true"
|
||||||
entries="@{viewModel.participants}"
|
|
||||||
layout="@{@layout/meeting_participant_list_cell}"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/separator_4"
|
app:layout_constraintTop_toBottomOf="@id/separator_4"
|
||||||
app:layout_constraintStart_toEndOf="@id/participants_icon"
|
app:layout_constraintStart_toEndOf="@id/participants_icon"
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue