Polls part 1 - displaying in timelines and voting (#1200)

* add entity classes

* change data models and add database migration

* add polls to StatusViewData

* show poll results

* add methods for vote handling

* add voting interface

* enable voting in TimelineFragment

* update polls immediately

* enable custom emojis for poll options

* enable voting from search fragment

* add voting layout to detailed statuses

* fix tests

* enable voting in ViewThreadFragment

* enable voting in ConversationsFragment

* small refactor for StatusBaseViewHolder
This commit is contained in:
Konrad Pozniak 2019-04-22 10:11:00 +02:00 committed by GitHub
commit fd7471f2ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 1637 additions and 68 deletions

View file

@ -76,7 +76,8 @@ data class ConversationStatusEntity(
val showingHiddenContent: Boolean,
val expanded: Boolean,
val collapsible: Boolean,
val collapsed: Boolean
val collapsed: Boolean,
val poll: Poll?
) {
/** its necessary to override this because Spanned.equals does not work as expected */
@ -104,6 +105,7 @@ data class ConversationStatusEntity(
if (expanded != other.expanded) return false
if (collapsible != other.collapsible) return false
if (collapsed != other.collapsed) return false
if (poll != other.poll) return false
return true
}
@ -127,6 +129,7 @@ data class ConversationStatusEntity(
result = 31 * result + expanded.hashCode()
result = 31 * result + collapsible.hashCode()
result = 31 * result + collapsed.hashCode()
result = 31 * result + poll.hashCode()
return result
}
@ -151,7 +154,8 @@ data class ConversationStatusEntity(
attachments = attachments,
mentions = mentions,
application = null,
pinned = false)
pinned = false,
poll = poll)
}
}
@ -172,7 +176,8 @@ fun Status.toEntity() =
false,
false,
!SmartLengthInputFilter.hasBadRatio(content, SmartLengthInputFilter.LENGTH_DEFAULT),
true
true,
poll
)

View file

@ -102,6 +102,8 @@ public class ConversationViewHolder extends StatusBaseViewHolder {
setAvatars(conversation.getAccounts());
setupPoll(status.getPoll(), status.getEmojis(), listener);
}
private void setConversationName(List<ConversationAccountEntity> accounts) {

View file

@ -18,9 +18,11 @@ package com.keylesspalace.tusky.components.conversation
import android.content.Intent
import android.os.Bundle
import android.preference.PreferenceManager
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.paging.PagedList
@ -34,11 +36,15 @@ import com.keylesspalace.tusky.db.AppDatabase
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.fragment.SFragment
import com.keylesspalace.tusky.fragment.SearchFragment
import com.keylesspalace.tusky.interfaces.ReselectableFragment
import com.keylesspalace.tusky.interfaces.StatusActionListener
import com.keylesspalace.tusky.util.NetworkState
import com.keylesspalace.tusky.util.ThemeUtils
import com.keylesspalace.tusky.util.hide
import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider
import com.uber.autodispose.autoDisposable
import io.reactivex.android.schedulers.AndroidSchedulers
import kotlinx.android.synthetic.main.fragment_timeline.*
import javax.inject.Inject
@ -187,6 +193,10 @@ class ConversationsFragment : SFragment(), StatusActionListener, Injectable, Res
jumpToTop()
}
override fun onVoteInPoll(position: Int, choices: MutableList<Int>) {
viewModel.voteInPoll(position, choices)
}
companion object {
fun newInstance() = ConversationsFragment()
}

View file

@ -67,6 +67,25 @@ class ConversationsViewModel @Inject constructor(
}
fun voteInPoll(position: Int, choices: MutableList<Int>) {
conversations.value?.getOrNull(position)?.let { conversation ->
timelineCases.voteInPoll(conversation.lastStatus.toStatus(), choices)
.flatMap { poll ->
val newConversation = conversation.copy(
lastStatus = conversation.lastStatus.copy(poll = poll)
)
Single.fromCallable {
database.conversationDao().insert(newConversation)
}
}
.subscribeOn(Schedulers.io())
.doOnError { t -> Log.w("ConversationViewModel", "Failed to favourite conversation", t) }
.subscribe()
.addTo(disposables)
}
}
fun expandHiddenStatus(expanded: Boolean, position: Int) {
conversations.value?.getOrNull(position)?.let { conversation ->
val newConversation = conversation.copy(