Code Cleanup

This commit is contained in:
Phillip Thelen 2021-01-28 11:48:30 +01:00
parent d9bcd3e133
commit ddcd5ed640
45 changed files with 186 additions and 147 deletions

View file

@ -150,7 +150,7 @@ android {
buildConfigField "String", "TESTING_LEVEL", "\"production\""
resConfigs "en", "bg", "de", "en-rGB", "es", "fr", "hr-rHR", "in", "it", "iw", "ja", "ko", "lt", "nl", "pl", "pt-rBR", "pt-rPT", "ru", "tr", "zh", "zh-rTW"
versionCode 2693
versionCode 2694
versionName "3.2"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 783 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 919 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -57,6 +57,18 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/iconViewTeamTask"
android:layout_width="@dimen/task_icon_size"
android:layout_height="@dimen/task_icon_size"
android:scaleType="center"
app:srcCompat="@drawable/task_icon_team"
android:layout_marginEnd="12dp"
app:tint="@color/text_ternary"
android:alpha="0.25"
android:visibility="gone"
app:tintMode="multiply"/>
<ImageView
android:id="@+id/iconViewCalendar"
android:layout_width="@dimen/task_icon_size"

View file

@ -0,0 +1,19 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.habitrpg.android.habitica.TaskActivity">
<item android:id="@+id/action_team_info"
android:title="@string/team_information"
android:icon="@drawable/team_info_icon"
app:showAsAction="collapseActionView|always" />
<item android:id="@+id/action_search"
android:title="@string/search"
android:icon="@drawable/ic_search"
app:showAsAction="collapseActionView|always"
app:actionLayout="@layout/toolbar_search" />
<item android:id="@+id/action_filter"
android:icon="@drawable/ic_action_filter_list"
android:title="@string/filter"
app:showAsAction="ifRoom" />
</menu>

View file

@ -1137,4 +1137,5 @@
<string name="six_months_one_time">6 month one-time subscription</string>
<string name="twelve_months_one_time">12 month one-time subscription</string>
<string name="sidebar_teams">Teams</string>
<string name="team_information">Team Information</string>
</resources>

View file

@ -22,15 +22,15 @@ interface UserRepository : BaseRepository {
fun getUser(): Flowable<User>
fun getUser(userID: String): Flowable<User>
fun updateUser(user: User?, updateData: Map<String, Any>): Flowable<User>
fun updateUser(user: User?, key: String, value: Any): Flowable<User>
fun updateUser(updateData: Map<String, Any>): Flowable<User>
fun updateUser(key: String, value: Any): Flowable<User>
fun retrieveUser(withTasks: Boolean): Flowable<User>
fun retrieveUser(withTasks: Boolean = false, forced: Boolean = false, overrideExisting: Boolean = false): Flowable<User>
fun revive(user: User): Flowable<User>
fun resetTutorial(user: User?)
fun resetTutorial()
fun sleep(user: User): Flowable<User>
@ -49,7 +49,7 @@ interface UserRepository : BaseRepository {
fun changeClass(selectedClass: String): Flowable<User>
fun unlockPath(user: User?, customization: Customization): Flowable<UnlockResponse>
fun unlockPath(user: User, set: CustomizationSet): Flowable<UnlockResponse>
fun unlockPath(set: CustomizationSet): Flowable<UnlockResponse>
fun runCron(tasks: MutableList<Task>)
fun runCron()
@ -60,7 +60,7 @@ interface UserRepository : BaseRepository {
fun changeCustomDayStart(dayStartTime: Int): Flowable<User>
fun updateLanguage(user: User?, languageCode: String): Flowable<User>
fun updateLanguage(languageCode: String): Flowable<User>
fun resetAccount(): Flowable<User>
fun deleteAccount(password: String): Flowable<Void>
@ -72,7 +72,7 @@ interface UserRepository : BaseRepository {
fun updatePassword(oldPassword: String, newPassword: String, newPasswordConfirmation: String): Flowable<Void>
fun verifyUsername(username: String): Flowable<VerifyUsernameResponse>
fun allocatePoint(user: User?, stat: String): Flowable<Stats>
fun allocatePoint(stat: String): Flowable<Stats>
fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable<Stats>
fun useCustomization(user: User?, type: String, category: String?, identifier: String): Flowable<User>

View file

@ -35,14 +35,16 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
override fun getUser(userID: String): Flowable<User> = localRepository.getUser(userID)
override fun updateUser(user: User?, updateData: Map<String, Any>): Flowable<User> {
return apiClient.updateUser(updateData).map { newUser -> mergeUser(user, newUser) }
override fun updateUser(updateData: Map<String, Any>): Flowable<User> {
return Flowable.zip(apiClient.updateUser(updateData),
localRepository.getUser(userID).firstElement().toFlowable(),
{ newUser, user -> mergeUser(user, newUser) })
}
override fun updateUser(user: User?, key: String, value: Any): Flowable<User> {
override fun updateUser(key: String, value: Any): Flowable<User> {
val updateData = HashMap<String, Any>()
updateData[key] = value
return updateUser(user, updateData)
return updateUser(updateData)
}
override fun retrieveUser(withTasks: Boolean): Flowable<User> =
@ -70,7 +72,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
val timeZone = calendar.timeZone
val offset = -TimeUnit.MINUTES.convert(timeZone.getOffset(calendar.timeInMillis).toLong(), TimeUnit.MILLISECONDS)
if (offset.toInt() != user.preferences?.timezoneOffset ?: 0) {
return@flatMap updateUser(user, "preferences.timezoneOffset", offset.toString())
return@flatMap updateUser("preferences.timezoneOffset", offset.toString())
} else {
return@flatMap Flowable.just(user)
}
@ -83,7 +85,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
override fun revive(user: User): Flowable<User> =
apiClient.revive().map { newUser -> mergeUser(user, newUser) }
override fun resetTutorial(user: User?) {
override fun resetTutorial() {
localRepository.getTutorialSteps()
.firstElement()
.map<Map<String, Any>> { tutorialSteps ->
@ -93,7 +95,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
}
updateData
}
.flatMap { updateData -> updateUser(user, updateData).firstElement() }
.flatMap { updateData -> updateUser(updateData).firstElement() }
.subscribe({ }, RxErrorHandler.handleEmptyError())
}
@ -142,19 +144,17 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
if (path.last() == '.' && customization.type == "background") {
path += user?.preferences?.background
}
return apiClient.unlockPath(path)
.doOnNext { unlockResponse ->
if (user == null) return@doOnNext
val copiedUser = localRepository.getUnmanagedCopy(user)
return Flowable.zip(apiClient.unlockPath(path), localRepository.getUser(userID).firstElement().toFlowable(), { unlockResponse, copiedUser ->
copiedUser.preferences = unlockResponse.preferences
copiedUser.purchased = unlockResponse.purchased
copiedUser.items = unlockResponse.items
copiedUser.balance = copiedUser.balance - (customization.price ?: 0) / 4.0
localRepository.saveUser(copiedUser, false)
}
unlockResponse
})
}
override fun unlockPath(user: User, set: CustomizationSet): Flowable<UnlockResponse> {
override fun unlockPath(set: CustomizationSet): Flowable<UnlockResponse> {
var path = ""
for (customization in set.customizations) {
path = path + "," + customization.path
@ -163,15 +163,14 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
return Flowable.just(null)
}
path = path.substring(1)
return apiClient.unlockPath(path)
.doOnNext { unlockResponse ->
val copiedUser = localRepository.getUnmanagedCopy(user)
return Flowable.zip(apiClient.unlockPath(path), localRepository.getUser(userID).firstElement().toFlowable(), { unlockResponse, copiedUser ->
copiedUser.preferences = unlockResponse.preferences
copiedUser.purchased = unlockResponse.purchased
copiedUser.items = unlockResponse.items
copiedUser.balance = copiedUser.balance - set.price / 4.0
localRepository.saveUser(copiedUser, false)
}
unlockResponse
})
}
override fun runCron() {
@ -200,8 +199,8 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
return apiClient.changeCustomDayStart(updateObject)
}
override fun updateLanguage(user: User?, languageCode: String): Flowable<User> {
return updateUser(user, "preferences.language", languageCode)
override fun updateLanguage(languageCode: String): Flowable<User> {
return updateUser("preferences.language", languageCode)
.doOnNext { apiClient.setLanguageCode(languageCode) }
}
@ -238,30 +237,26 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
override fun updatePassword(oldPassword: String, newPassword: String, newPasswordConfirmation: String): Flowable<Void> =
apiClient.updatePassword(oldPassword.trim(), newPassword.trim(), newPasswordConfirmation.trim())
override fun allocatePoint(user: User?, stat: String): Flowable<Stats> {
if (user != null && user.isManaged) {
localRepository.modify(user) { liveUser ->
when (stat) {
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()
}
liveUser.stats?.points = liveUser.stats?.points?.dec()
override fun allocatePoint(stat: String): Flowable<Stats> {
localRepository.getUser(userID).subscribe( { liveUser ->
when (stat) {
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()
}
}
liveUser.stats?.points = liveUser.stats?.points?.dec()
}, RxErrorHandler.handleEmptyError())
return apiClient.allocatePoint(stat)
.doOnNext { stats ->
if (user != null && user.isManaged) {
localRepository.modify(user) { liveUser ->
/*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
}
}
}*/
}
}
@ -325,7 +320,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
if (category != null) {
updatePath = "$updatePath.$category"
}
return updateUser(user, updatePath, identifier)
return updateUser(updatePath, identifier)
}
override fun retrieveAchievements(): Flowable<List<Achievement>> {

View file

@ -171,7 +171,7 @@ open class Task : RealmObject, BaseObject, Parcelable {
get() = this.checklist?.size != this.completedChecklistCount
val isGroupTask: Boolean
get() = group?.approvalApproved == true
get() = group?.groupID?.isNotBlank() == true
val isPendingApproval: Boolean
get() = (group?.approvalRequired == true && group?.approvalRequested == true && group?.approvalApproved == false)

View file

@ -1,14 +1,25 @@
package com.habitrpg.android.habitica.models.tasks
import com.google.gson.annotations.SerializedName
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import java.util.*
open class TaskGroupPlan : RealmObject() {
@PrimaryKey
internal var taskID: String? = null
@SerializedName("id")
var groupID: String? = null
var managerNotes: String? = null
var sharedCompletion: String? = null
var assignedDate: Date? = null
var assigningUsername: String? = null
var assignedUsers: RealmList<String> = RealmList()
var approvalRequested: Boolean = false
var approvalApproved: Boolean = false
var approvalRequired: Boolean = false

View file

@ -82,7 +82,7 @@ class FixCharacterValuesActivity: BaseActivity() {
userInfo["stats.mp"] = binding.manaEditText.getDoubleValue()
userInfo["stats.lvl"] = binding.levelEditText.getDoubleValue().toInt()
userInfo["achievements.streak"] = binding.streakEditText.getDoubleValue().toInt()
compositeSubscription.add(repository.updateUser(user, userInfo)
compositeSubscription.add(repository.updateUser(userInfo)
.flatMap { repository.retrieveUser(false, true, true) }
.subscribe({}, RxErrorHandler.handleEmptyError(), {
progressDialog.dismiss()

View file

@ -446,12 +446,12 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
compositeSubscription.add(inventoryRepository.getQuestContent(user?.party?.quest?.completed ?: "").firstElement().subscribe({
QuestCompletedDialog.showWithQuest(this, it)
userRepository.updateUser(user, "party.quest.completed", "").subscribe({}, RxErrorHandler.handleEmptyError())
userRepository.updateUser("party.quest.completed", "").subscribe({}, RxErrorHandler.handleEmptyError())
}, RxErrorHandler.handleEmptyError()))
}
if (user?.flags?.welcomed == false) {
compositeSubscription.add(userRepository.updateUser(user, "flags.welcomed", true).subscribe({}, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(userRepository.updateUser("flags.welcomed", true).subscribe({}, RxErrorHandler.handleEmptyError()))
}
if (appConfigManager.enableAdventureGuide()) {
@ -666,10 +666,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
}
override fun onTutorialCompleted(step: TutorialStep) {
val path = "flags.tutorial." + step.tutorialGroup + "." + step.identifier
val updateData = HashMap<String, Any>()
updateData[path] = true
compositeSubscription.add(userRepository.updateUser(user, updateData)
compositeSubscription.add(userRepository.updateUser("flags.tutorial." + step.tutorialGroup + "." + step.identifier, true)
.subscribe({ }, RxErrorHandler.handleEmptyError()))
binding.overlayFrameLayout.removeView(this.activeTutorialView)
this.removeActiveTutorialView()

View file

@ -203,7 +203,7 @@ class SetupActivity : BaseActivity(), ViewPager.OnPageChangeListener {
additionalData["status"] = "completed"
AmplitudeManager.sendEvent("setup", AmplitudeManager.EVENT_CATEGORY_BEHAVIOUR, AmplitudeManager.EVENT_HITTYPE_EVENT, additionalData)
compositeSubscription.add(userRepository.updateUser(user, "flags.welcomed", true).subscribe({
compositeSubscription.add(userRepository.updateUser("flags.welcomed", true).subscribe({
if (!compositeSubscription.isDisposed) {
compositeSubscription.dispose()
}
@ -227,7 +227,7 @@ class SetupActivity : BaseActivity(), ViewPager.OnPageChangeListener {
}
private fun confirmNames(displayName: String, username: String) {
compositeSubscription.add(userRepository.updateUser(null, "profile.name", displayName)
compositeSubscription.add(userRepository.updateUser("profile.name", displayName)
.flatMap { userRepository.updateLoginName(username).toFlowable() }
.subscribe({ }, RxErrorHandler.handleEmptyError()))
}

View file

@ -105,7 +105,7 @@ class VerifyUsernameActivity: BaseActivity() {
private fun confirmNames() {
binding.confirmUsernameButton.isClickable = false
compositeSubscription.add(userRepository.updateUser(null, "profile.name", binding.displayNameEditText.text.toString())
compositeSubscription.add(userRepository.updateUser("profile.name", binding.displayNameEditText.text.toString())
.flatMap { userRepository.updateLoginName(binding.usernameEditText.text.toString()).toFlowable() }
.doOnComplete { showConfirmationAndFinish() }
.doOnEach { binding.confirmUsernameButton.isClickable = true }

View file

@ -11,7 +11,6 @@ import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.InventoryRepository
import com.habitrpg.android.habitica.databinding.FragmentRefreshRecyclerviewBinding
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.ui.adapter.AchievementsAdapter
import com.habitrpg.android.habitica.ui.helpers.ToolbarColorHelper

View file

@ -44,6 +44,6 @@ class NewsFragment : BaseMainFragment<FragmentNewsBinding>() {
override fun onResume() {
super.onResume()
compositeSubscription.add(userRepository.updateUser(user, "flags.newStuff", false).subscribeWithErrorHandler({}))
compositeSubscription.add(userRepository.updateUser("flags.newStuff", false).subscribeWithErrorHandler({}))
}
}

View file

@ -89,11 +89,11 @@ class StatsFragment: BaseMainFragment<FragmentStatsBinding>() {
binding?.distributeTaskHelpButton?.setImageBitmap(HabiticaIconsHelper.imageOfInfoIcon(color))
}
compositeSubscription.add(userRepository.getUser(userId).subscribe({
compositeSubscription.add(userRepository.getUser().subscribe({ user ->
canAllocatePoints = user?.stats?.lvl ?: 0 >= 10 && user?.stats?.points ?: 0 > 0
binding?.unlockAtLevel?.visibility = if (it?.stats?.lvl ?: 0 < 10) View.VISIBLE else View.GONE
updateStats(it)
updateAttributePoints(it)
binding?.unlockAtLevel?.visibility = if (user.stats?.lvl ?: 0 < 10) View.VISIBLE else View.GONE
updateStats(user)
updateAttributePoints(user)
}, RxErrorHandler.handleEmptyError()))
binding?.distributeEvenlyButton?.setOnCheckedChangeListener { _, isChecked ->
@ -113,7 +113,7 @@ class StatsFragment: BaseMainFragment<FragmentStatsBinding>() {
}
binding?.automaticAllocationSwitch?.setOnCheckedChangeListener{ _, isChecked ->
userRepository.updateUser(user, "preferences.automaticAllocation", isChecked).subscribe({}, RxErrorHandler.handleEmptyError())
userRepository.updateUser("preferences.automaticAllocation", isChecked).subscribe({}, RxErrorHandler.handleEmptyError())
}
binding?.strengthStatsView?.allocateAction = { allocatePoint(Stats.STRENGTH) }
@ -140,7 +140,7 @@ class StatsFragment: BaseMainFragment<FragmentStatsBinding>() {
}
private fun changeAutoAllocationMode(allocationMode: String) {
compositeSubscription.add(userRepository.updateUser(user, "preferences.allocationMode", allocationMode).subscribe({}, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(userRepository.updateUser("preferences.allocationMode", allocationMode).subscribe({}, RxErrorHandler.handleEmptyError()))
binding?.distributeEvenlyButton?.isChecked = allocationMode == Stats.AUTO_ALLOCATE_FLAT
binding?.distributeClassButton?.isChecked = allocationMode == Stats.AUTO_ALLOCATE_CLASSBASED
binding?.distributeTaskButton?.isChecked = allocationMode == Stats.AUTO_ALLOCATE_TASKBASED
@ -155,7 +155,7 @@ class StatsFragment: BaseMainFragment<FragmentStatsBinding>() {
}
private fun allocatePoint(stat: String) {
compositeSubscription.add(userRepository.allocatePoint(user, stat).subscribe({ }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(userRepository.allocatePoint(stat).subscribe({ }, RxErrorHandler.handleEmptyError()))
}
private fun updateAttributePoints(user: User) {
@ -203,8 +203,8 @@ class StatsFragment: BaseMainFragment<FragmentStatsBinding>() {
component.inject(this)
}
private fun updateStats(currentUser: User) {
val levelStat = min((currentUser.stats?.lvl ?: 0) / 2.0f, 50f).toInt()
private fun updateStats(user: User) {
val levelStat = min((user.stats?.lvl ?: 0) / 2.0f, 50f).toInt()
totalStrength = levelStat
totalIntelligence = levelStat
@ -216,25 +216,25 @@ class StatsFragment: BaseMainFragment<FragmentStatsBinding>() {
binding?.constitutionStatsView?.levelValue = levelStat
binding?.perceptionStatsView?.levelValue = levelStat
totalStrength += currentUser.stats?.buffs?.str?.toInt() ?: 0
totalIntelligence += currentUser.stats?.buffs?._int?.toInt() ?: 0
totalConstitution += currentUser.stats?.buffs?.con?.toInt() ?: 0
totalPerception += currentUser.stats?.buffs?.per?.toInt() ?: 0
binding?.strengthStatsView?.buffValue = currentUser.stats?.buffs?.str?.toInt() ?: 0
binding?.intelligenceStatsView?.buffValue = currentUser.stats?.buffs?._int?.toInt() ?: 0
binding?.constitutionStatsView?.buffValue = currentUser.stats?.buffs?.con?.toInt() ?: 0
binding?.perceptionStatsView?.buffValue = currentUser.stats?.buffs?.per?.toInt() ?: 0
totalStrength += user.stats?.buffs?.str?.toInt() ?: 0
totalIntelligence += user.stats?.buffs?._int?.toInt() ?: 0
totalConstitution += user.stats?.buffs?.con?.toInt() ?: 0
totalPerception += user.stats?.buffs?.per?.toInt() ?: 0
binding?.strengthStatsView?.buffValue = user.stats?.buffs?.str?.toInt() ?: 0
binding?.intelligenceStatsView?.buffValue = user.stats?.buffs?._int?.toInt() ?: 0
binding?.constitutionStatsView?.buffValue = user.stats?.buffs?.con?.toInt() ?: 0
binding?.perceptionStatsView?.buffValue = user.stats?.buffs?.per?.toInt() ?: 0
totalStrength += currentUser.stats?.strength ?: 0
totalIntelligence += currentUser.stats?.intelligence ?: 0
totalConstitution += currentUser.stats?.constitution ?: 0
totalPerception += currentUser.stats?.per ?: 0
binding?.strengthStatsView?.allocatedValue = currentUser.stats?.strength ?: 0
binding?.intelligenceStatsView?.allocatedValue = currentUser.stats?.intelligence ?: 0
binding?.constitutionStatsView?.allocatedValue = currentUser.stats?.constitution ?: 0
binding?.perceptionStatsView?.allocatedValue = currentUser.stats?.per ?: 0
totalStrength += user.stats?.strength ?: 0
totalIntelligence += user.stats?.intelligence ?: 0
totalConstitution += user.stats?.constitution ?: 0
totalPerception += user.stats?.per ?: 0
binding?.strengthStatsView?.allocatedValue = user.stats?.strength ?: 0
binding?.intelligenceStatsView?.allocatedValue = user.stats?.intelligence ?: 0
binding?.constitutionStatsView?.allocatedValue = user.stats?.constitution ?: 0
binding?.perceptionStatsView?.allocatedValue = user.stats?.per ?: 0
val outfit = currentUser.items?.gear?.equipped
val outfit = user.items?.gear?.equipped
val outfitList = ArrayList<String>()
outfit?.let { thisOutfit ->
outfitList.add(thisOutfit.armor)

View file

@ -55,24 +55,14 @@ class AvatarCustomizationFragment : BaseMainFragment<FragmentRecyclerviewBinding
.subscribe({ }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(adapter.getUnlockCustomizationEvents()
.flatMap { customization ->
val user = this.user
if (user != null) {
userRepository.unlockPath(user, customization)
} else {
Flowable.empty()
}
}
.flatMap { userRepository.retrieveUser(withTasks = false, forced = true) }
.flatMap { inventoryRepository.retrieveInAppRewards() }
.subscribe({ }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(adapter.getUnlockSetEvents()
.flatMap { set ->
val user = this.user
if (user != null) {
userRepository.unlockPath(user, set)
} else {
Flowable.empty()
}
userRepository.unlockPath(set)
}
.flatMap { userRepository.retrieveUser(withTasks = false, forced = true) }
.flatMap { inventoryRepository.retrieveInAppRewards() }

View file

@ -54,12 +54,7 @@ class AvatarEquipmentFragment : BaseMainFragment<FragmentRecyclerviewBinding>()
.subscribe({ }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(adapter.getUnlockSetEvents()
.flatMap { set ->
val user = this.user
if (user != null) {
userRepository.unlockPath(user, set)
} else {
Flowable.empty()
}
userRepository.unlockPath(set)
}
.subscribe({ }, RxErrorHandler.handleEmptyError()))
return super.onCreateView(inflater, container, savedInstanceState)

View file

@ -94,10 +94,8 @@ class AvatarOverviewFragment : BaseMainFragment<FragmentAvatarOverviewBinding>()
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
val newSize: String = if (position == 0) "slim" else "broad"
if (this.user?.isValid == true && this.user?.preferences?.size != newSize) {
compositeSubscription.add(userRepository.updateUser(user, "preferences.size", newSize)
compositeSubscription.add(userRepository.updateUser("preferences.size", newSize)
.subscribe({ }, RxErrorHandler.handleEmptyError()))
}
}
override fun onNothingSelected(parent: AdapterView<*>) { /* no-on */ }

View file

@ -49,8 +49,8 @@ class EquipmentOverviewFragment : BaseMainFragment<FragmentEquipmentOverviewBind
binding?.autoEquipSwitch?.isChecked = user?.preferences?.autoEquip ?: false
binding?.costumeSwitch?.isChecked = user?.preferences?.costume ?: false
binding?.autoEquipSwitch?.setOnCheckedChangeListener { _, isChecked -> userRepository.updateUser(user, "preferences.autoEquip", isChecked).subscribe({ }, RxErrorHandler.handleEmptyError()) }
binding?.costumeSwitch?.setOnCheckedChangeListener { _, isChecked -> userRepository.updateUser(user, "preferences.costume", isChecked).subscribe({ }, RxErrorHandler.handleEmptyError()) }
binding?.autoEquipSwitch?.setOnCheckedChangeListener { _, isChecked -> userRepository.updateUser("preferences.autoEquip", isChecked).subscribe({ }, RxErrorHandler.handleEmptyError()) }
binding?.costumeSwitch?.setOnCheckedChangeListener { _, isChecked -> userRepository.updateUser("preferences.costume", isChecked).subscribe({ }, RxErrorHandler.handleEmptyError()) }
user?.items?.gear?.let {
updateGearData(it)

View file

@ -73,7 +73,7 @@ class EmailNotificationsPreferencesFragment : BasePreferencesFragment(), SharedP
else -> null
}
if (pathKey != null) {
compositeSubscription.add(userRepository.updateUser(user, "preferences.emailNotifications.$pathKey", sharedPreferences.getBoolean(key, false)).subscribe({ }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(userRepository.updateUser("preferences.emailNotifications.$pathKey", sharedPreferences.getBoolean(key, false)).subscribe({ }, RxErrorHandler.handleEmptyError()))
}
}
}

View file

@ -202,7 +202,7 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
return
}
userRepository.updateLanguage(user, languageHelper.languageCode ?: "en")
userRepository.updateLanguage(languageHelper.languageCode ?: "en")
.flatMap { contentRepository.retrieveContent(context,true) }
.subscribe({ }, RxErrorHandler.handleEmptyError())
@ -213,7 +213,7 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
"audioTheme" -> {
val newAudioTheme = sharedPreferences.getString(key, "off")
if (newAudioTheme != null) {
compositeSubscription.add(userRepository.updateUser(user, "preferences.sound", newAudioTheme)
compositeSubscription.add(userRepository.updateUser("preferences.sound", newAudioTheme)
.subscribe({ }, RxErrorHandler.handleEmptyError()))
soundManager.soundTheme = newAudioTheme
soundManager.preloadAllFiles()
@ -227,7 +227,7 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
val activity = activity as? PrefsActivity ?: return
activity.reload()
}
"dailyDueDefaultView" -> userRepository.updateUser(user, "preferences.dailyDueDefaultView", sharedPreferences.getBoolean(key, false))
"dailyDueDefaultView" -> userRepository.updateUser("preferences.dailyDueDefaultView", sharedPreferences.getBoolean(key, false))
.subscribe({ }, RxErrorHandler.handleEmptyError())
"server_url" -> {
apiClient.updateServerUrl(sharedPreferences.getString(key, ""))
@ -244,7 +244,7 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
"disablePMs" -> {
val isDisabled = sharedPreferences.getBoolean("disablePMs", false)
if (user?.inbox?.optOut != isDisabled) {
compositeSubscription.add(userRepository.updateUser(user, "inbox.optOut", isDisabled)
compositeSubscription.add(userRepository.updateUser("inbox.optOut", isDisabled)
.subscribe({ }, RxErrorHandler.handleEmptyError()))
}
}

View file

@ -58,21 +58,21 @@ class ProfilePreferencesFragment: BasePreferencesFragment(), SharedPreferences.O
val observable: Flowable<User>? = when (key) {
"display_name" -> {
if (newValue != user?.profile?.name) {
userRepository.updateUser(user, "profile.name", newValue)
userRepository.updateUser("profile.name", newValue)
} else {
null
}
}
"photo_url" -> {
if (newValue != user?.profile?.imageUrl) {
userRepository.updateUser(user, "profile.imageUrl", newValue)
userRepository.updateUser("profile.imageUrl", newValue)
} else {
null
}
}
"about" -> {
if (newValue != user?.profile?.blurb) {
userRepository.updateUser(user, "profile.blurb", newValue)
userRepository.updateUser("profile.blurb", newValue)
} else {
null
}

View file

@ -75,7 +75,7 @@ class PushNotificationsPreferencesFragment : BasePreferencesFragment(), SharedPr
else -> null
}
if (pathKey != null) {
compositeSubscription.add(userRepository.updateUser(user, "preferences.pushNotifications.$pathKey", sharedPreferences.getBoolean(key, false)).subscribe({ }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(userRepository.updateUser("preferences.pushNotifications.$pathKey", sharedPreferences.getBoolean(key, false)).subscribe({ }, RxErrorHandler.handleEmptyError()))
}
}
}

View file

@ -56,7 +56,7 @@ class AvatarSetupFragment : BaseFragment<FragmentSetupAvatarBinding>() {
this.adapter = CustomizationSetupAdapter()
this.adapter?.userSize = this.user?.preferences?.size ?: "slim"
adapter?.updateUserEvents?.flatMap { userRepository.updateUser(user, it) }?.subscribeWithErrorHandler {}?.let { compositeSubscription.add(it) }
adapter?.updateUserEvents?.flatMap { userRepository.updateUser(it) }?.subscribeWithErrorHandler {}?.let { compositeSubscription.add(it) }
adapter?.equipGearEvents?.flatMap { inventoryRepository.equip(user, "equipped", it) }?.subscribeWithErrorHandler {}?.let { compositeSubscription.add(it) }
this.adapter?.user = this.user
@ -185,7 +185,7 @@ class AvatarSetupFragment : BaseFragment<FragmentSetupAvatarBinding>() {
updateData["preferences.hair.bangs"] = chooseRandomKey(customizationRepository.getCustomizations(SetupCustomizationRepository.CATEGORY_HAIR, SetupCustomizationRepository.SUBCATEGORY_BANGS, user), false)
updateData["preferences.hair.flower"] = chooseRandomKey(customizationRepository.getCustomizations(SetupCustomizationRepository.CATEGORY_EXTRAS, SetupCustomizationRepository.SUBCATEGORY_FLOWER, user), true)
updateData["preferences.chair"] = chooseRandomKey(customizationRepository.getCustomizations(SetupCustomizationRepository.CATEGORY_EXTRAS, SetupCustomizationRepository.SUBCATEGORY_WHEELCHAIR, user), true)
compositeSubscription.add(userRepository.updateUser(user, updateData).subscribeWithErrorHandler({}))
compositeSubscription.add(userRepository.updateUser(updateData).subscribeWithErrorHandler({}))
}
@Suppress("ReturnCount")

View file

@ -51,7 +51,7 @@ class InboxOverviewFragment : BaseMainFragment<FragmentInboxBinding>(), androidx
binding?.inboxRefreshLayout?.setOnRefreshListener(this)
compositeSubscription.add(userRepository.getUser().map { user?.inbox?.optOut ?: false }.distinctUntilChanged().subscribe {
compositeSubscription.add(userRepository.getUser().map { it.inbox?.optOut ?: false }.distinctUntilChanged().subscribe {
binding?.optOutView?.visibility = if (it) View.VISIBLE else View.GONE
})

View file

@ -125,7 +125,7 @@ class QuestDetailFragment : BaseMainFragment<FragmentQuestDetailBinding>() {
}
private fun showParticipatantButtons(): Boolean {
return if (user == null || user?.party == null || user?.party?.quest == null) {
return if (user?.party?.quest == null) {
false
} else !isQuestActive && user?.party?.quest?.RSVPNeeded == true
}

View file

@ -79,10 +79,6 @@ class TavernFragment : BaseMainFragment<FragmentViewpagerBinding>() {
private fun setViewPagerAdapter() {
val fragmentManager = childFragmentManager
if (this.user == null) {
return
}
binding?.viewPager?.adapter = object : FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItem(position: Int): Fragment {
return when (position) {

View file

@ -185,9 +185,6 @@ class PartyFragment : BaseMainFragment<FragmentViewpagerBinding>() {
private fun setViewPagerAdapter() {
val fragmentManager = childFragmentManager
if (this.user == null) {
return
}
viewPagerAdapter = object : FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {

View file

@ -63,7 +63,7 @@ class SupportMainFragment : BaseMainFragment<FragmentSupportMainBinding>() {
}.subscribe())
binding?.resetTutorialButton?.setOnClickListener {
userRepository.resetTutorial(user)
userRepository.resetTutorial()
}
}

View file

@ -1,6 +1,7 @@
package com.habitrpg.android.habitica.ui.fragments.tasks
import android.content.Context
import android.content.Intent
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import android.util.TypedValue
@ -30,6 +31,7 @@ import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.models.user.User
import com.habitrpg.android.habitica.modules.AppModule
import com.habitrpg.android.habitica.ui.activities.MainActivity
import com.habitrpg.android.habitica.ui.activities.TaskFormActivity
import com.habitrpg.android.habitica.ui.adapter.tasks.*
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
@ -44,6 +46,7 @@ import javax.inject.Inject
import javax.inject.Named
open class TaskRecyclerViewFragment : BaseFragment<FragmentRefreshRecyclerviewBinding>(), androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener {
internal var canEditTasks: Boolean = true
override var binding: FragmentRefreshRecyclerviewBinding? = null
override fun createBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRefreshRecyclerviewBinding {
@ -401,6 +404,21 @@ open class TaskRecyclerViewFragment : BaseFragment<FragmentRefreshRecyclerviewBi
}
private fun openTaskForm(task: Task) {
if (Date().time - (TasksFragment.lastTaskFormOpen?.time ?: 0) < 2000 || !task.isValid || !canEditTasks) {
return
}
val bundle = Bundle()
bundle.putString(TaskFormActivity.TASK_TYPE_KEY, task.type)
bundle.putString(TaskFormActivity.TASK_ID_KEY, task.id)
bundle.putDouble(TaskFormActivity.TASK_VALUE_KEY, task.value)
val intent = Intent(activity, TaskFormActivity::class.java)
intent.putExtras(bundle)
TasksFragment.lastTaskFormOpen = Date()
if (isAdded) {
startActivityForResult(intent, TasksFragment.TASK_UPDATED_RESULT)
}
}
companion object {

View file

@ -21,6 +21,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.models.user.User
import com.habitrpg.android.habitica.modules.AppModule
import com.habitrpg.android.habitica.ui.activities.TaskFormActivity
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
import com.habitrpg.android.habitica.ui.views.navigation.HabiticaBottomNavigationViewListener
@ -28,6 +29,7 @@ import com.habitrpg.android.habitica.ui.views.tasks.TaskFilterDialog
import io.reactivex.rxjava3.disposables.Disposable
import java.util.*
import javax.inject.Inject
import javax.inject.Named
import kotlin.collections.ArrayList
@ -39,6 +41,8 @@ class TasksFragment : BaseMainFragment<FragmentViewpagerBinding>(), SearchView.O
return FragmentViewpagerBinding.inflate(inflater, container, false)
}
@field:[Inject Named(AppModule.NAMED_USER_ID)]
lateinit var userID: String
@Inject
lateinit var taskFilterHelper: TaskFilterHelper
@Inject
@ -158,10 +162,7 @@ class TasksFragment : BaseMainFragment<FragmentViewpagerBinding>(), SearchView.O
context?.let {
var disposable: Disposable? = null
val dialog = TaskFilterDialog(it, HabiticaBaseApplication.userComponent)
if (user != null) {
dialog.setTags(user?.tags?.createSnapshot() ?: emptyList())
disposable = tagRepository.getTags(user?.id ?: "").subscribe({ tagsList -> dialog.setTags(tagsList)}, RxErrorHandler.handleEmptyError())
}
disposable = tagRepository.getTags().subscribe({ tagsList -> dialog.setTags(tagsList)}, RxErrorHandler.handleEmptyError())
dialog.setActiveTags(taskFilterHelper.tags)
if (activeFragment != null) {
val taskType = activeFragment?.classType
@ -204,10 +205,10 @@ class TasksFragment : BaseMainFragment<FragmentViewpagerBinding>(), SearchView.O
val fragment: TaskRecyclerViewFragment = when (position) {
0 -> TaskRecyclerViewFragment.newInstance(context, Task.TYPE_HABIT)
1 -> TaskRecyclerViewFragment.newInstance(context, Task.TYPE_DAILY)
3 -> RewardsRecyclerviewFragment.newInstance(context, Task.TYPE_REWARD)
3 -> RewardsRecyclerviewFragment.newInstance(context, Task.TYPE_REWARD, true)
else -> TaskRecyclerViewFragment.newInstance(context, Task.TYPE_TODO)
}
fragment.ownerID = user?.id ?: ""
fragment.ownerID = userID
fragment.refreshAction = {
compositeSubscription.add(userRepository.retrieveUser(true, true)
.doOnTerminate {

View file

@ -7,6 +7,7 @@ import android.os.Bundle
import android.view.*
import androidx.appcompat.widget.SearchView
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import androidx.fragment.app.FragmentPagerAdapter
import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.R
@ -15,10 +16,7 @@ import com.habitrpg.android.habitica.data.TagRepository
import com.habitrpg.android.habitica.databinding.FragmentViewpagerBinding
import com.habitrpg.android.habitica.extensions.getThemeColor
import com.habitrpg.android.habitica.extensions.setTintWith
import com.habitrpg.android.habitica.helpers.AmplitudeManager
import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.helpers.TaskFilterHelper
import com.habitrpg.android.habitica.helpers.*
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.ui.activities.TaskFormActivity
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
@ -120,7 +118,7 @@ class TeamBoardFragment : BaseMainFragment<FragmentViewpagerBinding>(), SearchVi
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_main_activity, menu)
inflater.inflate(R.menu.menu_team_board, menu)
filterMenuItem = menu.findItem(R.id.action_filter)
updateFilterIcon()
@ -165,6 +163,10 @@ class TeamBoardFragment : BaseMainFragment<FragmentViewpagerBinding>(), SearchVi
refresh()
true
}
R.id.action_team_info -> {
MainNavigationController.navigate(R.id.guildFragment, bundleOf(Pair("groupID", teamID)))
true
}
else -> super.onOptionsItemSelected(item)
}
}
@ -173,10 +175,7 @@ class TeamBoardFragment : BaseMainFragment<FragmentViewpagerBinding>(), SearchVi
context?.let {
var disposable: Disposable? = null
val dialog = TaskFilterDialog(it, HabiticaBaseApplication.userComponent)
if (user != null) {
dialog.setTags(user?.tags?.createSnapshot() ?: emptyList())
disposable = tagRepository.getTags(user?.id ?: "").subscribe({ tagsList -> dialog.setTags(tagsList)}, RxErrorHandler.handleEmptyError())
}
disposable = tagRepository.getTags().subscribe({ tagsList -> dialog.setTags(tagsList)}, RxErrorHandler.handleEmptyError())
dialog.setActiveTags(taskFilterHelper.tags)
if (activeFragment != null) {
val taskType = activeFragment?.classType
@ -219,10 +218,11 @@ class TeamBoardFragment : BaseMainFragment<FragmentViewpagerBinding>(), SearchVi
val fragment: TaskRecyclerViewFragment = when (position) {
0 -> TaskRecyclerViewFragment.newInstance(context, Task.TYPE_HABIT)
1 -> TaskRecyclerViewFragment.newInstance(context, Task.TYPE_DAILY)
3 -> RewardsRecyclerviewFragment.newInstance(context, Task.TYPE_REWARD)
3 -> RewardsRecyclerviewFragment.newInstance(context, Task.TYPE_REWARD, false)
else -> TaskRecyclerViewFragment.newInstance(context, Task.TYPE_TODO)
}
fragment.ownerID = teamID
fragment.canEditTasks = false
fragment.refreshAction = {
compositeSubscription.add(userRepository.retrieveTeamPlan(teamID)
.doOnTerminate {

View file

@ -1,12 +1,14 @@
package com.habitrpg.android.habitica.ui.viewHolders.tasks
import android.content.Context
import android.text.TextUtils
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.ContextCompat
import androidx.core.text.TextUtilsCompat
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.extensions.dpToPx
import com.habitrpg.android.habitica.extensions.getThemeColor
@ -34,6 +36,7 @@ abstract class BaseTaskViewHolder constructor(itemView: View, var scoreTaskFunc:
protected val titleTextView: EllipsisTextView = itemView.findViewById(R.id.checkedTextView)
protected val notesTextView: EllipsisTextView? = itemView.findViewById(R.id.notesTextView)
protected val calendarIconView: ImageView? = itemView.findViewById(R.id.iconViewCalendar)
protected val iconViewTeam: ImageView? = itemView.findViewById(R.id.iconViewTeamTask)
protected val specialTaskTextView: TextView? = itemView.findViewById(R.id.specialTaskText)
private val iconViewChallenge: AppCompatImageView? = itemView.findViewById(R.id.iconviewChallenge)
private val iconViewReminder: ImageView? = itemView.findViewById(R.id.iconviewReminder)
@ -55,6 +58,9 @@ abstract class BaseTaskViewHolder constructor(itemView: View, var scoreTaskFunc:
get() {
var isVisible = false
if (iconViewTeam?.visibility == View.VISIBLE) {
isVisible = true
}
if (iconViewReminder?.visibility == View.VISIBLE) {
isVisible = true
}
@ -201,6 +207,8 @@ abstract class BaseTaskViewHolder constructor(itemView: View, var scoreTaskFunc:
}
configureSpecialTaskTextView(data)
iconViewTeam?.visibility = if (data.isGroupTask) View.VISIBLE else View.GONE
taskIconWrapper?.visibility = if (taskIconWrapperIsVisible) View.VISIBLE else View.GONE
} else {
taskIconWrapper?.visibility = View.GONE

View file

@ -43,6 +43,6 @@ abstract class BaseViewModel: ViewModel() {
}
fun updateUser(path: String, value: Any) {
disposable.add(userRepository.updateUser(getUserData().value, path, value).subscribe({ }, RxErrorHandler.handleEmptyError()))
disposable.add(userRepository.updateUser(path, value).subscribe({ }, RxErrorHandler.handleEmptyError()))
}
}

View file

@ -120,13 +120,15 @@ class TaskListDeserializer : JsonDeserializer<TaskList> {
}
if (obj.has("group")) {
val group = TaskGroupPlan()
val groupObject = obj.getAsJsonObject("group")
val approvalObject = groupObject.getAsJsonObject("approval")
if (approvalObject.has("requested")) group.approvalRequested = approvalObject.getAsJsonPrimitive("requested").asBoolean
if (approvalObject.has("approved")) group.approvalApproved = approvalObject.getAsJsonPrimitive("approved").asBoolean
if (approvalObject.has("required")) group.approvalRequired = approvalObject.getAsJsonPrimitive("required").asBoolean
task.group = group
val group: TaskGroupPlan = ctx.deserialize(groupObject, TaskGroupPlan::class.java)
if (group.groupID?.isNotBlank() == true) {
val approvalObject = groupObject.getAsJsonObject("approval")
if (approvalObject.has("requested")) group.approvalRequested = approvalObject.getAsJsonPrimitive("requested").asBoolean
if (approvalObject.has("approved")) group.approvalApproved = approvalObject.getAsJsonPrimitive("approved").asBoolean
if (approvalObject.has("required")) group.approvalRequired = approvalObject.getAsJsonPrimitive("required").asBoolean
task.group = group
}
}
// Work around since Realm does not support Arrays of ints
getMonthlyDays(e, task)