diff --git a/Habitica/src/androidTest/java/com/habitrpg/android/habitica/HabiticaTestCase.kt b/Habitica/src/androidTest/java/com/habitrpg/android/habitica/HabiticaTestCase.kt index 42a374f14..416756065 100644 --- a/Habitica/src/androidTest/java/com/habitrpg/android/habitica/HabiticaTestCase.kt +++ b/Habitica/src/androidTest/java/com/habitrpg/android/habitica/HabiticaTestCase.kt @@ -18,7 +18,6 @@ import com.habitrpg.android.habitica.helpers.MainNavigationController import com.habitrpg.android.habitica.helpers.NotificationsManager import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.helpers.SoundManager -import com.habitrpg.android.habitica.helpers.TaskFilterHelper import com.habitrpg.android.habitica.interactors.FeedPetUseCase import com.habitrpg.android.habitica.interactors.HatchPetUseCase import com.habitrpg.android.habitica.models.BaseObject @@ -65,7 +64,6 @@ open class HabiticaTestCase : TestCase() { val hostConfig: HostConfig = mockk(relaxed = true) val analyticsManager: AnalyticsManager = mockk(relaxed = true) val maintenanceService: MaintenanceApiService = mockk(relaxed = true) - val taskFilterHelper: TaskFilterHelper = mockk(relaxed = true) val tagRepository: TagRepository = mockk(relaxed = true) val hatchPetUseCase: HatchPetUseCase = mockk(relaxed = true) val feedPetUseCase: FeedPetUseCase = mockk(relaxed = true) @@ -132,7 +130,6 @@ open class HabiticaTestCase : TestCase() { if (it.returnType == HostConfig::class.starProjectedType) assign(it, obj, hostConfig) if (it.returnType == AnalyticsManager::class.starProjectedType) assign(it, obj, analyticsManager) if (it.returnType == MaintenanceApiService::class.starProjectedType) assign(it, obj, maintenanceService) - if (it.returnType == TaskFilterHelper::class.starProjectedType) assign(it, obj, taskFilterHelper) if (it.returnType == TagRepository::class.starProjectedType) assign(it, obj, tagRepository) if (it.returnType == FeedPetUseCase::class.starProjectedType) assign(it, obj, feedPetUseCase) if (it.returnType == HatchPetUseCase::class.starProjectedType) assign(it, obj, hatchPetUseCase) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AdHandler.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AdHandler.kt index be435a665..e2d93b8f8 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AdHandler.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/AdHandler.kt @@ -49,18 +49,18 @@ enum class AdType { } fun String.md5(): String? { - try { + return try { val md = MessageDigest.getInstance("MD5") val array = md.digest(this.toByteArray()) val sb = StringBuffer() for (i in array.indices) { sb.append(Integer.toHexString(array[i].toInt() and 0xFF or 0x100).substring(1, 3)) } - return sb.toString() + sb.toString() } catch (e: java.security.NoSuchAlgorithmException) { - return null + null } catch (ex: UnsupportedEncodingException) { - return null + null } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PurchaseHandler.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PurchaseHandler.kt index 9939e2e35..198c1b3bf 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PurchaseHandler.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PurchaseHandler.kt @@ -302,9 +302,9 @@ class PurchaseHandler( val result = withContext(Dispatchers.IO) { billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS) } + var fallback: Purchase? = null if (result.billingResult.responseCode == BillingClient.BillingResponseCode.OK) { val purchases = result.purchasesList.filter { it.isAcknowledged }.sortedByDescending { it.purchaseTime } - var fallback: Purchase? = null // If there is a subscription that is still active, prioritise that. Otherwise return the most recent one. for (purchase in purchases) { if (purchase.isAutoRenewing) { @@ -313,9 +313,8 @@ class PurchaseHandler( fallback = purchase } } - return fallback } - return null + return fallback } fun cancelSubscription(): Flowable { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.kt index fb15f644a..2cf911428 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/modules/AppModule.kt @@ -14,7 +14,6 @@ import com.habitrpg.android.habitica.helpers.KeyHelper import com.habitrpg.android.habitica.helpers.KeyHelper.Companion.getInstance import com.habitrpg.android.habitica.helpers.SoundFileLoader import com.habitrpg.android.habitica.helpers.SoundManager -import com.habitrpg.android.habitica.helpers.TaskFilterHelper import com.habitrpg.android.habitica.helpers.notifications.PushNotificationManager import com.habitrpg.shared.habitica.HLogger import dagger.Module @@ -69,12 +68,6 @@ class AppModule(private val application: Application) { } else getInstance(context, sharedPreferences, keyStore) } - @Provides - @Singleton - fun providesTagsHelper(): TaskFilterHelper { - return TaskFilterHelper() - } - @Provides fun providesResources(context: Context): Resources { return context.resources diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt index cc5e7972c..11cc42bd3 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarCustomizationFragment.kt @@ -175,16 +175,7 @@ class AvatarCustomizationFragment : if (filter.isFiltering) { val displayedCustomizations = mutableListOf() for (customization in customizations) { - if (filter.onlyPurchased) { - if (ownedCustomizations.find { it.key == customization.identifier } == null) { - continue - } - } - if (filter.months.isNotEmpty()) { - if (!filter.months.contains(customization.customizationSetName?.substringAfter('.'))) { - continue - } - } + if (shouldSkip(filter, ownedCustomizations, customization)) continue displayedCustomizations.add(customization) } adapter.setCustomizations( @@ -213,6 +204,16 @@ class AvatarCustomizationFragment : } } + private fun shouldSkip( + filter: CustomizationFilter, + ownedCustomizations: List, + customization: Customization + ): Boolean { + return if (filter.onlyPurchased && ownedCustomizations.find { it.key == customization.identifier } == null) { + true + } else filter.months.isNotEmpty() && !filter.months.contains(customization.customizationSetName?.substringAfter('.')) + } + fun updateUser(user: User?) { if (user == null) return this.updateActiveCustomization(user) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeFilterDialogHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeFilterDialogHolder.kt index 12ee33cd3..abd9a846f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeFilterDialogHolder.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeFilterDialogHolder.kt @@ -1,7 +1,6 @@ package com.habitrpg.android.habitica.ui.fragments.social.challenges import android.app.Activity -import android.app.AlertDialog import android.view.View import androidx.recyclerview.widget.LinearLayoutManager import com.habitrpg.android.habitica.R @@ -17,7 +16,6 @@ internal class ChallengeFilterDialogHolder private constructor( ) { private val binding = DialogChallengeFilterBinding.bind(view) - private var dialog: AlertDialog? = null private var filterGroups: List? = null private var currentFilter: ChallengeFilterOptions? = null private var selectedGroupsCallback: Action1? = null diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/ToolbarColorHelper.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/ToolbarColorHelper.kt index 822e41746..a1dd48519 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/ToolbarColorHelper.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/ToolbarColorHelper.kt @@ -70,17 +70,7 @@ object ToolbarColorHelper { // Step 2: Changing the color of any ActionMenuViews - icons that are not back button, nor text, nor overflow menu icon. // Colorize the ActionViews -> all icons that are NOT: back button | overflow menu - val innerView = v.getChildAt(j) - if (innerView is ActionMenuItemView) { - innerView.setTextColor(toolbarIconsColor) - for (k in innerView.compoundDrawables.indices) { - innerView.post { - if (innerView.compoundDrawables[k] != null) { - innerView.compoundDrawables[k].colorFilter = colorFilter - } - } - } - } + colorizeChild(v.getChildAt(j), toolbarIconsColor, colorFilter) } } else if (v is TextView) { v.setTextColor(toolbarIconsColor) @@ -95,6 +85,23 @@ object ToolbarColorHelper { setOverflowButtonColor(activity, toolbarIconsColor) } + private fun colorizeChild( + innerView: View, + toolbarIconsColor: Int, + colorFilter: PorterDuffColorFilter + ) { + if (innerView is ActionMenuItemView) { + innerView.setTextColor(toolbarIconsColor) + for (k in innerView.compoundDrawables.indices) { + innerView.post { + if (innerView.compoundDrawables[k] != null) { + innerView.compoundDrawables[k].colorFilter = colorFilter + } + } + } + } + } + /** * It's important to set overflowDescription atribute in styles, so we can grab the reference * to the overflow icon. Check: res/values/styles.xml diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt index 4c3d0b575..5a9e1c0b0 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/TasksViewModel.kt @@ -10,7 +10,6 @@ import com.habitrpg.android.habitica.data.TaskRepository import com.habitrpg.android.habitica.helpers.AmplitudeManager import com.habitrpg.android.habitica.helpers.AppConfigManager import com.habitrpg.android.habitica.helpers.RxErrorHandler -import com.habitrpg.android.habitica.helpers.TaskFilterHelper import com.habitrpg.android.habitica.models.responses.TaskDirection import com.habitrpg.android.habitica.models.responses.TaskScoringResult import com.habitrpg.android.habitica.models.tasks.Task @@ -37,8 +36,6 @@ class TasksViewModel : BaseViewModel() { @Inject lateinit var taskRepository: TaskRepository @Inject - lateinit var taskFilterHelper: TaskFilterHelper - @Inject lateinit var tagRepository: TagRepository @Inject lateinit var appConfigManager: AppConfigManager diff --git a/detekt_baseline.xml b/detekt_baseline.xml index 99794513b..ecff1cc8e 100644 --- a/detekt_baseline.xml +++ b/detekt_baseline.xml @@ -5,8 +5,6 @@ ComplexCondition:AutocompleteAdapter.kt$AutocompleteAdapter.<no name provided>$constraint[0] == '@' && constraint.length >= 3 && socialRepository != null && remoteAutocomplete ComplexCondition:AvatarStatsWidgetProvider.kt$AvatarStatsWidgetProvider$showManaBar && (stats.habitClass == null || (stats.lvl ?: 0) < 10 || user.preferences?.disableClasses == true) ComplexCondition:AvatarStatsWidgetProvider.kt$AvatarStatsWidgetProvider$user == null || stats == null || context == null || appWidgetManager == null - ComplexCondition:BaseDialogFragment.kt$BaseDialogFragment$step != null && step.isValid && step.isManaged && step.shouldDisplay() - ComplexCondition:BaseFragment.kt$BaseFragment$step != null && step.isValid && step.isManaged && step.shouldDisplay() ComplexCondition:ChallengeListFragment.kt$ChallengeListFragment$(!forced && binding?.refreshLayout?.isRefreshing == true) || loadedAllData || !this::challengeRepository.isInitialized ComplexCondition:ChatRecyclerViewHolder.kt$ChatRecyclerMessageViewHolder$(name != null && msg.text?.contains("@$name") == true) || (username != null && msg.text?.contains(username) == true) ComplexCondition:HabitViewHolder.kt$HabitViewHolder$data.counterUp != null && data.counterUp ?: 0 > 0 && data.counterDown != null && data.counterDown ?: 0 > 0 @@ -32,7 +30,6 @@ ComplexMethod:ChatRecyclerViewHolder.kt$ChatRecyclerMessageViewHolder$fun bind(msg: ChatMessage, uuid: String, user: User?, isExpanded: Boolean) ComplexMethod:ChecklistedViewHolder.kt$ChecklistedViewHolder$private fun updateChecklistDisplay() ComplexMethod:CustomizationSetupAdapter.kt$CustomizationSetupAdapter$private fun isCustomizationActive(customization: SetupCustomization): Boolean - ComplexMethod:DeviceName.kt$DeviceName$ fun getDeviceName(codename: String?, model: String?, fallback: String?): String? ComplexMethod:GroupSerialization.kt$GroupSerialization$@Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Group ComplexMethod:HabitViewHolder.kt$HabitViewHolder$override fun bind(data: Task, position: Int, displayMode: String) ComplexMethod:ItemRecyclerAdapter.kt$ItemRecyclerAdapter.ItemViewHolder$override fun onClick(v: View) @@ -41,7 +38,7 @@ ComplexMethod:NavigationDrawerFragment.kt$NavigationDrawerFragment$private fun updateUser(user: User) ComplexMethod:Notification.kt$Notification$fun getDataType(): java.lang.reflect.Type? ComplexMethod:NotificationsManager.kt$NotificationsManager$private fun handlePopupNotifications(notifications: List<Notification>): Boolean - ComplexMethod:PetSuggestHatchDialog.kt$PetSuggestHatchDialog$fun configure(pet: Animal, egg: Egg?, potion: HatchingPotion?, eggCount: Int, potionCount: Int, hasUnlockedEgg: Boolean, hasUnlockedPotion: Boolean, hasMount: Boolean) + ComplexMethod:PetSuggestHatchDialog.kt$PetSuggestHatchDialog$fun configure( pet: Animal, egg: Egg?, potion: HatchingPotion?, eggCount: Int, potionCount: Int, hasUnlockedEgg: Boolean, hasUnlockedPotion: Boolean, hasMount: Boolean ) ComplexMethod:PreferencesFragment.kt$PreferencesFragment$override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) ComplexMethod:PurchaseDialog.kt$PurchaseDialog$private fun buyItem(quantity: Int) ComplexMethod:SafeDefaultItemAnimator.kt$SafeDefaultItemAnimator$override fun runPendingAnimations() @@ -53,12 +50,13 @@ ComplexMethod:Task.kt$Task$fun isBeingEdited(task: Task): Boolean ComplexMethod:TaskFormActivity.kt$TaskFormActivity$override fun onCreate(savedInstanceState: Bundle?) ComplexMethod:TaskFormActivity.kt$TaskFormActivity$private fun fillForm(task: Task) - ComplexMethod:TaskRepositoryImpl.kt$TaskRepositoryImpl$private fun handleTaskResponse(user: User, res: TaskDirectionData, task: Task, up: Boolean, localDelta: Float) + ComplexMethod:TaskRecyclerViewFragment.kt$TaskRecyclerViewFragment$private fun setInnerAdapter() + ComplexMethod:TaskRepositoryImpl.kt$TaskRepositoryImpl$private fun handleTaskResponse( user: User, res: TaskDirectionData, task: Task, up: Boolean, localDelta: Float ) ComplexMethod:TaskSchedulingControls.kt$TaskSchedulingControls$private fun generateSummary() - ComplexMethod:TaskSerializer.kt$TaskSerializer$override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext): Task + ComplexMethod:TaskSerializer.kt$TaskSerializer$override fun deserialize( json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext ): Task ComplexMethod:UserDeserializer.kt$UserDeserializer$@Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): User ComplexMethod:UserStatComputer.kt$UserStatComputer$fun computeClassBonus(equipmentList: List<Equipment>, user: Avatar): List<StatsRow> - ComplexMethod:WorldStateSerialization.kt$WorldStateSerialization$override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): WorldState + ComplexMethod:WorldStateSerialization.kt$WorldStateSerialization$override fun deserialize( json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext? ): WorldState ConstructorParameterNaming:Days.kt$Days$`in`: Parcel ConstructorParameterNaming:Task.kt$Task$`in`: Parcel DuplicateCaseInWhenExpression:Notification.kt$Notification$when (type) { Type.LOGIN_INCENTIVE.type -> LoginIncentiveData::class.java Type.NEW_STUFF.type -> NewStuffData::class.java Type.NEW_CHAT_MESSAGE.type -> NewChatMessageData::class.java Type.GROUP_TASK_NEEDS_WORK.type -> GroupTaskNeedsWorkData::class.java Type.GROUP_TASK_APPROVED.type -> GroupTaskApprovedData::class.java Type.GROUP_TASK_REQUIRES_APPROVAL.type -> GroupTaskRequiresApprovalData::class.java Type.UNALLOCATED_STATS_POINTS.type -> UnallocatedPointsData::class.java Type.GUILD_INVITATION.type -> GuildInvitationData::class.java Type.PARTY_INVITATION.type -> PartyInvitationData::class.java Type.QUEST_INVITATION.type -> QuestInvitationData::class.java Type.FIRST_DROP.type -> FirstDropData::class.java Type.ACHIEVEMENT_GENERIC.type -> AchievementData::class.java Type.WON_CHALLENGE.type -> ChallengeWonData::class.java Type.ACHIEVEMENT_ALL_YOUR_BASE.type -> AchievementData::class.java Type.ACHIEVEMENT_BACK_TO_BASICS.type -> AchievementData::class.java Type.ACHIEVEMENT_JUST_ADD_WATER.type -> AchievementData::class.java Type.ACHIEVEMENT_LOST_MASTERCLASSER.type -> AchievementData::class.java Type.ACHIEVEMENT_MIND_OVER_MATTER.type -> AchievementData::class.java Type.ACHIEVEMENT_DUST_DEVIL.type -> AchievementData::class.java Type.ACHIEVEMENT_ARID_AUTHORITY.type -> AchievementData::class.java Type.ACHIEVEMENT_MONSTER_MAGUS.type -> AchievementData::class.java Type.ACHIEVEMENT_UNDEAD_UNDERTAKER.type -> AchievementData::class.java Type.ACHIEVEMENT_PRIMED_FOR_PAINTING.type -> AchievementData::class.java Type.ACHIEVEMENT_PEARLY_PRO.type -> AchievementData::class.java Type.ACHIEVEMENT_TICKLED_PINK.type -> AchievementData::class.java Type.ACHIEVEMENT_ROSY_OUTLOOK.type -> AchievementData::class.java Type.ACHIEVEMENT_BUG_BONANZA.type -> AchievementData::class.java Type.ACHIEVEMENT_BARE_NECESSITIES.type -> AchievementData::class.java Type.ACHIEVEMENT_FRESHWATER_FRIENDS.type -> AchievementData::class.java Type.ACHIEVEMENT_GOOD_AS_GOLD.type -> AchievementData::class.java Type.ACHIEVEMENT_ALL_THAT_GLITTERS.type -> AchievementData::class.java Type.ACHIEVEMENT_GOOD_AS_GOLD.type -> AchievementData::class.java Type.ACHIEVEMENT_BONE_COLLECTOR.type -> AchievementData::class.java Type.ACHIEVEMENT_SKELETON_CREW.type -> AchievementData::class.java Type.ACHIEVEMENT_SEEING_RED.type -> AchievementData::class.java Type.ACHIEVEMENT_RED_LETTER_DAY.type -> AchievementData::class.java else -> null } @@ -82,41 +80,40 @@ FunctionParameterNaming:BaseLocalRepository.kt$BaseLocalRepository$`object`: T FunctionParameterNaming:DragLinearLayout.kt$DragLinearLayout.Companion$`val`: Float FunctionParameterNaming:FullProfileActivity.kt$FullProfileActivity$`val`: Float + LargeClass:ApiClientImpl.kt$ApiClientImpl : ConsumerApiClient LongMethod:AvatarView.kt$AvatarView$@Suppress("ReturnCount") private fun getAvatarLayerMap(avatar: Avatar, substitutions: Map<String, Map<String, String>>): EnumMap<LayerType, String> LongMethod:BaseTaskViewHolder.kt$BaseTaskViewHolder$override fun bind(data: Task, position: Int, displayMode: String) LongMethod:ChallengeDetailFragment.kt$ChallengeDetailFragment$@Suppress("ReturnCount") override fun onViewCreated(view: View, savedInstanceState: Bundle?) LongMethod:ChatRecyclerViewHolder.kt$ChatRecyclerMessageViewHolder$fun bind(msg: ChatMessage, uuid: String, user: User?, isExpanded: Boolean) LongMethod:ContentDeserializer.kt$ContentDeserializer$@Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ContentResult - LongMethod:DeviceName.kt$DeviceName$ fun getDeviceName(codename: String?, model: String?, fallback: String?): String? LongMethod:GroupSerialization.kt$GroupSerialization$@Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Group LongMethod:HabitViewHolder.kt$HabitViewHolder$override fun bind(data: Task, position: Int, displayMode: String) - LongMethod:ItemDialogFragment.kt$ItemDialogFragment$override fun onViewCreated(view: View, savedInstanceState: Bundle?) - LongMethod:ItemRecyclerFragment.kt$ItemRecyclerFragment$override fun onViewCreated(view: View, savedInstanceState: Bundle?) LongMethod:NavigationDrawerFragment.kt$NavigationDrawerFragment$@OptIn(ExperimentalTime::class) override fun onViewCreated(view: View, savedInstanceState: Bundle?) LongMethod:NavigationDrawerFragment.kt$NavigationDrawerFragment$private fun updateUser(user: User) LongMethod:NoPartyFragmentFragment.kt$NoPartyFragmentFragment$override fun onViewCreated(view: View, savedInstanceState: Bundle?) - LongMethod:PetSuggestHatchDialog.kt$PetSuggestHatchDialog$fun configure(pet: Animal, egg: Egg?, potion: HatchingPotion?, eggCount: Int, potionCount: Int, hasUnlockedEgg: Boolean, hasUnlockedPotion: Boolean, hasMount: Boolean) + LongMethod:PetSuggestHatchDialog.kt$PetSuggestHatchDialog$fun configure( pet: Animal, egg: Egg?, potion: HatchingPotion?, eggCount: Int, potionCount: Int, hasUnlockedEgg: Boolean, hasUnlockedPotion: Boolean, hasMount: Boolean ) LongMethod:PreferencesFragment.kt$PreferencesFragment$override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) + LongMethod:PurchaseDialog.kt$PurchaseDialog$private fun buyItem(quantity: Int) LongMethod:SafeDefaultItemAnimator.kt$SafeDefaultItemAnimator$override fun endAnimations() LongMethod:SafeDefaultItemAnimator.kt$SafeDefaultItemAnimator$override fun runPendingAnimations() LongMethod:TaskFormActivity.kt$TaskFormActivity$override fun onCreate(savedInstanceState: Bundle?) LongMethod:UserDeserializer.kt$UserDeserializer$@Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): User LongMethod:UserStatComputer.kt$UserStatComputer$fun computeClassBonus(equipmentList: List<Equipment>, user: Avatar): List<StatsRow> - LongParameterList:FullProfileActivity.kt$FullProfileActivity$(label: String, strVal: Float, intVal: Float, conVal: Float, perVal: Float, roundDown: Boolean, isSummary: Boolean) - LongParameterList:HabiticaSnackbar.kt$HabiticaSnackbar.Companion$(container: ViewGroup, leftImage: Drawable, title: CharSequence?, content: CharSequence?, displayType: SnackbarDisplayType, isCelebratory: Boolean = false) - LongParameterList:HabiticaSnackbar.kt$HabiticaSnackbar.Companion$(container: ViewGroup, leftImage: Drawable?, title: CharSequence?, content: CharSequence?, specialView: View?, rightIcon: Drawable?, rightTextColor: Int?, rightText: String?, displayType: SnackbarDisplayType, isCelebratory: Boolean = false) - LongParameterList:HabiticaSnackbar.kt$HabiticaSnackbar.Companion$(container: ViewGroup, title: CharSequence?, content: CharSequence?, rightIcon: Drawable, rightTextColor: Int?, rightText: String, displayType: SnackbarDisplayType, isCelebratory: Boolean = false) - LongParameterList:HabiticaSnackbar.kt$HabiticaSnackbar.Companion$(container: ViewGroup, title: CharSequence?, content: CharSequence?, specialView: View?, displayType: SnackbarDisplayType, isCelebratory: Boolean = false) + LongParameterList:FullProfileActivity.kt$FullProfileActivity$( label: String, strVal: Float, intVal: Float, conVal: Float, perVal: Float, roundDown: Boolean, isSummary: Boolean ) + LongParameterList:HabiticaSnackbar.kt$HabiticaSnackbar.Companion$( container: ViewGroup, leftImage: Drawable, title: CharSequence?, content: CharSequence?, displayType: SnackbarDisplayType, isCelebratory: Boolean = false ) + LongParameterList:HabiticaSnackbar.kt$HabiticaSnackbar.Companion$( container: ViewGroup, leftImage: Drawable?, title: CharSequence?, content: CharSequence?, specialView: View?, rightIcon: Drawable?, rightTextColor: Int?, rightText: String?, displayType: SnackbarDisplayType, isCelebratory: Boolean = false ) + LongParameterList:HabiticaSnackbar.kt$HabiticaSnackbar.Companion$( container: ViewGroup, title: CharSequence?, content: CharSequence?, rightIcon: Drawable, rightTextColor: Int?, rightText: String, displayType: SnackbarDisplayType, isCelebratory: Boolean = false ) + LongParameterList:HabiticaSnackbar.kt$HabiticaSnackbar.Companion$( container: ViewGroup, title: CharSequence?, content: CharSequence?, specialView: View?, displayType: SnackbarDisplayType, isCelebratory: Boolean = false ) LongParameterList:HabiticaSnackbar.kt$SnackbarActivity$( leftImage: Drawable? = null, title: CharSequence? = null, content: CharSequence? = null, specialView: View? = null, rightIcon: Drawable? = null, rightTextColor: Int? = null, rightText: String? = null, displayType: HabiticaSnackbar.SnackbarDisplayType = HabiticaSnackbar.SnackbarDisplayType.NORMAL, isCelebratory: Boolean = false ) - LongParameterList:NotifyUserUseCase.kt$NotifyUserUseCase.Companion$(context: Context, xp: Double?, hp: Double?, gold: Double?, mp: Double?, questDamage: Double?, user: User?) - LongParameterList:NotifyUserUseCase.kt$NotifyUserUseCase.RequestValues$(val context: BaseActivity, val snackbarTargetView: ViewGroup, val user: User?, val xp: Double?, val hp: Double?, val gold: Double?, val mp: Double?, val questDamage: Double?, val hasLeveledUp: Boolean?, val level: Int?) - LongParameterList:PetSuggestHatchDialog.kt$PetSuggestHatchDialog$(pet: Animal, egg: Egg?, potion: HatchingPotion?, eggCount: Int, potionCount: Int, hasUnlockedEgg: Boolean, hasUnlockedPotion: Boolean, hasMount: Boolean) + LongParameterList:NotifyUserUseCase.kt$NotifyUserUseCase.Companion$( context: Context, xp: Double?, hp: Double?, gold: Double?, mp: Double?, questDamage: Double?, user: User? ) + LongParameterList:NotifyUserUseCase.kt$NotifyUserUseCase.RequestValues$( val context: BaseActivity, val snackbarTargetView: ViewGroup, val user: User?, val xp: Double?, val hp: Double?, val gold: Double?, val mp: Double?, val questDamage: Double?, val hasLeveledUp: Boolean?, val level: Int? ) + LongParameterList:PetDetailRecyclerAdapter.kt$PetDetailRecyclerAdapter.CanHatchViewHolder$( item: Pet, eggCount: Int, potionCount: Int, hasUnlockedEgg: Boolean, hasUnlockedPotion: Boolean, hasMount: Boolean, ) + LongParameterList:PetSuggestHatchDialog.kt$PetSuggestHatchDialog$( pet: Animal, egg: Egg?, potion: HatchingPotion?, eggCount: Int, potionCount: Int, hasUnlockedEgg: Boolean, hasUnlockedPotion: Boolean, hasMount: Boolean ) LongParameterList:PetViewHolder.kt$PetViewHolder$( item: Pet, trained: Int, eggCount: Int, potionCount: Int, canRaiseToMount: Boolean, ownsSaddles: Boolean, hasUnlockedEgg: Boolean, hasUnlockedPotion: Boolean, hasMount: Boolean, currentPet: String? ) - LongParameterList:ScoreTaskLocallyInteractor.kt$ScoreTaskLocallyInteractor.Companion$(result: TaskDirectionData, delta: Double, stats: Stats, computedStats: Stats, task: Task, direction: TaskDirection) - LongParameterList:SocialRepository.kt$SocialRepository$(name: String?, description: String?, leader: String?, type: String?, privacy: String?, leaderCreateChallenge: Boolean?) + LongParameterList:ScoreTaskLocallyInteractor.kt$ScoreTaskLocallyInteractor.Companion$( result: TaskDirectionData, delta: Double, stats: Stats, computedStats: Stats, task: Task, direction: TaskDirection ) + LongParameterList:SocialRepository.kt$SocialRepository$( name: String?, description: String?, leader: String?, type: String?, privacy: String?, leaderCreateChallenge: Boolean? ) + LongParameterList:UserRepositoryModule.kt$UserRepositoryModule$( localRepository: UserLocalRepository, apiClient: ApiClient, @Named(AppModule.NAMED_USER_ID) userId: String, taskRepository: TaskRepository, appConfigManager: AppConfigManager, analyticsManager: AnalyticsManager ) MatchingDeclarationName:Date-Extensions.kt$DateUtils - MemberNameEqualsClassName:DeviceName.kt$DeviceName$/** * Get the consumer friendly name of the device. * * @return the market name of the current device. * @see .getDeviceName */ val deviceName: String? get() = getDeviceName(Build.DEVICE, Build.MODEL, Build.MODEL.capitalize(Locale.getDefault())) - MemberNameEqualsClassName:DeviceName.kt$DeviceName.Request$ fun request(callback: Callback) MemberNameEqualsClassName:KeyHelper.kt$KeyHelper.Companion$private var keyHelper: KeyHelper? = null MemberNameEqualsClassName:Status.kt$Status$var status: String? = null NestedBlockDepth:AvatarView.kt$AvatarView$private fun getLayerBounds(layerType: LayerType, layerName: String, drawable: Drawable): Rect @@ -125,7 +122,6 @@ NestedBlockDepth:ChallengeDeserializer.kt$ChallengeDeserializer$@Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Challenge NestedBlockDepth:ChecklistedViewHolder.kt$ChecklistedViewHolder$private fun updateChecklistDisplay() NestedBlockDepth:CustomizationDeserializer.kt$CustomizationDeserializer$@Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): List<Customization> - NestedBlockDepth:DeviceName.kt$DeviceName$ @WorkerThread fun getDeviceInfo(context: Context, codename: String?, model: String?): DeviceInfo NestedBlockDepth:GroupSerialization.kt$GroupSerialization$@Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Group NestedBlockDepth:GuildDetailFragment.kt$GuildDetailFragment$private fun getGroupChallenges(): List<Challenge> NestedBlockDepth:InsufficientGemsDialog.kt$InsufficientGemsDialog$override fun onAttachedToWindow() @@ -138,24 +134,21 @@ NestedBlockDepth:QuestDetailFragment.kt$QuestDetailFragment$private fun setQuestParticipants(participants: List<Member>?) NestedBlockDepth:QuestDropItemsListSerialization.kt$QuestDropItemsListSerialization$@Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): RealmList<QuestDropItem> NestedBlockDepth:SafeDefaultItemAnimator.kt$SafeDefaultItemAnimator$override fun endAnimation(item: RecyclerView.ViewHolder) - NestedBlockDepth:ShopRecyclerAdapter.kt$ShopRecyclerAdapter$@Suppress("ReturnCount") override fun onBindViewHolder(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder, position: Int) + NestedBlockDepth:ShopRecyclerAdapter.kt$ShopRecyclerAdapter$@Suppress("ReturnCount") override fun onBindViewHolder( holder: androidx.recyclerview.widget.RecyclerView.ViewHolder, position: Int ) NestedBlockDepth:Task.kt$Task$fun getDaysOfMonth(): List<Int>? NestedBlockDepth:Task.kt$Task$fun getWeeksOfMonth(): List<Int>? - NestedBlockDepth:TaskFilterHelper.kt$TaskFilterHelper$fun createQuery(unfilteredData: OrderedRealmCollection<Task>): RealmQuery<Task>? NestedBlockDepth:TaskListDeserializer.kt$TaskListDeserializer$override fun deserialize(json: JsonElement, typeOfT: Type, ctx: JsonDeserializationContext): TaskList - NestedBlockDepth:TaskListDeserializer.kt$TaskListDeserializer$private fun handleTags(databaseTags: List<Tag>, json: JsonArray?, context: JsonDeserializationContext): RealmList<Tag> + NestedBlockDepth:TaskListDeserializer.kt$TaskListDeserializer$private fun handleTags( databaseTags: List<Tag>, json: JsonArray?, context: JsonDeserializationContext ): RealmList<Tag> NestedBlockDepth:TaskTagDeserializer.kt$TaskTagDeserializer$@Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): List<Tag> - NestedBlockDepth:ToolbarColorHelper.kt$ToolbarColorHelper$ fun colorizeToolbar(toolbar: Toolbar, activity: Activity?, overrideModernHeader: Boolean? = null) + NestedBlockDepth:TasksViewModel.kt$TasksViewModel$fun createQuery(unfilteredData: OrderedRealmCollection<Task>): RealmQuery<Task>? NestedBlockDepth:UserDeserializer.kt$UserDeserializer$@Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): User - NestedBlockDepth:WorldStateSerialization.kt$WorldStateSerialization$override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): WorldState + NestedBlockDepth:WorldStateSerialization.kt$WorldStateSerialization$override fun deserialize( json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext? ): WorldState ProtectedMemberInFinalClass:InboxViewModel.kt$InboxViewModel$protected var memberIDSubject = BehaviorSubject.create<Optional<String>>() ReturnCount:AccountPreferenceFragment.kt$AccountPreferenceFragment$override fun onPreferenceTreeClick(preference: Preference): Boolean ReturnCount:ApiClientImpl.kt$ApiClientImpl$override fun accept(throwable: Throwable) ReturnCount:AppConfigManager.kt$AppConfigManager$fun activePromo(): HabiticaPromotion? ReturnCount:BaseTaskViewHolder.kt$BaseTaskViewHolder$override fun onTouch(view: View?, motionEvent: MotionEvent?): Boolean ReturnCount:Customization.kt$Customization$fun getImageName(userSize: String?, hairColor: String?): String - ReturnCount:DeviceName.kt$DeviceName$ @WorkerThread fun getDeviceInfo(context: Context, codename: String?, model: String?): DeviceInfo - ReturnCount:DeviceName.kt$DeviceName$ fun getDeviceName(codename: String?, model: String?, fallback: String?): String? ReturnCount:DragLinearLayout.kt$DragLinearLayout$override fun onInterceptTouchEvent(event: MotionEvent): Boolean ReturnCount:DragLinearLayout.kt$DragLinearLayout$override fun onTouchEvent(event: MotionEvent): Boolean ReturnCount:PetDetailRecyclerAdapter.kt$PetDetailRecyclerAdapter$private fun canRaiseToMount(pet: Pet): Boolean @@ -170,8 +163,6 @@ ThrowingExceptionsWithoutMessageOrCause:EllipsisTextView.kt$EllipsisTextView$NullPointerException() TooGenericExceptionCaught:AuthenticationViewModel.kt$AuthenticationViewModel$e: Exception TooGenericExceptionCaught:CustomizationDeserializer.kt$CustomizationDeserializer$e: Exception - TooGenericExceptionCaught:DeviceName.kt$DeviceName$e: Exception - TooGenericExceptionCaught:DeviceName.kt$DeviceName.Request.GetDeviceRunnable$e: Exception TooGenericExceptionCaught:KeyHelper.kt$KeyHelper$e: Exception TooGenericExceptionCaught:MainActivityViewModel.kt$MainActivityViewModel$e: Exception TooGenericExceptionCaught:MainNavigationController.kt$MainNavigationController$error: Exception @@ -194,7 +185,6 @@ UnusedPrivateMember:AppTestingLevel.kt$AppTestingLevel$identifier: String UnusedPrivateMember:BaseTasksRecyclerViewAdapter.kt$BaseTasksRecyclerViewAdapter$private fun updateTask(task: Task) UnusedPrivateMember:BaseTasksRecyclerViewAdapter.kt$BaseTasksRecyclerViewAdapter$private val userID: String? - UnusedPrivateMember:ClassSelectionActivity.kt$ClassSelectionActivity$val dialog = HabiticaProgressDialog.show(this, progressText) UnusedPrivateMember:DragLinearLayout.kt$DragLinearLayout.Companion$`val`: Float UnusedPrivateMember:EquipmentOverviewViewModel.kt$EquipmentOverviewViewModel$savedStateHandle: SavedStateHandle UnusedPrivateMember:FullProfileActivity.kt$FullProfileActivity$`val`: Float @@ -205,13 +195,11 @@ UnusedPrivateMember:PurchaseDialog.kt$PurchaseDialog$val sub = maybe.flatMap { for (thisItem in it) { if (thisItem.key == item.key) { ownedCount += thisItem.numberOwned } } inventoryRepository.getOwnedMounts().firstElement() }.flatMap { for (mount in it) { if (mount.key?.contains(item.key) == true) { ownedCount += if (mount.owned) 1 else 0 } } inventoryRepository.getOwnedPets().firstElement() }.subscribe( { for (pet in it) { if (pet.key?.contains(item.key) == true) { ownedCount += if (pet.trained > 0) 1 else 0 } } if (calledResult) return@subscribe calledResult = true if (!shouldWarn) { onResult(-1) return@subscribe } val remaining = totalCount - ownedCount onResult(max(0, remaining)) }, RxErrorHandler.handleEmptyError(), { if (calledResult) return@subscribe calledResult = true if (!shouldWarn) { onResult(-1) return@subscribe } val remaining = totalCount - ownedCount onResult(max(0, remaining)) } ) UnusedPrivateMember:PurchaseDialog.kt$PurchaseDialog$val subscription = observable .doOnNext { val text = if (snackbarText[0].isNotEmpty()) { snackbarText[0] } else { context.getString(R.string.successful_purchase, shopItem.text) } val rightTextColor = when (item.currency) { "gold" -> ContextCompat.getColor(context, R.color.text_yellow) "gems" -> ContextCompat.getColor(context, R.color.text_green) "hourglasses" -> ContextCompat.getColor(context, R.color.text_brand) else -> 0 } ((application?.currentActivity?.get() ?: getActivity() ?: ownerActivity) as? SnackbarActivity)?.showSnackbar( content = text, rightIcon = priceLabel.compoundDrawables[0], rightTextColor = rightTextColor, rightText = "-" + priceLabel.text ) } .flatMap { userRepository.retrieveUser(withTasks = false, forced = true) } .flatMap { inventoryRepository.retrieveInAppRewards() } .subscribe({ if (item.isTypeGear || item.currency == "hourglasses") { onGearPurchased?.invoke(item) } }) { throwable -> if (throwable.javaClass.isAssignableFrom(retrofit2.HttpException::class.java)) { val error = throwable as retrofit2.HttpException if (error.code() == 401 && shopItem.currency == "gems") { MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", false))) } } } UnusedPrivateMember:PurchaseHandler.kt$PurchaseHandler$purchase: Purchase - UnusedPrivateMember:QuestMenuView.kt$QuestMenuView$context: Context UnusedPrivateMember:ScoreTaskLocallyInteractor.kt$ScoreTaskLocallyInteractor.Companion$direction: TaskDirection UnusedPrivateMember:ScoreTaskLocallyInteractor.kt$ScoreTaskLocallyInteractor.Companion$task: Task UnusedPrivateMember:ScoreTaskLocallyInteractor.kt$ScoreTaskLocallyInteractor.Companion$user: User UnusedPrivateMember:SubscriptionFragment.kt$SubscriptionFragment.Companion$iSG1G1: Boolean UnusedPrivateMember:TaskAlarmManager.kt$TaskAlarmManager$private fun removeAlarmsForTask(task: Task) - UnusedPrivateMember:TaskRecyclerViewFragment.kt$TaskRecyclerViewFragment$containerView: View UnusedPrivateMember:UserRepositoryModule.kt$UserRepositoryModule$context: Context? UtilityClassWithPublicConstructor:AprilFoolsHandler.kt$AprilFoolsHandler UtilityClassWithPublicConstructor:Date-Extensions.kt$DateUtils diff --git a/habitica.resources.example b/habitica.resources.example index 989a5322f..8d68b8005 100644 --- a/habitica.resources.example +++ b/habitica.resources.example @@ -1,3 +1,4 @@ fabric_key=CHANGE_ME facebook_app_id=CHANGE_ME amplitude_app_id=CHANGE_ME +application_ad_id=CHANGE_ME