improve klint score, minor refactoring

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2022-06-30 14:36:02 +02:00 committed by Andy Scherzinger (Rebase PR Action)
parent b347fbf1b5
commit 3224ae1e1f
16 changed files with 59 additions and 100 deletions

View File

@ -12,7 +12,7 @@ class PollCreateOptionViewHolder(
) : RecyclerView.ViewHolder(binding.root) { ) : RecyclerView.ViewHolder(binding.root) {
lateinit var optionText: EmojiTextInputEditText lateinit var optionText: EmojiTextInputEditText
var textListener: TextWatcher? = null private var textListener: TextWatcher? = null
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun bind( fun bind(

View File

@ -14,6 +14,6 @@ data class PollResultHeaderItem(
companion object { companion object {
// layout is used as view type for uniqueness // layout is used as view type for uniqueness
public val VIEW_TYPE: Int = R.layout.poll_result_header_item const val VIEW_TYPE: Int = R.layout.poll_result_header_item
} }
} }

View File

@ -3,10 +3,8 @@ package com.nextcloud.talk.polls.adapters
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.graphics.Typeface import android.graphics.Typeface
import com.nextcloud.talk.databinding.PollResultHeaderItemBinding import com.nextcloud.talk.databinding.PollResultHeaderItemBinding
import com.nextcloud.talk.models.database.UserEntity
class PollResultHeaderViewHolder( class PollResultHeaderViewHolder(
private val user: UserEntity,
override val binding: PollResultHeaderItemBinding override val binding: PollResultHeaderItemBinding
) : PollResultViewHolder(binding) { ) : PollResultViewHolder(binding) {

View File

@ -1,7 +1,5 @@
package com.nextcloud.talk.polls.adapters package com.nextcloud.talk.polls.adapters
interface PollResultItem { interface PollResultItem {
fun getViewType(): Int fun getViewType(): Int
// fun getView(inflater: LayoutInflater?, convertView: View?): View? }
}

View File

@ -13,6 +13,6 @@ data class PollResultVoterItem(
companion object { companion object {
// layout is used as view type for uniqueness // layout is used as view type for uniqueness
public val VIEW_TYPE: Int = R.layout.poll_result_voter_item const val VIEW_TYPE: Int = R.layout.poll_result_voter_item
} }
} }

View File

@ -20,24 +20,7 @@ class PollResultVoterViewHolder(
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun bind(pollResultItem: PollResultItem, clickListener: PollResultItemClickListener) { override fun bind(pollResultItem: PollResultItem, clickListener: PollResultItemClickListener) {
val item = pollResultItem as PollResultVoterItem val item = pollResultItem as PollResultVoterItem
// binding.root.setOnClickListener { clickListener.onClick(pollResultVoterItem) }
// binding.pollVoterAvatar = pollResultHeaderItem.name
binding.pollVoterName.text = item.details.actorDisplayName binding.pollVoterName.text = item.details.actorDisplayName
// val lp = LinearLayout.LayoutParams(
// 60,
// 50
// )
//
// val avatar = SimpleDraweeView(binding.root.context)
// avatar.layoutParams = lp
// val roundingParams = RoundingParams.fromCornersRadius(5f)
// roundingParams.roundAsCircle = true
//
// binding.pollVoterAvatar.hierarchy.roundingParams = roundingParams
binding.pollVoterAvatar.controller = getAvatarDraweeController(item.details) binding.pollVoterAvatar.controller = getAvatarDraweeController(item.details)
} }
@ -47,8 +30,7 @@ class PollResultVoterViewHolder(
if (!TextUtils.isEmpty(pollDetail.actorDisplayName)) { if (!TextUtils.isEmpty(pollDetail.actorDisplayName)) {
displayName = pollDetail.actorDisplayName!! displayName = pollDetail.actorDisplayName!!
} }
val draweeController: DraweeController = Fresco.newDraweeControllerBuilder() return Fresco.newDraweeControllerBuilder()
// .setOldController(binding.avatar.controller)
.setAutoPlayAnimations(true) .setAutoPlayAnimations(true)
.setImageRequest( .setImageRequest(
DisplayUtils.getImageRequestForUrl( DisplayUtils.getImageRequestForUrl(
@ -61,10 +43,8 @@ class PollResultVoterViewHolder(
) )
) )
.build() .build()
return draweeController
} else if (pollDetail.actorType == "users") { } else if (pollDetail.actorType == "users") {
val draweeController: DraweeController = Fresco.newDraweeControllerBuilder() return Fresco.newDraweeControllerBuilder()
// .setOldController(binding.avatar.controller)
.setAutoPlayAnimations(true) .setAutoPlayAnimations(true)
.setImageRequest( .setImageRequest(
DisplayUtils.getImageRequestForUrl( DisplayUtils.getImageRequestForUrl(
@ -77,7 +57,6 @@ class PollResultVoterViewHolder(
) )
) )
.build() .build()
return draweeController
} }
return null return null
} }

View File

@ -20,7 +20,7 @@ class PollResultsAdapter(
LayoutInflater.from(parent.context), parent, LayoutInflater.from(parent.context), parent,
false false
) )
return PollResultHeaderViewHolder(user, itemBinding) return PollResultHeaderViewHolder(itemBinding)
} }
PollResultVoterItem.VIEW_TYPE -> { PollResultVoterItem.VIEW_TYPE -> {
val itemBinding = PollResultVoterItemBinding.inflate( val itemBinding = PollResultVoterItemBinding.inflate(
@ -32,7 +32,7 @@ class PollResultsAdapter(
} }
val itemBinding = PollResultHeaderItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) val itemBinding = PollResultHeaderItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return PollResultHeaderViewHolder(user, itemBinding) return PollResultHeaderViewHolder(itemBinding)
} }
override fun onBindViewHolder(holder: PollResultViewHolder, position: Int) { override fun onBindViewHolder(holder: PollResultViewHolder, position: Int) {

View File

@ -119,7 +119,7 @@ class PollRepositoryImpl(private val ncApi: NcApi, private val currentUserProvid
private fun mapToPoll(pollResponse: PollResponse): Poll { private fun mapToPoll(pollResponse: PollResponse): Poll {
val pollDetails = pollResponse.details?.map { it -> mapToPollDetails(it) } val pollDetails = pollResponse.details?.map { it -> mapToPollDetails(it) }
val poll = Poll( return Poll(
pollResponse.id, pollResponse.id,
pollResponse.question, pollResponse.question,
pollResponse.options, pollResponse.options,
@ -134,7 +134,6 @@ class PollRepositoryImpl(private val ncApi: NcApi, private val currentUserProvid
pollResponse.numVoters, pollResponse.numVoters,
pollDetails, pollDetails,
) )
return poll
} }
private fun convertVotes(votes: Map<String, Int>?): Map<String, Int> { private fun convertVotes(votes: Map<String, Int>?): Map<String, Int> {

View File

@ -48,14 +48,12 @@ class PollCreateDialogFragment(
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
binding = DialogPollCreateBinding.inflate(LayoutInflater.from(context)) binding = DialogPollCreateBinding.inflate(LayoutInflater.from(context))
val dialog = AlertDialog.Builder(requireContext()) return AlertDialog.Builder(requireContext())
.setView(binding.root) .setView(binding.root)
.create() .create()
return dialog
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return binding.root return binding.root
} }
@ -81,7 +79,7 @@ class PollCreateDialogFragment(
private fun setupListeners() { private fun setupListeners() {
binding.pollAddOptionsItem.setOnClickListener { binding.pollAddOptionsItem.setOnClickListener {
viewModel.addOption() viewModel.addOption()
adapter?.itemCount?.minus(1)?.let { it -> binding.pollCreateOptionsList.scrollToPosition(it) } adapter?.itemCount?.minus(1)?.let { binding.pollCreateOptionsList.scrollToPosition(it) }
} }
binding.pollDismiss.setOnClickListener { binding.pollDismiss.setOnClickListener {
@ -135,8 +133,8 @@ class PollCreateDialogFragment(
private fun showError() { private fun showError() {
dismiss() dismiss()
Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show()
Log.e(TAG, "Failed to create poll") Log.e(TAG, "Failed to create poll")
Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show()
} }
override fun onRemoveOptionsItemClick(pollCreateOptionItem: PollCreateOptionItem, position: Int) { override fun onRemoveOptionsItemClick(pollCreateOptionItem: PollCreateOptionItem, position: Int) {

View File

@ -52,7 +52,7 @@ class PollMainDialogFragment(
return dialog return dialog
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return binding.root return binding.root
} }
@ -64,7 +64,7 @@ class PollMainDialogFragment(
PollMainViewModel.InitialState -> {} PollMainViewModel.InitialState -> {}
is PollMainViewModel.PollVoteHiddenState -> { is PollMainViewModel.PollVoteHiddenState -> {
binding.pollDetailsText.visibility = View.VISIBLE binding.pollDetailsText.visibility = View.VISIBLE
binding.pollDetailsText.text = "You already voted for this private poll" binding.pollDetailsText.text = context?.resources?.getString(R.string.polls_private_voted)
showVoteScreen() showVoteScreen()
} }
is PollMainViewModel.PollVoteState -> { is PollMainViewModel.PollVoteState -> {
@ -94,9 +94,7 @@ class PollMainDialogFragment(
val contentFragment = PollResultsFragment( val contentFragment = PollResultsFragment(
user, user,
viewModel, viewModel
roomToken,
pollId
) )
val transaction = childFragmentManager.beginTransaction() val transaction = childFragmentManager.beginTransaction()
transaction.replace(binding.messagePollContentFragment.id, contentFragment) transaction.replace(binding.messagePollContentFragment.id, contentFragment)

View File

@ -21,7 +21,6 @@
package com.nextcloud.talk.polls.ui package com.nextcloud.talk.polls.ui
import android.content.DialogInterface
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -45,9 +44,7 @@ import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
class PollResultsFragment( class PollResultsFragment(
private val user: UserEntity, private val user: UserEntity,
private val parentViewModel: PollMainViewModel, private val parentViewModel: PollMainViewModel
private val roomToken: String,
private val pollId: String
) : Fragment(), PollResultItemClickListener { ) : Fragment(), PollResultItemClickListener {
@Inject @Inject
@ -55,9 +52,7 @@ class PollResultsFragment(
lateinit var viewModel: PollResultsViewModel lateinit var viewModel: PollResultsViewModel
var _binding: DialogPollResultsBinding? = null lateinit var binding: DialogPollResultsBinding
val binding: DialogPollResultsBinding
get() = _binding!!
private var adapter: PollResultsAdapter? = null private var adapter: PollResultsAdapter? = null
@ -72,7 +67,7 @@ class PollResultsFragment(
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
_binding = DialogPollResultsBinding.inflate(inflater, container, false) binding = DialogPollResultsBinding.inflate(inflater, container, false)
return binding.root return binding.root
} }
@ -98,49 +93,40 @@ class PollResultsFragment(
private fun initAdapter() { private fun initAdapter() {
adapter = PollResultsAdapter(user, this) adapter = PollResultsAdapter(user, this)
_binding?.pollResultsList?.adapter = adapter binding.pollResultsList.adapter = adapter
_binding?.pollResultsList?.layoutManager = LinearLayoutManager(context) binding.pollResultsList.layoutManager = LinearLayoutManager(context)
} }
private fun initEditButton(showEditButton: Boolean) { private fun initEditButton(showEditButton: Boolean) {
if (showEditButton) { if (showEditButton) {
_binding?.editVoteButton?.visibility = View.VISIBLE binding.editVoteButton.visibility = View.VISIBLE
_binding?.editVoteButton?.setOnClickListener { binding.editVoteButton.setOnClickListener {
parentViewModel.edit() parentViewModel.edit()
} }
} else { } else {
_binding?.editVoteButton?.visibility = View.GONE binding.editVoteButton.visibility = View.GONE
} }
} }
private fun initEndPollButton(showEndPollButton: Boolean) { private fun initEndPollButton(showEndPollButton: Boolean) {
if (showEndPollButton) { if (showEndPollButton) {
_binding?.pollResultsEndPollButton?.visibility = View.VISIBLE binding.pollResultsEndPollButton.visibility = View.VISIBLE
_binding?.pollResultsEndPollButton?.setOnClickListener { binding.pollResultsEndPollButton.setOnClickListener {
AlertDialog.Builder(requireContext()) AlertDialog.Builder(requireContext())
.setTitle(R.string.polls_end_poll) .setTitle(R.string.polls_end_poll)
.setMessage(R.string.polls_end_poll_confirm) .setMessage(R.string.polls_end_poll_confirm)
.setPositiveButton(R.string.polls_end_poll, DialogInterface.OnClickListener { _, _ -> .setPositiveButton(R.string.polls_end_poll) { _, _ ->
parentViewModel.closePoll() parentViewModel.closePoll()
}) }
.setNegativeButton(R.string.nc_cancel, null) .setNegativeButton(R.string.nc_cancel, null)
.show() .show()
} }
} else { } else {
_binding?.pollResultsEndPollButton?.visibility = View.GONE binding.pollResultsEndPollButton.visibility = View.GONE
} }
} }
override fun onClick(pollResultHeaderItem: PollResultHeaderItem) { override fun onClick(pollResultHeaderItem: PollResultHeaderItem) {
viewModel.filterItems() viewModel.filterItems()
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
companion object {
private val TAG = PollResultsFragment::class.java.simpleName
}
} }

View File

@ -21,7 +21,6 @@
package com.nextcloud.talk.polls.ui package com.nextcloud.talk.polls.ui
import android.content.DialogInterface
import android.graphics.Typeface import android.graphics.Typeface
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
@ -56,9 +55,7 @@ class PollVoteFragment(
lateinit var viewModel: PollVoteViewModel lateinit var viewModel: PollVoteViewModel
var _binding: DialogPollVoteBinding? = null private lateinit var binding: DialogPollVoteBinding
val binding: DialogPollVoteBinding
get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -71,7 +68,7 @@ class PollVoteFragment(
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
_binding = DialogPollVoteBinding.inflate(inflater, container, false) binding = DialogPollVoteBinding.inflate(inflater, container, false)
return binding.root return binding.root
} }
@ -93,7 +90,8 @@ class PollVoteFragment(
when (state) { when (state) {
PollVoteViewModel.InitialState -> {} PollVoteViewModel.InitialState -> {}
is PollVoteViewModel.PollVoteFailedState -> { is PollVoteViewModel.PollVoteFailedState -> {
Log.d(TAG, "fail") Log.e(TAG, "Failed to vote on poll.")
Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show()
} }
is PollVoteViewModel.PollVoteSuccessState -> { is PollVoteViewModel.PollVoteSuccessState -> {
parentViewModel.voted() parentViewModel.voted()
@ -101,7 +99,7 @@ class PollVoteFragment(
} }
} }
binding.pollVoteRadioGroup.setOnCheckedChangeListener { group, checkedId -> binding.pollVoteRadioGroup.setOnCheckedChangeListener { _, checkedId ->
viewModel.selectOption(checkedId, true) viewModel.selectOption(checkedId, true)
updateSubmitButton() updateSubmitButton()
} }
@ -135,13 +133,13 @@ class PollVoteFragment(
binding.voteOptionsCheckboxesWrapper.addView(checkBox) binding.voteOptionsCheckboxesWrapper.addView(checkBox)
checkBox.isChecked = viewModel.selectedOptions.contains(index) == true checkBox.isChecked = viewModel.selectedOptions.contains(index) == true
checkBox.setOnCheckedChangeListener { buttonView, isChecked -> checkBox.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) { if (isChecked) {
if (poll.maxVotes == UNLIMITED_VOTES || viewModel.selectedOptions.size < poll.maxVotes) { if (poll.maxVotes == UNLIMITED_VOTES || viewModel.selectedOptions.size < poll.maxVotes) {
viewModel.selectOption(index, false) viewModel.selectOption(index, false)
} else { } else {
checkBox.isChecked = false checkBox.isChecked = false
Toast.makeText(context, "max votes reached", Toast.LENGTH_LONG).show() Toast.makeText(context, R.string.polls_max_votes_reached, Toast.LENGTH_LONG).show()
} }
} else { } else {
viewModel.deSelectOption(index) viewModel.deSelectOption(index)
@ -170,27 +168,22 @@ class PollVoteFragment(
private fun initEndPollButton(showEndPollButton: Boolean) { private fun initEndPollButton(showEndPollButton: Boolean) {
if (showEndPollButton) { if (showEndPollButton) {
_binding?.pollVoteEndPollButton?.visibility = View.VISIBLE binding.pollVoteEndPollButton.visibility = View.VISIBLE
_binding?.pollVoteEndPollButton?.setOnClickListener { binding.pollVoteEndPollButton.setOnClickListener {
AlertDialog.Builder(requireContext()) AlertDialog.Builder(requireContext())
.setTitle(R.string.polls_end_poll) .setTitle(R.string.polls_end_poll)
.setMessage(R.string.polls_end_poll_confirm) .setMessage(R.string.polls_end_poll_confirm)
.setPositiveButton(R.string.polls_end_poll, DialogInterface.OnClickListener { _, _ -> .setPositiveButton(R.string.polls_end_poll) { _, _ ->
parentViewModel.closePoll() parentViewModel.closePoll()
}) }
.setNegativeButton(R.string.nc_cancel, null) .setNegativeButton(R.string.nc_cancel, null)
.show() .show()
} }
} else { } else {
_binding?.pollVoteEndPollButton?.visibility = View.GONE binding.pollVoteEndPollButton.visibility = View.GONE
} }
} }
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
companion object { companion object {
private val TAG = PollVoteFragment::class.java.simpleName private val TAG = PollVoteFragment::class.java.simpleName
private const val UNLIMITED_VOTES = 0 private const val UNLIMITED_VOTES = 0

View File

@ -1,5 +1,6 @@
package com.nextcloud.talk.polls.viewmodels package com.nextcloud.talk.polls.viewmodels
import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@ -21,7 +22,12 @@ class PollCreateViewModel @Inject constructor(private val repository: PollReposi
object PollCreatedState : ViewState object PollCreatedState : ViewState
object PollCreationFailedState : ViewState object PollCreationFailedState : ViewState
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(PollCreationState(true, false)) private val _viewState: MutableLiveData<ViewState> = MutableLiveData(
PollCreationState(
enableAddOptionButton = true,
enableCreatePollButton = false
)
)
val viewState: LiveData<ViewState> val viewState: LiveData<ViewState>
get() = _viewState get() = _viewState
@ -154,6 +160,7 @@ class PollCreateViewModel @Inject constructor(private val repository: PollReposi
} }
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
Log.e(TAG, "Failed to create poll", e)
_viewState.value = PollCreationFailedState _viewState.value = PollCreationFailedState
} }

View File

@ -21,6 +21,7 @@
package com.nextcloud.talk.polls.viewmodels package com.nextcloud.talk.polls.viewmodels
import android.util.Log
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@ -28,11 +29,10 @@ import com.nextcloud.talk.polls.adapters.PollResultHeaderItem
import com.nextcloud.talk.polls.adapters.PollResultItem import com.nextcloud.talk.polls.adapters.PollResultItem
import com.nextcloud.talk.polls.adapters.PollResultVoterItem import com.nextcloud.talk.polls.adapters.PollResultVoterItem
import com.nextcloud.talk.polls.model.Poll import com.nextcloud.talk.polls.model.Poll
import com.nextcloud.talk.polls.repositories.PollRepository
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import javax.inject.Inject import javax.inject.Inject
class PollResultsViewModel @Inject constructor(private val repository: PollRepository) : ViewModel() { class PollResultsViewModel @Inject constructor() : ViewModel() {
sealed interface ViewState sealed interface ViewState
object InitialState : ViewState object InitialState : ViewState
@ -103,6 +103,7 @@ class PollResultsViewModel @Inject constructor(private val repository: PollRepos
} else if (poll.votes != null) { } else if (poll.votes != null) {
return poll.numVoters return poll.numVoters
} }
Log.e(TAG, "something went wrong while getting amount of voters.")
return 0 return 0
} }

View File

@ -38,7 +38,7 @@ class PollVoteViewModel @Inject constructor(private val repository: PollReposito
sealed interface ViewState sealed interface ViewState
object InitialState : ViewState object InitialState : ViewState
open class PollVoteSuccessState(val poll: Poll) : ViewState open class PollVoteSuccessState(val poll: Poll) : ViewState
open class PollVoteFailedState() : ViewState open class PollVoteFailedState : ViewState
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState) private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
val viewState: LiveData<ViewState> val viewState: LiveData<ViewState>
@ -60,10 +60,10 @@ class PollVoteViewModel @Inject constructor(private val repository: PollReposito
} }
fun selectOption(option: Int, isRadioBox: Boolean) { fun selectOption(option: Int, isRadioBox: Boolean) {
if (isRadioBox) { _selectedOptions = if (isRadioBox) {
_selectedOptions = listOf(option) listOf(option)
} else { } else {
_selectedOptions = _selectedOptions.plus(option) _selectedOptions.plus(option)
} }
} }
@ -97,7 +97,7 @@ class PollVoteViewModel @Inject constructor(private val repository: PollReposito
} }
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
Log.d(TAG, "An error occurred: $e") Log.e(TAG, "An error occurred: $e")
_viewState.value = PollVoteFailedState() _viewState.value = PollVoteFailedState()
} }

View File

@ -539,8 +539,10 @@
<!-- Polls --> <!-- Polls -->
<string name="polls_amount_voters">Poll results - %1$s votes</string> <string name="polls_amount_voters">Poll results - %1$s votes</string>
<string name="polls_add_option">Add Option</string> <string name="polls_add_option">Add Option</string>
<string name="polls_private_voted">You successfully voted for this private poll.</string>
<string name="polls_end_poll">End Poll</string> <string name="polls_end_poll">End Poll</string>
<string name="polls_end_poll_confirm">Do you really want to end this poll? This can\'t be undone.</string> <string name="polls_end_poll_confirm">Do you really want to end this poll? This can\'t be undone.</string>
<string name="polls_max_votes_reached">You can\'t vote with more options for this poll.</string>
<string name="title_attachments">Attachments</string> <string name="title_attachments">Attachments</string>