upgrade realm

This commit is contained in:
Phillip Thelen 2020-10-06 14:41:49 +02:00
parent e80389cffb
commit 5e1a2dfc74
41 changed files with 285 additions and 278 deletions

View file

@ -115,7 +115,6 @@ dependencies {
implementation 'com.google.firebase:firebase-config:19.2.0'
implementation 'com.google.firebase:firebase-perf:19.0.9'
implementation 'com.google.android.gms:play-services-auth:18.1.0'
implementation 'io.realm:android-adapters:4.0.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.nex3z:flow-layout:1.2.2'

View file

@ -1,5 +1,6 @@
package com.habitrpg.android.habitica.data
import com.habitrpg.android.habitica.models.BaseObject
import com.habitrpg.android.habitica.models.responses.TaskScoringResult
import com.habitrpg.android.habitica.models.tasks.RemindersItem
import com.habitrpg.android.habitica.models.tasks.Task
@ -40,7 +41,7 @@ interface TaskRepository : BaseRepository {
fun saveReminder(remindersItem: RemindersItem)
fun executeTransaction(transaction: Realm.Transaction)
fun <T: BaseObject> modify(obj: T, transaction: (T) -> Unit)
fun swapTaskPosition(firstPosition: Int, secondPosition: Int)

View file

@ -135,21 +135,23 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie
private fun sellItem(user: User?, item: Item, ownedItem: OwnedItem): Flowable<User> {
if (user != null && appConfigManager.enableLocalChanges()) {
localRepository.executeTransaction {
ownedItem.numberOwned -= 1
user.stats?.gp = (user.stats?.gp ?: 0.0) + item.value
val liveItem = localRepository.getLiveObject(ownedItem)
val liveUser = localRepository.getLiveObject(user)
liveItem?.numberOwned = 1 + (liveItem?.numberOwned ?: 0)
liveUser?.stats?.gp = (user.stats?.gp ?: 0.0) + item.value
}
}
return apiClient.sellItem(item.type, item.key)
.map { user1 ->
localRepository.executeTransaction { realm ->
localRepository.modifyWithRealm(user1) { realm, liveUser ->
if (user != null) {
val items = user1.items
val items = liveUser.items
if (items != null) {
items.userId = user.id
val newItems = realm.copyToRealmOrUpdate(items)
user.items = newItems
}
val stats = user1.stats
val stats = liveUser.stats
if (stats != null) {
stats.userId = user.id
val newStats = realm.copyToRealmOrUpdate(stats)
@ -167,16 +169,16 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie
override fun equip(user: User?, type: String, key: String): Flowable<Items> {
if (user != null && appConfigManager.enableLocalChanges()) {
localRepository.executeTransaction {
localRepository.modify(user) { liveUser ->
if (type == "mount") {
user.items?.currentMount = key
liveUser.items?.currentMount = key
} else if (type == "pet") {
user.items?.currentPet = key
liveUser.items?.currentPet = key
}
val outfit = if (type == "costume") {
user.items?.gear?.costume
liveUser.items?.gear?.costume
} else {
user.items?.gear?.equipped
liveUser.items?.gear?.equipped
}
when (key.split("_").firstOrNull()) {
"weapon" -> outfit?.weapon = key
@ -195,16 +197,16 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie
if (user == null) {
return@doOnNext
}
localRepository.executeTransaction {
localRepository.modify(user) { liveUser ->
val newEquipped = items.gear?.equipped
val oldEquipped = user.items?.gear?.equipped
val oldEquipped = liveUser.items?.gear?.equipped
val newCostume = items.gear?.costume
val oldCostume = user.items?.gear?.costume
val oldCostume = liveUser.items?.gear?.costume
newEquipped?.let { equipped -> oldEquipped?.updateWith(equipped) }
newCostume?.let { costume -> oldCostume?.updateWith(costume) }
user.items?.currentMount = items.currentMount
user.items?.currentPet = items.currentPet
user.balance = user.balance
liveUser.items?.currentMount = items.currentMount
liveUser.items?.currentPet = items.currentPet
liveUser.balance = liveUser.balance
}
}
}

View file

@ -266,7 +266,7 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
return apiClient.markPrivateMessagesRead()
.doOnNext {
if (user?.isManaged == true) {
localRepository.executeTransaction { user.inbox?.newMessages = 0 }
localRepository.modify(user) { it.inbox?.newMessages = 0 }
}
}
}

View file

@ -6,6 +6,7 @@ import com.habitrpg.android.habitica.data.local.TaskLocalRepository
import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.interactors.ScoreTaskLocallyInteractor
import com.habitrpg.android.habitica.models.BaseObject
import com.habitrpg.android.habitica.models.responses.TaskDirection
import com.habitrpg.android.habitica.models.responses.TaskDirectionData
import com.habitrpg.android.habitica.models.responses.TaskScoringResult
@ -117,11 +118,9 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli
}
private fun handleTaskResponse(user: User, res: TaskDirectionData, task: Task, up: Boolean, localDelta: Float) {
val userID = user.id
val taskID = task.id
this.localRepository.executeTransaction {
val bgTask = it.where(Task::class.java).equalTo("id", taskID).findFirst() ?: return@executeTransaction
val bgUser = it.where(User::class.java).equalTo("id", userID).findFirst() ?: return@executeTransaction
val bgTask = localRepository.getLiveObject(task) ?: return@executeTransaction
val bgUser = localRepository.getLiveObject(user) ?: return@executeTransaction
if (bgTask.type != "reward" && (bgTask.value - localDelta) + res.delta != bgTask.value) {
bgTask.value = (bgTask.value - localDelta) + res.delta
if (Task.TYPE_DAILY == bgTask.type || Task.TYPE_TODO == bgTask.type) {
@ -177,7 +176,7 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli
.doOnNext { task ->
val updatedItem: ChecklistItem? = task.checklist?.lastOrNull { itemId == it.id }
if (updatedItem != null) {
localRepository.executeTransaction { updatedItem.completed = !updatedItem.completed }
localRepository.modify(updatedItem) { liveItem -> liveItem.completed = !liveItem.completed }
}
}
}
@ -259,8 +258,8 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli
localRepository.saveReminder(remindersItem)
}
override fun executeTransaction(transaction: Realm.Transaction) {
localRepository.executeTransaction(transaction)
override fun <T: BaseObject> modify(obj: T, transaction: (T) -> Unit) {
localRepository.modify(obj, transaction)
}
override fun swapTaskPosition(firstPosition: Int, secondPosition: Int) {

View file

@ -96,7 +96,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
}
override fun sleep(user: User): Flowable<User> {
localRepository.executeTransaction { user.preferences?.sleep = !(user.preferences?.sleep ?: false) }
localRepository.modify(user) { it.preferences?.sleep = !(it.preferences?.sleep ?: false) }
return apiClient.sleep().map { user }
}
@ -210,9 +210,9 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
apiClient.updateUsername(newLoginName.trim())
}).flatMapMaybe { localRepository.getUser(userID).firstElement() }
.doOnNext { user ->
localRepository.executeTransaction {
user.authentication?.localAuthentication?.username = newLoginName
user.flags?.verifiedUsername = true
localRepository.modify(user) { liveUser ->
liveUser.authentication?.localAuthentication?.username = newLoginName
liveUser.flags?.verifiedUsername = true
}
}
.firstElement()
@ -228,26 +228,26 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
override fun allocatePoint(user: User?, stat: String): Flowable<Stats> {
if (user != null && user.isManaged) {
localRepository.executeTransaction {
localRepository.modify(user) { liveUser ->
when (stat) {
Stats.STRENGTH -> user.stats?.strength = user.stats?.strength?.inc()
Stats.INTELLIGENCE -> user.stats?.intelligence = user.stats?.intelligence?.inc()
Stats.CONSTITUTION -> user.stats?.constitution= user.stats?.constitution?.inc()
Stats.PERCEPTION -> user.stats?.per = user.stats?.per?.inc()
Stats.STRENGTH -> liveUser.stats?.strength = liveUser.stats?.strength?.inc()
Stats.INTELLIGENCE -> liveUser.stats?.intelligence = liveUser.stats?.intelligence?.inc()
Stats.CONSTITUTION -> liveUser.stats?.constitution= liveUser.stats?.constitution?.inc()
Stats.PERCEPTION -> liveUser.stats?.per = liveUser.stats?.per?.inc()
}
user.stats?.points = user.stats?.points?.dec()
liveUser.stats?.points = liveUser.stats?.points?.dec()
}
}
return apiClient.allocatePoint(stat)
.doOnNext { stats ->
if (user != null && user.isManaged) {
localRepository.executeTransaction {
user.stats?.strength = stats.strength
user.stats?.constitution = stats.constitution
user.stats?.per = stats.per
user.stats?.intelligence = stats.intelligence
user.stats?.points = stats.points
user.stats?.mp = stats.mp
localRepository.modify(user) { liveUser ->
liveUser.stats?.strength = stats.strength
liveUser.stats?.constitution = stats.constitution
liveUser.stats?.per = stats.per
liveUser.stats?.intelligence = stats.intelligence
liveUser.stats?.points = stats.points
liveUser.stats?.mp = stats.mp
}
}
}
@ -257,13 +257,13 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
apiClient.bulkAllocatePoints(strength, intelligence, constitution, perception)
.doOnNext { stats ->
if (user != null && user.isManaged) {
localRepository.executeTransaction {
user.stats?.strength = stats.strength
user.stats?.constitution = stats.constitution
user.stats?.per = stats.per
user.stats?.intelligence = stats.intelligence
user.stats?.points = stats.points
user.stats?.mp = stats.mp
localRepository.modify(user) { liveUser ->
liveUser.stats?.strength = stats.strength
liveUser.stats?.constitution = stats.constitution
liveUser.stats?.per = stats.per
liveUser.stats?.intelligence = stats.intelligence
liveUser.stats?.points = stats.points
liveUser.stats?.mp = stats.mp
}
}
}
@ -271,10 +271,11 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
override fun runCron(tasks: MutableList<Task>) {
var observable: Maybe<Any> = localRepository.getUser(userID).firstElement()
.filter { it.needsCron }
.map { user -> localRepository.executeTransaction {
user.needsCron = false
user.lastCron = Date()
}
.map { user ->
localRepository.modify(user) { liveUser ->
liveUser.needsCron = false
liveUser.lastCron = Date()
}
user
}
if (tasks.isNotEmpty()) {
@ -289,22 +290,22 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
override fun useCustomization(user: User?, type: String, category: String?, identifier: String): Flowable<User> {
if (user != null && appConfigManager.enableLocalChanges()) {
localRepository.executeTransaction {
localRepository.modify(user) { liveUser ->
when (type) {
"skin" -> user.preferences?.skin =identifier
"shirt" -> user.preferences?.shirt = identifier
"skin" -> liveUser.preferences?.skin =identifier
"shirt" -> liveUser.preferences?.shirt = identifier
"hair" -> {
when (category) {
"color" -> user.preferences?.hair?.color = identifier
"flower" -> user.preferences?.hair?.flower = identifier.toInt()
"mustache" -> user.preferences?.hair?.mustache = identifier.toInt()
"beard" -> user.preferences?.hair?.beard = identifier.toInt()
"bangs" -> user.preferences?.hair?.bangs = identifier.toInt()
"base" -> user.preferences?.hair?.base = identifier.toInt()
"color" -> liveUser.preferences?.hair?.color = identifier
"flower" -> liveUser.preferences?.hair?.flower = identifier.toInt()
"mustache" -> liveUser.preferences?.hair?.mustache = identifier.toInt()
"beard" -> liveUser.preferences?.hair?.beard = identifier.toInt()
"bangs" -> liveUser.preferences?.hair?.bangs = identifier.toInt()
"base" -> liveUser.preferences?.hair?.base = identifier.toInt()
}
}
"background" -> user.preferences?.background = identifier
"chair" -> user.preferences?.chair = identifier
"background" -> liveUser.preferences?.background = identifier
"chair" -> liveUser.preferences?.chair = identifier
}
}
}

View file

@ -1,11 +1,15 @@
package com.habitrpg.android.habitica.data.local
import android.renderscript.BaseObj
import com.habitrpg.android.habitica.models.BaseObject
import io.realm.Realm
import io.realm.RealmModel
import io.realm.RealmObject
interface BaseLocalRepository {
val isClosed: Boolean
var realm: Realm
fun close()
@ -13,11 +17,14 @@ interface BaseLocalRepository {
fun executeTransaction(transaction: Realm.Transaction)
fun executeTransactionAsync(transaction: (Realm) -> Unit)
fun executeTransactionAsync(transaction: Realm.Transaction)
fun <T: BaseObject> modify(obj: T, transaction: (T) -> Unit)
fun <T: BaseObject> modifyWithRealm(obj: T, transaction: (Realm, T) -> Unit)
fun <T: RealmModel> getLiveObject(obj: T): T?
fun <T : RealmObject> getUnmanagedCopy(managedObject: T): T
fun <T : RealmObject> getUnmanagedCopy(list: List<T>): List<T>
fun <T: RealmObject> getUnmanagedCopy(managedObject: T): T
fun <T: RealmObject> getUnmanagedCopy(list: List<T>): List<T>
fun <T : RealmObject> save(objects: List<T>)
fun <T : RealmObject> save(`object`: T)
fun <T : RealmObject> saveSyncronous(`object`: T)
fun <T: RealmObject> save(objects: List<T>)
fun <T: RealmObject> save(`object`: T)
fun <T: RealmObject> saveSyncronous(`object`: T)
}

View file

@ -1,11 +1,15 @@
package com.habitrpg.android.habitica.data.local.implementation
import android.renderscript.BaseObj
import com.habitrpg.android.habitica.data.local.BaseLocalRepository
import com.habitrpg.android.habitica.models.BaseObject
import io.realm.Realm
import io.realm.RealmModel
import io.realm.RealmObject
import io.realm.kotlin.where
abstract class RealmBaseLocalRepository internal constructor(protected var realm: Realm) : BaseLocalRepository {
abstract class RealmBaseLocalRepository internal constructor(override var realm: Realm) : BaseLocalRepository {
override val isClosed: Boolean
get() = realm.isClosed
@ -65,4 +69,26 @@ abstract class RealmBaseLocalRepository internal constructor(protected var realm
if (isClosed) { return }
realm.executeTransaction { realm1 -> realm1.insertOrUpdate(`object`) }
}
override fun <T: BaseObject> modify(obj: T, transaction: (T) -> Unit) {
if (isClosed) { return }
val liveObject = getLiveObject(obj) ?: return
realm.executeTransaction {
transaction(liveObject)
}
}
override fun <T: BaseObject> modifyWithRealm(obj: T, transaction: (Realm, T) -> Unit) {
if (isClosed) { return }
val liveObject = getLiveObject(obj) ?: return
realm.executeTransaction {
transaction(it, liveObject)
}
}
override fun <T: RealmModel> getLiveObject(obj: T): T? {
if (isClosed) return null
val baseObject = obj as? BaseObject ?: return null
return realm.where(baseObject.realmClass).equalTo(baseObject.primaryIdentifierName, baseObject.primaryIdentifier).findFirst() as? T
}
}

View file

@ -0,0 +1,10 @@
package com.habitrpg.android.habitica.models
import io.realm.RealmModel
interface BaseObject: RealmModel {
val realmClass: Class<out RealmModel>
val primaryIdentifier: String?
val primaryIdentifierName: String
}

View file

@ -1,10 +1,11 @@
package com.habitrpg.android.habitica.models
import io.realm.RealmModel
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import java.util.*
open class TutorialStep : RealmObject() {
open class TutorialStep: RealmObject(), BaseObject {
@PrimaryKey
var key: String? = null
@ -23,4 +24,11 @@ open class TutorialStep : RealmObject() {
fun shouldDisplay(): Boolean =
!this.wasCompleted && (this.displayedOn == null || Date().time - (displayedOn?.time ?: 0) > 86400000)
override val realmClass: Class<out RealmModel>
get() = TutorialStep::class.java
override val primaryIdentifier: String?
get() = key
override val primaryIdentifierName: String
get() = "key"
}

View file

@ -2,16 +2,20 @@ package com.habitrpg.android.habitica.models.tasks
import android.os.Parcel
import android.os.Parcelable
import java.util.UUID
import com.habitrpg.android.habitica.models.BaseObject
import io.realm.RealmModel
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import java.util.*
/**
* Created by viirus on 06/07/15.
*/
open class ChecklistItem : RealmObject, Parcelable {
open class ChecklistItem : RealmObject, BaseObject, Parcelable {
override val realmClass: Class<ChecklistItem>
get() = ChecklistItem::class.java
override val primaryIdentifier: String?
get() = id
override val primaryIdentifierName: String
get() = "id"
@PrimaryKey
var id: String? = null
@ -56,7 +60,7 @@ open class ChecklistItem : RealmObject, Parcelable {
dest.writeInt(position)
}
companion object CREATOR : Parcelable.Creator<ChecklistItem> {
companion object CREATOR : Parcelable.Creator<ChecklistItem>, RealmModel {
override fun createFromParcel(source: Parcel): ChecklistItem = ChecklistItem(source)
override fun newArray(size: Int): Array<ChecklistItem?> = arrayOfNulls(size)

View file

@ -6,6 +6,7 @@ import android.text.Spanned
import androidx.annotation.StringDef
import com.google.gson.annotations.SerializedName
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.models.BaseObject
import com.habitrpg.android.habitica.models.Tag
import com.habitrpg.android.habitica.models.user.Stats
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
@ -17,7 +18,15 @@ import org.json.JSONArray
import org.json.JSONException
import java.util.*
open class Task : RealmObject, Parcelable {
open class Task : RealmObject, BaseObject, Parcelable {
override val realmClass: Class<Task>
get() = Task::class.java
override val primaryIdentifier: String?
get() = id
override val primaryIdentifierName: String
get() = "id"
@PrimaryKey
@SerializedName("_id")
var id: String? = null

View file

@ -1,9 +1,17 @@
package com.habitrpg.android.habitica.models.user
import com.habitrpg.android.habitica.models.BaseObject
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
open class OwnedItem : RealmObject(), OwnedObject {
open class OwnedItem : RealmObject(), BaseObject, OwnedObject {
override val realmClass: Class<OwnedItem>
get() = OwnedItem::class.java
override val primaryIdentifier: String?
get() = combinedKey
override val primaryIdentifierName: String
get() = "combinedKey"
@PrimaryKey
override var combinedKey: String? = null

View file

@ -14,8 +14,15 @@ import io.realm.annotations.Ignore
import io.realm.annotations.PrimaryKey
import java.util.*
open class User : RealmObject(), Avatar, VersionedObject {
open class User : RealmObject(), BaseObject, Avatar, VersionedObject {
override val realmClass: Class<User>
get() = User::class.java
override val primaryIdentifier: String?
get() = id
override val primaryIdentifierName: String
get() = "id"
@Ignore
var tasks: TaskList? = null

View file

@ -68,13 +68,13 @@ class HabitButtonWidgetActivity : BaseActivity() {
binding.recyclerView.layoutManager = layoutManager
}
adapter = SkillTasksRecyclerViewAdapter(null, true)
adapter = SkillTasksRecyclerViewAdapter()
adapter?.getTaskSelectionEvents()?.subscribe({ task -> taskSelected(task.id) },
RxErrorHandler.handleEmptyError())
?.let { compositeSubscription.add(it) }
binding.recyclerView.adapter = adapter
compositeSubscription.add(taskRepository.getTasks(Task.TYPE_HABIT, userId).firstElement().subscribe({ adapter?.updateData(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(taskRepository.getTasks(Task.TYPE_HABIT, userId).subscribe({ adapter?.data = it }, RxErrorHandler.handleEmptyError()))
}
private fun taskSelected(taskId: String?) {

View file

@ -661,7 +661,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
}
override fun onTutorialDeferred(step: TutorialStep) {
taskRepository.executeTransaction { step.displayedOn = Date() }
taskRepository.modify(step) { it.displayedOn = Date() }
this.removeActiveTutorialView()
}

View file

@ -44,7 +44,7 @@ class SkillMemberActivity : BaseActivity() {
private fun loadMemberList() {
binding.recyclerView.layoutManager = LinearLayoutManager(this)
viewAdapter = PartyMemberRecyclerViewAdapter(null, true)
viewAdapter = PartyMemberRecyclerViewAdapter()
viewAdapter?.getUserClickedEvents()?.subscribe({ userId ->
val resultIntent = Intent()
resultIntent.putExtra("member_id", userId)
@ -54,8 +54,7 @@ class SkillMemberActivity : BaseActivity() {
binding.recyclerView.adapter = viewAdapter
compositeSubscription.add(userRepository.getUser()
.firstElement()
.flatMap { user -> socialRepository.getGroupMembers(user.party?.id ?: "").firstElement() }
.subscribe({ viewAdapter?.updateData(it) }, RxErrorHandler.handleEmptyError()))
.flatMap { user -> socialRepository.getGroupMembers(user.party?.id ?: "") }
.subscribe({ viewAdapter?.data = it }, RxErrorHandler.handleEmptyError()))
}
}

View file

@ -0,0 +1,28 @@
package com.habitrpg.android.habitica.ui.adapter
import androidx.recyclerview.widget.RecyclerView
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.ui.viewHolders.BindableViewHolder
import io.realm.OrderedRealmCollection
import io.realm.RealmModel
abstract class BaseRecyclerViewAdapter<T, VH: RecyclerView.ViewHolder>: RecyclerView.Adapter<VH>() {
var data: List<T> = emptyList()
set(value) {
field = value
notifyDataSetChanged()
}
override fun getItemCount(): Int {
return data.size
}
open fun getItem(position: Int): T? {
return if (position >= 0 && data.size > position) {
data[position]
} else {
null
}
}
}

View file

@ -10,21 +10,17 @@ import com.habitrpg.android.habitica.models.tasks.Task
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
import java.util.*
class SkillTasksRecyclerViewAdapter(data: OrderedRealmCollection<Task>?, autoUpdate: Boolean) : RealmRecyclerViewAdapter<Task, SkillTasksRecyclerViewAdapter.TaskViewHolder>(data, autoUpdate) {
class SkillTasksRecyclerViewAdapter : BaseRecyclerViewAdapter<Task, SkillTasksRecyclerViewAdapter.TaskViewHolder>() {
private val taskSelectionEvents = PublishSubject.create<Task>()
override fun getItemId(position: Int): Long {
if (data != null) {
val task = data?.get(position)
if (task?.id?.length == 36) {
return UUID.fromString(task.id).mostSignificantBits
}
val task = getItem(position)
if (task?.id?.length == 36) {
return UUID.fromString(task.id).mostSignificantBits
}
return UUID.randomUUID().mostSignificantBits
}

View file

@ -11,13 +11,12 @@ import androidx.core.content.ContextCompat
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.databinding.GearListItemBinding
import com.habitrpg.android.habitica.models.inventory.Equipment
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import io.reactivex.rxjava3.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
class EquipmentRecyclerViewAdapter(data: OrderedRealmCollection<Equipment>?, autoUpdate: Boolean) : RealmRecyclerViewAdapter<Equipment, EquipmentRecyclerViewAdapter.GearViewHolder>(data, autoUpdate) {
class EquipmentRecyclerViewAdapter : BaseRecyclerViewAdapter<Equipment, EquipmentRecyclerViewAdapter.GearViewHolder>() {
var equippedGear: String? = null
var isCostume: Boolean? = null
@ -31,9 +30,7 @@ class EquipmentRecyclerViewAdapter(data: OrderedRealmCollection<Equipment>?, aut
}
override fun onBindViewHolder(holder: GearViewHolder, position: Int) {
data?.let {
holder.bind(it[position])
}
holder.bind(data[position])
}
inner class GearViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) {

View file

@ -12,6 +12,7 @@ import com.habitrpg.android.habitica.extensions.layoutInflater
import com.habitrpg.android.habitica.models.inventory.*
import com.habitrpg.android.habitica.models.user.OwnedItem
import com.habitrpg.android.habitica.models.user.OwnedPet
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemRecyclerFragment
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.menu.BottomSheetMenu
@ -21,13 +22,12 @@ import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
import io.realm.RealmResults
import org.greenrobot.eventbus.EventBus
import java.text.SimpleDateFormat
import java.util.*
class ItemRecyclerAdapter(data: OrderedRealmCollection<OwnedItem>?, autoUpdate: Boolean, val context: Context) : RealmRecyclerViewAdapter<OwnedItem, ItemRecyclerAdapter.ItemViewHolder>(data, autoUpdate) {
class ItemRecyclerAdapter(data: OrderedRealmCollection<OwnedItem>?, autoUpdate: Boolean, val context: Context) : BaseRecyclerViewAdapter<OwnedItem, ItemRecyclerAdapter.ItemViewHolder>() {
var isHatching: Boolean = false
var isFeeding: Boolean = false

View file

@ -8,16 +8,16 @@ import com.habitrpg.android.habitica.databinding.ChallengeItemBinding
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.models.social.Challenge
import com.habitrpg.android.habitica.models.social.ChallengeMembership
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.fragments.social.challenges.ChallengeFilterOptions
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.helpers.EmojiParser
import io.realm.OrderedRealmCollection
class ChallengesListViewAdapter(data: OrderedRealmCollection<Challenge>?, autoUpdate: Boolean, private val viewUserChallengesOnly: Boolean, private val userId: String) : RealmRecyclerViewAdapter<Challenge, ChallengesListViewAdapter.ChallengeViewHolder>(data, autoUpdate) {
class ChallengesListViewAdapter(private val viewUserChallengesOnly: Boolean, private val userId: String) : BaseRecyclerViewAdapter<Challenge, ChallengesListViewAdapter.ChallengeViewHolder>() {
private var unfilteredData: OrderedRealmCollection<Challenge>? = null
private var challengeMemberships: OrderedRealmCollection<ChallengeMembership>? = null
@ -41,7 +41,7 @@ class ChallengesListViewAdapter(data: OrderedRealmCollection<Challenge>?, autoUp
}
fun updateUnfilteredData(data: OrderedRealmCollection<Challenge>?) {
super.updateData(data)
this.data = data ?: emptyList()
unfilteredData = data
}
@ -71,7 +71,7 @@ class ChallengesListViewAdapter(data: OrderedRealmCollection<Challenge>?, autoUp
}
query?.let {
this.updateData(it.findAll())
data = it.findAll()
}
}

View file

@ -8,14 +8,14 @@ import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.models.social.ChatMessage
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.viewHolders.BindableViewHolder
import com.habitrpg.android.habitica.ui.viewHolders.ChatRecyclerMessageViewHolder
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
class ChatRecyclerViewAdapter(data: OrderedRealmCollection<ChatMessage>?, autoUpdate: Boolean, user: User?, private val isTavern: Boolean) : RealmRecyclerViewAdapter<ChatMessage, RecyclerView.ViewHolder>(data, autoUpdate) {
class ChatRecyclerViewAdapter(user: User?, private val isTavern: Boolean) : BaseRecyclerViewAdapter<ChatMessage, RecyclerView.ViewHolder>() {
internal var user = user
set(value) {
field = value
@ -44,29 +44,27 @@ class ChatRecyclerViewAdapter(data: OrderedRealmCollection<ChatMessage>?, autoUp
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
data?.let { data ->
if (data[position].isSystemMessage) {
(holder as? SystemChatMessageViewHolder)?.bind(data[position])
} else {
val chatHolder = holder as? ChatRecyclerMessageViewHolder ?: return
val message = data[position]
chatHolder.bind(message,
uuid,
user,
expandedMessageId == message.id)
chatHolder.onShouldExpand = { expandMessage(message.id, position) }
chatHolder.onLikeMessage = { likeMessageEvents.onNext(it) }
chatHolder.onOpenProfile = { userLabelClickEvents.onNext(it) }
chatHolder.onReply = { replyMessageEvents.onNext(it) }
chatHolder.onCopyMessage = { copyMessageEvents.onNext(it) }
chatHolder.onFlagMessage = { flagMessageEvents.onNext(it) }
chatHolder.onDeleteMessage = { deleteMessageEvents.onNext(it) }
}
if (data[position].isSystemMessage) {
(holder as? SystemChatMessageViewHolder)?.bind(data[position])
} else {
val chatHolder = holder as? ChatRecyclerMessageViewHolder ?: return
val message = data[position]
chatHolder.bind(message,
uuid,
user,
expandedMessageId == message.id)
chatHolder.onShouldExpand = { expandMessage(message.id, position) }
chatHolder.onLikeMessage = { likeMessageEvents.onNext(it) }
chatHolder.onOpenProfile = { userLabelClickEvents.onNext(it) }
chatHolder.onReply = { replyMessageEvents.onNext(it) }
chatHolder.onCopyMessage = { copyMessageEvents.onNext(it) }
chatHolder.onFlagMessage = { flagMessageEvents.onNext(it) }
chatHolder.onDeleteMessage = { deleteMessageEvents.onNext(it) }
}
}
override fun getItemViewType(position: Int): Int {
return if (data?.get(position)?.isSystemMessage == true) 0 else 1
return if (data[position].isSystemMessage) 0 else 1
}
fun getLikeMessageFlowable(): Flowable<ChatMessage> {

View file

@ -4,14 +4,13 @@ import android.view.ViewGroup
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.models.members.Member
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.viewHolders.GroupMemberViewHolder
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.subjects.PublishSubject
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection<Member>?, autoUpdate: Boolean) : RealmRecyclerViewAdapter<Member, GroupMemberViewHolder>(data, autoUpdate) {
class PartyMemberRecyclerViewAdapter : BaseRecyclerViewAdapter<Member, GroupMemberViewHolder>() {
var leaderID: String? = null
@ -22,11 +21,9 @@ class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection<Member>?, auto
}
override fun onBindViewHolder(holder: GroupMemberViewHolder, position: Int) {
data?.let {
holder.bind(it[position], leaderID, null)
holder.onClickEvent = {
userClickedEvents.onNext(it[position].id ?: "")
}
holder.bind(data[position], leaderID, null)
holder.onClickEvent = {
userClickedEvents.onNext(data[position].id ?: "")
}
}

View file

@ -12,13 +12,13 @@ import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.fragments.social.PublicGuildsFragmentDirections
import com.habitrpg.android.habitica.ui.helpers.setMarkdown
import io.realm.Case
import io.realm.OrderedRealmCollection
import io.realm.RealmRecyclerViewAdapter
class PublicGuildsRecyclerViewAdapter(data: OrderedRealmCollection<Group>?, autoUpdate: Boolean) : RealmRecyclerViewAdapter<Group, PublicGuildsRecyclerViewAdapter.GuildViewHolder>(data, autoUpdate), Filterable {
class PublicGuildsRecyclerViewAdapter : BaseRecyclerViewAdapter<Group, PublicGuildsRecyclerViewAdapter.GuildViewHolder>(), Filterable {
var socialRepository: SocialRepository? = null
private var memberGuildIDs: List<String> = listOf()
@ -41,18 +41,14 @@ class PublicGuildsRecyclerViewAdapter(data: OrderedRealmCollection<Group>?, auto
if (isMember) {
this@PublicGuildsRecyclerViewAdapter.socialRepository?.leaveGroup(guild.id, true)
?.subscribe({
if (data != null) {
val indexOfGroup = data?.indexOf(guild)
notifyItemChanged(indexOfGroup ?: 0)
}
val indexOfGroup = data.indexOf(guild)
notifyItemChanged(indexOfGroup)
}, RxErrorHandler.handleEmptyError())
} else {
this@PublicGuildsRecyclerViewAdapter.socialRepository?.joinGroup(guild.id)
?.subscribe({ group ->
if (data != null) {
val indexOfGroup = data?.indexOf(group)
notifyItemChanged(indexOfGroup ?: 0)
}
val indexOfGroup = data.indexOf(group)
notifyItemChanged(indexOfGroup)
}, RxErrorHandler.handleEmptyError())
}
@ -61,13 +57,11 @@ class PublicGuildsRecyclerViewAdapter(data: OrderedRealmCollection<Group>?, auto
}
override fun onBindViewHolder(holder: GuildViewHolder, position: Int) {
data?.let {
val guild = it[position]
val isInGroup = isInGroup(guild)
holder.bind(guild, isInGroup)
holder.itemView.tag = guild
holder.binding.joinleaveButton.tag = guild
}
val guild = data[position]
val isInGroup = isInGroup(guild)
holder.bind(guild, isInGroup)
holder.itemView.tag = guild
holder.binding.joinleaveButton.tag = guild
}
private fun isInGroup(guild: Group): Boolean {
@ -77,7 +71,7 @@ class PublicGuildsRecyclerViewAdapter(data: OrderedRealmCollection<Group>?, auto
private var unfilteredData: OrderedRealmCollection<Group>? = null
fun setUnfilteredData(data: OrderedRealmCollection<Group>?) {
updateData(data)
this.data = data ?: emptyList()
unfilteredData = data
}
@ -92,13 +86,13 @@ class PublicGuildsRecyclerViewAdapter(data: OrderedRealmCollection<Group>?, auto
override fun publishResults(constraint: CharSequence, results: FilterResults) {
unfilteredData?.let {
if (constraint.isNotEmpty()) {
updateData(it.where()
data = it.where()
.beginGroup()
.contains("name", constraint.toString(), Case.INSENSITIVE)
.or()
.contains("summary", constraint.toString(), Case.INSENSITIVE)
.endGroup()
.findAll())
.findAll()
}
}
}

View file

@ -12,6 +12,7 @@ import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.helpers.TaskFilterHelper
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.viewHolders.BindableViewHolder
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
@ -20,18 +21,16 @@ import java.util.*
import javax.inject.Inject
abstract class BaseTasksRecyclerViewAdapter<VH : BindableViewHolder<Task>>(var taskType: String, private val taskFilterHelper: TaskFilterHelper?, private val layoutResource: Int,
newContext: Context, private val userID: String?) : RecyclerView.Adapter<VH>() {
newContext: Context, private val userID: String?) : BaseRecyclerViewAdapter<Task, VH>() {
@Inject
lateinit var crashlyticsProxy: CrashlyticsProxy
@Inject
lateinit var taskRepository: TaskRepository
protected var content: MutableList<Task>? = null
protected var filteredContent: MutableList<Task>? = null
internal var context: Context
internal var context: Context = newContext.applicationContext
init {
this.setHasStableIds(true)
this.context = newContext.applicationContext
this.filteredContent = ArrayList()
HabiticaBaseApplication.userComponent?.let { injectThis(it) }
@ -54,7 +53,7 @@ abstract class BaseTasksRecyclerViewAdapter<VH : BindableViewHolder<Task>>(var t
return task?.id?.hashCode()?.toLong() ?: 0
}
override fun getItemCount(): Int =filteredContent?.size ?: 0
override fun getItemCount(): Int = filteredContent?.size ?: 0
internal fun getContentView(parent: ViewGroup): View = getContentView(parent, layoutResource)

View file

@ -8,7 +8,6 @@ import io.realm.OrderedRealmCollection
class HabitsRecyclerViewAdapter(data: OrderedRealmCollection<Task>?, autoUpdate: Boolean, layoutResource: Int, taskFilterHelper: TaskFilterHelper) : RealmBaseTasksRecyclerViewAdapter<HabitViewHolder>(data, autoUpdate, layoutResource, taskFilterHelper) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HabitViewHolder =
HabitViewHolder(getContentView(parent), { task, direction -> taskScoreEventsSubject.onNext(Pair(task, direction)) }, {
task -> taskOpenEventsSubject.onNext(task)

View file

@ -3,24 +3,24 @@ package com.habitrpg.android.habitica.ui.adapter.tasks
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.habitrpg.android.habitica.helpers.TaskFilterHelper
import com.habitrpg.android.habitica.models.responses.TaskDirection
import com.habitrpg.android.habitica.models.tasks.ChecklistItem
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.viewHolders.tasks.BaseTaskViewHolder
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.functions.Action
import io.reactivex.rxjava3.subjects.PublishSubject
import io.realm.*
import io.realm.OrderedRealmCollection
abstract class RealmBaseTasksRecyclerViewAdapter<VH : BaseTaskViewHolder>(
private var unfilteredData: OrderedRealmCollection<Task>?,
private val hasAutoUpdates: Boolean,
private val layoutResource: Int,
private val taskFilterHelper: TaskFilterHelper?
) : RealmRecyclerViewAdapter<Task, VH>(null, false), TaskRecyclerViewAdapter {
) : BaseRecyclerViewAdapter<Task, VH>(), TaskRecyclerViewAdapter {
private var updateOnModification: Boolean = false
override var ignoreUpdates: Boolean = false
@ -32,78 +32,6 @@ abstract class RealmBaseTasksRecyclerViewAdapter<VH : BaseTaskViewHolder>(
}
}
private val resultsListener: OrderedRealmCollectionChangeListener<RealmResults<Task>> by lazy {
OrderedRealmCollectionChangeListener<RealmResults<Task>> { _, changeSet ->
buildChangeSet(changeSet)
}
}
private val listListener: OrderedRealmCollectionChangeListener<RealmList<Task>> by lazy {
OrderedRealmCollectionChangeListener<RealmList<Task>> { _, changeSet ->
buildChangeSet(changeSet)
}
}
private fun buildChangeSet(changeSet: OrderedCollectionChangeSet) {
if (ignoreUpdates) return
if (changeSet.state == OrderedCollectionChangeSet.State.INITIAL) {
notifyDataSetChanged()
return
}
// For deletions, the adapter has to be notified in reverse order.
val deletions = changeSet.deletionRanges
for (i in deletions.indices.reversed()) {
val range = deletions[i]
notifyItemRangeRemoved(range.startIndex + dataOffset(), range.length)
}
val insertions = changeSet.insertionRanges
for (range in insertions) {
notifyItemRangeInserted(range.startIndex + dataOffset(), range.length)
}
if (!updateOnModification) {
return
}
val modifications = changeSet.changeRanges
for (range in modifications) {
notifyItemRangeChanged(range.startIndex + dataOffset(), range.length)
}
}
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
data?.takeIf { it.isValid }?.addListener()
}
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
super.onDetachedFromRecyclerView(recyclerView)
data?.takeIf { it.isValid }?.removeListener()
}
override fun updateData(tasks: OrderedRealmCollection<Task>?) {
data?.takeIf { it.isValid && !it.isFrozen }?.removeListener()
tasks?.takeIf { it.isValid && !it.isFrozen }?.addListener()
super.updateData(tasks)
}
private fun OrderedRealmCollection<Task>.addListener() {
when (this) {
is RealmResults<Task> -> addChangeListener(resultsListener)
is RealmList<Task> -> addChangeListener(listListener)
else -> throw IllegalArgumentException("RealmCollection not supported: $javaClass")
}
}
private fun OrderedRealmCollection<Task>.removeListener() {
when (this) {
is RealmResults<Task> -> removeChangeListener(resultsListener)
is RealmList<Task> -> removeChangeListener(listListener)
else -> throw IllegalArgumentException("RealmCollection not supported: $javaClass")
}
}
private var errorButtonEventsSubject = PublishSubject.create<String>()
override val errorButtonEvents: Flowable<String> = errorButtonEventsSubject.toFlowable(BackpressureStrategy.DROP)
protected var taskScoreEventsSubject = PublishSubject.create<Pair<Task, TaskDirection>>()
@ -115,9 +43,6 @@ abstract class RealmBaseTasksRecyclerViewAdapter<VH : BaseTaskViewHolder>(
protected var brokenTaskEventsSubject = PublishSubject.create<Task>()
override val brokenTaskEvents: Flowable<Task> = brokenTaskEventsSubject.toFlowable(BackpressureStrategy.DROP)
private val isDataValid: Boolean
get() = data?.isValid ?: false
init {
check(!(unfilteredData != null && unfilteredData?.isManaged == false)) { "Only use this adapter with managed RealmCollection, " + "for un-managed lists you can just use the BaseRecyclerViewAdapter" }
this.updateOnModification = true
@ -126,13 +51,9 @@ abstract class RealmBaseTasksRecyclerViewAdapter<VH : BaseTaskViewHolder>(
override fun getItemId(index: Int): Long = index.toLong()
override fun getItemCount(): Int = if (isDataValid) data?.size ?: 0 else 0
override fun getItem(index: Int): Task? = if (isDataValid) data?.get(index) else null
override fun updateUnfilteredData(data: OrderedRealmCollection<Task>?) {
unfilteredData = data
updateData(data)
this.data = data ?: emptyList()
}
override fun onBindViewHolder(holder: VH, position: Int) {
@ -156,12 +77,12 @@ abstract class RealmBaseTasksRecyclerViewAdapter<VH : BaseTaskViewHolder>(
if (taskFilterHelper != null) {
val query = taskFilterHelper.createQuery(unfilteredData)
if (query != null) {
updateData(query.findAll())
data = query.findAll()
}
}
}
override fun getTaskIDAt(position: Int): String {
return data?.get(position)?.id ?: ""
return data[position].id ?: ""
}
}

View file

@ -12,6 +12,7 @@ import com.habitrpg.android.habitica.models.shops.ShopItem
import com.habitrpg.android.habitica.models.tasks.ChecklistItem
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.ui.adapter.BaseRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.viewHolders.ShopItemViewHolder
import com.habitrpg.android.habitica.ui.viewHolders.tasks.RewardViewHolder
import io.reactivex.rxjava3.core.BackpressureStrategy
@ -19,7 +20,7 @@ import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.subjects.PublishSubject
import io.realm.OrderedRealmCollection
class RewardsRecyclerViewAdapter(private var customRewards: OrderedRealmCollection<Task>?, private val layoutResource: Int, private val user: User?) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), TaskRecyclerViewAdapter {
class RewardsRecyclerViewAdapter(private var customRewards: OrderedRealmCollection<Task>?, private val layoutResource: Int, private val user: User?) : BaseRecyclerViewAdapter<Task, RecyclerView.ViewHolder>(), TaskRecyclerViewAdapter {
private var inAppRewards: OrderedRealmCollection<ShopItem>? = null
private val errorButtonEventsSubject = PublishSubject.create<String>()
@ -113,7 +114,7 @@ class RewardsRecyclerViewAdapter(private var customRewards: OrderedRealmCollecti
return rewardCount
}
override fun updateData(tasks: OrderedRealmCollection<Task>?) {
fun updateData(tasks: OrderedRealmCollection<Task>?) {
this.customRewards = tasks
notifyDataSetChanged()
}

View file

@ -5,16 +5,16 @@ import com.habitrpg.android.habitica.models.tasks.ChecklistItem
import com.habitrpg.android.habitica.models.tasks.Task
import io.reactivex.rxjava3.core.Flowable
import io.realm.OrderedRealmCollection
import io.realm.RealmResults
interface TaskRecyclerViewAdapter {
var data: List<Task>
var ignoreUpdates: Boolean
val errorButtonEvents: Flowable<String>
var taskDisplayMode: String
fun updateData(tasks: OrderedRealmCollection<Task>?)
fun filter()
fun notifyItemMoved(adapterPosition: Int, adapterPosition1: Int)

View file

@ -30,7 +30,7 @@ class EquipmentDetailFragment : BaseMainFragment<FragmentRecyclerviewBinding>()
var equippedGear: String? = null
var isCostume: Boolean? = null
private var adapter: EquipmentRecyclerViewAdapter = EquipmentRecyclerViewAdapter(null, true)
private var adapter: EquipmentRecyclerViewAdapter = EquipmentRecyclerViewAdapter()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
@ -59,7 +59,7 @@ class EquipmentDetailFragment : BaseMainFragment<FragmentRecyclerviewBinding>()
binding?.recyclerView?.addItemDecoration(DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL))
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
type?.let { type -> inventoryRepository.getOwnedEquipment(type).firstElement().subscribe({ this.adapter.updateData(it) }, RxErrorHandler.handleEmptyError()) }
type?.let { type -> inventoryRepository.getOwnedEquipment(type).subscribe({ this.adapter.data = it }, RxErrorHandler.handleEmptyError()) }
}
override fun onDestroy() {

View file

@ -214,7 +214,7 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
} else {
items
}
adapter?.updateData(filteredItems)
adapter?.data = filteredItems
}
}
.map { items -> items.mapNotNull { it.key } }
@ -232,7 +232,7 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
}
compositeSubscription.add(inventoryRepository.getPets().subscribe({ adapter?.setExistingPets(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(inventoryRepository.getOwnedPets().firstElement()
compositeSubscription.add(inventoryRepository.getOwnedPets()
.map { ownedMounts ->
val mountMap = mutableMapOf<String, OwnedPet>()
ownedMounts.forEach { mountMap[it.key ?: ""] = it }

View file

@ -32,7 +32,7 @@ class SkillTasksRecyclerViewFragment : BaseFragment<FragmentRecyclerviewBinding>
return FragmentRecyclerviewBinding.inflate(inflater, container, false)
}
var adapter: SkillTasksRecyclerViewAdapter = SkillTasksRecyclerViewAdapter(null, true)
var adapter: SkillTasksRecyclerViewAdapter = SkillTasksRecyclerViewAdapter()
internal var layoutManager: LinearLayoutManager? = null
private val taskSelectionEvents = PublishSubject.create<Task>()
@ -51,7 +51,7 @@ class SkillTasksRecyclerViewFragment : BaseFragment<FragmentRecyclerviewBinding>
val layoutManager = LinearLayoutManager(context)
binding?.recyclerView?.layoutManager = layoutManager
adapter = SkillTasksRecyclerViewAdapter(null, true)
adapter = SkillTasksRecyclerViewAdapter()
compositeSubscription.add(adapter.getTaskSelectionEvents().subscribe({
taskSelectionEvents.onNext(it)
}, RxErrorHandler.handleEmptyError()))
@ -66,7 +66,7 @@ class SkillTasksRecyclerViewFragment : BaseFragment<FragmentRecyclerviewBinding>
tasks = tasks.map { it.where().equalTo("completed", false).findAll() }
}
compositeSubscription.add(tasks.subscribe({
adapter.updateData(it)
adapter.data = it
}, RxErrorHandler.handleEmptyError()))
}
}

View file

@ -78,8 +78,8 @@ class SkillsFragment : BaseMainFragment<FragmentSkillsBinding>() {
adapter?.level = this.user?.stats?.lvl ?: 0
adapter?.specialItems = this.user?.items?.special
user?.let { user ->
Observable.concat(userRepository.getSkills(user).firstElement().toObservable().flatMap { Observable.fromIterable(it) },
userRepository.getSpecialItems(user).firstElement().toObservable().flatMap { Observable.fromIterable(it) })
Observable.concat(userRepository.getSkills(user).toObservable().flatMap { Observable.fromIterable(it) },
userRepository.getSpecialItems(user).toObservable().flatMap { Observable.fromIterable(it) })
.toList()
.subscribe({ skills -> adapter?.setSkillList(skills) }, RxErrorHandler.handleEmptyError())
}

View file

@ -64,7 +64,7 @@ class ChatFragment : BaseFragment<FragmentChatBinding>() {
layoutManager.stackFromEnd = false
binding?.recyclerView?.layoutManager = layoutManager
chatAdapter = ChatRecyclerViewAdapter(null, true, null, true)
chatAdapter = ChatRecyclerViewAdapter(null, true)
chatAdapter?.let {adapter ->
compositeSubscription.add(adapter.getUserLabelClickFlowable().subscribe({ userId ->
FullProfileActivity.open(userId)
@ -194,7 +194,7 @@ class ChatFragment : BaseFragment<FragmentChatBinding>() {
}
private fun setChatMessages(chatMessages: RealmResults<ChatMessage>) {
chatAdapter?.updateData(chatMessages)
chatAdapter?.data = chatMessages
viewModel?.socialRepository?.getUnmanagedCopy(chatMessages)?.let { binding?.chatBarView?.chatMessages = it }
viewModel?.gotNewMessages = true

View file

@ -27,7 +27,7 @@ class PublicGuildsFragment : BaseMainFragment<FragmentRecyclerviewBinding>(), Se
return FragmentRecyclerviewBinding.inflate(inflater, container, false)
}
private var viewAdapter = PublicGuildsRecyclerViewAdapter(null, true)
private var viewAdapter = PublicGuildsRecyclerViewAdapter()
override fun injectFragment(component: UserComponent) {
component.inject(this)
@ -38,10 +38,9 @@ class PublicGuildsFragment : BaseMainFragment<FragmentRecyclerviewBinding>(), Se
binding?.recyclerView?.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(activity)
binding?.recyclerView?.addItemDecoration(androidx.recyclerview.widget.DividerItemDecoration(activity, androidx.recyclerview.widget.DividerItemDecoration.VERTICAL))
viewAdapter = PublicGuildsRecyclerViewAdapter(null, true)
compositeSubscription.add(socialRepository.getGroupMemberships()
.map { it.map { membership -> membership.groupID } }
.subscribeWithErrorHandler({ viewAdapter.setMemberGuildIDs(it) }))
.subscribeWithErrorHandler { viewAdapter.setMemberGuildIDs(it) })
viewAdapter.socialRepository = socialRepository
binding?.recyclerView?.adapter = viewAdapter
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
@ -55,7 +54,6 @@ class PublicGuildsFragment : BaseMainFragment<FragmentRecyclerviewBinding>(), Se
private fun fetchGuilds() {
compositeSubscription.add(this.socialRepository.getPublicGuilds()
.firstElement()
.subscribe({ groups ->
this@PublicGuildsFragment.viewAdapter.setUnfilteredData(groups)
}, RxErrorHandler.handleEmptyError()))

View file

@ -90,7 +90,7 @@ class QuestDetailFragment : BaseMainFragment<FragmentQuestDetailBinding>() {
party = group
quest = group.quest
setQuestParticipants(group.quest?.participants)
compositeSubscription.add(socialRepository.getMember(quest?.leader).firstElement().subscribe({ member ->
compositeSubscription.add(socialRepository.getMember(quest?.leader).subscribe({ member ->
if (context != null && binding?.questLeaderView != null && member != null) {
binding?.questLeaderView?.text = context?.getString(R.string.quest_leader_header, member.displayName)
}

View file

@ -67,7 +67,7 @@ class ChallengeListFragment : BaseFragment<FragmentChallengeslistBinding>(), and
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
challengeAdapter = ChallengesListViewAdapter(null, true, viewUserChallengesOnly, userId)
challengeAdapter = ChallengesListViewAdapter(viewUserChallengesOnly, userId)
challengeAdapter?.getOpenDetailFragmentFlowable()?.subscribe({ openDetailFragment(it) }, RxErrorHandler.handleEmptyError())
?.let { compositeSubscription.add(it) }
@ -127,7 +127,7 @@ class ChallengeListFragment : BaseFragment<FragmentChallengeslistBinding>(), and
challengeRepository.getChallenges()
}
compositeSubscription.add(observable.firstElement().subscribe({ challenges ->
compositeSubscription.add(observable.subscribe({ challenges ->
if (challenges.size == 0) {
retrieveChallengesPage()
}

View file

@ -131,7 +131,6 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
GlobalScope.launch(Dispatchers.Main) {
delay(500)
inventoryRepository.getQuestContent(party.quest?.key ?: "")
.firstElement()
.subscribe({ this@PartyDetailFragment.updateQuestContent(it) }, RxErrorHandler.handleEmptyError())
}
} else {

View file

@ -102,7 +102,7 @@ open class TaskRecyclerViewFragment : BaseFragment<FragmentRefreshRecyclerviewBi
binding?.recyclerView?.adapter = adapter
if (this.classType != null) {
compositeSubscription.add(taskRepository.getTasks(this.classType ?: "", userID).firstElement().subscribe({
compositeSubscription.add(taskRepository.getTasks(this.classType ?: "", userID).subscribe({
this.recyclerAdapter?.updateUnfilteredData(it)
this.recyclerAdapter?.filter()
}, RxErrorHandler.handleEmptyError()))
@ -283,7 +283,7 @@ open class TaskRecyclerViewFragment : BaseFragment<FragmentRefreshRecyclerviewBi
if (Task.TYPE_REWARD == className) {
compositeSubscription.add(taskRepository.getTasks(this.className, userID)
.subscribe({ recyclerAdapter?.updateData(it) }, RxErrorHandler.handleEmptyError()))
.subscribe({ recyclerAdapter?.data = it }, RxErrorHandler.handleEmptyError()))
}
}

View file

@ -126,7 +126,7 @@ open class GroupViewModel : BaseViewModel() {
fun getChatMessages(): Flowable<RealmResults<ChatMessage>> {
return groupIDFlowable
.filterMapEmpty()
.flatMapMaybe { socialRepository.getGroupChat(it).firstElement() }
.flatMap { socialRepository.getGroupChat(it) }
}
fun retrieveGroup(function: (() -> Unit)?) {