Fix nullability problems
This commit is contained in:
parent
9e32d3c9bd
commit
bf12d66423
4 changed files with 292 additions and 244 deletions
|
@ -34,13 +34,21 @@ import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener
|
||||||
import com.keylesspalace.tusky.di.Injectable
|
import com.keylesspalace.tusky.di.Injectable
|
||||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||||
import com.keylesspalace.tusky.settings.PrefKeys
|
import com.keylesspalace.tusky.settings.PrefKeys
|
||||||
import com.keylesspalace.tusky.util.*
|
import com.keylesspalace.tusky.util.Error
|
||||||
|
import com.keylesspalace.tusky.util.Loading
|
||||||
|
import com.keylesspalace.tusky.util.Success
|
||||||
|
import com.keylesspalace.tusky.util.hide
|
||||||
|
import com.keylesspalace.tusky.util.show
|
||||||
import com.keylesspalace.tusky.view.EmojiPicker
|
import com.keylesspalace.tusky.view.EmojiPicker
|
||||||
import kotlinx.android.synthetic.main.activity_announcements.*
|
|
||||||
import kotlinx.android.synthetic.main.toolbar_basic.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlinx.android.synthetic.main.activity_announcements.announcementsList
|
||||||
|
import kotlinx.android.synthetic.main.activity_announcements.errorMessageView
|
||||||
|
import kotlinx.android.synthetic.main.activity_announcements.progressBar
|
||||||
|
import kotlinx.android.synthetic.main.activity_announcements.swipeRefreshLayout
|
||||||
|
import kotlinx.android.synthetic.main.toolbar_basic.toolbar
|
||||||
|
|
||||||
class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener, OnEmojiSelectedListener, Injectable {
|
class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener,
|
||||||
|
OnEmojiSelectedListener, Injectable {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var viewModelFactory: ViewModelFactory
|
lateinit var viewModelFactory: ViewModelFactory
|
||||||
|
@ -52,13 +60,13 @@ class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener,
|
||||||
private val picker by lazy { EmojiPicker(this) }
|
private val picker by lazy { EmojiPicker(this) }
|
||||||
private val pickerDialog by lazy {
|
private val pickerDialog by lazy {
|
||||||
PopupWindow(this)
|
PopupWindow(this)
|
||||||
.apply {
|
.apply {
|
||||||
contentView = picker
|
contentView = picker
|
||||||
isFocusable = true
|
isFocusable = true
|
||||||
setOnDismissListener {
|
setOnDismissListener {
|
||||||
currentAnnouncementId = null
|
currentAnnouncementId = null
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private var currentAnnouncementId: String? = null
|
private var currentAnnouncementId: String? = null
|
||||||
|
|
||||||
|
@ -89,12 +97,15 @@ class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener,
|
||||||
announcementsList.adapter = adapter
|
announcementsList.adapter = adapter
|
||||||
|
|
||||||
viewModel.announcements.observe(this) {
|
viewModel.announcements.observe(this) {
|
||||||
when (it) {
|
when(it) {
|
||||||
is Success -> {
|
is Success -> {
|
||||||
progressBar.hide()
|
progressBar.hide()
|
||||||
swipeRefreshLayout.isRefreshing = false
|
swipeRefreshLayout.isRefreshing = false
|
||||||
if (it.data.isNullOrEmpty()) {
|
if(it.data.isNullOrEmpty()) {
|
||||||
errorMessageView.setup(R.drawable.elephant_friend_empty, R.string.no_announcements)
|
errorMessageView.setup(
|
||||||
|
R.drawable.elephant_friend_empty,
|
||||||
|
R.string.no_announcements
|
||||||
|
)
|
||||||
errorMessageView.show()
|
errorMessageView.show()
|
||||||
} else {
|
} else {
|
||||||
errorMessageView.hide()
|
errorMessageView.hide()
|
||||||
|
@ -116,7 +127,9 @@ class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener,
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.emojis.observe(this) {
|
viewModel.emojis.observe(this) {
|
||||||
picker.adapter = EmojiAdapter(it, this)
|
it?.let { list ->
|
||||||
|
picker.adapter = EmojiAdapter(list, this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.load()
|
viewModel.load()
|
||||||
|
@ -124,7 +137,7 @@ class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener,
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when(item.itemId) {
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
onBackPressed()
|
onBackPressed()
|
||||||
return true
|
return true
|
||||||
|
@ -163,13 +176,13 @@ class AnnouncementsActivity : BottomSheetActivity(), AnnouncementActionListener,
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewAccount(id: String?) {
|
override fun onViewAccount(id: String?) {
|
||||||
if (id != null) {
|
if(id != null) {
|
||||||
viewAccount(id)
|
viewAccount(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewUrl(url: String?) {
|
override fun onViewUrl(url: String?) {
|
||||||
if (url != null) {
|
if(url != null) {
|
||||||
viewUrl(url)
|
viewUrl(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,159 +27,166 @@ import com.keylesspalace.tusky.entity.Announcement
|
||||||
import com.keylesspalace.tusky.entity.Emoji
|
import com.keylesspalace.tusky.entity.Emoji
|
||||||
import com.keylesspalace.tusky.entity.Instance
|
import com.keylesspalace.tusky.entity.Instance
|
||||||
import com.keylesspalace.tusky.network.MastodonApi
|
import com.keylesspalace.tusky.network.MastodonApi
|
||||||
import com.keylesspalace.tusky.util.*
|
import com.keylesspalace.tusky.util.Either
|
||||||
|
import com.keylesspalace.tusky.util.Error
|
||||||
|
import com.keylesspalace.tusky.util.Loading
|
||||||
|
import com.keylesspalace.tusky.util.Resource
|
||||||
|
import com.keylesspalace.tusky.util.RxAwareViewModel
|
||||||
|
import com.keylesspalace.tusky.util.Success
|
||||||
import io.reactivex.rxkotlin.Singles
|
import io.reactivex.rxkotlin.Singles
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class AnnouncementsViewModel @Inject constructor(
|
class AnnouncementsViewModel @Inject constructor(
|
||||||
accountManager: AccountManager,
|
accountManager: AccountManager,
|
||||||
private val appDatabase: AppDatabase,
|
private val appDatabase: AppDatabase,
|
||||||
private val mastodonApi: MastodonApi,
|
private val mastodonApi: MastodonApi,
|
||||||
private val eventHub: EventHub
|
private val eventHub: EventHub
|
||||||
) : RxAwareViewModel() {
|
) : RxAwareViewModel() {
|
||||||
|
|
||||||
private val announcementsMutable = MutableLiveData<Resource<List<Announcement>>>()
|
private val announcementsMutable = MutableLiveData<Resource<List<Announcement>>>()
|
||||||
val announcements: LiveData<Resource<List<Announcement>>> = announcementsMutable
|
val announcements: LiveData<Resource<List<Announcement>>> = announcementsMutable
|
||||||
|
|
||||||
private val emojisMutable = MutableLiveData<List<Emoji>>()
|
private val emojisMutable = MutableLiveData<List<Emoji>?>()
|
||||||
val emojis: LiveData<List<Emoji>> = emojisMutable
|
val emojis: LiveData<List<Emoji>?>
|
||||||
|
get() = emojisMutable
|
||||||
|
|
||||||
init {
|
init {
|
||||||
Singles.zip(
|
Singles.zip(
|
||||||
mastodonApi.getCustomEmojis(),
|
mastodonApi.getCustomEmojis(),
|
||||||
appDatabase.instanceDao().loadMetadataForInstance(accountManager.activeAccount?.domain!!)
|
appDatabase.instanceDao()
|
||||||
.map<Either<InstanceEntity, Instance>> { Either.Left(it) }
|
.loadMetadataForInstance(accountManager.activeAccount?.domain!!)
|
||||||
.onErrorResumeNext(
|
.map<Either<InstanceEntity, Instance>> { Either.Left(it) }
|
||||||
mastodonApi.getInstance()
|
.onErrorResumeNext(
|
||||||
.map { Either.Right(it) }
|
mastodonApi.getInstance()
|
||||||
)
|
.map { Either.Right(it) }
|
||||||
|
)
|
||||||
) { emojis, either ->
|
) { emojis, either ->
|
||||||
either.asLeftOrNull()?.copy(emojiList = emojis)
|
either.asLeftOrNull()?.copy(emojiList = emojis)
|
||||||
?: InstanceEntity(
|
?: InstanceEntity(
|
||||||
accountManager.activeAccount?.domain!!,
|
accountManager.activeAccount?.domain!!,
|
||||||
emojis,
|
emojis,
|
||||||
either.asRight().maxTootChars,
|
either.asRight().maxTootChars,
|
||||||
either.asRight().pollLimits?.maxOptions,
|
either.asRight().pollLimits?.maxOptions,
|
||||||
either.asRight().pollLimits?.maxOptionChars,
|
either.asRight().pollLimits?.maxOptionChars,
|
||||||
either.asRight().version,
|
either.asRight().version,
|
||||||
either.asRight().chatLimit
|
either.asRight().chatLimit
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.doOnSuccess {
|
.doOnSuccess {
|
||||||
appDatabase.instanceDao().insertOrReplace(it)
|
appDatabase.instanceDao().insertOrReplace(it)
|
||||||
}
|
}
|
||||||
.subscribe({
|
.subscribe({ instanceEntity ->
|
||||||
emojisMutable.postValue(it.emojiList)
|
emojisMutable.postValue(instanceEntity.emojiList)
|
||||||
}, {
|
}, {
|
||||||
Log.w(TAG, "Failed to get custom emojis.", it)
|
Log.w(TAG, "Failed to get custom emojis.", it)
|
||||||
})
|
})
|
||||||
.autoDispose()
|
.autoDispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun load() {
|
fun load() {
|
||||||
announcementsMutable.postValue(Loading())
|
announcementsMutable.postValue(Loading())
|
||||||
mastodonApi.listAnnouncements()
|
mastodonApi.listAnnouncements()
|
||||||
.subscribe({
|
.subscribe({
|
||||||
announcementsMutable.postValue(Success(it))
|
announcementsMutable.postValue(Success(it))
|
||||||
it.filter { announcement -> !announcement.read }
|
it.filter { announcement -> !announcement.read }
|
||||||
.forEach { announcement ->
|
.forEach { announcement ->
|
||||||
mastodonApi.dismissAnnouncement(announcement.id)
|
mastodonApi.dismissAnnouncement(announcement.id)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{
|
{
|
||||||
eventHub.dispatch(AnnouncementReadEvent(announcement.id))
|
eventHub.dispatch(AnnouncementReadEvent(announcement.id))
|
||||||
},
|
},
|
||||||
{ throwable ->
|
{ throwable ->
|
||||||
Log.d(TAG, "Failed to mark announcement as read.", throwable)
|
Log.d(TAG, "Failed to mark announcement as read.", throwable)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.autoDispose()
|
.autoDispose()
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
announcementsMutable.postValue(Error(cause = it))
|
announcementsMutable.postValue(Error(cause = it))
|
||||||
})
|
})
|
||||||
.autoDispose()
|
.autoDispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addReaction(announcementId: String, name: String) {
|
fun addReaction(announcementId: String, name: String) {
|
||||||
mastodonApi.addAnnouncementReaction(announcementId, name)
|
mastodonApi.addAnnouncementReaction(announcementId, name)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
announcementsMutable.postValue(
|
announcementsMutable.postValue(
|
||||||
Success(
|
Success(
|
||||||
announcements.value!!.data!!.map { announcement ->
|
announcements.value!!.data!!.map { announcement ->
|
||||||
if (announcement.id == announcementId) {
|
if(announcement.id == announcementId) {
|
||||||
announcement.copy(
|
announcement.copy(
|
||||||
reactions = if (announcement.reactions.find { reaction -> reaction.name == name } != null) {
|
reactions = if(announcement.reactions.find { reaction -> reaction.name == name } != null) {
|
||||||
announcement.reactions.map { reaction ->
|
announcement.reactions.map { reaction ->
|
||||||
if (reaction.name == name) {
|
if(reaction.name == name) {
|
||||||
reaction.copy(
|
reaction.copy(
|
||||||
count = reaction.count + 1,
|
count = reaction.count + 1,
|
||||||
me = true
|
me = true
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
reaction
|
reaction
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
listOf(
|
|
||||||
*announcement.reactions.toTypedArray(),
|
|
||||||
emojis.value!!.find { emoji -> emoji.shortcode == name }
|
|
||||||
!!.run {
|
|
||||||
Announcement.Reaction(
|
|
||||||
name,
|
|
||||||
1,
|
|
||||||
true,
|
|
||||||
url,
|
|
||||||
staticUrl
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
announcement
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
listOf(
|
||||||
|
*announcement.reactions.toTypedArray(),
|
||||||
|
emojis.value!!.find { emoji -> emoji.shortcode == name }
|
||||||
|
!!.run {
|
||||||
|
Announcement.Reaction(
|
||||||
|
name,
|
||||||
|
1,
|
||||||
|
true,
|
||||||
|
url,
|
||||||
|
staticUrl
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
announcement
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}, {
|
)
|
||||||
Log.w(TAG, "Failed to add reaction to the announcement.", it)
|
}, {
|
||||||
})
|
Log.w(TAG, "Failed to add reaction to the announcement.", it)
|
||||||
.autoDispose()
|
})
|
||||||
|
.autoDispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeReaction(announcementId: String, name: String) {
|
fun removeReaction(announcementId: String, name: String) {
|
||||||
mastodonApi.removeAnnouncementReaction(announcementId, name)
|
mastodonApi.removeAnnouncementReaction(announcementId, name)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
announcementsMutable.postValue(
|
announcementsMutable.postValue(
|
||||||
Success(
|
Success(
|
||||||
announcements.value!!.data!!.map { announcement ->
|
announcements.value!!.data!!.map { announcement ->
|
||||||
if (announcement.id == announcementId) {
|
if(announcement.id == announcementId) {
|
||||||
announcement.copy(
|
announcement.copy(
|
||||||
reactions = announcement.reactions.mapNotNull { reaction ->
|
reactions = announcement.reactions.mapNotNull { reaction ->
|
||||||
if (reaction.name == name) {
|
if(reaction.name == name) {
|
||||||
if (reaction.count > 1) {
|
if(reaction.count > 1) {
|
||||||
reaction.copy(
|
reaction.copy(
|
||||||
count = reaction.count - 1,
|
count = reaction.count - 1,
|
||||||
me = false
|
me = false
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
reaction
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
announcement
|
reaction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
announcement
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}, {
|
)
|
||||||
Log.w(TAG, "Failed to remove reaction from the announcement.", it)
|
}, {
|
||||||
})
|
Log.w(TAG, "Failed to remove reaction from the announcement.", it)
|
||||||
.autoDispose()
|
})
|
||||||
|
.autoDispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -13,15 +13,18 @@ import com.keylesspalace.tusky.util.Listing
|
||||||
import com.keylesspalace.tusky.util.NetworkState
|
import com.keylesspalace.tusky.util.NetworkState
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import retrofit2.Call
|
|
||||||
import retrofit2.Callback
|
|
||||||
import retrofit2.Response
|
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class ConversationsRepository @Inject constructor(val mastodonApi: MastodonApi, val db: AppDatabase) {
|
class ConversationsRepository @Inject constructor(
|
||||||
|
val mastodonApi: MastodonApi,
|
||||||
|
val db: AppDatabase
|
||||||
|
) {
|
||||||
|
|
||||||
private val ioExecutor = Executors.newSingleThreadExecutor()
|
private val ioExecutor = Executors.newSingleThreadExecutor()
|
||||||
|
|
||||||
|
@ -37,23 +40,26 @@ class ConversationsRepository @Inject constructor(val mastodonApi: MastodonApi,
|
||||||
}
|
}
|
||||||
|
|
||||||
mastodonApi.getConversations(limit = DEFAULT_PAGE_SIZE).enqueue(
|
mastodonApi.getConversations(limit = DEFAULT_PAGE_SIZE).enqueue(
|
||||||
object : Callback<List<Conversation>> {
|
object : Callback<List<Conversation>> {
|
||||||
override fun onFailure(call: Call<List<Conversation>>, t: Throwable) {
|
override fun onFailure(call: Call<List<Conversation>>, t: Throwable) {
|
||||||
// retrofit calls this on main thread so safe to call set value
|
// retrofit calls this on main thread so safe to call set value
|
||||||
networkState.value = NetworkState.error(t.message)
|
networkState.value = NetworkState.error(t.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(call: Call<List<Conversation>>, response: Response<List<Conversation>>) {
|
override fun onResponse(
|
||||||
ioExecutor.execute {
|
call: Call<List<Conversation>>,
|
||||||
db.runInTransaction {
|
response: Response<List<Conversation>>
|
||||||
db.conversationDao().deleteForAccount(accountId)
|
) {
|
||||||
insertResultIntoDb(accountId, response.body())
|
ioExecutor.execute {
|
||||||
}
|
db.runInTransaction {
|
||||||
// since we are in bg thread now, post the result.
|
db.conversationDao().deleteForAccount(accountId)
|
||||||
networkState.postValue(NetworkState.LOADED)
|
insertResultIntoDb(accountId, response.body())
|
||||||
}
|
}
|
||||||
|
// since we are in bg thread now, post the result.
|
||||||
|
networkState.postValue(NetworkState.LOADED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
return networkState
|
return networkState
|
||||||
}
|
}
|
||||||
|
@ -63,11 +69,12 @@ class ConversationsRepository @Inject constructor(val mastodonApi: MastodonApi,
|
||||||
// create a boundary callback which will observe when the user reaches to the edges of
|
// create a boundary callback which will observe when the user reaches to the edges of
|
||||||
// the list and update the database with extra data.
|
// the list and update the database with extra data.
|
||||||
val boundaryCallback = ConversationsBoundaryCallback(
|
val boundaryCallback = ConversationsBoundaryCallback(
|
||||||
accountId = accountId,
|
accountId = accountId,
|
||||||
mastodonApi = mastodonApi,
|
mastodonApi = mastodonApi,
|
||||||
handleResponse = this::insertResultIntoDb,
|
handleResponse = this::insertResultIntoDb,
|
||||||
ioExecutor = ioExecutor,
|
ioExecutor = ioExecutor,
|
||||||
networkPageSize = DEFAULT_PAGE_SIZE)
|
networkPageSize = DEFAULT_PAGE_SIZE
|
||||||
|
)
|
||||||
// we are using a mutable live data to trigger refresh requests which eventually calls
|
// we are using a mutable live data to trigger refresh requests which eventually calls
|
||||||
// refresh method and gets a new live data. Each refresh request by the user becomes a newly
|
// refresh method and gets a new live data. Each refresh request by the user becomes a newly
|
||||||
// dispatched data in refreshTrigger
|
// dispatched data in refreshTrigger
|
||||||
|
@ -77,21 +84,25 @@ class ConversationsRepository @Inject constructor(val mastodonApi: MastodonApi,
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use toLiveData Kotlin extension function here, you could also use LivePagedListBuilder
|
// We use toLiveData Kotlin extension function here, you could also use LivePagedListBuilder
|
||||||
val livePagedList = db.conversationDao().conversationsForAccount(accountId).toLiveData(
|
val livePagedList = db.conversationDao().conversationsForAccount(accountId).toLiveData(
|
||||||
config = Config(pageSize = DEFAULT_PAGE_SIZE, prefetchDistance = DEFAULT_PAGE_SIZE / 2, enablePlaceholders = false),
|
config = Config(
|
||||||
boundaryCallback = boundaryCallback
|
pageSize = DEFAULT_PAGE_SIZE,
|
||||||
|
prefetchDistance = DEFAULT_PAGE_SIZE / 2,
|
||||||
|
enablePlaceholders = false
|
||||||
|
),
|
||||||
|
boundaryCallback = boundaryCallback
|
||||||
)
|
)
|
||||||
|
|
||||||
return Listing(
|
return Listing(
|
||||||
pagedList = livePagedList,
|
pagedList = livePagedList,
|
||||||
networkState = boundaryCallback.networkState,
|
networkState = boundaryCallback.networkState,
|
||||||
retry = {
|
retry = {
|
||||||
boundaryCallback.helper.retryAllFailed()
|
boundaryCallback.helper.retryAllFailed()
|
||||||
},
|
},
|
||||||
refresh = {
|
refresh = {
|
||||||
refreshTrigger.value = null
|
refreshTrigger.value = Unit
|
||||||
},
|
},
|
||||||
refreshState = refreshState
|
refreshState = refreshState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,13 +110,13 @@ class ConversationsRepository @Inject constructor(val mastodonApi: MastodonApi,
|
||||||
Single.fromCallable {
|
Single.fromCallable {
|
||||||
db.conversationDao().deleteForAccount(accountId)
|
db.conversationDao().deleteForAccount(accountId)
|
||||||
}.subscribeOn(Schedulers.io())
|
}.subscribeOn(Schedulers.io())
|
||||||
.subscribe()
|
.subscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun insertResultIntoDb(accountId: Long, result: List<Conversation>?) {
|
private fun insertResultIntoDb(accountId: Long, result: List<Conversation>?) {
|
||||||
result?.filter { it.lastStatus != null }
|
result?.filter { it.lastStatus != null }
|
||||||
?.map{ it.toEntity(accountId) }
|
?.map { it.toEntity(accountId) }
|
||||||
?.let { db.conversationDao().insert(it) }
|
?.let { db.conversationDao().insert(it) }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,18 +27,26 @@ import com.keylesspalace.tusky.components.report.model.StatusViewState
|
||||||
import com.keylesspalace.tusky.entity.Relationship
|
import com.keylesspalace.tusky.entity.Relationship
|
||||||
import com.keylesspalace.tusky.entity.Status
|
import com.keylesspalace.tusky.entity.Status
|
||||||
import com.keylesspalace.tusky.network.MastodonApi
|
import com.keylesspalace.tusky.network.MastodonApi
|
||||||
import com.keylesspalace.tusky.util.*
|
import com.keylesspalace.tusky.util.BiListing
|
||||||
|
import com.keylesspalace.tusky.util.Error
|
||||||
|
import com.keylesspalace.tusky.util.Loading
|
||||||
|
import com.keylesspalace.tusky.util.NetworkState
|
||||||
|
import com.keylesspalace.tusky.util.Resource
|
||||||
|
import com.keylesspalace.tusky.util.RxAwareViewModel
|
||||||
|
import com.keylesspalace.tusky.util.Success
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ReportViewModel @Inject constructor(
|
class ReportViewModel @Inject constructor(
|
||||||
private val mastodonApi: MastodonApi,
|
private val mastodonApi: MastodonApi,
|
||||||
private val eventHub: EventHub,
|
private val eventHub: EventHub,
|
||||||
private val statusesRepository: StatusesRepository) : RxAwareViewModel() {
|
private val statusesRepository: StatusesRepository
|
||||||
|
) : RxAwareViewModel() {
|
||||||
|
|
||||||
private val navigationMutable = MutableLiveData<Screen>()
|
private val navigationMutable = MutableLiveData<Screen?>()
|
||||||
val navigation: LiveData<Screen> = navigationMutable
|
val navigation: LiveData<Screen?>
|
||||||
|
get() = navigationMutable
|
||||||
|
|
||||||
private val muteStateMutable = MutableLiveData<Resource<Boolean>>()
|
private val muteStateMutable = MutableLiveData<Resource<Boolean>>()
|
||||||
val muteState: LiveData<Resource<Boolean>> = muteStateMutable
|
val muteState: LiveData<Resource<Boolean>> = muteStateMutable
|
||||||
|
@ -49,14 +57,19 @@ class ReportViewModel @Inject constructor(
|
||||||
private val reportingStateMutable = MutableLiveData<Resource<Boolean>>()
|
private val reportingStateMutable = MutableLiveData<Resource<Boolean>>()
|
||||||
var reportingState: LiveData<Resource<Boolean>> = reportingStateMutable
|
var reportingState: LiveData<Resource<Boolean>> = reportingStateMutable
|
||||||
|
|
||||||
private val checkUrlMutable = MutableLiveData<String>()
|
private val checkUrlMutable = MutableLiveData<String?>()
|
||||||
val checkUrl: LiveData<String> = checkUrlMutable
|
val checkUrl: LiveData<String?>
|
||||||
|
get() = checkUrlMutable
|
||||||
|
|
||||||
private val repoResult = MutableLiveData<BiListing<Status>>()
|
private val repoResult = MutableLiveData<BiListing<Status>>()
|
||||||
val statuses: LiveData<PagedList<Status>> = Transformations.switchMap(repoResult) { it.pagedList }
|
val statuses: LiveData<PagedList<Status>> =
|
||||||
val networkStateAfter: LiveData<NetworkState> = Transformations.switchMap(repoResult) { it.networkStateAfter }
|
Transformations.switchMap(repoResult) { it.pagedList }
|
||||||
val networkStateBefore: LiveData<NetworkState> = Transformations.switchMap(repoResult) { it.networkStateBefore }
|
val networkStateAfter: LiveData<NetworkState> =
|
||||||
val networkStateRefresh: LiveData<NetworkState> = Transformations.switchMap(repoResult) { it.refreshState }
|
Transformations.switchMap(repoResult) { it.networkStateAfter }
|
||||||
|
val networkStateBefore: LiveData<NetworkState> =
|
||||||
|
Transformations.switchMap(repoResult) { it.networkStateBefore }
|
||||||
|
val networkStateRefresh: LiveData<NetworkState> =
|
||||||
|
Transformations.switchMap(repoResult) { it.refreshState }
|
||||||
|
|
||||||
private val selectedIds = HashSet<String>()
|
private val selectedIds = HashSet<String>()
|
||||||
val statusViewState = StatusViewState()
|
val statusViewState = StatusViewState()
|
||||||
|
@ -79,7 +92,7 @@ class ReportViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
isRemoteAccount = userName.contains('@')
|
isRemoteAccount = userName.contains('@')
|
||||||
if (isRemoteAccount) {
|
if(isRemoteAccount) {
|
||||||
remoteServer = userName.substring(userName.indexOf('@') + 1)
|
remoteServer = userName.substring(userName.indexOf('@') + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,29 +108,28 @@ class ReportViewModel @Inject constructor(
|
||||||
navigationMutable.value = null
|
navigationMutable.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun obtainRelationship() {
|
private fun obtainRelationship() {
|
||||||
val ids = listOf(accountId)
|
val ids = listOf(accountId)
|
||||||
muteStateMutable.value = Loading()
|
muteStateMutable.value = Loading()
|
||||||
blockStateMutable.value = Loading()
|
blockStateMutable.value = Loading()
|
||||||
mastodonApi.relationships(ids)
|
mastodonApi.relationships(ids)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ data ->
|
{ data ->
|
||||||
updateRelationship(data.getOrNull(0))
|
updateRelationship(data.getOrNull(0))
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
updateRelationship(null)
|
updateRelationship(null)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.autoDispose()
|
.autoDispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun updateRelationship(relationship: Relationship?) {
|
private fun updateRelationship(relationship: Relationship?) {
|
||||||
if (relationship != null) {
|
if(relationship != null) {
|
||||||
muteStateMutable.value = Success(relationship.muting)
|
muteStateMutable.value = Success(relationship.muting)
|
||||||
blockStateMutable.value = Success(relationship.blocking)
|
blockStateMutable.value = Success(relationship.blocking)
|
||||||
} else {
|
} else {
|
||||||
|
@ -128,69 +140,74 @@ class ReportViewModel @Inject constructor(
|
||||||
|
|
||||||
fun toggleMute() {
|
fun toggleMute() {
|
||||||
val alreadyMuted = muteStateMutable.value?.data == true
|
val alreadyMuted = muteStateMutable.value?.data == true
|
||||||
if (alreadyMuted) {
|
if(alreadyMuted) {
|
||||||
mastodonApi.unmuteAccount(accountId)
|
mastodonApi.unmuteAccount(accountId)
|
||||||
} else {
|
} else {
|
||||||
mastodonApi.muteAccount(accountId)
|
mastodonApi.muteAccount(accountId)
|
||||||
}
|
}
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ relationship ->
|
{ relationship ->
|
||||||
val muting = relationship?.muting == true
|
val muting = relationship?.muting == true
|
||||||
muteStateMutable.value = Success(muting)
|
muteStateMutable.value = Success(muting)
|
||||||
if (muting) {
|
if(muting) {
|
||||||
eventHub.dispatch(MuteEvent(accountId, true))
|
eventHub.dispatch(MuteEvent(accountId, true))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ error ->
|
{ error ->
|
||||||
muteStateMutable.value = Error(false, error.message)
|
muteStateMutable.value = Error(false, error.message)
|
||||||
}
|
}
|
||||||
).autoDispose()
|
).autoDispose()
|
||||||
|
|
||||||
muteStateMutable.value = Loading()
|
muteStateMutable.value = Loading()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleBlock() {
|
fun toggleBlock() {
|
||||||
val alreadyBlocked = blockStateMutable.value?.data == true
|
val alreadyBlocked = blockStateMutable.value?.data == true
|
||||||
if (alreadyBlocked) {
|
if(alreadyBlocked) {
|
||||||
mastodonApi.unblockAccount(accountId)
|
mastodonApi.unblockAccount(accountId)
|
||||||
} else {
|
} else {
|
||||||
mastodonApi.blockAccount(accountId)
|
mastodonApi.blockAccount(accountId)
|
||||||
}
|
}
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{ relationship ->
|
{ relationship ->
|
||||||
val blocking = relationship?.blocking == true
|
val blocking = relationship?.blocking == true
|
||||||
blockStateMutable.value = Success(blocking)
|
blockStateMutable.value = Success(blocking)
|
||||||
if (blocking) {
|
if(blocking) {
|
||||||
eventHub.dispatch(BlockEvent(accountId))
|
eventHub.dispatch(BlockEvent(accountId))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ error ->
|
{ error ->
|
||||||
blockStateMutable.value = Error(false, error.message)
|
blockStateMutable.value = Error(false, error.message)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.autoDispose()
|
.autoDispose()
|
||||||
|
|
||||||
blockStateMutable.value = Loading()
|
blockStateMutable.value = Loading()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doReport() {
|
fun doReport() {
|
||||||
reportingStateMutable.value = Loading()
|
reportingStateMutable.value = Loading()
|
||||||
mastodonApi.reportObservable(accountId, selectedIds.toList(), reportNote, if (isRemoteAccount) isRemoteNotify else null)
|
mastodonApi.reportObservable(
|
||||||
.subscribeOn(Schedulers.io())
|
accountId,
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
selectedIds.toList(),
|
||||||
.subscribe(
|
reportNote,
|
||||||
{
|
if(isRemoteAccount) isRemoteNotify else null
|
||||||
reportingStateMutable.value = Success(true)
|
)
|
||||||
},
|
.subscribeOn(Schedulers.io())
|
||||||
{ error ->
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
reportingStateMutable.value = Error(cause = error)
|
.subscribe(
|
||||||
}
|
{
|
||||||
)
|
reportingStateMutable.value = Success(true)
|
||||||
.autoDispose()
|
},
|
||||||
|
{ error ->
|
||||||
|
reportingStateMutable.value = Error(cause = error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.autoDispose()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +228,7 @@ class ReportViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setStatusChecked(status: Status, checked: Boolean) {
|
fun setStatusChecked(status: Status, checked: Boolean) {
|
||||||
if (checked) {
|
if(checked) {
|
||||||
selectedIds.add(status.id)
|
selectedIds.add(status.id)
|
||||||
} else {
|
} else {
|
||||||
selectedIds.remove(status.id)
|
selectedIds.remove(status.id)
|
||||||
|
@ -222,4 +239,4 @@ class ReportViewModel @Inject constructor(
|
||||||
return selectedIds.contains(id)
|
return selectedIds.contains(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue