Merge branch '3.5.2' into Fixes#1475
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||
<uses-permission android:name="com.android.vending.BILLING" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
|
||||
|
|
|
|||
|
|
@ -51,10 +51,10 @@ dependencies {
|
|||
compileOnly 'javax.annotation:javax.annotation-api:1.3.2'
|
||||
compileOnly 'com.github.pengrad:jdk9-deps:1.0'
|
||||
//App Compatibility and Material Design
|
||||
implementation 'androidx.appcompat:appcompat:1.4.0'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'com.google.android.material:material:1.5.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation "androidx.preference:preference-ktx:1.1.1"
|
||||
implementation "androidx.preference:preference-ktx:1.2.0"
|
||||
|
||||
|
||||
// Markdown
|
||||
|
|
@ -121,10 +121,10 @@ dependencies {
|
|||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0"
|
||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.4.0"
|
||||
implementation "androidx.lifecycle:lifecycle-common-java8:2.4.0"
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.0'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.4.0'
|
||||
implementation 'com.plattysoft.leonids:LeonidsLib:1.3.2'
|
||||
implementation "androidx.fragment:fragment-ktx:1.4.0"
|
||||
implementation "androidx.fragment:fragment-ktx:1.4.1"
|
||||
implementation "androidx.paging:paging-runtime-ktx:3.1.0"
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
|
||||
|
|
@ -142,7 +142,7 @@ dependencies {
|
|||
|
||||
android {
|
||||
compileSdkVersion 32
|
||||
buildToolsVersion '30.0.2'
|
||||
buildToolsVersion '30.0.3'
|
||||
testOptions {
|
||||
unitTests {
|
||||
includeAndroidResources = true
|
||||
|
|
@ -157,7 +157,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 3218
|
||||
versionCode 3223
|
||||
versionName "3.5"
|
||||
|
||||
targetSdkVersion 32
|
||||
|
|
@ -382,8 +382,8 @@ def mainSrc = "${project.projectDir}/src/main/java"
|
|||
task jacocoTestReport(type: JacocoReport, dependsOn: 'testProdDebugUnitTest') {
|
||||
group = "Reporting"
|
||||
reports {
|
||||
html.enabled = true
|
||||
xml.enabled = true
|
||||
html.required.set(true)
|
||||
xml.required.set(true)
|
||||
//html.destination = "${buildDir}/reports/jacoco"
|
||||
}
|
||||
|
||||
|
|
@ -404,7 +404,6 @@ task jacocoTestReport(type: JacocoReport, dependsOn: 'testProdDebugUnitTest') {
|
|||
task ktlint(type: JavaExec, group: "verification") {
|
||||
description = "Check Kotlin code style."
|
||||
classpath = configurations.ktlint
|
||||
main = "com.pinterest.ktlint.Main"
|
||||
args "--disabled_rules=no-wildcard-imports", "--reporter=plain?group_by_file", "src/**/*.kt"
|
||||
// to generate report in checkstyle format prepend following args:
|
||||
// "--reporter=plain", "--reporter=checkstyle,output=${buildDir}/ktlint.xml"
|
||||
|
|
@ -417,6 +416,5 @@ check.dependsOn ktlint
|
|||
task ktlintFormat(type: JavaExec, group: "formatting") {
|
||||
description = "Fix Kotlin code style deviations."
|
||||
classpath = configurations.ktlint
|
||||
main = "com.pinterest.ktlint.Main"
|
||||
args "--disabled_rules=no-wildcard-imports", "-F", "src/**/*.kt"
|
||||
}
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 893 B After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 694 B After Width: | Height: | Size: 968 B |
|
Before Width: | Height: | Size: 958 B After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
|
@ -233,11 +233,12 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:paddingStart="41dp"
|
||||
android:paddingEnd="41dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:paddingBottom="30dp"
|
||||
android:paddingTop="70dp"
|
||||
android:text="@string/gem_purchase_title"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:gravity="center"
|
||||
android:lineSpacingExtra="3dp"
|
||||
android:textColor="@color/white"
|
||||
style="@style/Caption2"
|
||||
android:drawablePadding="@dimen/spacing_medium"/>
|
||||
|
|
|
|||
|
|
@ -17,19 +17,37 @@
|
|||
android:contentDescription="@string/gems"
|
||||
android:layout_marginTop="20dp"/>
|
||||
|
||||
<com.habitrpg.android.habitica.ui.views.DayNightTextView
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/gem_amount"
|
||||
app:dayTextColor="@color/white"
|
||||
app:nightTextColor="@color/white"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:letterSpacing="0.027"
|
||||
android:fontFamily="@string/font_family_medium"
|
||||
android:layout_margin="10dp"
|
||||
tools:text="21 GEMS" />
|
||||
android:orientation="horizontal">
|
||||
<com.habitrpg.android.habitica.ui.views.DayNightTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/gem_amount"
|
||||
app:dayTextColor="@color/white"
|
||||
app:nightTextColor="@color/white"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:letterSpacing="0.03"
|
||||
android:fontFamily="@string/font_family_medium"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:layout_marginEnd="2dp"
|
||||
tools:text="21" />
|
||||
<com.habitrpg.android.habitica.ui.views.DayNightTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:dayTextColor="@color/white"
|
||||
app:nightTextColor="@color/white"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:letterSpacing="0.03"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:textAllCaps="true"
|
||||
android:text="@string/gems" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -38,7 +56,7 @@
|
|||
android:background="@drawable/purchase_button_background"
|
||||
android:textColor="@color/brand_400"
|
||||
android:gravity="center"
|
||||
android:textSize="16sp"
|
||||
style="@style/Subheader1"
|
||||
android:letterSpacing="0.02"
|
||||
android:layout_marginStart="@dimen/spacing_medium"
|
||||
android:layout_marginEnd="@dimen/spacing_medium"
|
||||
|
|
|
|||
|
|
@ -464,7 +464,7 @@
|
|||
<argument
|
||||
android:name="url"
|
||||
app:argType="string" />
|
||||
<deepLink app:uri="habitica.com/promo/web" />
|
||||
<deepLink app:uri="habitica.com/promo/web?url={url}" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/teamBoardFragment"
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@
|
|||
<string name="rewards">Rewards</string>
|
||||
<string name="yes">Yes</string>
|
||||
<string name="no">No</string>
|
||||
<string name="discard">Discard</string>
|
||||
<string name="quest">Quest</string>
|
||||
<string name="avatar_body">Body</string>
|
||||
<string name="avatar_hair">Hair</string>
|
||||
|
|
@ -378,7 +379,7 @@
|
|||
<string name="google_services_missing">Google play services could not be found.</string>
|
||||
<string name="gem_purchase_toolbartitle">Purchase</string>
|
||||
<string name="gem_purchase_title">Buying gems supports the developers and helps keep Habitica running</string>
|
||||
<string name="gem_purchase_subtitle">Gems allow you to buy fun extras for your account:</string>
|
||||
<string name="gem_purchase_subtitle">Gems allow you to buy fun extras for your account</string>
|
||||
<string name="gem_purchase_listitem1">Cool costumes for your avatar</string>
|
||||
<string name="gem_purchase_listitem2">Awesome backgrounds</string>
|
||||
<string name="gem_purchase_listitem3">Quests that reward you with pet eggs</string>
|
||||
|
|
@ -470,6 +471,7 @@
|
|||
<string name="myster_item_notes">Each month, subscribers will receive a mystery item. This is usually released about one week before the end of the month.</string>
|
||||
<string name="open">Open</string>>
|
||||
<string name="is_open">Open</string>
|
||||
<string name="use_item">Use Item on party member</string>>
|
||||
<string name="checkInRewardEarned">You earned a %1$s as a reward for your devotion to improving your life.</string>
|
||||
<string name="nextPrizeUnlocks" tools:ignore="PluralsCandidate">Next prize in %1$d Check-Ins</string>
|
||||
<string name="pending_approval">pending approval</string>
|
||||
|
|
@ -527,6 +529,7 @@
|
|||
<string name="no_billing_gems">Your device does not have any of the supported payment methods. Please use the habitica website if you want to purchase gems.</string>
|
||||
<string name="no_billing_subscriptions">Your device does not have any of the supported payment methods. Please use the habitica website if you want to purchase a subscription.</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="unsaved_changes">Unsaved Changes</string>
|
||||
<string name="location">Location</string>
|
||||
<string name="gem_reward">Gem prize</string>
|
||||
<string name="tasks">Tasks</string>
|
||||
|
|
@ -551,6 +554,7 @@
|
|||
<string name="start_day">Start My Day</string>
|
||||
<string name="leave_party_confirmation">Are you sure you want to leave this party?</string>
|
||||
<string name="leave_party_challenges_confirmation">Do you want to keep participating in the Challenge when leaving the Party?</string>
|
||||
<string name="discard_changes_to_task_message">Are you sure you want to discard changes to this task?</string>
|
||||
<string name="rejoin_party">You will not be able to rejoin this party unless invited.</string>
|
||||
<string name="pending">Pending</string>
|
||||
<string name="accepted">Accepted</string>
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ import com.habitrpg.android.habitica.ui.viewmodels.AuthenticationViewModel;
|
|||
import com.habitrpg.android.habitica.ui.viewmodels.GroupViewModel;
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.InboxViewModel;
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainActivityViewModel;
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel;
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.NotificationsViewModel;
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.inventory.equipment.EquipmentOverviewViewModel;
|
||||
import com.habitrpg.android.habitica.ui.views.insufficientCurrency.InsufficientGemsDialog;
|
||||
|
|
@ -352,4 +353,6 @@ public interface UserComponent {
|
|||
void inject(@NotNull MainActivityViewModel mainActivityViewModel);
|
||||
|
||||
void inject(@NotNull GuidelinesActivity guidelinesActivity);
|
||||
|
||||
void inject(@NotNull MainUserViewModel mainUserViewModel);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,5 @@ interface SocialRepository : BaseRepository {
|
|||
|
||||
fun getGroupMembership(id: String): Flowable<GroupMembership>
|
||||
fun getGroupMemberships(): Flowable<out List<GroupMembership>>
|
||||
fun getChatmessage(messageID: String): Flowable<ChatMessage>
|
||||
fun blockMember(userID: String): Flowable<List<String>>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import com.habitrpg.android.habitica.models.ContentResult
|
|||
import com.habitrpg.android.habitica.models.WorldState
|
||||
import com.habitrpg.android.habitica.models.inventory.SpecialItem
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.realm.RealmList
|
||||
import java.util.*
|
||||
|
||||
class ContentRepositoryImpl<T : ContentLocalRepository>(localRepository: T, apiClient: ApiClient, context: Context) : BaseRepositoryImpl<T>(localRepository, apiClient), ContentRepository {
|
||||
|
|
@ -24,7 +23,6 @@ class ContentRepositoryImpl<T : ContentLocalRepository>(localRepository: T, apiC
|
|||
return if (forced || now - this.lastContentSync > 300000) {
|
||||
lastContentSync = now
|
||||
apiClient.content.doOnNext {
|
||||
it.special = RealmList()
|
||||
it.special.add(mysteryItem)
|
||||
localRepository.saveContent(it)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,10 +37,6 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
|
|||
}
|
||||
}
|
||||
|
||||
override fun getChatmessage(messageID: String): Flowable<ChatMessage> {
|
||||
return localRepository.getChatMessage(messageID)
|
||||
}
|
||||
|
||||
override fun blockMember(userID: String): Flowable<List<String>> {
|
||||
return apiClient.blockMember(userID)
|
||||
}
|
||||
|
|
@ -92,7 +88,9 @@ class SocialRepositoryImpl(localRepository: SocialLocalRepository, apiClient: Ap
|
|||
return Flowable.empty()
|
||||
}
|
||||
val liked = chatMessage.userLikesMessage(userID)
|
||||
localRepository.likeMessage(chatMessage, userID, !liked)
|
||||
if (chatMessage.isManaged) {
|
||||
localRepository.likeMessage(chatMessage, userID, !liked)
|
||||
}
|
||||
return apiClient.likeMessage(chatMessage.groupId ?: "", chatMessage.id)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,5 +47,4 @@ interface SocialLocalRepository : BaseLocalRepository {
|
|||
fun saveGroupMemberships(userID: String?, memberships: List<GroupMembership>)
|
||||
fun saveInboxMessages(userID: String, recipientID: String, messages: List<ChatMessage>, page: Int)
|
||||
fun saveInboxConversations(userID: String, conversations: List<InboxConversation>)
|
||||
fun getChatMessage(messageID: String): Flowable<ChatMessage>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ open class RealmContentLocalRepository(realm: Realm) : RealmBaseLocalRepository(
|
|||
realm1.insertOrUpdate(contentResult.mounts)
|
||||
|
||||
realm1.insertOrUpdate(contentResult.spells)
|
||||
realm1.insertOrUpdate(contentResult.special)
|
||||
realm1.insertOrUpdate(contentResult.appearances)
|
||||
realm1.insertOrUpdate(contentResult.backgrounds)
|
||||
realm1.insertOrUpdate(contentResult.faq)
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
"hatchingPotions" -> it.items?.hatchingPotions
|
||||
"food" -> it.items?.food
|
||||
"quests" -> it.items?.quests
|
||||
"special" -> it.items?.special?.ownedItems
|
||||
"special" -> it.items?.special
|
||||
else -> emptyList()
|
||||
} ?: emptyList()
|
||||
if (includeZero) {
|
||||
|
|
@ -286,7 +286,7 @@ class RealmInventoryLocalRepository(realm: Realm) : RealmContentLocalRepository(
|
|||
return
|
||||
}
|
||||
val liveUser = getLiveObject(user)
|
||||
val ownedItems = liveUser?.items?.special?.ownedItems
|
||||
val ownedItems = liveUser?.items?.special
|
||||
val item = ownedItems?.firstOrNull() { it.key == "inventory_present" }
|
||||
executeTransaction {
|
||||
if (item != null && item.isValid) {
|
||||
|
|
|
|||
|
|
@ -12,14 +12,6 @@ import io.realm.Sort
|
|||
import java.util.*
|
||||
|
||||
class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), SocialLocalRepository {
|
||||
override fun getChatMessage(messageID: String): Flowable<ChatMessage> = RxJavaBridge.toV3Flowable(
|
||||
realm.where(ChatMessage::class.java)
|
||||
.equalTo("id", messageID)
|
||||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded && it.isNotEmpty() }
|
||||
.map { it.first() }
|
||||
)
|
||||
|
||||
override fun getGroupMembership(userId: String, id: String): Flowable<GroupMembership> = RxJavaBridge.toV3Flowable(
|
||||
realm.where(GroupMembership::class.java)
|
||||
|
|
|
|||
|
|
@ -146,22 +146,10 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
override fun getSpecialItems(user: User): Flowable<out List<Skill>> {
|
||||
val specialItems = user.items?.special
|
||||
val ownedItems = ArrayList<String>()
|
||||
if (specialItems != null) {
|
||||
if (specialItems.snowball > 0) {
|
||||
ownedItems.add("snowball")
|
||||
for (key in listOf("snowball", "shinySeed", "seafoam", "spookySparkles")) {
|
||||
if (specialItems?.firstOrNull() { it.key == key }?.numberOwned ?: 0 > 0) {
|
||||
ownedItems.add(key)
|
||||
}
|
||||
if (specialItems.shinySeed > 0) {
|
||||
ownedItems.add("shinySeed")
|
||||
}
|
||||
if (specialItems.seafoam > 0) {
|
||||
ownedItems.add("seafoam")
|
||||
}
|
||||
if (specialItems.spookySparkles > 0) {
|
||||
ownedItems.add("spookySparkles")
|
||||
}
|
||||
}
|
||||
if (ownedItems.size == 0) {
|
||||
ownedItems.add("")
|
||||
}
|
||||
return RxJavaBridge.toV3Flowable(
|
||||
realm.where(Skill::class.java)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.habitrpg.android.habitica.helpers
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.AlarmManager.AlarmClockInfo
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
|
@ -121,6 +122,7 @@ class TaskAlarmManager(private var context: Context, private var taskRepository:
|
|||
const val TASK_NAME_INTENT_KEY = "TASK_NAME"
|
||||
|
||||
fun scheduleDailyReminder(context: Context?) {
|
||||
if (context == null) return
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
if (prefs.getBoolean("use_reminder", false)) {
|
||||
val timeval = prefs.getString("reminder_time", "19:00")
|
||||
|
|
@ -174,7 +176,7 @@ class TaskAlarmManager(private var context: Context, private var taskRepository:
|
|||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
alarmManager?.setWindow(AlarmManager.RTC_WAKEUP, time, 60000, pendingIntent)
|
||||
} else {
|
||||
alarmManager?.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pendingIntent)
|
||||
alarmManager?.setAlarmClock(AlarmClockInfo(time, pendingIntent), pendingIntent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ open class SpecialItem : RealmObject(), Item {
|
|||
internal var notes: String = ""
|
||||
override var value: Int = 0
|
||||
override var event: ItemEvent? = null
|
||||
var target: String? = null
|
||||
var isMysteryItem: Boolean = false
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -256,6 +256,47 @@ open class Task : RealmObject, BaseMainObject, Parcelable {
|
|||
}
|
||||
}
|
||||
|
||||
fun isBeingEdited(task: Task): Boolean {
|
||||
|
||||
when {
|
||||
text != task.text -> return true
|
||||
notes != task.notes -> return true
|
||||
reminders != task.reminders -> return true
|
||||
checklist != task.checklist -> return true
|
||||
priority != task.priority -> return true
|
||||
attribute != task.attribute && attribute != null -> return true
|
||||
tags != task.tags -> return true
|
||||
}
|
||||
if (type == TaskType.HABIT) {
|
||||
return when {
|
||||
up != task.up -> true
|
||||
down != task.down -> true
|
||||
frequency != task.frequency -> true
|
||||
counterUp != task.counterUp -> true
|
||||
counterDown != task.counterDown -> true
|
||||
else -> false
|
||||
}
|
||||
} else if (type == TaskType.DAILY) {
|
||||
return when {
|
||||
startDate != task.startDate -> true
|
||||
everyX != task.everyX -> true
|
||||
frequency != task.frequency -> true
|
||||
repeat != task.repeat -> true
|
||||
streak != task.streak -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
} else if (type == TaskType.TODO) {
|
||||
return dueDate != task.dueDate
|
||||
|
||||
} else if (type == TaskType.REWARD) {
|
||||
return value != task.value
|
||||
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return id?.hashCode() ?: 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ open class Items : RealmObject, BaseObject {
|
|||
eggs?.forEach { it.itemType = "eggs" }
|
||||
food?.forEach { it.itemType = "food" }
|
||||
quests?.forEach { it.itemType = "quests" }
|
||||
special?.forEach { it.itemType = "special" }
|
||||
}
|
||||
|
||||
var eggs: RealmList<OwnedItem>? = null
|
||||
|
|
@ -35,6 +36,12 @@ open class Items : RealmObject, BaseObject {
|
|||
field = value
|
||||
field?.forEach { it.itemType = "quests" }
|
||||
}
|
||||
var special: RealmList<OwnedItem>? = null
|
||||
set(value) {
|
||||
field = value
|
||||
field?.forEach { it.itemType = "special" }
|
||||
}
|
||||
|
||||
var pets: RealmList<OwnedPet>? = null
|
||||
var mounts: RealmList<OwnedMount>? = null
|
||||
var currentMount: String? = null
|
||||
|
|
@ -44,7 +51,6 @@ open class Items : RealmObject, BaseObject {
|
|||
|
||||
// private QuestContent quest;
|
||||
var gear: Gear? = null
|
||||
var special: SpecialItems? = null
|
||||
|
||||
constructor(currentMount: String, currentPet: String, lastDropCount: Int, lastDropDate: Date) {
|
||||
this.currentMount = currentMount
|
||||
|
|
@ -54,4 +60,14 @@ open class Items : RealmObject, BaseObject {
|
|||
}
|
||||
|
||||
constructor()
|
||||
|
||||
val hasTransformationItems: Boolean
|
||||
get() {
|
||||
return special?.any { transformationItem ->
|
||||
transformationItem.key == ("seafoam") && transformationItem.numberOwned > 0||
|
||||
transformationItem.key == ("shinySeed") && transformationItem.numberOwned > 0||
|
||||
transformationItem.key == ("snowball") && transformationItem.numberOwned > 0||
|
||||
transformationItem.key == ("spookySparkles") && transformationItem.numberOwned > 0
|
||||
} ?: false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
package com.habitrpg.android.habitica.models.user
|
||||
|
||||
import com.habitrpg.android.habitica.models.BaseObject
|
||||
import io.realm.RealmList
|
||||
import io.realm.RealmObject
|
||||
import io.realm.annotations.RealmClass
|
||||
|
||||
@RealmClass(embedded = true)
|
||||
open class SpecialItems : RealmObject(), BaseObject {
|
||||
var ownedItems: RealmList<OwnedItem>? = null
|
||||
var seafoam: Int = 0
|
||||
var shinySeed: Int = 0
|
||||
var snowball: Int = 0
|
||||
var spookySparkles: Int = 0
|
||||
|
||||
val hasSpecialItems: Boolean
|
||||
get() {
|
||||
return seafoam > 0 || shinySeed > 0 || snowball > 0 || spookySparkles > 0
|
||||
}
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ class AppModule(private val application: Application) {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSharedPreferences(context: Context?): SharedPreferences {
|
||||
fun provideSharedPreferences(context: Context): SharedPreferences {
|
||||
return PreferenceManager.getDefaultSharedPreferences(context)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ import android.content.Context;
|
|||
import android.content.SharedPreferences;
|
||||
|
||||
import com.habitrpg.android.habitica.data.TaskRepository;
|
||||
import com.habitrpg.android.habitica.data.UserRepository;
|
||||
import com.habitrpg.android.habitica.helpers.TaskAlarmManager;
|
||||
import com.habitrpg.android.habitica.helpers.UserScope;
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
|
|
@ -28,4 +30,10 @@ public class UserModule {
|
|||
public String providesUserID(SharedPreferences sharedPreferences) {
|
||||
return sharedPreferences.getString("UserID", "");
|
||||
}
|
||||
|
||||
@Provides
|
||||
@UserScope
|
||||
MainUserViewModel providesUserViewModel(UserRepository userRepository) {
|
||||
return new MainUserViewModel(userRepository);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import androidx.preference.DialogPreference
|
|||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
class TimePreference(ctxt: Context?, attrs: AttributeSet?) : DialogPreference(ctxt, attrs) {
|
||||
class TimePreference(ctxt: Context, attrs: AttributeSet?) : DialogPreference(ctxt, attrs) {
|
||||
private var timeval: String? = null
|
||||
override fun onGetDefaultValue(a: TypedArray, index: Int): Any {
|
||||
return a.getString(index)!!
|
||||
|
|
@ -39,7 +39,7 @@ class TimePreference(ctxt: Context?, attrs: AttributeSet?) : DialogPreference(ct
|
|||
}
|
||||
}
|
||||
|
||||
override fun setSummary(summary: CharSequence) {
|
||||
override fun setSummary(summary: CharSequence?) {
|
||||
val calendar = Calendar.getInstance(Locale.getDefault())
|
||||
calendar.set(Calendar.HOUR_OF_DAY, getHour(timeval))
|
||||
calendar.set(Calendar.MINUTE, getMinute(timeval))
|
||||
|
|
|
|||
|
|
@ -73,9 +73,9 @@ class AvatarWithBarsViewModel(private val context: Context, private val binding:
|
|||
if (!stats.isBuffed) {
|
||||
binding.buffImageView.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding.currencyView.gold = stats.gp ?: 0.0
|
||||
|
||||
if (user is User) {
|
||||
binding.currencyView.gold = stats.gp ?: 0.0
|
||||
binding.currencyView.hourglasses = user.hourglassCount.toDouble()
|
||||
binding.currencyView.gems = user.gemCount.toDouble()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class GemPurchaseOptionsView(context: Context, attrs: AttributeSet) : FrameLayou
|
|||
0, 0
|
||||
)
|
||||
|
||||
binding.gemAmount.text = "${a.getText(R.styleable.GemPurchaseOptionsView_gemAmount)} GEMS"
|
||||
binding.gemAmount.text = a.getText(R.styleable.GemPurchaseOptionsView_gemAmount)
|
||||
|
||||
val iconRes = a.getDrawable(R.styleable.GemPurchaseOptionsView_gemDrawable)
|
||||
if (iconRes != null) {
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction, Snack
|
|||
navigationController.addOnDestinationChangedListener { _, destination, arguments -> updateToolbarTitle(destination, arguments) }
|
||||
|
||||
if (launchScreen == "/party") {
|
||||
if (viewModel.isUserInParty) {
|
||||
if (viewModel.userViewModel.isUserInParty) {
|
||||
MainNavigationController.navigate(R.id.partyFragment)
|
||||
}
|
||||
}
|
||||
|
|
@ -430,7 +430,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction, Snack
|
|||
}
|
||||
|
||||
private fun displayDeathDialogIfNeeded() {
|
||||
if (!viewModel.isUserFainted) {
|
||||
if (!viewModel.userViewModel.isUserFainted) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.res.ColorStateList
|
||||
|
|
@ -13,6 +14,7 @@ import android.widget.CheckBox
|
|||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.AppCompatCheckBox
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.forEachIndexed
|
||||
import androidx.core.widget.NestedScrollView
|
||||
|
|
@ -21,7 +23,6 @@ import com.habitrpg.android.habitica.components.UserComponent
|
|||
import com.habitrpg.android.habitica.data.ChallengeRepository
|
||||
import com.habitrpg.android.habitica.data.TagRepository
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.databinding.ActivityTaskFormBinding
|
||||
import com.habitrpg.android.habitica.extensions.OnChangeTextWatcher
|
||||
import com.habitrpg.android.habitica.extensions.addCancelButton
|
||||
|
|
@ -64,6 +65,7 @@ class TaskFormActivity : BaseActivity() {
|
|||
private var isChallengeTask = false
|
||||
private var usesTaskAttributeStats = false
|
||||
private var task: Task? = null
|
||||
private var initialTaskInstance: Task? = null
|
||||
private var taskType: TaskType = TaskType.HABIT
|
||||
private var tags = listOf<Tag>()
|
||||
private var preselectedTags: ArrayList<String>? = null
|
||||
|
|
@ -74,6 +76,7 @@ class TaskFormActivity : BaseActivity() {
|
|||
setSelectedAttribute(value)
|
||||
}
|
||||
|
||||
private var isDiscardCancelled: Boolean = false
|
||||
private var canSave: Boolean = false
|
||||
|
||||
private var tintColor: Int = 0
|
||||
|
|
@ -198,6 +201,7 @@ class TaskFormActivity : BaseActivity() {
|
|||
{
|
||||
if (!it.isValid) return@subscribe
|
||||
task = it
|
||||
initialTaskInstance = it
|
||||
// tintColor = ContextCompat.getColor(this, it.mediumTaskColor)
|
||||
fillForm(it)
|
||||
it.challengeID?.let { challengeID ->
|
||||
|
|
@ -224,17 +228,21 @@ class TaskFormActivity : BaseActivity() {
|
|||
task = bundle.getParcelable(PARCELABLE_TASK)
|
||||
task?.let { fillForm(it) }
|
||||
}
|
||||
else -> title = getString(
|
||||
R.string.create_task,
|
||||
getString(
|
||||
when (taskType) {
|
||||
TaskType.DAILY -> R.string.daily
|
||||
TaskType.TODO -> R.string.todo
|
||||
TaskType.REWARD -> R.string.reward
|
||||
else -> R.string.habit
|
||||
}
|
||||
else -> {
|
||||
title = getString(
|
||||
R.string.create_task,
|
||||
getString(
|
||||
when (taskType) {
|
||||
TaskType.DAILY -> R.string.daily
|
||||
TaskType.TODO -> R.string.todo
|
||||
TaskType.REWARD -> R.string.reward
|
||||
else -> R.string.habit
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
initialTaskInstance = configureTask(Task())
|
||||
}
|
||||
|
||||
}
|
||||
configureForm()
|
||||
}
|
||||
|
|
@ -252,6 +260,29 @@ class TaskFormActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
val currentTaskInstance = configureTask(Task())
|
||||
if (initialTaskInstance?.isBeingEdited(currentTaskInstance) == true) {
|
||||
val alert = HabiticaAlertDialog(this)
|
||||
alert.setTitle(R.string.unsaved_changes)
|
||||
alert.setMessage(R.string.discard_changes_to_task_message)
|
||||
alert.addButton(R.string.discard, true, true) { _, _ ->
|
||||
analyticsManager.logEvent("discard_task", bundleOf(Pair("is_creating", isCreating)))
|
||||
super.onBackPressed()
|
||||
}
|
||||
alert.addButton(R.string.cancel, false) { _, _ ->
|
||||
isDiscardCancelled = true
|
||||
alert.dismiss()
|
||||
}
|
||||
alert.setOnDismissListener(DialogInterface.OnDismissListener {
|
||||
isDiscardCancelled = true
|
||||
})
|
||||
alert.show()
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
if (isCreating) {
|
||||
menuInflater.inflate(R.menu.menu_task_create, menu)
|
||||
|
|
@ -437,19 +468,10 @@ class TaskFormActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun saveTask() {
|
||||
if (isSaving) {
|
||||
return
|
||||
}
|
||||
isSaving = true
|
||||
var thisTask = task
|
||||
if (thisTask == null) {
|
||||
thisTask = Task()
|
||||
thisTask.type = taskType
|
||||
thisTask.dateCreated = Date()
|
||||
} else {
|
||||
if (!thisTask.isValid) return
|
||||
}
|
||||
private fun configureTask(thisTask: Task): Task {
|
||||
thisTask.type = taskType
|
||||
thisTask.dateCreated = Date()
|
||||
|
||||
thisTask.text = binding.textEditText.text.toString()
|
||||
thisTask.notes = binding.notesEditText.text.toString()
|
||||
thisTask.priority = binding.taskDifficultyButtons.selectedDifficulty
|
||||
|
|
@ -460,8 +482,10 @@ class TaskFormActivity : BaseActivity() {
|
|||
thisTask.up = binding.habitScoringButtons.isPositive
|
||||
thisTask.down = binding.habitScoringButtons.isNegative
|
||||
thisTask.frequency = binding.habitResetStreakButtons.selectedResetOption.value
|
||||
if (binding.habitAdjustPositiveStreakView.text?.isNotEmpty() == true) thisTask.counterUp = binding.habitAdjustPositiveStreakView.text.toString().toIntCatchOverflow()
|
||||
if (binding.habitAdjustNegativeStreakView.text?.isNotEmpty() == true) thisTask.counterDown = binding.habitAdjustNegativeStreakView.text.toString().toIntCatchOverflow()
|
||||
if (binding.habitAdjustPositiveStreakView.text?.isNotEmpty() == true) thisTask.counterUp =
|
||||
binding.habitAdjustPositiveStreakView.text.toString().toIntCatchOverflow()
|
||||
if (binding.habitAdjustNegativeStreakView.text?.isNotEmpty() == true) thisTask.counterDown =
|
||||
binding.habitAdjustNegativeStreakView.text.toString().toIntCatchOverflow()
|
||||
} else if (taskType == TaskType.DAILY) {
|
||||
thisTask.startDate = binding.taskSchedulingControls.startDate
|
||||
thisTask.everyX = binding.taskSchedulingControls.everyX
|
||||
|
|
@ -469,15 +493,13 @@ class TaskFormActivity : BaseActivity() {
|
|||
thisTask.repeat = binding.taskSchedulingControls.weeklyRepeat
|
||||
thisTask.setDaysOfMonth(binding.taskSchedulingControls.daysOfMonth)
|
||||
thisTask.setWeeksOfMonth(binding.taskSchedulingControls.weeksOfMonth)
|
||||
if (binding.habitAdjustPositiveStreakView.text?.isNotEmpty() == true) thisTask.streak = binding.habitAdjustPositiveStreakView.text.toString().toIntCatchOverflow()
|
||||
if (binding.habitAdjustPositiveStreakView.text?.isNotEmpty() == true) thisTask.streak =
|
||||
binding.habitAdjustPositiveStreakView.text.toString().toIntCatchOverflow()
|
||||
} else if (taskType == TaskType.TODO) {
|
||||
thisTask.dueDate = binding.taskSchedulingControls.dueDate
|
||||
} else if (taskType == TaskType.REWARD) {
|
||||
thisTask.value = binding.rewardValue.value
|
||||
}
|
||||
|
||||
val resultIntent = Intent()
|
||||
resultIntent.putExtra(TASK_TYPE_KEY, taskType)
|
||||
if (!isChallengeTask) {
|
||||
if (taskType == TaskType.DAILY || taskType == TaskType.TODO) {
|
||||
thisTask.checklist = RealmList()
|
||||
|
|
@ -492,10 +514,40 @@ class TaskFormActivity : BaseActivity() {
|
|||
thisTask.tags?.add(tags[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return thisTask
|
||||
}
|
||||
|
||||
private fun saveTask() {
|
||||
if (isSaving) {
|
||||
return
|
||||
}
|
||||
isSaving = true
|
||||
var thisTask = task
|
||||
if (thisTask == null) {
|
||||
thisTask = Task()
|
||||
thisTask.type = taskType
|
||||
thisTask.dateCreated = Date()
|
||||
} else {
|
||||
if (!thisTask.isValid) return
|
||||
}
|
||||
|
||||
thisTask = configureTask(thisTask)
|
||||
|
||||
val resultIntent = Intent()
|
||||
resultIntent.putExtra(TASK_TYPE_KEY, taskType)
|
||||
if (!isChallengeTask) {
|
||||
if (isCreating) {
|
||||
if (isDiscardCancelled){
|
||||
analyticsManager.logEvent("back_to_task", bundleOf(Pair("is_creating", isCreating)))
|
||||
}
|
||||
taskRepository.createTaskInBackground(thisTask)
|
||||
|
||||
} else {
|
||||
if (isDiscardCancelled){
|
||||
analyticsManager.logEvent("back_to_task", bundleOf(Pair("is_creating", isCreating)))
|
||||
}
|
||||
taskRepository.updateTaskInBackground(thisTask)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,12 +12,13 @@ import com.habitrpg.android.habitica.databinding.SkillListItemBinding
|
|||
import com.habitrpg.android.habitica.extensions.inflate
|
||||
import com.habitrpg.android.habitica.extensions.isUsingNightModeResources
|
||||
import com.habitrpg.android.habitica.models.Skill
|
||||
import com.habitrpg.android.habitica.models.user.SpecialItems
|
||||
import com.habitrpg.android.habitica.models.user.OwnedItem
|
||||
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
|
||||
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.RealmList
|
||||
|
||||
class SkillsRecyclerViewAdapter : RecyclerView.Adapter<SkillsRecyclerViewAdapter.SkillViewHolder>() {
|
||||
|
||||
|
|
@ -34,7 +35,7 @@ class SkillsRecyclerViewAdapter : RecyclerView.Adapter<SkillsRecyclerViewAdapter
|
|||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
var specialItems: SpecialItems? = null
|
||||
var specialItems: RealmList<OwnedItem>?? = null
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
|
|
@ -134,13 +135,7 @@ class SkillsRecyclerViewAdapter : RecyclerView.Adapter<SkillsRecyclerViewAdapter
|
|||
}
|
||||
|
||||
private fun getOwnedCount(key: String): Int {
|
||||
return when (key) {
|
||||
"snowball" -> specialItems?.snowball
|
||||
"shinySeed" -> specialItems?.shinySeed
|
||||
"seafoam" -> specialItems?.seafoam
|
||||
"spookySparkles" -> specialItems?.spookySparkles
|
||||
else -> 0
|
||||
} ?: 0
|
||||
return specialItems?.firstOrNull() { it.key == key }?.numberOwned ?: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV
|
|||
private val hatchPetSubject = PublishSubject.create<Pair<HatchingPotion, Egg>>()
|
||||
private val feedPetSubject = PublishSubject.create<Food>()
|
||||
private val createNewPartySubject = PublishSubject.create<Boolean>()
|
||||
private val useSpecialSubject = PublishSubject.create<SpecialItem>()
|
||||
|
||||
fun getSellItemFlowable(): Flowable<OwnedItem> {
|
||||
return sellItemEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
|
|
@ -63,6 +64,7 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV
|
|||
val hatchPetEvents: Flowable<Pair<HatchingPotion, Egg>> = hatchPetSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
val feedPetEvents: Flowable<Food> = feedPetSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
val startNewPartyEvents: Flowable<Boolean> = createNewPartySubject.toFlowable(BackpressureStrategy.DROP)
|
||||
val useSpecialEvents: Flowable<SpecialItem> = useSpecialSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
|
||||
return ItemViewHolder(ItemItemBinding.inflate(context.layoutInflater, parent, false))
|
||||
|
|
@ -115,9 +117,14 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV
|
|||
if (item is QuestContent) {
|
||||
imageName = "inventory_quest_scroll_" + ownedItem.key
|
||||
} else if (item is SpecialItem) {
|
||||
val sdf = SimpleDateFormat("MM", Locale.getDefault())
|
||||
val month = sdf.format(Date())
|
||||
imageName = "inventory_present_$month"
|
||||
if (item.key == "inventory_present") {
|
||||
val sdf = SimpleDateFormat("MM", Locale.getDefault())
|
||||
val month = sdf.format(Date())
|
||||
imageName = "inventory_present_$month"
|
||||
} else {
|
||||
imageName = "shop_" + ownedItem.key
|
||||
}
|
||||
|
||||
} else {
|
||||
val type = when (ownedItem.itemType) {
|
||||
"eggs" -> "Egg"
|
||||
|
|
@ -164,7 +171,10 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV
|
|||
val specialItem = item as SpecialItem
|
||||
if (specialItem.isMysteryItem && ownedItem?.numberOwned ?: 0 > 0) {
|
||||
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.open)))
|
||||
} else if (ownedItem?.numberOwned ?: 0 > 0){
|
||||
menu.addMenuItem(BottomSheetMenuItem(resources.getString(R.string.use_item)))
|
||||
}
|
||||
|
||||
}
|
||||
menu.setSelectionRunnable { index ->
|
||||
item?.let { selectedItem ->
|
||||
|
|
@ -189,7 +199,12 @@ class ItemRecyclerAdapter(val context: Context, val user: User?) : BaseRecyclerV
|
|||
|
||||
}
|
||||
}
|
||||
is SpecialItem -> openMysteryItemEvents.onNext(selectedItem)
|
||||
is SpecialItem ->
|
||||
if (item?.key != "inventory_present") {
|
||||
useSpecialSubject.onNext(selectedItem)
|
||||
} else {
|
||||
openMysteryItemEvents.onNext(selectedItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,11 @@ class MountDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Ada
|
|||
private var ownedMounts: Map<String, OwnedMount>? = null
|
||||
|
||||
private val equipEvents = PublishSubject.create<String>()
|
||||
private var user: User? = null
|
||||
var currentMount: String? = null
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private var itemList: List<Any> = ArrayList()
|
||||
|
||||
|
|
@ -37,7 +41,7 @@ class MountDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Ada
|
|||
override fun onBindViewHolder(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder, position: Int) {
|
||||
when (val obj = this.itemList[position]) {
|
||||
is StableSection -> (holder as? SectionViewHolder)?.bind(obj)
|
||||
is Mount -> (holder as? MountViewHolder)?.bind(obj, ownedMounts?.get(obj.key ?: "")?.owned == true, user)
|
||||
is Mount -> (holder as? MountViewHolder)?.bind(obj, ownedMounts?.get(obj.key ?: "")?.owned == true, currentMount)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,9 +53,4 @@ class MountDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Ada
|
|||
this.ownedMounts = ownedMounts
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun setUser(user: User) {
|
||||
this.user = user
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,11 @@ class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapt
|
|||
private var ownedPets: Map<String, OwnedPet>? = null
|
||||
private var ownedMounts: Map<String, OwnedMount>? = null
|
||||
private var ownedItems: Map<String, OwnedItem>? = null
|
||||
private var user: User? = null
|
||||
var currentPet: String? = null
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
private val equipEvents = PublishSubject.create<String>()
|
||||
private val feedEvents = PublishSubject.create<Pair<Pet, Food?>>()
|
||||
private var ownsSaddles: Boolean = false
|
||||
|
|
@ -29,11 +33,6 @@ class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapt
|
|||
this.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun setUser(user: User) {
|
||||
this.user = user
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun getEquipFlowable(): Flowable<String> {
|
||||
return equipEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
|
|
@ -81,7 +80,7 @@ class PetDetailRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapt
|
|||
ownedItems?.get(obj.animal + "-eggs") != null,
|
||||
ownedItems?.get(obj.color + "-hatchingPotions") != null,
|
||||
ownedMounts?.containsKey(obj.key) == true,
|
||||
user
|
||||
currentPet
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,16 @@ class StableRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
|||
var animalIngredientsRetriever: ((Animal, ((Pair<Egg?, HatchingPotion?>) -> Unit)) -> Unit)? = null
|
||||
private val feedEvents = PublishSubject.create<Pair<Pet, Food?>>()
|
||||
var itemType: String? = null
|
||||
private var user: User? = null
|
||||
var currentPet: String? = null
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
var currentMount: String? = null
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
private val equipEvents = PublishSubject.create<String>()
|
||||
private var existingMounts: List<Mount>? = null
|
||||
private var ownedMounts: Map<String, OwnedMount>? = null
|
||||
|
|
@ -43,11 +52,6 @@ class StableRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
|||
return equipEvents.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
|
||||
fun setUser(user: User) {
|
||||
this.user = user
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun canRaiseToMount(pet: Pet): Boolean {
|
||||
if (pet.type == "special") return false
|
||||
for (mount in existingMounts ?: emptyList()) {
|
||||
|
|
@ -122,10 +126,10 @@ class StableRecyclerAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
|||
hasUnlockedEgg = ownedItems?.get(item.animal + "-eggs") != null,
|
||||
hasUnlockedPotion = ownedItems?.get(item.color + "-hatchingPotions") != null,
|
||||
hasMount = ownedMounts?.containsKey(item.key) == true,
|
||||
user = user
|
||||
currentPet = currentPet
|
||||
)
|
||||
} else if (item is Mount) {
|
||||
(holder as? MountViewHolder)?.bind(item, item.numberOwned > 0, user)
|
||||
(holder as? MountViewHolder)?.bind(item, item.numberOwned > 0, currentMount)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.habitrpg.android.habitica.databinding.FragmentRefreshRecyclerviewBind
|
|||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.ui.adapter.AchievementsAdapter
|
||||
import com.habitrpg.android.habitica.ui.helpers.ToolbarColorHelper
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import io.reactivex.rxjava3.kotlin.Flowables
|
||||
import io.reactivex.rxjava3.kotlin.combineLatest
|
||||
import javax.inject.Inject
|
||||
|
|
@ -22,6 +23,8 @@ class AchievementsFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding
|
|||
|
||||
@Inject
|
||||
lateinit var inventoryRepository: InventoryRepository
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
override var binding: FragmentRefreshRecyclerviewBinding? = null
|
||||
|
||||
|
|
@ -125,6 +128,7 @@ class AchievementsFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding
|
|||
}
|
||||
)
|
||||
|
||||
val user = userViewModel.user.value
|
||||
val challengeAchievementCount = user?.challengeAchievements?.size ?: 0
|
||||
if (challengeAchievementCount > 0) {
|
||||
entries.add(Pair("Challenges won", challengeAchievementCount))
|
||||
|
|
|
|||
|
|
@ -39,23 +39,12 @@ abstract class BaseMainFragment<VB : ViewBinding> : BaseFragment<VB>() {
|
|||
var usesTabLayout: Boolean = false
|
||||
var hidesToolbar: Boolean = false
|
||||
var usesBottomNavigation = false
|
||||
open var user: User? = null
|
||||
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
|
||||
if (activity is MainActivity) {
|
||||
user = activity?.viewModel?.user?.value
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
compositeSubscription.add(userRepository.getUser().subscribe({ user = it }, RxErrorHandler.handleEmptyError()))
|
||||
|
||||
if (this.usesBottomNavigation) {
|
||||
bottomNavigation?.visibility = View.VISIBLE
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import com.habitrpg.android.habitica.extensions.*
|
|||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.WorldState
|
||||
import com.habitrpg.android.habitica.models.WorldStateEvent
|
||||
import com.habitrpg.android.habitica.models.inventory.Item
|
||||
import com.habitrpg.android.habitica.models.inventory.Quest
|
||||
|
|
@ -41,7 +40,6 @@ import com.habitrpg.android.habitica.models.user.User
|
|||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import com.habitrpg.android.habitica.ui.activities.NotificationsActivity
|
||||
import com.habitrpg.android.habitica.ui.adapter.NavigationDrawerAdapter
|
||||
import com.habitrpg.android.habitica.ui.fragments.social.TavernDetailFragment
|
||||
import com.habitrpg.android.habitica.ui.menu.HabiticaDrawerItem
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.NotificationsViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
|
|
@ -339,10 +337,10 @@ class NavigationDrawerFragment : DialogFragment() {
|
|||
tavernItem?.subtitle = null
|
||||
}
|
||||
|
||||
val specialItems = user.items?.special
|
||||
val userItems = user.items
|
||||
var hasSpecialItems = false
|
||||
if (specialItems != null) {
|
||||
hasSpecialItems = specialItems.hasSpecialItems
|
||||
if (userItems != null) {
|
||||
hasSpecialItems = userItems.hasTransformationItems
|
||||
}
|
||||
val item = getItemWithIdentifier(SIDEBAR_SKILLS)
|
||||
if (item != null) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.habitrpg.android.habitica.ui.adapter.CustomizationRecyclerViewAdapter
|
|||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarginDecoration
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
class AvatarCustomizationFragment :
|
||||
|
|
@ -34,6 +35,8 @@ class AvatarCustomizationFragment :
|
|||
lateinit var customizationRepository: CustomizationRepository
|
||||
@Inject
|
||||
lateinit var inventoryRepository: InventoryRepository
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
var type: String? = null
|
||||
var category: String? = null
|
||||
|
|
@ -52,7 +55,7 @@ class AvatarCustomizationFragment :
|
|||
adapter.getSelectCustomizationEvents()
|
||||
.flatMap { customization ->
|
||||
if (customization.type == "background") {
|
||||
userRepository.unlockPath(user, customization)
|
||||
userRepository.unlockPath(userViewModel.user.value, customization)
|
||||
.flatMap { userRepository.retrieveUser(false, true, true) }
|
||||
} else {
|
||||
userRepository.useCustomization(customization.type ?: "", customization.category, customization.identifier ?: "")
|
||||
|
|
@ -63,7 +66,7 @@ class AvatarCustomizationFragment :
|
|||
compositeSubscription.add(
|
||||
adapter.getUnlockCustomizationEvents()
|
||||
.flatMap { customization ->
|
||||
userRepository.unlockPath(user, customization)
|
||||
userRepository.unlockPath(userViewModel.user.value, customization)
|
||||
}
|
||||
.flatMap { userRepository.retrieveUser(withTasks = false, forced = true) }
|
||||
.flatMap { inventoryRepository.retrieveInAppRewards() }
|
||||
|
|
@ -112,11 +115,7 @@ class AvatarCustomizationFragment :
|
|||
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
|
||||
this.loadCustomizations()
|
||||
|
||||
compositeSubscription.add(
|
||||
userRepository.getUser().subscribeWithErrorHandler {
|
||||
updateUser(it)
|
||||
}
|
||||
)
|
||||
userViewModel.user.observe(viewLifecycleOwner) { updateUser(it) }
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
|
@ -153,7 +152,8 @@ class AvatarCustomizationFragment :
|
|||
layoutManager.spanCount = spanCount
|
||||
}
|
||||
|
||||
fun updateUser(user: User) {
|
||||
fun updateUser(user: User?) {
|
||||
if (user == null) return
|
||||
this.updateActiveCustomization(user)
|
||||
if (adapter.customizationList.size != 0) {
|
||||
val ownedCustomizations = ArrayList<String>()
|
||||
|
|
@ -162,8 +162,8 @@ class AvatarCustomizationFragment :
|
|||
} else {
|
||||
this.loadCustomizations()
|
||||
}
|
||||
this.adapter.userSize = this.user?.preferences?.size
|
||||
this.adapter.hairColor = this.user?.preferences?.hair?.color
|
||||
this.adapter.userSize = user.preferences?.size
|
||||
this.adapter.hairColor = user.preferences?.hair?.color
|
||||
this.adapter.gemBalance = user.gemCount
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.habitrpg.android.habitica.ui.adapter.CustomizationEquipmentRecyclerVi
|
|||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarginDecoration
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -27,6 +28,8 @@ class AvatarEquipmentFragment :
|
|||
|
||||
@Inject
|
||||
lateinit var inventoryRepository: InventoryRepository
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
override var binding: FragmentRefreshRecyclerviewBinding? = null
|
||||
|
||||
|
|
@ -51,7 +54,7 @@ class AvatarEquipmentFragment :
|
|||
adapter.getSelectCustomizationEvents()
|
||||
.flatMap { equipment ->
|
||||
val key = (if (equipment.key?.isNotBlank() != true) activeEquipment else equipment.key) ?: ""
|
||||
inventoryRepository.equip(user, if (user?.preferences?.costume == true) "costume" else "equipped", key)
|
||||
inventoryRepository.equip(userViewModel.user.value, if (userViewModel.user.value?.preferences?.costume == true) "costume" else "equipped", key)
|
||||
}
|
||||
.subscribe({ }, RxErrorHandler.handleEmptyError())
|
||||
)
|
||||
|
|
@ -143,7 +146,7 @@ class AvatarEquipmentFragment :
|
|||
if (this.type == null || user.preferences == null) {
|
||||
return
|
||||
}
|
||||
val outfit = if (user.preferences?.costume == true) this.user?.items?.gear?.costume else this.user?.items?.gear?.equipped
|
||||
val outfit = if (user.preferences?.costume == true) user.items?.gear?.costume else user.items?.gear?.equipped
|
||||
val activeEquipment = when (this.type) {
|
||||
"headAccessory" -> outfit?.headAccessory
|
||||
"back" -> outfit?.back
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class EquipmentDetailFragment :
|
|||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
compositeSubscription.add(
|
||||
this.adapter.equipEvents.flatMapMaybe { key -> inventoryRepository.equipGear(user, key, isCostume ?: false).firstElement() }
|
||||
this.adapter.equipEvents.flatMapMaybe { key -> inventoryRepository.equipGear(null, key, isCostume ?: false).firstElement() }
|
||||
.subscribe({ }, RxErrorHandler.handleEmptyError())
|
||||
)
|
||||
return super.onCreateView(inflater, container, savedInstanceState)
|
||||
|
|
|
|||
|
|
@ -45,10 +45,10 @@ class EquipmentOverviewFragment : BaseMainFragment<FragmentEquipmentOverviewBind
|
|||
it?.items?.gear?.let {
|
||||
updateGearData(it)
|
||||
}
|
||||
binding?.autoEquipSwitch?.isChecked = user?.preferences?.autoEquip ?: false
|
||||
binding?.costumeSwitch?.isChecked = user?.preferences?.costume ?: false
|
||||
binding?.autoEquipSwitch?.isChecked = viewModel.usesAutoEquip
|
||||
binding?.costumeSwitch?.isChecked = viewModel.usesCostume
|
||||
|
||||
binding?.costumeView?.isEnabled = user?.preferences?.costume == true
|
||||
binding?.costumeView?.isEnabled = viewModel.usesCostume
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
package com.habitrpg.android.habitica.ui.fragments.inventory.items
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
|
|
@ -18,17 +21,23 @@ import com.habitrpg.android.habitica.helpers.MainNavigationController
|
|||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.interactors.HatchPetUseCase
|
||||
import com.habitrpg.android.habitica.models.inventory.*
|
||||
import com.habitrpg.android.habitica.models.responses.SkillResponse
|
||||
import com.habitrpg.android.habitica.models.user.OwnedItem
|
||||
import com.habitrpg.android.habitica.models.user.OwnedPet
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.activities.BaseActivity
|
||||
import com.habitrpg.android.habitica.ui.activities.MainActivity
|
||||
import com.habitrpg.android.habitica.ui.activities.SkillMemberActivity
|
||||
import com.habitrpg.android.habitica.ui.adapter.inventory.ItemRecyclerAdapter
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.EmptyItem
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import com.habitrpg.android.habitica.ui.helpers.loadImage
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.OpenedMysteryitemDialog
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import javax.inject.Inject
|
||||
|
||||
class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshLayout.OnRefreshListener {
|
||||
|
|
@ -41,11 +50,15 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
lateinit var userRepository: UserRepository
|
||||
@Inject
|
||||
internal lateinit var hatchPetUseCase: HatchPetUseCase
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
var adapter: ItemRecyclerAdapter? = null
|
||||
var itemType: String? = null
|
||||
var transformationItems: MutableList<OwnedItem> = mutableListOf()
|
||||
var itemTypeText: String? = null
|
||||
var user: User? = null
|
||||
private var selectedSpecialItem: SpecialItem? = null
|
||||
internal var layoutManager: androidx.recyclerview.widget.LinearLayoutManager? = null
|
||||
|
||||
override var binding: FragmentItemsBinding? = null
|
||||
|
|
@ -91,7 +104,7 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
adapter = ItemRecyclerAdapter(context, user)
|
||||
}
|
||||
binding?.recyclerView?.adapter = adapter
|
||||
|
||||
adapter?.useSpecialEvents?.subscribeWithErrorHandler { onSpecialItemSelected(it) }?.let { compositeSubscription.add(it) }
|
||||
adapter?.let { adapter ->
|
||||
compositeSubscription.add(
|
||||
adapter.getSellItemFlowable()
|
||||
|
|
@ -112,7 +125,7 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
)
|
||||
compositeSubscription.add(
|
||||
adapter.getOpenMysteryItemFlowable()
|
||||
.flatMap { inventoryRepository.openMysteryItem(user) }
|
||||
.flatMap { inventoryRepository.openMysteryItem(userViewModel.user.value) }
|
||||
.doOnNext {
|
||||
val activity = activity as? MainActivity
|
||||
if (activity != null) {
|
||||
|
|
@ -123,7 +136,7 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
dialog.binding.titleView.text = it.text
|
||||
dialog.binding.descriptionView.text = it.notes
|
||||
dialog.addButton(R.string.equip, true) { _, _ ->
|
||||
inventoryRepository.equip(user, "equipped", it.key ?: "").subscribe({}, RxErrorHandler.handleEmptyError())
|
||||
inventoryRepository.equip(userViewModel.user.value, "equipped", it.key ?: "").subscribe({}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
dialog.addCloseButton()
|
||||
dialog.enqueue()
|
||||
|
|
@ -253,7 +266,9 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
adapter?.data = items
|
||||
}
|
||||
.map { items -> items.mapNotNull { it.key } }
|
||||
.flatMap { inventoryRepository.getItems(itemClass, it.toTypedArray()) }
|
||||
.flatMap {
|
||||
inventoryRepository.getItems(itemClass, it.toTypedArray())
|
||||
}
|
||||
.map {
|
||||
val itemMap = mutableMapOf<String, Item>()
|
||||
for (item in it) {
|
||||
|
|
@ -268,6 +283,7 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
RxErrorHandler.handleEmptyError()
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
compositeSubscription.add(inventoryRepository.getPets().subscribe({ adapter?.setExistingPets(it) }, RxErrorHandler.handleEmptyError()))
|
||||
|
|
@ -286,6 +302,51 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
MainNavigationController.navigate(R.id.marketFragment)
|
||||
}
|
||||
|
||||
private fun onSpecialItemSelected(specialItem: SpecialItem) {
|
||||
selectedSpecialItem = specialItem
|
||||
val intent = Intent(activity, SkillMemberActivity::class.java)
|
||||
memberSelectionResult.launch(intent)
|
||||
}
|
||||
|
||||
private val memberSelectionResult =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
useSpecialItem(selectedSpecialItem, it.data?.getStringExtra("member_id"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun useSpecialItem(specialItem: SpecialItem?, memberID: String? = null) {
|
||||
if (specialItem == null || memberID == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val observable: Flowable<SkillResponse> =
|
||||
userRepository.useSkill(specialItem.key, specialItem.target, memberID)
|
||||
|
||||
compositeSubscription.add(
|
||||
observable.subscribe(
|
||||
{ skillResponse -> this.displaySpecialItemResult(specialItem) },
|
||||
RxErrorHandler.handleEmptyError()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun displaySpecialItemResult(specialItem: SpecialItem?) {
|
||||
if (!isAdded) return
|
||||
|
||||
val activity = activity as? MainActivity
|
||||
activity?.let {
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
it.snackbarContainer,
|
||||
context?.getString(R.string.used_skill_without_mana, specialItem?.text),
|
||||
HabiticaSnackbar.SnackbarDisplayType.BLUE
|
||||
)
|
||||
}
|
||||
|
||||
loadItems()
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val ITEM_TYPE_KEY = "CLASS_TYPE_KEY"
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ class ItemsFragment : BaseMainFragment<FragmentViewpagerBinding>() {
|
|||
4 -> "special"
|
||||
else -> ""
|
||||
}
|
||||
fragment.user = this@ItemsFragment.user
|
||||
fragment.itemTypeText =
|
||||
if (position == 4 && isAdded) getString(R.string.special_items)
|
||||
else getPageTitle(position)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.habitrpg.android.habitica.ui.adapter.inventory.ShopRecyclerAdapter
|
|||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.RecyclerViewState
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.CurrencyViews
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import javax.inject.Inject
|
||||
|
|
@ -44,6 +45,8 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
|
|||
lateinit var socialRepository: SocialRepository
|
||||
@Inject
|
||||
lateinit var configManager: AppConfigManager
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
private var layoutManager: GridLayoutManager? = null
|
||||
|
||||
|
|
@ -106,7 +109,7 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
|
|||
this.shopIdentifier = savedInstanceState.getString(SHOP_IDENTIFIER_KEY, "")
|
||||
}
|
||||
|
||||
adapter?.selectedGearCategory = user?.stats?.habitClass ?: ""
|
||||
adapter?.selectedGearCategory = userViewModel.user.value?.stats?.habitClass ?: ""
|
||||
|
||||
if (shop != null) {
|
||||
adapter?.setShop(shop)
|
||||
|
|
@ -122,15 +125,10 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
|
|||
}
|
||||
}
|
||||
|
||||
compositeSubscription.add(
|
||||
userRepository.getUser().subscribe(
|
||||
{
|
||||
adapter?.user = user
|
||||
updateCurrencyView(it)
|
||||
},
|
||||
RxErrorHandler.handleEmptyError()
|
||||
)
|
||||
)
|
||||
userViewModel.user.observe(viewLifecycleOwner) {
|
||||
adapter?.user = it
|
||||
updateCurrencyView(it)
|
||||
}
|
||||
|
||||
compositeSubscription.add(
|
||||
socialRepository.getGroup(Group.TAVERN_ID)
|
||||
|
|
@ -183,7 +181,7 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
|
|||
this.inventoryRepository.retrieveShopInventory(shopUrl)
|
||||
.map { shop1 ->
|
||||
if (shop1.identifier == Shop.MARKET) {
|
||||
val user = user
|
||||
val user = userViewModel.user.value
|
||||
val specialCategory = ShopCategory()
|
||||
specialCategory.text = getString(R.string.special)
|
||||
if (user?.isValid == true && user.purchased?.plan?.isActive == true) {
|
||||
|
|
@ -315,9 +313,9 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
|
|||
private const val SHOP_IDENTIFIER_KEY = "SHOP_IDENTIFIER_KEY"
|
||||
}
|
||||
|
||||
private fun updateCurrencyView(user: User) {
|
||||
currencyView.gold = user.stats?.gp ?: 0.0
|
||||
currencyView.gems = user.gemCount.toDouble()
|
||||
currencyView.hourglasses = user.hourglassCount.toDouble()
|
||||
private fun updateCurrencyView(user: User?) {
|
||||
currencyView.gold = user?.stats?.gp ?: 0.0
|
||||
currencyView.gems = user?.gemCount?.toDouble() ?: 0.0
|
||||
currencyView.hourglasses = user?.hourglassCount?.toDouble() ?: 0.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.habitrpg.android.habitica.ui.adapter.inventory.MountDetailRecyclerAda
|
|||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarginDecoration
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
class MountDetailRecyclerFragment :
|
||||
|
|
@ -26,6 +27,8 @@ class MountDetailRecyclerFragment :
|
|||
|
||||
@Inject
|
||||
internal lateinit var inventoryRepository: InventoryRepository
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
var adapter: MountDetailRecyclerAdapter? = null
|
||||
var animalType: String? = null
|
||||
|
|
@ -86,14 +89,15 @@ class MountDetailRecyclerFragment :
|
|||
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
|
||||
this.loadItems()
|
||||
|
||||
adapter?.getEquipFlowable()?.flatMap { key -> inventoryRepository.equip(user, "mount", key) }
|
||||
adapter?.getEquipFlowable()?.flatMap { key -> inventoryRepository.equip(null, "mount", key) }
|
||||
?.subscribe(
|
||||
{
|
||||
user?.let { updatedUser -> adapter?.setUser(updatedUser) }
|
||||
adapter?.currentMount = it.currentMount
|
||||
},
|
||||
RxErrorHandler.handleEmptyError()
|
||||
)?.let { compositeSubscription.add(it) }
|
||||
}
|
||||
userViewModel.user.observe(viewLifecycleOwner) { adapter?.currentMount = it?.currentMount }
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
this.animalType = savedInstanceState.getString(ANIMAL_TYPE_KEY, "")
|
||||
|
|
@ -134,7 +138,6 @@ class MountDetailRecyclerFragment :
|
|||
return@map mountMap
|
||||
}.doOnNext {
|
||||
adapter?.setOwnedMounts(it)
|
||||
user?.let { updatedUser -> adapter?.setUser(updatedUser) }
|
||||
},
|
||||
{ unsortedAnimals, ownedAnimals ->
|
||||
val items = mutableListOf<Any>()
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import com.habitrpg.android.habitica.ui.adapter.inventory.PetDetailRecyclerAdapt
|
|||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemDialogFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import io.reactivex.rxjava3.core.Maybe
|
||||
import io.reactivex.rxjava3.kotlin.Flowables
|
||||
import javax.inject.Inject
|
||||
|
|
@ -34,6 +35,8 @@ class PetDetailRecyclerFragment :
|
|||
lateinit var inventoryRepository: InventoryRepository
|
||||
@Inject
|
||||
lateinit var feedPetUseCase: FeedPetUseCase
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
var adapter: PetDetailRecyclerAdapter = PetDetailRecyclerAdapter()
|
||||
private var animalType: String? = null
|
||||
|
|
@ -109,14 +112,15 @@ class PetDetailRecyclerFragment :
|
|||
|
||||
compositeSubscription.add(
|
||||
adapter.getEquipFlowable()
|
||||
.flatMap { key -> inventoryRepository.equip(user, "pet", key) }
|
||||
.flatMap { key -> inventoryRepository.equip(null, "pet", key) }
|
||||
.subscribe(
|
||||
{
|
||||
user?.let { updatedUser -> adapter.setUser(updatedUser) }
|
||||
adapter.currentPet = it.currentPet
|
||||
},
|
||||
RxErrorHandler.handleEmptyError()
|
||||
)
|
||||
)
|
||||
userViewModel.user.observe(viewLifecycleOwner) { adapter.currentPet = it?.currentPet }
|
||||
compositeSubscription.add(adapter.feedFlowable.subscribe({ showFeedingDialog(it.first, it.second) }, RxErrorHandler.handleEmptyError()))
|
||||
|
||||
view.post { setGridSpanCount(view.width) }
|
||||
|
|
@ -168,7 +172,6 @@ class PetDetailRecyclerFragment :
|
|||
return@map petMap
|
||||
}.doOnNext {
|
||||
adapter.setOwnedPets(it)
|
||||
user?.let { updatedUser -> adapter.setUser(updatedUser) }
|
||||
}
|
||||
).map {
|
||||
val items = mutableListOf<Any>()
|
||||
|
|
|
|||
|
|
@ -56,8 +56,7 @@ class StableFragment : BaseMainFragment<FragmentViewpagerBinding>() {
|
|||
fragment.itemType = "mounts"
|
||||
}
|
||||
}
|
||||
fragment.user = this@StableFragment.user
|
||||
fragment.itemTypeText = getPageTitle(position).toString()
|
||||
fragment.itemTypeText = getPageTitle(position)
|
||||
|
||||
return fragment
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.habitrpg.android.habitica.ui.fragments.BaseFragment
|
|||
import com.habitrpg.android.habitica.ui.helpers.EmptyItem
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarginDecoration
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.core.Maybe
|
||||
import io.reactivex.rxjava3.kotlin.combineLatest
|
||||
|
|
@ -39,11 +40,12 @@ class StableRecyclerFragment :
|
|||
lateinit var userRepository: UserRepository
|
||||
@Inject
|
||||
lateinit var configManager: AppConfigManager
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
var adapter: StableRecyclerAdapter? = null
|
||||
var itemType: String? = null
|
||||
var itemTypeText: String? = null
|
||||
var user: User? = null
|
||||
internal var layoutManager: androidx.recyclerview.widget.GridLayoutManager? = null
|
||||
|
||||
override var binding: FragmentRefreshRecyclerviewBinding? = null
|
||||
|
|
@ -96,7 +98,6 @@ class StableRecyclerFragment :
|
|||
adapter = binding?.recyclerView?.adapter as? StableRecyclerAdapter
|
||||
if (adapter == null) {
|
||||
adapter = StableRecyclerAdapter()
|
||||
user?.let { adapter?.setUser(it) }
|
||||
adapter?.animalIngredientsRetriever = { animal, callback ->
|
||||
Maybe.zip(
|
||||
inventoryRepository.getItems(Egg::class.java, arrayOf(animal.animal)).firstElement(),
|
||||
|
|
@ -119,11 +120,15 @@ class StableRecyclerFragment :
|
|||
adapter?.let {
|
||||
compositeSubscription.add(
|
||||
it.getEquipFlowable()
|
||||
.flatMap { key -> inventoryRepository.equip(user, if (itemType == "pets") "pet" else "mount", key) }
|
||||
.flatMap { key -> inventoryRepository.equip(null, if (itemType == "pets") "pet" else "mount", key) }
|
||||
.subscribe({ }, RxErrorHandler.handleEmptyError())
|
||||
)
|
||||
}
|
||||
}
|
||||
userViewModel.user.observe(viewLifecycleOwner) {
|
||||
adapter?.currentPet = it?.currentPet
|
||||
adapter?.currentMount = it?.currentMount
|
||||
}
|
||||
|
||||
this.loadItems()
|
||||
view.post { setGridSpanCount(view.width) }
|
||||
|
|
|
|||
|
|
@ -64,11 +64,11 @@ class AccountPreferenceFragment: BasePreferencesFragment(),
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
|
||||
preferenceManager.sharedPreferences?.registerOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||
preferenceManager.sharedPreferences?.unregisterOnSharedPreferenceChangeListener(this)
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
|
|
@ -130,8 +130,8 @@ class AccountPreferenceFragment: BasePreferencesFragment(),
|
|||
preference?.summary = value
|
||||
}
|
||||
|
||||
override fun onPreferenceTreeClick(preference: Preference?): Boolean {
|
||||
when(preference?.key) {
|
||||
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
||||
when(preference.key) {
|
||||
"username" -> showLoginNameDialog()
|
||||
"confirm_username" -> showConfirmUsernameDialog()
|
||||
"email" -> {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class DayStartPreferenceDialogFragment : PreferenceDialogFragmentCompat() {
|
|||
return lastHour.toString() + ":00"
|
||||
}
|
||||
|
||||
override fun onCreateDialogView(context: Context?): View {
|
||||
override fun onCreateDialogView(context: Context): View {
|
||||
val wrapper = LinearLayout(context)
|
||||
wrapper.orientation = LinearLayout.VERTICAL
|
||||
picker = TimePicker(context)
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ class EmailNotificationsPreferencesFragment : BasePreferencesFragment(), SharedP
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
preferenceScreen.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
|
||||
preferenceScreen.sharedPreferences?.registerOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
preferenceScreen.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||
preferenceScreen.sharedPreferences?.unregisterOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
override fun setupPreferences() { /* no-on */ }
|
||||
|
|
|
|||
|
|
@ -62,16 +62,16 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
|
||||
override fun setupPreferences() {
|
||||
timePreference = findPreference("reminder_time") as? TimePreference
|
||||
val useReminder = preferenceManager.sharedPreferences.getBoolean("use_reminder", false)
|
||||
timePreference?.isEnabled = useReminder
|
||||
val useReminder = preferenceManager.sharedPreferences?.getBoolean("use_reminder", false)
|
||||
timePreference?.isEnabled = useReminder ?: false
|
||||
|
||||
pushNotificationsPreference = findPreference("pushNotifications") as? PreferenceScreen
|
||||
val usePushNotifications = preferenceManager.sharedPreferences.getBoolean("usePushNotifications", true)
|
||||
pushNotificationsPreference?.isEnabled = usePushNotifications
|
||||
val usePushNotifications = preferenceManager.sharedPreferences?.getBoolean("usePushNotifications", true)
|
||||
pushNotificationsPreference?.isEnabled = usePushNotifications ?: false
|
||||
|
||||
emailNotificationsPreference = findPreference("emailNotifications") as? PreferenceScreen
|
||||
val useEmailNotifications = preferenceManager.sharedPreferences.getBoolean("useEmailNotifications", true)
|
||||
emailNotificationsPreference?.isEnabled = useEmailNotifications
|
||||
val useEmailNotifications = preferenceManager.sharedPreferences?.getBoolean("useEmailNotifications", true)
|
||||
emailNotificationsPreference?.isEnabled = useEmailNotifications ?: false
|
||||
|
||||
classSelectionPreference = findPreference("choose_class")
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
|
||||
serverUrlPreference = findPreference("server_url") as? ListPreference
|
||||
serverUrlPreference?.isVisible = false
|
||||
serverUrlPreference?.summary = preferenceManager.sharedPreferences.getString("server_url", "")
|
||||
serverUrlPreference?.summary = preferenceManager.sharedPreferences?.getString("server_url", "")
|
||||
|
||||
val themePreference = findPreference("theme_name") as? ListPreference
|
||||
themePreference?.summary = themePreference?.entry ?: "Default"
|
||||
|
|
@ -101,11 +101,11 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
|
||||
preferenceManager.sharedPreferences?.registerOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||
preferenceManager.sharedPreferences?.unregisterOnSharedPreferenceChangeListener(this)
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ class PushNotificationsPreferencesFragment : BasePreferencesFragment(), SharedPr
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
preferenceScreen.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
|
||||
preferenceScreen.sharedPreferences?.registerOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
preferenceScreen.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||
preferenceScreen.sharedPreferences?.unregisterOnSharedPreferenceChangeListener(this)
|
||||
}
|
||||
|
||||
override fun setupPreferences() { /* no-on */ }
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class TimePreferenceDialogFragment : PreferenceDialogFragmentCompat() {
|
|||
return lastHour.toString() + ":" + String.format(Locale.UK, "%02d", lastMinute)
|
||||
}
|
||||
|
||||
override fun onCreateDialogView(context: Context?): View {
|
||||
override fun onCreateDialogView(context: Context): View {
|
||||
picker = TimePicker(context)
|
||||
picker.setIs24HourView(android.text.format.DateFormat.is24HourFormat(context))
|
||||
return picker
|
||||
|
|
|
|||
|
|
@ -23,12 +23,14 @@ import com.habitrpg.android.habitica.ui.activities.SkillTasksActivity
|
|||
import com.habitrpg.android.habitica.ui.adapter.SkillsRecyclerViewAdapter
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.Companion.showSnackbar
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class SkillsFragment : BaseMainFragment<FragmentSkillsBinding>() {
|
||||
internal var adapter: SkillsRecyclerViewAdapter? = null
|
||||
|
|
@ -36,20 +38,16 @@ class SkillsFragment : BaseMainFragment<FragmentSkillsBinding>() {
|
|||
|
||||
override var binding: FragmentSkillsBinding? = null
|
||||
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
override fun createBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSkillsBinding {
|
||||
return FragmentSkillsBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override var user: User? = null
|
||||
set(value) {
|
||||
field = value
|
||||
checkUserLoadSkills()
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
adapter = SkillsRecyclerViewAdapter()
|
||||
adapter?.useSkillEvents?.subscribeWithErrorHandler { onSkillSelected(it) }?.let { compositeSubscription.add(it) }
|
||||
checkUserLoadSkills()
|
||||
|
||||
this.tutorialStepIdentifier = "skills"
|
||||
this.tutorialText = getString(R.string.tutorial_skills)
|
||||
|
|
@ -62,20 +60,21 @@ class SkillsFragment : BaseMainFragment<FragmentSkillsBinding>() {
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
userViewModel.user.observe(viewLifecycleOwner) { user ->
|
||||
user?.let { checkUserLoadSkills(it) }
|
||||
}
|
||||
binding?.recyclerView?.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(activity)
|
||||
binding?.recyclerView?.adapter = adapter
|
||||
binding?.recyclerView?.itemAnimator = SafeDefaultItemAnimator()
|
||||
}
|
||||
|
||||
private fun checkUserLoadSkills() {
|
||||
if (user == null || adapter == null) {
|
||||
private fun checkUserLoadSkills(user: User) {
|
||||
if (adapter == null) {
|
||||
return
|
||||
}
|
||||
adapter?.mana = this.user?.stats?.mp ?: 0.0
|
||||
adapter?.level = this.user?.stats?.lvl ?: 0
|
||||
adapter?.specialItems = this.user?.items?.special
|
||||
user?.let { user ->
|
||||
adapter?.mana = user.stats?.mp ?: 0.0
|
||||
adapter?.level = user.stats?.lvl ?: 0
|
||||
adapter?.specialItems = user.items?.special
|
||||
Flowable.combineLatest(
|
||||
userRepository.getSkills(user),
|
||||
userRepository.getSpecialItems(user),
|
||||
|
|
@ -89,9 +88,7 @@ class SkillsFragment : BaseMainFragment<FragmentSkillsBinding>() {
|
|||
}
|
||||
return@combineLatest allEntries
|
||||
}
|
||||
)
|
||||
.subscribe({ skills -> adapter?.setSkillList(skills) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
).subscribe({ skills -> adapter?.setSkillList(skills) }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
private fun onSkillSelected(skill: Skill) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import android.os.Bundle
|
|||
import android.view.*
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.habitrpg.android.habitica.MainNavDirections
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
|
|
@ -88,7 +89,14 @@ class InboxMessageListFragment : BaseMainFragment<FragmentInboxMessageListBindin
|
|||
{ member ->
|
||||
setReceivingUser(member.username, member.id)
|
||||
activity?.title = member.displayName
|
||||
chatAdapter = InboxAdapter(user, member)
|
||||
chatAdapter = InboxAdapter(viewModel.user.value, member)
|
||||
chatAdapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
||||
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
|
||||
if (positionStart == 0) {
|
||||
binding?.recyclerView?.scrollToPosition(0)
|
||||
}
|
||||
}
|
||||
})
|
||||
viewModel.messages.observe(this.viewLifecycleOwner) {
|
||||
markMessagesAsRead(it)
|
||||
chatAdapter?.submitList(it)
|
||||
|
|
@ -170,7 +178,7 @@ class InboxMessageListFragment : BaseMainFragment<FragmentInboxMessageListBindin
|
|||
}
|
||||
|
||||
private fun markMessagesAsRead(messages: List<ChatMessage>) {
|
||||
socialRepository.markSomePrivateMessagesAsRead(user, messages)
|
||||
socialRepository.markSomePrivateMessagesAsRead(viewModel.user.value, messages)
|
||||
}
|
||||
|
||||
private fun startAutoRefreshing() {
|
||||
|
|
@ -215,7 +223,6 @@ class InboxMessageListFragment : BaseMainFragment<FragmentInboxMessageListBindin
|
|||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
binding?.recyclerView?.scrollToPosition(0)
|
||||
viewModel.invalidateDataSource()
|
||||
},
|
||||
{ error ->
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class InboxOverviewFragment : BaseMainFragment<FragmentInboxBinding>(), androidx
|
|||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
this.hidesToolbar = true
|
||||
compositeSubscription.add(this.socialRepository.markPrivateMessagesRead(user).subscribe({ }, RxErrorHandler.handleEmptyError()))
|
||||
compositeSubscription.add(this.socialRepository.markPrivateMessagesRead(null).subscribe({ }, RxErrorHandler.handleEmptyError()))
|
||||
return super.onCreateView(inflater, container, savedInstanceState)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.habitrpg.android.habitica.modules.AppModule
|
|||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
|
||||
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
|
|
@ -38,6 +39,8 @@ class QuestDetailFragment : BaseMainFragment<FragmentQuestDetailBinding>() {
|
|||
lateinit var inventoryRepository: InventoryRepository
|
||||
@field:[Inject Named(AppModule.NAMED_USER_ID)]
|
||||
lateinit var userId: String
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
override var binding: FragmentQuestDetailBinding? = null
|
||||
|
||||
|
|
@ -101,7 +104,7 @@ class QuestDetailFragment : BaseMainFragment<FragmentQuestDetailBinding>() {
|
|||
compositeSubscription.add(
|
||||
socialRepository.getMember(quest?.leader).subscribe(
|
||||
{ member ->
|
||||
if (context != null && binding?.questLeaderView != null && member != null) {
|
||||
if (context != null && binding?.questLeaderView != null) {
|
||||
binding?.questLeaderView?.text = context?.getString(R.string.quest_leader_header, member.displayName)
|
||||
}
|
||||
},
|
||||
|
|
@ -109,6 +112,7 @@ class QuestDetailFragment : BaseMainFragment<FragmentQuestDetailBinding>() {
|
|||
)
|
||||
)
|
||||
|
||||
val user = userViewModel.user.value
|
||||
if (binding?.questResponseWrapper != null) {
|
||||
if (userId != party?.quest?.leader && user?.party?.quest?.key == group.quest?.key && user?.party?.quest?.RSVPNeeded == false) {
|
||||
binding?.questLeaveButton?.visibility = View.VISIBLE
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import com.habitrpg.android.habitica.ui.viewHolders.tasks.DailyViewHolder
|
|||
import com.habitrpg.android.habitica.ui.viewHolders.tasks.HabitViewHolder
|
||||
import com.habitrpg.android.habitica.ui.viewHolders.tasks.RewardViewHolder
|
||||
import com.habitrpg.android.habitica.ui.viewHolders.tasks.TodoViewHolder
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import retrofit2.HttpException
|
||||
|
|
@ -41,6 +42,9 @@ class ChallengeDetailFragment : BaseMainFragment<FragmentChallengeDetailBinding>
|
|||
lateinit var challengeRepository: ChallengeRepository
|
||||
@Inject
|
||||
lateinit var socialRepository: SocialRepository
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
|
||||
override var binding: FragmentChallengeDetailBinding? = null
|
||||
|
||||
|
|
@ -236,7 +240,7 @@ class ChallengeDetailFragment : BaseMainFragment<FragmentChallengeDetailBinding>
|
|||
binding?.creatorAvatarview?.setAvatar(creator)
|
||||
binding?.creatorLabel?.tier = creator.contributor?.level ?: 0
|
||||
binding?.creatorLabel?.username = creator.displayName
|
||||
isCreator = creator.id == user?.id
|
||||
isCreator = creator.id == userViewModel.userID
|
||||
this.activity?.invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import com.habitrpg.android.habitica.ui.activities.GroupFormActivity
|
|||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
|
||||
import com.habitrpg.android.habitica.ui.helpers.setMarkdown
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.roundToInt
|
||||
|
|
@ -40,6 +41,8 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
|
|||
lateinit var socialRepository: SocialRepository
|
||||
@Inject
|
||||
lateinit var configManager: AppConfigManager
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
override var binding: FragmentNoPartyBinding? = null
|
||||
|
||||
|
|
@ -65,7 +68,7 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
|
|||
parentFragmentManager.popBackStack()
|
||||
MainNavigationController.navigate(
|
||||
R.id.partyFragment,
|
||||
bundleOf(Pair("partyID", user?.party?.id))
|
||||
bundleOf(Pair("partyID", userViewModel.partyID))
|
||||
)
|
||||
},
|
||||
RxErrorHandler.handleEmptyError()
|
||||
|
|
@ -92,7 +95,7 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
|
|||
|
||||
binding?.usernameTextview?.setOnClickListener {
|
||||
val clipboard = context?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager
|
||||
val clip = ClipData.newPlainText(context?.getString(R.string.username), user?.username)
|
||||
val clip = ClipData.newPlainText(context?.getString(R.string.username), userViewModel.username)
|
||||
clipboard?.setPrimaryClip(clip)
|
||||
val activity = activity
|
||||
if (activity != null) {
|
||||
|
|
@ -103,7 +106,7 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
|
|||
binding?.createPartyButton?.setOnClickListener {
|
||||
val bundle = Bundle()
|
||||
bundle.putString("groupType", "party")
|
||||
bundle.putString("leader", user?.id)
|
||||
bundle.putString("leader", userViewModel.userID)
|
||||
val intent = Intent(activity, GroupFormActivity::class.java)
|
||||
intent.putExtras(bundle)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
|
||||
|
|
@ -132,14 +135,15 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
|
|||
}
|
||||
}
|
||||
|
||||
if ((user?.invitations?.parties?.count() ?: 0) > 0) {
|
||||
val partyInvitations = userViewModel.partyInvitations
|
||||
if (partyInvitations.size > 0) {
|
||||
binding?.invitationWrapper?.visibility = View.VISIBLE
|
||||
user?.invitations?.parties?.let { binding?.invitationsView?.setInvitations(it) }
|
||||
binding?.invitationsView?.setInvitations(partyInvitations)
|
||||
} else {
|
||||
binding?.invitationWrapper?.visibility = View.GONE
|
||||
}
|
||||
|
||||
binding?.usernameTextview?.text = user?.formattedUsername
|
||||
binding?.usernameTextview?.text = userViewModel.formattedUsername
|
||||
}
|
||||
|
||||
private val groupFormResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
|
|
@ -164,7 +168,7 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
|
|||
}
|
||||
MainNavigationController.navigate(
|
||||
R.id.partyFragment,
|
||||
bundleOf(Pair("partyID", user?.party?.id))
|
||||
bundleOf(Pair("partyID", userViewModel.partyID))
|
||||
)
|
||||
},
|
||||
RxErrorHandler.handleEmptyError()
|
||||
|
|
@ -196,12 +200,11 @@ class NoPartyFragmentFragment : BaseMainFragment<FragmentNoPartyBinding>() {
|
|||
|
||||
companion object {
|
||||
|
||||
fun newInstance(user: User?): NoPartyFragmentFragment {
|
||||
fun newInstance(): NoPartyFragmentFragment {
|
||||
val args = Bundle()
|
||||
|
||||
val fragment = NoPartyFragmentFragment()
|
||||
fragment.arguments = args
|
||||
fragment.user = user
|
||||
return fragment
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,15 +96,11 @@ class PartyFragment : BaseMainFragment<FragmentViewpagerBinding>() {
|
|||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
val group = viewModel.getGroupData().value
|
||||
if (group != null && this.user != null) {
|
||||
if (group.leaderID == this.user?.id) {
|
||||
inflater.inflate(R.menu.menu_party_admin, menu)
|
||||
if (group.memberCount > 1) {
|
||||
menu.findItem(R.id.menu_guild_leave).isVisible = false
|
||||
}
|
||||
} else {
|
||||
inflater.inflate(R.menu.menu_party, menu)
|
||||
}
|
||||
if (viewModel.isLeader) {
|
||||
inflater.inflate(R.menu.menu_party_admin, menu)
|
||||
menu.findItem(R.id.menu_guild_leave).isVisible = group?.memberCount != 1
|
||||
} else {
|
||||
inflater.inflate(R.menu.menu_party, menu)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,7 +155,7 @@ class PartyFragment : BaseMainFragment<FragmentViewpagerBinding>() {
|
|||
private val sendInvitesResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
val inviteData = HashMap<String, Any>()
|
||||
inviteData["inviter"] = user?.profile?.name ?: ""
|
||||
inviteData["inviter"] = viewModel.user.value?.profile?.name ?: ""
|
||||
val emails = it.data?.getStringArrayExtra(GroupInviteActivity.EMAILS_KEY)
|
||||
if (emails != null && emails.isNotEmpty()) {
|
||||
val invites = ArrayList<HashMap<String, String>>()
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import com.habitrpg.android.habitica.helpers.DeviceName
|
|||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.modules.AppModule
|
||||
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import io.reactivex.rxjava3.core.Completable
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import javax.inject.Inject
|
||||
|
|
@ -42,6 +43,8 @@ class BugFixFragment : BaseMainFragment<FragmentSupportBugFixBinding>() {
|
|||
|
||||
@Inject
|
||||
lateinit var appConfigManager: AppConfigManager
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
override fun injectFragment(component: UserComponent) {
|
||||
component.inject(this)
|
||||
|
|
@ -124,8 +127,7 @@ class BugFixFragment : BaseMainFragment<FragmentSupportBugFixBinding>() {
|
|||
}
|
||||
bodyOfEmail += newLine + Uri.encode("User ID: $userId")
|
||||
|
||||
val user = this.user
|
||||
if (user != null) {
|
||||
userViewModel.user.value?.let { user ->
|
||||
bodyOfEmail += newLine + Uri.encode("Level: " + (user.stats?.lvl ?: 0)) +
|
||||
newLine + Uri.encode(
|
||||
"Class: " + (if (user.preferences?.disableClasses == true) "Disabled" else (user.stats?.habitClass
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ class MountViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject
|
|||
private var binding: MountOverviewItemBinding = MountOverviewItemBinding.bind(itemView)
|
||||
private var owned: Boolean = false
|
||||
var animal: Mount? = null
|
||||
private var user: User? = null
|
||||
private var currentMount: String? = null
|
||||
|
||||
var resources: Resources = itemView.resources
|
||||
|
||||
|
|
@ -27,10 +27,10 @@ class MountViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject
|
|||
itemView.setOnClickListener(this)
|
||||
}
|
||||
|
||||
fun bind(item: Mount, owned: Boolean, user: User?) {
|
||||
fun bind(item: Mount, owned: Boolean, currentMount: String?) {
|
||||
animal = item
|
||||
this.owned = owned
|
||||
this.user = user
|
||||
this.currentMount = currentMount
|
||||
binding.titleTextView.visibility = View.GONE
|
||||
binding.ownedTextView.visibility = View.GONE
|
||||
val imageName = "stable_Mount_Icon_" + item.animal + "-" + item.color
|
||||
|
|
@ -39,7 +39,7 @@ class MountViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject
|
|||
binding.imageView.alpha = 0.2f
|
||||
}
|
||||
binding.imageView.background = null
|
||||
binding.activeIndicator.visibility = if (user?.currentMount.equals(animal?.key)) View.VISIBLE else View.GONE
|
||||
binding.activeIndicator.visibility = if (currentMount.equals(animal?.key)) View.VISIBLE else View.GONE
|
||||
DataBindingUtils.loadImage(itemView.context, imageName) {
|
||||
val drawable = if (owned) it else BitmapDrawable(itemView.context.resources, it.toBitmap().extractAlpha())
|
||||
binding.imageView.background = drawable
|
||||
|
|
@ -53,7 +53,7 @@ class MountViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject
|
|||
val menu = BottomSheetMenu(itemView.context)
|
||||
menu.setTitle(animal?.text)
|
||||
|
||||
val hasCurrentMount = user?.currentMount.equals(animal?.key)
|
||||
val hasCurrentMount = currentMount.equals(animal?.key)
|
||||
val labelId = if (hasCurrentMount) R.string.unequip else R.string.equip
|
||||
menu.addMenuItem(BottomSheetMenuItem(resources.getString(labelId)))
|
||||
menu.setSelectionRunnable {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class PetViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject<S
|
|||
private var potionCount: Int = 0
|
||||
private var ownsSaddles = false
|
||||
private var animal: Pet? = null
|
||||
private var user: User? = null
|
||||
private var currentPet: String? = null
|
||||
|
||||
private var binding: PetDetailItemBinding = PetDetailItemBinding.bind(itemView)
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ class PetViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject<S
|
|||
hasUnlockedEgg: Boolean,
|
||||
hasUnlockedPotion: Boolean,
|
||||
hasMount: Boolean,
|
||||
user: User?
|
||||
currentPet: String?
|
||||
) {
|
||||
this.animal = item
|
||||
isOwned = trained > 0
|
||||
|
|
@ -61,7 +61,7 @@ class PetViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject<S
|
|||
this.hasUnlockedEgg = hasUnlockedEgg
|
||||
this.hasUnlockedPotion = hasUnlockedPotion
|
||||
this.hasMount = hasMount
|
||||
this.user = user
|
||||
this.currentPet = currentPet
|
||||
binding.imageView.visibility = View.VISIBLE
|
||||
binding.itemWrapper.visibility = View.GONE
|
||||
binding.checkmarkView.visibility = View.GONE
|
||||
|
|
@ -93,7 +93,7 @@ class PetViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject<S
|
|||
binding.trainedProgressBar.progressBackgroundTintMode = PorterDuff.Mode.SRC_OVER
|
||||
}
|
||||
binding.imageView.background = null
|
||||
binding.activeIndicator.visibility = if (user?.currentPet.equals(animal?.key)) View.VISIBLE else View.GONE
|
||||
binding.activeIndicator.visibility = if (currentPet.equals(animal?.key)) View.VISIBLE else View.GONE
|
||||
DataBindingUtils.loadImage(itemView.context, imageName) {
|
||||
val resources = itemView.context.resources ?: return@loadImage
|
||||
val drawable = if (trained == 0) BitmapDrawable(resources, it.toBitmap().extractAlpha()) else it
|
||||
|
|
@ -110,7 +110,7 @@ class PetViewHolder(parent: ViewGroup, private val equipEvents: PublishSubject<S
|
|||
val menu = BottomSheetMenu(context)
|
||||
menu.setTitle(animal?.text)
|
||||
|
||||
val hasCurrentPet = user?.currentPet.equals(animal?.key)
|
||||
val hasCurrentPet = currentPet.equals(animal?.key)
|
||||
val labelId = if (hasCurrentPet) R.string.unequip else R.string.equip
|
||||
menu.addMenuItem(BottomSheetMenuItem(itemView.resources.getString(labelId)))
|
||||
|
||||
|
|
|
|||
|
|
@ -15,20 +15,13 @@ import javax.inject.Inject
|
|||
|
||||
abstract class BaseViewModel(initializeComponent: Boolean = true) : ViewModel() {
|
||||
|
||||
val isUserFainted: Boolean
|
||||
get() = (user.value?.stats?.hp ?: 1.0) == 0.0
|
||||
val isUserInParty: Boolean
|
||||
get() = user.value?.hasParty == true
|
||||
|
||||
@Inject
|
||||
lateinit var userRepository: UserRepository
|
||||
@Inject
|
||||
lateinit var userViewModel: MainUserViewModel
|
||||
|
||||
private val _user: MutableLiveData<User?> by lazy {
|
||||
loadUserFromLocal()
|
||||
MutableLiveData<User?>()
|
||||
}
|
||||
val user: LiveData<User?> by lazy {
|
||||
_user
|
||||
userViewModel.user
|
||||
}
|
||||
|
||||
init {
|
||||
|
|
@ -47,11 +40,6 @@ abstract class BaseViewModel(initializeComponent: Boolean = true) : ViewModel()
|
|||
|
||||
internal val disposable = CompositeDisposable()
|
||||
|
||||
internal fun loadUserFromLocal() {
|
||||
disposable.add(userRepository.getUser().observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ _user.value = it }, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
|
||||
fun updateUser(path: String, value: Any) {
|
||||
disposable.add(userRepository.updateUser(path, value)
|
||||
.subscribe({ }, RxErrorHandler.handleEmptyError()))
|
||||
|
|
|
|||
|
|
@ -249,7 +249,8 @@ open class GroupViewModel(initializeComponent: Boolean) : BaseViewModel(initiali
|
|||
}
|
||||
|
||||
fun likeMessage(message: ChatMessage) {
|
||||
val index = _chatMessages.value?.indexOf(message) ?: return
|
||||
val index = _chatMessages.value?.indexOf(message)
|
||||
if (index == null || index < 0) return
|
||||
disposable.add(socialRepository.likeMessage(message).subscribe(
|
||||
{
|
||||
val list = _chatMessages.value?.toMutableList()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
package com.habitrpg.android.habitica.ui.viewmodels
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.invitations.GenericInvitation
|
||||
import com.habitrpg.android.habitica.models.invitations.PartyInvite
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import javax.inject.Inject
|
||||
|
||||
class MainUserViewModel(val userRepository: UserRepository) {
|
||||
|
||||
val formattedUsername: CharSequence?
|
||||
get() = user.value?.formattedUsername
|
||||
val partyInvitations: List<PartyInvite>
|
||||
get() = user.value?.invitations?.parties ?: emptyList()
|
||||
val userID: String?
|
||||
get() = user.value?.id
|
||||
val username: CharSequence
|
||||
get() = user.value?.username ?: ""
|
||||
val partyID: String?
|
||||
get() = user.value?.party?.id
|
||||
val isUserFainted: Boolean
|
||||
get() = (user.value?.stats?.hp ?: 1.0) == 0.0
|
||||
val isUserInParty: Boolean
|
||||
get() = user.value?.hasParty == true
|
||||
|
||||
private val _user: MutableLiveData<User?> by lazy {
|
||||
loadUserFromLocal()
|
||||
MutableLiveData<User?>()
|
||||
}
|
||||
val user: LiveData<User?> by lazy {
|
||||
_user
|
||||
}
|
||||
|
||||
init {
|
||||
HabiticaBaseApplication.userComponent?.inject(this)
|
||||
}
|
||||
|
||||
fun onCleared() {
|
||||
userRepository.close()
|
||||
disposable.clear()
|
||||
}
|
||||
|
||||
internal val disposable = CompositeDisposable()
|
||||
|
||||
internal fun loadUserFromLocal() {
|
||||
disposable.add(userRepository.getUser().observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ _user.value = it }, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
|
||||
fun updateUser(path: String, value: Any) {
|
||||
disposable.add(userRepository.updateUser(path, value)
|
||||
.subscribe({ }, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,10 @@ import com.habitrpg.android.habitica.ui.viewmodels.BaseViewModel
|
|||
import javax.inject.Inject
|
||||
|
||||
class EquipmentOverviewViewModel(savedStateHandle: SavedStateHandle): BaseViewModel() {
|
||||
val usesAutoEquip: Boolean
|
||||
get() = user.value?.preferences?.autoEquip == true
|
||||
val usesCostume: Boolean
|
||||
get() = user.value?.preferences?.costume == true
|
||||
|
||||
@Inject
|
||||
lateinit var inventoryRepository: InventoryRepository
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import androidx.preference.PreferenceViewHolder
|
|||
import com.habitrpg.android.habitica.R
|
||||
|
||||
class ExtraLabelPreference(
|
||||
context: Context?,
|
||||
context: Context,
|
||||
attrs: AttributeSet?
|
||||
) : Preference(context, attrs) {
|
||||
var extraText: String? = null
|
||||
|
|
@ -18,9 +18,9 @@ class ExtraLabelPreference(
|
|||
layoutResource = R.layout.preference_button
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder?) {
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
super.onBindViewHolder(holder)
|
||||
val textView = holder?.itemView?.findViewById<TextView>(R.id.extra_label)
|
||||
val textView = holder.itemView.findViewById<TextView>(R.id.extra_label)
|
||||
textView?.text = extraText
|
||||
extraTextColor?.let {
|
||||
textView?.setTextColor(it)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.databinding.DialogPetSuggestHatchBinding
|
||||
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
||||
|
|
@ -36,6 +37,7 @@ class PetSuggestHatchDialog(context: Context) : HabiticaAlertDialog(context) {
|
|||
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as? LayoutInflater
|
||||
inflater?.let { binding = DialogPetSuggestHatchBinding.inflate(it) }
|
||||
setAdditionalContentView(binding.root)
|
||||
HabiticaBaseApplication.userComponent?.inject(this)
|
||||
}
|
||||
|
||||
fun configure(pet: Animal, egg: Egg?, potion: HatchingPotion?, eggCount: Int, potionCount: Int, hasUnlockedEgg: Boolean, hasUnlockedPotion: Boolean, hasMount: Boolean) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.core.graphics.drawable.toDrawable
|
||||
import androidx.core.os.bundleOf
|
||||
import com.google.firebase.analytics.FirebaseAnalytics
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.InventoryRepository
|
||||
|
|
@ -319,6 +320,7 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop
|
|||
}
|
||||
|
||||
private fun buyItem(quantity: Int) {
|
||||
val application = ownerActivity?.application as? HabiticaBaseApplication
|
||||
FirebaseAnalytics.getInstance(context).logEvent(
|
||||
"item_purchased",
|
||||
bundleOf(
|
||||
|
|
@ -373,7 +375,7 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop
|
|||
"hourglasses" -> ContextCompat.getColor(context, R.color.text_brand)
|
||||
else -> 0
|
||||
}
|
||||
(ownerActivity as? SnackbarActivity)?.showSnackbar(
|
||||
((application?.currentActivity?.get() ?: getActivity() ?: ownerActivity) as? SnackbarActivity)?.showSnackbar(
|
||||
content = text,
|
||||
rightIcon = priceLabel.compoundDrawables[0],
|
||||
rightTextColor = rightTextColor,
|
||||
|
|
|
|||
|
|
@ -158,7 +158,8 @@ class YesterdailyDialog private constructor(context: Context, private val userRe
|
|||
|
||||
private fun configureTaskView(taskView: View, task: Task) {
|
||||
val completed = !task.isDisplayedActive
|
||||
val checkmark = taskView.findViewById<View>(R.id.checkmark)
|
||||
val checkmark = taskView.findViewById<ImageView>(R.id.checkmark)
|
||||
checkmark?.drawable?.setTint(ContextCompat.getColor(context, R.color.gray_400))
|
||||
val checkboxHolder = taskView.findViewById<View>(R.id.checkBoxHolder)
|
||||
val checkboxBackground = taskView.findViewById<View>(R.id.checkbox_background)
|
||||
checkmark?.visibility = if (completed) View.VISIBLE else View.GONE
|
||||
|
|
|
|||
|
|
@ -11,14 +11,7 @@ import com.habitrpg.android.habitica.models.ContentGear
|
|||
import com.habitrpg.android.habitica.models.ContentResult
|
||||
import com.habitrpg.android.habitica.models.FAQArticle
|
||||
import com.habitrpg.android.habitica.models.Skill
|
||||
import com.habitrpg.android.habitica.models.inventory.Customization
|
||||
import com.habitrpg.android.habitica.models.inventory.Egg
|
||||
import com.habitrpg.android.habitica.models.inventory.Equipment
|
||||
import com.habitrpg.android.habitica.models.inventory.Food
|
||||
import com.habitrpg.android.habitica.models.inventory.HatchingPotion
|
||||
import com.habitrpg.android.habitica.models.inventory.Mount
|
||||
import com.habitrpg.android.habitica.models.inventory.Pet
|
||||
import com.habitrpg.android.habitica.models.inventory.QuestContent
|
||||
import com.habitrpg.android.habitica.models.inventory.*
|
||||
import io.realm.RealmList
|
||||
import java.lang.reflect.Type
|
||||
|
||||
|
|
@ -101,6 +94,13 @@ class ContentDeserializer : JsonDeserializer<ContentResult> {
|
|||
result.spells.add(skill)
|
||||
}
|
||||
}
|
||||
|
||||
if (obj.has("special")) {
|
||||
for (entry in obj.get("special").asJsonObject.entrySet()) {
|
||||
result.special.add(context.deserialize(entry.value, SpecialItem::class.java))
|
||||
}
|
||||
}
|
||||
|
||||
result.appearances = context.deserialize(obj.get("appearances"), object : TypeToken<RealmList<Customization>>() {}.type)
|
||||
result.backgrounds = context.deserialize(obj.get("backgrounds"), object : TypeToken<RealmList<Customization>>() {}.type)
|
||||
val noBackground = Customization()
|
||||
|
|
|
|||
|
|
@ -13,10 +13,12 @@ class OwnedItemListDeserializer : JsonDeserializer<List<OwnedItem>> {
|
|||
val entrySet = json?.asJsonObject?.entrySet()
|
||||
if (entrySet != null) {
|
||||
for (entry in entrySet) {
|
||||
val item = OwnedItem()
|
||||
item.key = entry.key
|
||||
item.numberOwned = entry.value.asInt
|
||||
ownedItems.add(item)
|
||||
if (entry.value.isJsonPrimitive){
|
||||
val item = OwnedItem()
|
||||
item.key = entry.key
|
||||
item.numberOwned = entry.value.asInt
|
||||
ownedItems.add(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ownedItems
|
||||
|
|
|
|||
|
|
@ -99,8 +99,7 @@ class UserDeserializer : JsonDeserializer<User> {
|
|||
item.key = "inventory_present"
|
||||
item.userID = user.id
|
||||
item.numberOwned = user.purchased?.plan?.mysteryItemCount ?: 0
|
||||
user.items?.special?.ownedItems = RealmList()
|
||||
user.items?.special?.ownedItems?.add(item)
|
||||
user.items?.special?.add(item)
|
||||
user.items?.setItemTypes()
|
||||
}
|
||||
if (obj.has("auth")) {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class AddTaskWidgetProvider : BaseWidgetProvider() {
|
|||
}
|
||||
|
||||
private fun getSelectedTaskType(widgetId: Int): TaskType {
|
||||
val preferences = PreferenceManager.getDefaultSharedPreferences(this.context)
|
||||
return TaskType.from(preferences.getString("add_task_widget_$widgetId", TaskType.HABIT.value)) ?: TaskType.HABIT
|
||||
val preferences = context?.let { PreferenceManager.getDefaultSharedPreferences(it) }
|
||||
return TaskType.from(preferences?.getString("add_task_widget_$widgetId", TaskType.HABIT.value)) ?: TaskType.HABIT
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
package com.habitrpg.android.habitica.models.user
|
||||
|
||||
import io.kotest.common.ExperimentalKotest
|
||||
import io.kotest.core.spec.style.WordSpec
|
||||
import io.kotest.datatest.withData
|
||||
import io.kotest.matchers.shouldBe
|
||||
|
||||
@ExperimentalKotest
|
||||
class SpecialItemsTest : WordSpec({
|
||||
data class SpecialItemsData(val snowBalls: Int, val seafoam: Int, val shinyseed: Int, val spookySparkles: Int)
|
||||
lateinit var items: SpecialItems
|
||||
beforeEach {
|
||||
items = SpecialItems()
|
||||
}
|
||||
"hasSpecialItems" should {
|
||||
"false if none are owned" {
|
||||
items.hasSpecialItems shouldBe false
|
||||
}
|
||||
"true if any are owned" {
|
||||
items.snowball = 4
|
||||
items.hasSpecialItems shouldBe true
|
||||
}
|
||||
withData(
|
||||
SpecialItemsData(1, 0, 0, 0),
|
||||
SpecialItemsData(0, 1, 0, 0),
|
||||
SpecialItemsData(0, 0, 1, 0),
|
||||
SpecialItemsData(0, 0, 0, 1),
|
||||
SpecialItemsData(1, 3, 4, 8)
|
||||
) { (snowballs, seafoam, shinyseeds, spookySparkles) ->
|
||||
items.snowball = snowballs
|
||||
items.seafoam = seafoam
|
||||
items.shinySeed = shinyseeds
|
||||
items.spookySparkles = spookySparkles
|
||||
items.hasSpecialItems shouldBe true
|
||||
}
|
||||
}
|
||||
})
|
||||