mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-11 14:54:09 +01:00
wip: view poll results
Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
parent
7d8aebe234
commit
5a070f5e1b
@ -25,6 +25,7 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.nextcloud.talk.remotefilebrowser.viewmodels.RemoteFileBrowserItemsViewModel
|
import com.nextcloud.talk.remotefilebrowser.viewmodels.RemoteFileBrowserItemsViewModel
|
||||||
import com.nextcloud.talk.messagesearch.MessageSearchViewModel
|
import com.nextcloud.talk.messagesearch.MessageSearchViewModel
|
||||||
|
import com.nextcloud.talk.polls.viewmodels.PollResultsViewModel
|
||||||
import com.nextcloud.talk.polls.viewmodels.PollViewModel
|
import com.nextcloud.talk.polls.viewmodels.PollViewModel
|
||||||
import com.nextcloud.talk.polls.viewmodels.PollVoteViewModel
|
import com.nextcloud.talk.polls.viewmodels.PollVoteViewModel
|
||||||
import com.nextcloud.talk.shareditems.viewmodels.SharedItemsViewModel
|
import com.nextcloud.talk.shareditems.viewmodels.SharedItemsViewModel
|
||||||
@ -73,6 +74,11 @@ abstract class ViewModelModule {
|
|||||||
@ViewModelKey(PollVoteViewModel::class)
|
@ViewModelKey(PollVoteViewModel::class)
|
||||||
abstract fun pollVoteViewModel(viewModel: PollVoteViewModel): ViewModel
|
abstract fun pollVoteViewModel(viewModel: PollVoteViewModel): ViewModel
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ViewModelKey(PollResultsViewModel::class)
|
||||||
|
abstract fun pollResultsViewModel(viewModel: PollResultsViewModel): ViewModel
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@ViewModelKey(RemoteFileBrowserItemsViewModel::class)
|
@ViewModelKey(RemoteFileBrowserItemsViewModel::class)
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.nextcloud.talk.polls.adapters
|
||||||
|
|
||||||
|
class PollResultItem(
|
||||||
|
val pollOption: String,
|
||||||
|
val pollPercent: Int
|
||||||
|
|
||||||
|
// val voters....
|
||||||
|
)
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.nextcloud.talk.polls.adapters
|
||||||
|
|
||||||
|
interface PollResultItemClickListener {
|
||||||
|
fun onClick(pollResultItem: PollResultItem)
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.nextcloud.talk.polls.adapters
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.nextcloud.talk.databinding.PollResultItemBinding
|
||||||
|
|
||||||
|
class PollResultViewHolder(
|
||||||
|
private val binding: PollResultItemBinding
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
fun bind(pollResultItem: PollResultItem, clickListener: PollResultItemClickListener) {
|
||||||
|
binding.root.setOnClickListener { clickListener.onClick(pollResultItem) }
|
||||||
|
binding.pollOptionText.text = pollResultItem.pollOption
|
||||||
|
binding.pollOptionPercentText.text = pollResultItem.pollPercent.toString() + "%"
|
||||||
|
binding.pollOptionBar.progress = pollResultItem.pollPercent
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.nextcloud.talk.polls.adapters
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.nextcloud.talk.databinding.PollResultItemBinding
|
||||||
|
|
||||||
|
class PollResultsAdapter(
|
||||||
|
private val clickListener: PollResultItemClickListener
|
||||||
|
) : RecyclerView.Adapter<PollResultViewHolder>() {
|
||||||
|
internal var list: MutableList<PollResultItem> = ArrayList<PollResultItem>()
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PollResultViewHolder {
|
||||||
|
val itemBinding = PollResultItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
|
return PollResultViewHolder(itemBinding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: PollResultViewHolder, position: Int) {
|
||||||
|
holder.bind(list[position], clickListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return list.size
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ data class Poll(
|
|||||||
val id: String,
|
val id: String,
|
||||||
val question: String?,
|
val question: String?,
|
||||||
val options: List<String>?,
|
val options: List<String>?,
|
||||||
val votes: List<Int>?,
|
val votes: Map<String, Int>?,
|
||||||
val actorType: String?,
|
val actorType: String?,
|
||||||
val actorId: String?,
|
val actorId: String?,
|
||||||
val actorDisplayName: String?,
|
val actorDisplayName: String?,
|
||||||
|
@ -49,7 +49,6 @@ class PollRepositoryImpl(private val ncApi: NcApi, private val currentUserProvid
|
|||||||
),
|
),
|
||||||
).map { mapToPoll(it.ocs?.data!!) }
|
).map { mapToPoll(it.ocs?.data!!) }
|
||||||
|
|
||||||
// // // TODO actual api call
|
|
||||||
// return Observable.just(
|
// return Observable.just(
|
||||||
// Poll(
|
// Poll(
|
||||||
// id = "aaa",
|
// id = "aaa",
|
||||||
|
@ -37,7 +37,7 @@ data class PollResponse(
|
|||||||
var options: ArrayList<String>? = null,
|
var options: ArrayList<String>? = null,
|
||||||
|
|
||||||
@JsonField(name = ["votes"])
|
@JsonField(name = ["votes"])
|
||||||
var votes: ArrayList<Int>? = null,
|
var votes: Map<String, Int>? = null,
|
||||||
|
|
||||||
@JsonField(name = ["actorType"])
|
@JsonField(name = ["actorType"])
|
||||||
var actorType: String? = null,
|
var actorType: String? = null,
|
||||||
|
@ -12,6 +12,7 @@ import androidx.lifecycle.ViewModelProvider
|
|||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.databinding.DialogPollMainBinding
|
import com.nextcloud.talk.databinding.DialogPollMainBinding
|
||||||
|
import com.nextcloud.talk.polls.model.Poll
|
||||||
import com.nextcloud.talk.polls.viewmodels.PollViewModel
|
import com.nextcloud.talk.polls.viewmodels.PollViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -58,8 +59,29 @@ class PollMainDialogFragment(
|
|||||||
viewModel.viewState.observe(viewLifecycleOwner) { state ->
|
viewModel.viewState.observe(viewLifecycleOwner) { state ->
|
||||||
when (state) {
|
when (state) {
|
||||||
PollViewModel.InitialState -> {}
|
PollViewModel.InitialState -> {}
|
||||||
is PollViewModel.PollClosedState -> TODO()
|
|
||||||
is PollViewModel.PollOpenState -> {
|
is PollViewModel.PollVotedState -> {
|
||||||
|
if (state.poll.resultMode == Poll.RESULT_MODE_HIDDEN) {
|
||||||
|
showVoteFragment()
|
||||||
|
} else {
|
||||||
|
showResultsFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is PollViewModel.PollUnvotedState -> {
|
||||||
|
if (state.poll.status == Poll.STATUS_CLOSED) {
|
||||||
|
showResultsFragment()
|
||||||
|
} else {
|
||||||
|
showVoteFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.initialize(roomToken, pollId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showVoteFragment() {
|
||||||
val contentFragment = PollVoteFragment(
|
val contentFragment = PollVoteFragment(
|
||||||
viewModel,
|
viewModel,
|
||||||
roomToken,
|
roomToken,
|
||||||
@ -69,10 +91,16 @@ class PollMainDialogFragment(
|
|||||||
transaction.replace(binding.messagePollContentFragment.id, contentFragment)
|
transaction.replace(binding.messagePollContentFragment.id, contentFragment)
|
||||||
transaction.commit()
|
transaction.commit()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.initialize(roomToken, pollId)
|
private fun showResultsFragment() {
|
||||||
|
val contentFragment = PollResultsFragment(
|
||||||
|
viewModel,
|
||||||
|
roomToken,
|
||||||
|
pollId
|
||||||
|
)
|
||||||
|
val transaction = childFragmentManager.beginTransaction()
|
||||||
|
transaction.replace(binding.messagePollContentFragment.id, contentFragment)
|
||||||
|
transaction.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Álvaro Brey
|
||||||
|
* Copyright (C) 2022 Álvaro Brey
|
||||||
|
* Copyright (C) 2022 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.polls.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import autodagger.AutoInjector
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
|
import com.nextcloud.talk.databinding.DialogPollResultsBinding
|
||||||
|
import com.nextcloud.talk.polls.adapters.PollResultItem
|
||||||
|
import com.nextcloud.talk.polls.adapters.PollResultItemClickListener
|
||||||
|
import com.nextcloud.talk.polls.adapters.PollResultsAdapter
|
||||||
|
import com.nextcloud.talk.polls.model.Poll
|
||||||
|
import com.nextcloud.talk.polls.viewmodels.PollResultsViewModel
|
||||||
|
import com.nextcloud.talk.polls.viewmodels.PollViewModel
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
|
class PollResultsFragment(
|
||||||
|
private val parentViewModel: PollViewModel,
|
||||||
|
private val roomToken: String,
|
||||||
|
private val pollId: String
|
||||||
|
) : Fragment(), PollResultItemClickListener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||||
|
|
||||||
|
lateinit var viewModel: PollResultsViewModel
|
||||||
|
|
||||||
|
var _binding: DialogPollResultsBinding? = null
|
||||||
|
val binding: DialogPollResultsBinding
|
||||||
|
get() = _binding!!
|
||||||
|
|
||||||
|
private var adapter: PollResultsAdapter? = null
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||||
|
viewModel = ViewModelProvider(this, viewModelFactory)[PollResultsViewModel::class.java]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
_binding = DialogPollResultsBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
adapter = PollResultsAdapter(this)
|
||||||
|
_binding?.pollResultsList?.adapter = adapter
|
||||||
|
_binding?.pollResultsList?.layoutManager = LinearLayoutManager(context)
|
||||||
|
|
||||||
|
parentViewModel.viewState.observe(viewLifecycleOwner) { state ->
|
||||||
|
if (state is PollViewModel.PollVotedState &&
|
||||||
|
state.poll.resultMode == Poll.RESULT_MODE_PUBLIC
|
||||||
|
) {
|
||||||
|
|
||||||
|
initPollResults(state.poll)
|
||||||
|
initAmountVotersInfo(state)
|
||||||
|
initEditButton(state)
|
||||||
|
} else if (state is PollViewModel.PollUnvotedState &&
|
||||||
|
state.poll.status == Poll.STATUS_CLOSED
|
||||||
|
) {
|
||||||
|
Log.d(TAG, "show results also if self never voted")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initPollResults(poll: Poll) {
|
||||||
|
if (poll.details != null) {
|
||||||
|
val votersAmount = poll.details.size
|
||||||
|
val oneVoteInPercent = 100 / votersAmount // TODO: poll.numVoters when fixed on api
|
||||||
|
|
||||||
|
poll.options?.forEachIndexed { index, option ->
|
||||||
|
val votersForThisOption = poll.details.filter { it.optionId == index }.size
|
||||||
|
val optionsPercent = oneVoteInPercent * votersForThisOption
|
||||||
|
|
||||||
|
val pollResultItem = PollResultItem(option, optionsPercent) // TODO add participants to PollResultItem
|
||||||
|
adapter?.list?.add(pollResultItem)
|
||||||
|
}
|
||||||
|
} else if (poll.votes != null) {
|
||||||
|
val votersAmount = poll.numVoters
|
||||||
|
val oneVoteInPercent = 100 / votersAmount
|
||||||
|
|
||||||
|
poll.options?.forEachIndexed { index, option ->
|
||||||
|
val votersForThisOption = poll.votes?.filter { it.value == index }?.size!!
|
||||||
|
val optionsPercent = oneVoteInPercent * votersForThisOption
|
||||||
|
|
||||||
|
val pollResultItem = PollResultItem(option, optionsPercent)
|
||||||
|
adapter?.list?.add(pollResultItem)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "failed to get data to show poll results")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initAmountVotersInfo(state: PollViewModel.PollVotedState) {
|
||||||
|
_binding?.pollAmountVoters?.text = String.format(
|
||||||
|
resources.getString(R.string.polls_amount_voters),
|
||||||
|
state.poll.numVoters
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initEditButton(state: PollViewModel.PollVotedState) {
|
||||||
|
if (state.poll.status == Poll.STATUS_OPEN && state.poll.resultMode == Poll.RESULT_MODE_PUBLIC) {
|
||||||
|
_binding?.editVoteButton?.visibility = View.VISIBLE
|
||||||
|
_binding?.editVoteButton?.setOnClickListener {
|
||||||
|
parentViewModel.edit()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_binding?.editVoteButton?.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val TAG = PollResultsFragment::class.java.simpleName
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(pollResultItem: PollResultItem) {
|
||||||
|
Log.d(TAG, "click..")
|
||||||
|
}
|
||||||
|
}
|
@ -32,6 +32,7 @@ import androidx.lifecycle.ViewModelProvider
|
|||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.databinding.DialogPollVoteBinding
|
import com.nextcloud.talk.databinding.DialogPollVoteBinding
|
||||||
|
import com.nextcloud.talk.polls.model.Poll
|
||||||
import com.nextcloud.talk.polls.viewmodels.PollViewModel
|
import com.nextcloud.talk.polls.viewmodels.PollViewModel
|
||||||
import com.nextcloud.talk.polls.viewmodels.PollVoteViewModel
|
import com.nextcloud.talk.polls.viewmodels.PollVoteViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -70,7 +71,7 @@ class PollVoteFragment(
|
|||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
parentViewModel.viewState.observe(viewLifecycleOwner) { state ->
|
parentViewModel.viewState.observe(viewLifecycleOwner) { state ->
|
||||||
if (state is PollViewModel.PollOpenState) {
|
if (state is PollViewModel.PollUnvotedState) {
|
||||||
val poll = state.poll
|
val poll = state.poll
|
||||||
binding.radioGroup.removeAllViews()
|
binding.radioGroup.removeAllViews()
|
||||||
poll.options?.map { option ->
|
poll.options?.map { option ->
|
||||||
@ -79,6 +80,9 @@ class PollVoteFragment(
|
|||||||
radioButton.id = index
|
radioButton.id = index
|
||||||
binding.radioGroup.addView(radioButton)
|
binding.radioGroup.addView(radioButton)
|
||||||
}
|
}
|
||||||
|
} else if (state is PollViewModel.PollVotedState && state.poll.resultMode == Poll.RESULT_MODE_HIDDEN) {
|
||||||
|
Log.d(TAG, "show vote screen also for resultMode hidden poll when already voted")
|
||||||
|
// TODO: other text for submit button
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Álvaro Brey
|
||||||
|
* Copyright (C) 2022 Álvaro Brey
|
||||||
|
* Copyright (C) 2022 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.polls.viewmodels
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import com.nextcloud.talk.polls.repositories.PollRepository
|
||||||
|
import io.reactivex.disposables.Disposable
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class PollResultsViewModel @Inject constructor(private val repository: PollRepository) : ViewModel() {
|
||||||
|
|
||||||
|
sealed interface ViewState
|
||||||
|
object InitialState : ViewState
|
||||||
|
|
||||||
|
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
|
||||||
|
val viewState: LiveData<ViewState>
|
||||||
|
get() = _viewState
|
||||||
|
|
||||||
|
private var disposable: Disposable? = null
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
super.onCleared()
|
||||||
|
disposable?.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val TAG = PollResultsViewModel::class.java.simpleName
|
||||||
|
}
|
||||||
|
}
|
@ -28,11 +28,12 @@ class PollViewModel @Inject constructor(private val repository: PollRepository)
|
|||||||
private lateinit var roomToken: String
|
private lateinit var roomToken: String
|
||||||
private lateinit var pollId: String
|
private lateinit var pollId: String
|
||||||
|
|
||||||
|
private var editPoll: Boolean = false
|
||||||
|
|
||||||
sealed interface ViewState
|
sealed interface ViewState
|
||||||
object InitialState : ViewState
|
object InitialState : ViewState
|
||||||
open class PollOpenState(val poll: Poll) : ViewState
|
open class PollUnvotedState(val poll: Poll) : ViewState
|
||||||
open class PollVotedState(val poll: Poll) : ViewState
|
open class PollVotedState(val poll: Poll) : ViewState
|
||||||
open class PollClosedState(val poll: Poll) : ViewState
|
|
||||||
|
|
||||||
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
|
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
|
||||||
val viewState: LiveData<ViewState>
|
val viewState: LiveData<ViewState>
|
||||||
@ -51,6 +52,11 @@ class PollViewModel @Inject constructor(private val repository: PollRepository)
|
|||||||
loadPoll() // TODO load other view
|
loadPoll() // TODO load other view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun edit() {
|
||||||
|
editPoll = true
|
||||||
|
loadPoll()
|
||||||
|
}
|
||||||
|
|
||||||
private fun loadPoll() {
|
private fun loadPoll() {
|
||||||
repository.getPoll(roomToken, pollId)
|
repository.getPoll(roomToken, pollId)
|
||||||
?.doOnSubscribe { disposable = it }
|
?.doOnSubscribe { disposable = it }
|
||||||
@ -79,11 +85,13 @@ class PollViewModel @Inject constructor(private val repository: PollRepository)
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onComplete() {
|
override fun onComplete() {
|
||||||
// TODO check attributes and decide if poll is open/closed/selfvoted...
|
if (editPoll) {
|
||||||
|
_viewState.value = PollUnvotedState(poll)
|
||||||
when (poll.status) {
|
editPoll = false
|
||||||
Poll.STATUS_OPEN -> _viewState.value = PollOpenState(poll)
|
} else if (poll.votedSelf.isNullOrEmpty()) {
|
||||||
Poll.STATUS_CLOSED -> _viewState.value = PollClosedState(poll)
|
_viewState.value = PollUnvotedState(poll)
|
||||||
|
} else {
|
||||||
|
_viewState.value = PollVotedState(poll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,8 @@
|
|||||||
<androidx.emoji.widget.EmojiTextView
|
<androidx.emoji.widget.EmojiTextView
|
||||||
android:id="@+id/message_poll_title"
|
android:id="@+id/message_poll_title"
|
||||||
android:layout_width="257dp"
|
android:layout_width="257dp"
|
||||||
android:layout_height="55dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:textAlignment="viewStart"
|
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintStart_toEndOf="@id/message_poll_icon"
|
app:layout_constraintStart_toEndOf="@id/message_poll_icon"
|
||||||
app:layout_constraintTop_toTopOf="@+id/message_poll_icon"
|
app:layout_constraintTop_toTopOf="@+id/message_poll_icon"
|
||||||
@ -50,6 +49,7 @@
|
|||||||
android:id="@+id/message_poll_content_fragment"
|
android:id="@+id/message_poll_content_fragment"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
app:layout_constraintTop_toBottomOf="@id/message_poll_title"
|
app:layout_constraintTop_toBottomOf="@id/message_poll_title"
|
||||||
tools:layout_height="400dp" />
|
tools:layout_height="400dp" />
|
||||||
|
|
||||||
|
62
app/src/main/res/layout/dialog_poll_results.xml
Normal file
62
app/src/main/res/layout/dialog_poll_results.xml
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<!--
|
||||||
|
Nextcloud Android client application
|
||||||
|
|
||||||
|
@author Marcel Hibbe
|
||||||
|
Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License version 2,
|
||||||
|
as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
-->
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:padding="@dimen/standard_padding"
|
||||||
|
tools:background="@color/white">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/poll_results_list_wrapper"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="288dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/poll_results_list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:listitem="@layout/poll_result_item" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/poll_amount_voters"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:textColor="@color/low_emphasis_text"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/poll_results_list_wrapper"
|
||||||
|
tools:text="Poll results - 93 votes" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/edit_vote_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="@string/edit"
|
||||||
|
android:theme="@style/Button.Primary"
|
||||||
|
app:cornerRadius="@dimen/button_corner_radius"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/poll_results_list_wrapper" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -28,9 +28,9 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:layout_height="400dp"
|
||||||
</RadioGroup>
|
tools:layout_width="match_parent"></RadioGroup>
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/submitVote"
|
android:id="@+id/submitVote"
|
||||||
|
33
app/src/main/res/layout/poll_result_item.xml
Normal file
33
app/src/main/res/layout/poll_result_item.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="@dimen/standard_padding"
|
||||||
|
tools:background="@color/white">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/poll_option_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Option Number One" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/poll_option_percent_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="25 %" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/poll_option_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/poll_option_text"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/poll_option_text"
|
||||||
|
style="?android:attr/progressBarStyleHorizontal" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -534,6 +534,9 @@
|
|||||||
<string name="message_search_begin_typing">Start typing to search …</string>
|
<string name="message_search_begin_typing">Start typing to search …</string>
|
||||||
<string name="message_search_begin_empty">No search results</string>
|
<string name="message_search_begin_empty">No search results</string>
|
||||||
|
|
||||||
|
<!-- Polls -->
|
||||||
|
<string name="polls_amount_voters">Poll results - %1$s votes</string>
|
||||||
|
|
||||||
<string name="title_attachments">Attachments</string>
|
<string name="title_attachments">Attachments</string>
|
||||||
|
|
||||||
<string name="reactions_tab_all">All</string>
|
<string name="reactions_tab_all">All</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user