diff --git a/Habitica/res/layout/fragment_report_message.xml b/Habitica/res/layout/fragment_report_message.xml
index 4644159b3..5d65ce580 100644
--- a/Habitica/res/layout/fragment_report_message.xml
+++ b/Habitica/res/layout/fragment_report_message.xml
@@ -1,176 +1,170 @@
-
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:background="@drawable/bottom_sheet_background"
+ app:behavior_hideable="true">
+
+
-
+
+
+
+
+
+
+
+
+
+ android:layout_marginBottom="0dp">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_marginBottom="0dp"
+ android:focusableInTouchMode="true"
+ android:orientation="vertical"
+ android:paddingStart="24dp"
+ android:paddingTop="16dp"
+ android:paddingEnd="24dp"
+ android:paddingBottom="25dp">
-
-
-
-
-
-
-
+ android:layout_height="wrap_content"
+ app:cardBackgroundColor="@color/material_card_background_color"
+ app:cardCornerRadius="8dp"
+ app:strokeColor="@color/gray200_gray400"
+ app:strokeWidth="1dp">
+ tools:text="This is the message that is reported" />
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+ android:gravity="center_vertical"
+ android:hint="@string/report_hint"
+ android:overScrollMode="always"
+ android:padding="16dp"
+ android:paddingTop="12dp"
+ android:textColor="@color/text_primary"
+ android:textColorHint="@color/gray200_gray400" />
+
+
+
+
+
+
+
+
+
+
diff --git a/Habitica/res/menu/menu_challenge_details.xml b/Habitica/res/menu/menu_challenge_details.xml
index 33ad438bb..6ca33ca5b 100644
--- a/Habitica/res/menu/menu_challenge_details.xml
+++ b/Habitica/res/menu/menu_challenge_details.xml
@@ -14,4 +14,6 @@
+
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index 55992cfb5..3d4cefc20 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -811,11 +811,13 @@
Report %s for violation:
You should only report a post that violates the [Community Guidelines](https://habitica.com/static/community-guidelines) and/or [Terms of Service](https://habitica.com/static/terms). Submitting a false report is a violation of Habitica\'s Community Guidelines.
You should only report a player that violates the [Community Guidelines](https://habitica.com/static/community-guidelines) and/or [Terms of Service](https://habitica.com/static/terms). Submitting a false report is a violation of Habitica\'s Community Guidelines.
+ You should only report a challenge that violates the [Community Guidelines](https://habitica.com/static/community-guidelines) and/or [Terms of Service](https://habitica.com/static/terms). Submitting a false report is a violation of Habitica\'s Community Guidelines.
Report %s?
Report Player
Reason for report
Why are you reporting this message?
Why are you reporting this player?
+ Why are you reporting this challenge?
%1$s\n@%2$s
This will also block @%s
Reason for report
@@ -1476,6 +1478,7 @@
Unable to find player
There was an error when loading this player\'s data. Please make sure you typed their @username correctly.
Content releases + Events
+ Report Challenge
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.kt
index 76bdd40cb..d757e7bba 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.kt
@@ -484,4 +484,7 @@ interface ApiService {
@GET("looking-for-party")
suspend fun retrievePartySeekingUsers(@Query("page") page: Int): HabitResponse>
+
+ @POST("challenges/{challengeId}/flag")
+ suspend fun reportChallenge(@Query("challengeId") challengeid: String, @Body updateData: Map): HabitResponse
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt
index 723a1a310..dd456b7bc 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.kt
@@ -284,4 +284,5 @@ interface ApiClient {
suspend fun retrievePartySeekingUsers(page: Int): List?
suspend fun getGroupInvites(groupId: String, includeAllPublicFields: Boolean?): List?
suspend fun syncUserStats(): User?
+ suspend fun reportChallenge(challengeid: String, updateData: Map): Void?
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.kt
index 626216fb5..08e938bf4 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ChallengeRepository.kt
@@ -44,4 +44,5 @@ interface ChallengeRepository : BaseRepository {
fun getChallengepMembership(id: String): Flow
fun getChallengeMemberships(): Flow>
fun isChallengeMember(challengeID: String): Flow
+ suspend fun reportChallenge(challengeid: String, updateData: Map): Void?
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
index 9d5b8b701..e7bf61107 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt
@@ -391,6 +391,12 @@ class ApiClientImpl(
override suspend fun getStatus(): Status? = process { apiService.getStatus() }
override suspend fun syncUserStats(): User? = process { apiService.syncUserStats() }
+ override suspend fun reportChallenge(
+ challengeid: String,
+ updateData: Map
+ ): Void? {
+ return process { apiService.reportChallenge(challengeid, updateData) }
+ }
override suspend fun getContent(language: String?): ContentResult? {
return process { apiService.getContent(language ?: this.languageCode) }
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt
index 0a900c4fb..3b74376c5 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ChallengeRepositoryImpl.kt
@@ -23,6 +23,13 @@ class ChallengeRepositoryImpl(
return localRepository.isChallengeMember(currentUserID, challengeID)
}
+ override suspend fun reportChallenge(
+ challengeid: String,
+ updateData: Map
+ ): Void? {
+ return apiClient.reportChallenge(challengeid, updateData)
+ }
+
override fun getChallengepMembership(id: String): Flow {
return localRepository.getChallengeMembership(currentUserID, id)
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
index d8fca45ea..4218517eb 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
@@ -28,6 +28,7 @@ import com.habitrpg.android.habitica.data.InventoryRepository
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.databinding.ActivityFullProfileBinding
import com.habitrpg.android.habitica.extensions.addCancelButton
+import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.helpers.ReviewManager
import com.habitrpg.android.habitica.helpers.UserStatComputer
import com.habitrpg.android.habitica.interactors.ShareAvatarUseCase
@@ -83,6 +84,9 @@ class FullProfileActivity : BaseActivity() {
@Inject
lateinit var reviewManager: ReviewManager
+ @Inject
+ lateinit var configManager: AppConfigManager
+
private var userID = ""
private var username: String? = null
private var userDisplayName: String? = null
@@ -109,7 +113,7 @@ class FullProfileActivity : BaseActivity() {
binding.avatarWithBars.setContent {
HabiticaTheme {
- AppHeaderView(member.value, isMyProfile = false, onMemberRowClicked = {}, onClassSelectionClicked = {})
+ AppHeaderView(member.value, isMyProfile = false, onMemberRowClicked = {}, onClassSelectionClicked = {}, configManager = configManager)
}
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt
index ef32d7246..bfddc3412 100755
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt
@@ -311,7 +311,7 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
verticalArrangement = Arrangement.spacedBy(4.dp),
modifier = Modifier.padding(22.dp)
) {
- ComposableAvatarView(avatar = user)
+ ComposableAvatarView(avatar = user, configManager = appConfigManager)
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(15.dp),
@@ -370,7 +370,7 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
null
)
val members by viewModel.userViewModel.currentTeamPlanMembers.observeAsState()
- GroupPlanMemberList(members, group) {
+ GroupPlanMemberList(members, group, appConfigManager) {
onClose()
FullProfileActivity.open(it)
}
@@ -383,7 +383,8 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
val intent = Intent(this@MainActivity, ClassSelectionActivity::class.java)
intent.putExtras(bundle)
classSelectionResult.launch(intent)
- }
+ },
+ configManager = appConfigManager
)
}
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt
index fb0daf80c..ebc8d39b6 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.kt
@@ -41,6 +41,7 @@ import com.habitrpg.android.habitica.data.TaskRepository
import com.habitrpg.android.habitica.databinding.ActivityTaskFormBinding
import com.habitrpg.android.habitica.extensions.OnChangeTextWatcher
import com.habitrpg.android.habitica.extensions.addCancelButton
+import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.helpers.TaskAlarmManager
import com.habitrpg.android.habitica.helpers.notifications.PushNotificationManager
import com.habitrpg.android.habitica.models.Tag
@@ -115,6 +116,9 @@ class TaskFormActivity : BaseActivity() {
@Inject
lateinit var socialRepository: SocialRepository
+ @Inject
+ lateinit var configManager: AppConfigManager
+
private var challenge: Challenge? = null
private val notificationPermissionLauncher = registerForActivityResult(
@@ -325,6 +329,7 @@ class TaskFormActivity : BaseActivity() {
task?.let { it1 -> taskRepository.markTaskNeedsWork(it1, it) }
}
},
+ configManager = configManager,
showEditButton = true
)
}
@@ -962,6 +967,7 @@ class TaskFormActivity : BaseActivity() {
AssignSheet(
groupMembers,
assignedIDs,
+ configManager,
{
if (assignedIDs.contains(it)) {
assignedIDs.remove(it)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt
index da31f90bc..ca9a2b2ed 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskSummaryActivity.kt
@@ -47,6 +47,7 @@ import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.data.TaskRepository
import com.habitrpg.android.habitica.data.UserRepository
+import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.common.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.helpers.TaskDescriptionBuilder
import com.habitrpg.android.habitica.models.members.Member
@@ -76,7 +77,8 @@ class TaskSummaryViewModel @Inject constructor(
userRepository: UserRepository,
userViewModel: MainUserViewModel,
val taskRepository: TaskRepository,
- val socialRepository: SocialRepository
+ val socialRepository: SocialRepository,
+ val configManager: AppConfigManager
) : BaseViewModel(userRepository, userViewModel) {
val taskID: String = savedStateHandle[TaskFormActivity.TASK_ID_KEY] ?: ""
@@ -295,6 +297,7 @@ fun TaskSummaryView(viewModel: TaskSummaryViewModel) {
.heightIn(min = 24.dp)
.fillMaxWidth(),
color = darkestColor,
+ configManager = viewModel.configManager,
extraContent = if (item.completed) {
(
{
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
index 86150a870..69852cb18 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
@@ -133,6 +133,7 @@ class NavigationDrawerFragment : DialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = DrawerMainBinding.bind(view)
+ binding?.avatarView?.configManager = configManager
binding?.recyclerView?.adapter = adapter
binding?.recyclerView?.layoutManager =
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/ReportBottomSheetFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/ReportBottomSheetFragment.kt
index a7f5dde18..6de55440a 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/ReportBottomSheetFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/ReportBottomSheetFragment.kt
@@ -10,13 +10,17 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
+import androidx.core.content.ContextCompat
+import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.lifecycleScope
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.data.ChallengeRepository
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.databinding.FragmentReportMessageBinding
+import com.habitrpg.android.habitica.models.social.Challenge
import com.habitrpg.common.habitica.helpers.ExceptionHandler
import com.habitrpg.common.habitica.helpers.launchCatching
import com.habitrpg.common.habitica.helpers.setMarkdown
@@ -31,6 +35,8 @@ class ReportBottomSheetFragment : BottomSheetDialogFragment() {
@Inject
lateinit var socialRepository: SocialRepository
+ @Inject
+ lateinit var challengeRepository: ChallengeRepository
private var reportType: String? = null
private var messageID: String? = null
@@ -38,6 +44,7 @@ class ReportBottomSheetFragment : BottomSheetDialogFragment() {
private var profileName: String? = null
private var displayName: String? = null
private var reportingUserId: String? = null
+ private var reportingChallengeId: String? = null
private var groupID: String? = null
private var isReporting: Boolean = false
private var source: String? = null
@@ -71,15 +78,19 @@ class ReportBottomSheetFragment : BottomSheetDialogFragment() {
profileName = arguments?.getString(PROFILE_NAME)
displayName = arguments?.getString(DISPLAY_NAME)
reportingUserId = arguments?.getString(REPORTING_USER_ID)
+ reportingChallengeId = arguments?.getString(REPORTING_CHALLENGE_ID)
source = arguments?.getString(SOURCE_VIEW)
binding.messageTextView.text = arguments?.getString(messageText)
binding.reportButton.setOnClickListener {
- if (reportType == REPORT_TYPE_MESSAGE)
+ if (reportType == REPORT_TYPE_MESSAGE) {
reportMessage()
- else if (reportType == REPORT_TYPE_USER)
+ } else if (reportType == REPORT_TYPE_USER) {
reportUser()
+ } else if (reportType == REPORT_TYPE_CHALLENGE) {
+ reportChallenge()
+ }
}
if (reportType == REPORT_TYPE_USER) {
@@ -93,7 +104,8 @@ class ReportBottomSheetFragment : BottomSheetDialogFragment() {
)
)
binding.reportExplanationTextview.setMarkdown(getString(R.string.report_user_explanation))
- val formattedString = getString(R.string.report_formatted_name, displayName, profileName)
+ val formattedString =
+ getString(R.string.report_formatted_name, displayName, profileName)
val spannable = SpannableStringBuilder(formattedString)
spannable.setSpan(
TypefaceSpan("sans-serif-medium"),
@@ -109,6 +121,14 @@ class ReportBottomSheetFragment : BottomSheetDialogFragment() {
)
binding.messageTextView.text = spannable
binding.reportReasonTitle.text = getString(R.string.report_reason_title_player)
+ } else if (reportType == REPORT_TYPE_CHALLENGE) {
+ binding.toolbarTitle.text = getString(R.string.report_challenge)
+ binding.additionalExplanationTextview.visibility = View.VISIBLE
+ binding.additionalExplanationTextview.visibility = View.GONE
+ binding.additionalInfoEdittext.hint = getString(R.string.report_hint)
+ binding.reportExplanationTextview.setMarkdown(getString(R.string.report_challenge_explanation))
+ binding.messageTextView.text = displayName
+ binding.reportReasonTitle.text = getString(R.string.report_reason_title_challenge)
} else if (reportType == REPORT_TYPE_MESSAGE) {
binding.toolbarTitle.text = getString(R.string.report_message)
binding.additionalExplanationTextview.visibility = View.GONE
@@ -117,6 +137,17 @@ class ReportBottomSheetFragment : BottomSheetDialogFragment() {
binding.messageTextView.text = messageText
binding.reportReasonTitle.text = getString(R.string.report_reason_title_message)
}
+
+ binding.additionalInfoEdittext.addTextChangedListener { editable ->
+ binding.reportButton.isEnabled = !editable.isNullOrBlank()
+ binding.reportButton.setTextColor(
+ if (editable.isNullOrBlank()) {
+ ContextCompat.getColor(requireContext(), R.color.text_dimmed)
+ } else {
+ ContextCompat.getColor(requireContext(), R.color.text_red)
+ }
+ )
+ }
}
private fun reportMessage() {
@@ -162,12 +193,35 @@ class ReportBottomSheetFragment : BottomSheetDialogFragment() {
}
}
+ private fun reportChallenge() {
+ if (isReporting) {
+ return
+ }
+ val challengeId = reportingChallengeId
+ if (challengeId.isNullOrBlank()) {
+ return
+ }
+ isReporting = true
+ lifecycleScope.launchCatching {
+ val reportReasonInfo = binding.additionalInfoEdittext.text.toString()
+ val updateData = mapOf(
+ "comment" to reportReasonInfo,
+ "source" to (source ?: "")
+ )
+ challengeRepository.reportChallenge(challengeId, updateData)
+ Toast.makeText(context, "$displayName Reported", Toast.LENGTH_SHORT).show()
+ dismiss()
+ }
+ }
+
companion object {
const val TAG = "ReportBottomSheetFragment"
const val REPORT_TYPE_MESSAGE = "report_type_message"
const val REPORT_TYPE_USER = "report_type_user"
+ const val REPORT_TYPE_CHALLENGE = "report_type_challenge"
private const val REPORTING_USER_ID = "reporting_user_id"
+ private const val REPORTING_CHALLENGE_ID = "reporting_challenge_id"
private const val REPORT_TYPE = "report_type"
private const val PROFILE_NAME = "profile_name"
private const val DISPLAY_NAME = "display_name"
@@ -181,10 +235,11 @@ class ReportBottomSheetFragment : BottomSheetDialogFragment() {
reportType: String,
profileName: String = "",
displayName: String = "",
- userIdBeingReported: String,
+ challengeBeingReported: String = "",
+ userIdBeingReported: String = "",
messageId: String = "",
- messageText: String,
- groupId: String,
+ messageText: String = "",
+ groupId: String = "",
sourceView: String
): ReportBottomSheetFragment {
val args = Bundle()
@@ -192,6 +247,7 @@ class ReportBottomSheetFragment : BottomSheetDialogFragment() {
args.putString(PROFILE_NAME, profileName)
args.putString(DISPLAY_NAME, displayName)
args.putString(REPORTING_USER_ID, userIdBeingReported)
+ args.putString(REPORTING_CHALLENGE_ID, challengeBeingReported)
args.putString(MESSAGE_ID, messageId)
args.putString(MESSAGE_TEXT, messageText)
args.putString(GROUP_ID, groupId)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailFragment.kt
index fe4dc2c36..36dfed016 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/challenges/ChallengeDetailFragment.kt
@@ -26,6 +26,7 @@ import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.ui.activities.ChallengeFormActivity
import com.habitrpg.android.habitica.ui.activities.FullProfileActivity
import com.habitrpg.android.habitica.ui.fragments.BaseMainFragment
+import com.habitrpg.android.habitica.ui.fragments.ReportBottomSheetFragment
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
@@ -193,6 +194,9 @@ class ChallengeDetailFragment : BaseMainFragment
R.id.action_end_challenge -> {
showEndChallengeDialog()
}
+ R.id.action_report -> {
+ showReportChallengeBottomSheet()
+ }
}
return super.onOptionsItemSelected(item)
@@ -217,6 +221,17 @@ class ChallengeDetailFragment : BaseMainFragment
dialog.show()
}
+ private fun showReportChallengeBottomSheet() {
+ val reportBottomSheetFragment = ReportBottomSheetFragment.newInstance(
+ reportType = ReportBottomSheetFragment.REPORT_TYPE_CHALLENGE,
+ challengeBeingReported = challengeID ?: "",
+ displayName = challenge?.name ?: "",
+ sourceView = this::class.simpleName ?: ""
+ )
+
+ activity?.supportFragmentManager?.let { reportBottomSheetFragment.show(it, ReportBottomSheetFragment.TAG) }
+ }
+
private fun refresh() {
challengeID?.let { id ->
lifecycleScope.launchCatching({
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt
index 87be64b6e..3db3ef11d 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartyDetailFragment.kt
@@ -21,6 +21,7 @@ import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.databinding.FragmentPartyDetailBinding
import com.habitrpg.android.habitica.extensions.inflate
+import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.helpers.HapticFeedbackManager
import com.habitrpg.common.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.models.inventory.QuestContent
@@ -83,6 +84,9 @@ class PartyDetailFragment : BaseFragment() {
@Inject
lateinit var inventoryRepository: InventoryRepository
+ @Inject
+ lateinit var appConfigManager: AppConfigManager
+
override fun onDestroyView() {
inventoryRepository.close()
super.onDestroyView()
@@ -136,6 +140,7 @@ class PartyDetailFragment : BaseFragment() {
isInvited = true,
showHeader = true,
showExtendedInfo = false,
+ configManager = appConfigManager,
onInvite = {
viewModel.rescindInvite(invitedMember)
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartySeekingFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartySeekingFragment.kt
index 8e6d3f592..3db12aedb 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartySeekingFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/party/PartySeekingFragment.kt
@@ -55,6 +55,7 @@ import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.databinding.FragmentComposeBinding
import com.habitrpg.android.habitica.helpers.Analytics
+import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.helpers.EventCategory
import com.habitrpg.android.habitica.helpers.HitType
import com.habitrpg.android.habitica.models.invitations.InviteResponse
@@ -83,7 +84,8 @@ import kotlin.time.toDuration
class PartySeekingViewModel @Inject constructor(
userRepository: UserRepository,
userViewModel: MainUserViewModel,
- val socialRepository: SocialRepository
+ val socialRepository: SocialRepository,
+ val configManager: AppConfigManager
) : BaseViewModel(userRepository, userViewModel) {
val isRefreshing = mutableStateOf(false)
val seekingUsers: Flow>
@@ -259,6 +261,7 @@ fun PartySeekingView(
user = item,
inviteState = viewModel.inviteStates[item.id]?.second ?: LoadingButtonState.CONTENT,
isInvited = viewModel.inviteStates[item.id]?.first ?: false,
+ configManager = viewModel.configManager,
modifier = Modifier
.animateItemPlacement()
.padding(horizontal = 14.dp)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt
index 6686e940a..3df91b2b8 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/AppHeaderView.kt
@@ -50,6 +50,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.os.bundleOf
import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.common.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.models.TeamPlan
import com.habitrpg.android.habitica.models.auth.LocalAuthentication
@@ -111,13 +112,15 @@ fun AppHeaderView(
teamPlanMembers : List? = null,
onAvatarClicked: (() -> Unit)? = null,
onMemberRowClicked : () -> Unit,
- onClassSelectionClicked: () -> Unit
+ onClassSelectionClicked: () -> Unit,
+ configManager: AppConfigManager
) {
val isPlayerOptedOutOfClass = user?.preferences?.disableClasses ?: false
Column(modifier) {
Row {
ComposableAvatarView(
user,
+ configManager,
Modifier
.size(110.dp, 100.dp)
.padding(end = 16.dp)
@@ -278,6 +281,7 @@ fun AppHeaderView(
) {
ComposableAvatarView(
avatar = member,
+ configManager,
Modifier
.size(64.dp)
.requiredSize(64.dp)
@@ -404,7 +408,8 @@ private fun Preview(@PreviewParameter(UserProvider::class) data: Pair?,
group: Group?,
- onMemberClicked: (String) -> Unit
+ configManager: AppConfigManager,
+ onMemberClicked: (String) -> Unit,
) {
LazyColumn {
item {
@@ -73,6 +75,7 @@ fun GroupPlanMemberList(
member,
role,
onMemberClicked,
+ configManager,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
)
}
@@ -85,6 +88,7 @@ fun MemberItem(
member: Member,
role: String,
onMemberClicked: (String) -> Unit,
+ configManager: AppConfigManager,
modifier: Modifier = Modifier
) {
Box(
@@ -93,7 +97,7 @@ fun MemberItem(
.clip(HabiticaTheme.shapes.large)
.background(HabiticaTheme.colors.windowBackground)
.clickable {
- member.id?.let { onMemberClicked(it) }
+ onMemberClicked(member.id)
}
) {
Row(
@@ -102,6 +106,7 @@ fun MemberItem(
) {
ComposableAvatarView(
avatar = member,
+ configManager = configManager,
modifier = Modifier
.padding(6.dp)
.size(94.dp, 98.dp)
@@ -221,5 +226,5 @@ private class MemberProvider : PreviewParameterProvider {
@Composable
@Preview
private fun Preview(@PreviewParameter(MemberProvider::class) member: Member) {
- MemberItem(member = member, role = "Manager", onMemberClicked = {})
+ MemberItem(member = member, role = "Manager", onMemberClicked = {}, AppConfigManager(null))
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/UserRow.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/UserRow.kt
index 98ece1432..2bf876c12 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/UserRow.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/UserRow.kt
@@ -19,6 +19,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.common.habitica.views.ComposableAvatarView
import com.habitrpg.shared.habitica.models.Avatar
@@ -30,7 +31,8 @@ fun UserRow(
mainContentModifier: Modifier = Modifier,
extraContent: @Composable (() -> Unit)? = null,
endContent: @Composable (() -> Unit)? = null,
- color: Color? = null
+ color: Color? = null,
+ configManager: AppConfigManager
) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier.fillMaxWidth()) {
Box(
@@ -43,6 +45,7 @@ fun UserRow(
if (avatar != null) {
ComposableAvatarView(
avatar = avatar,
+ configManager,
Modifier
.size(96.dp)
.requiredSize(96.dp)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/PartySeekingListItem.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/PartySeekingListItem.kt
index a1cc051a5..7d1778fc9 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/PartySeekingListItem.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/PartySeekingListItem.kt
@@ -25,6 +25,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.habitrpg.android.habitica.MainNavDirections
import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.common.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.models.auth.LocalAuthentication
import com.habitrpg.android.habitica.models.members.Member
@@ -53,7 +54,8 @@ fun PartySeekingListItem(
isInvited: Boolean = false,
showHeader: Boolean = false,
showExtendedInfo: Boolean = true,
- onInvite: (Member) -> Unit
+ configManager: AppConfigManager,
+ onInvite: (Member) -> Unit,
) {
Column(
modifier
@@ -72,6 +74,7 @@ fun PartySeekingListItem(
) {
ComposableAvatarView(
user,
+ configManager,
Modifier
.size(94.dp, 98.dp)
.padding(top = 4.dp)
@@ -206,5 +209,5 @@ private class MemberProvider : PreviewParameterProvider {
@Preview
@Composable
private fun Preview(@PreviewParameter(MemberProvider::class) data: Member) {
- PartySeekingListItem(user = data, onInvite = {})
+ PartySeekingListItem(user = data, onInvite = {}, configManager = AppConfigManager(null))
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignSheet.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignSheet.kt
index ea7b13e53..2e827f6f5 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignSheet.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignSheet.kt
@@ -38,6 +38,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.models.members.Member
import com.habitrpg.android.habitica.ui.views.UserRow
@@ -45,6 +46,7 @@ import com.habitrpg.android.habitica.ui.views.UserRow
fun AssignSheet(
members: List,
assignedMembers: List,
+ configManager: AppConfigManager,
onAssignClick: (String) -> Unit,
onCloseClick: () -> Unit,
modifier: Modifier = Modifier
@@ -71,7 +73,7 @@ fun AssignSheet(
}
for (member in members) {
val isAssigned = assignedMembers.contains(member.id)
- AssignSheetRow(member = member, isAssigned = isAssigned, onAssignClick = onAssignClick)
+ AssignSheetRow(member = member, isAssigned = isAssigned, configManager, onAssignClick = onAssignClick)
}
}
}
@@ -80,6 +82,7 @@ fun AssignSheet(
fun AssignSheetRow(
member: Member,
isAssigned: Boolean,
+ configManager: AppConfigManager,
onAssignClick: (String) -> Unit,
modifier: Modifier = Modifier
) {
@@ -96,6 +99,7 @@ fun AssignSheetRow(
endContent = {
IsAssignedIndicator(isAssigned = isAssigned)
},
+ configManager = configManager,
modifier = modifier
.clickable {
onAssignClick(member.id)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignedView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignedView.kt
index 0aa27fb8d..252c3cca2 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignedView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/tasks/AssignedView.kt
@@ -26,11 +26,13 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.helpers.AppConfigManager
import com.habitrpg.android.habitica.models.Assignable
import com.habitrpg.android.habitica.ui.theme.colors
import com.habitrpg.common.habitica.theme.HabiticaTheme
import com.habitrpg.android.habitica.ui.views.CompletedAt
import com.habitrpg.android.habitica.ui.views.UserRow
+import com.habitrpg.common.habitica.helpers.MainNavigationController
import java.util.Date
@Composable
@@ -41,6 +43,7 @@ fun AssignedView(
color: Color,
onEditClick: () -> Unit,
onUndoClick: (String) -> Unit,
+ configManager: AppConfigManager,
modifier: Modifier = Modifier,
showEditButton: Boolean = false
) {
@@ -67,6 +70,7 @@ fun AssignedView(
extraContent = {
completedAt[assignable.id]?.let { CompletedAt(completedAt = it) }
},
+ configManager = configManager,
endContent = {
completedAt[assignable.id]?.let {
if (showEditButton) {
diff --git a/common/src/main/java/com/habitrpg/common/habitica/views/AvatarView.kt b/common/src/main/java/com/habitrpg/common/habitica/views/AvatarView.kt
index fda8480cf..dcb0bd7a7 100644
--- a/common/src/main/java/com/habitrpg/common/habitica/views/AvatarView.kt
+++ b/common/src/main/java/com/habitrpg/common/habitica/views/AvatarView.kt
@@ -12,6 +12,7 @@ import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.text.TextUtils
import android.util.AttributeSet
+import android.util.Log
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.core.view.marginStart
@@ -48,6 +49,8 @@ class AvatarView : FrameLayout {
private var avatarCanvas: Canvas? = null
private var currentLayers: Map? = null
+ var configManager: AppConfigManager? = null
+
private val layerMap: Map
get() {
val avatar = this.avatar ?: return emptyMap()
@@ -57,7 +60,8 @@ class AvatarView : FrameLayout {
private var spriteSubstitutions: Map> = HashMap()
get() {
if (Date().time - (lastSubstitutionCheck?.time ?: 0) > 180000) {
- field = AppConfigManager().spriteSubstitutions()
+ field = (configManager ?: AppConfigManager()).spriteSubstitutions()
+ Log.i("AvatarView", field.toString())
lastSubstitutionCheck = Date()
}
return field
diff --git a/common/src/main/java/com/habitrpg/common/habitica/views/ComposableAvatarView.kt b/common/src/main/java/com/habitrpg/common/habitica/views/ComposableAvatarView.kt
index 4460df251..3b36640fb 100644
--- a/common/src/main/java/com/habitrpg/common/habitica/views/ComposableAvatarView.kt
+++ b/common/src/main/java/com/habitrpg/common/habitica/views/ComposableAvatarView.kt
@@ -3,17 +3,21 @@ package com.habitrpg.common.habitica.views
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
+import com.habitrpg.common.habitica.helpers.AppConfigManager
import com.habitrpg.shared.habitica.models.Avatar
@Composable
fun ComposableAvatarView(
avatar: Avatar?,
+ configManager: AppConfigManager,
modifier: Modifier = Modifier
) {
AndroidView(
modifier = modifier, // Occupy the max size in the Compose UI tree
factory = { context ->
- AvatarView(context)
+ val view = AvatarView(context)
+ view.configManager = configManager
+ return@AndroidView view
},
update = { view ->
if (avatar != null) {
diff --git a/common/src/main/res/drawable-hdpi/ic_gryphon_white.png b/common/src/main/res/drawable-hdpi/ic_gryphon_white.png
new file mode 100644
index 000000000..b4725cc99
Binary files /dev/null and b/common/src/main/res/drawable-hdpi/ic_gryphon_white.png differ
diff --git a/common/src/main/res/drawable-hdpi/ic_gryphon_white.webp b/common/src/main/res/drawable-hdpi/ic_gryphon_white.webp
deleted file mode 100644
index d98990a20..000000000
Binary files a/common/src/main/res/drawable-hdpi/ic_gryphon_white.webp and /dev/null differ
diff --git a/common/src/main/res/drawable-mdpi/ic_gryphon_white.png b/common/src/main/res/drawable-mdpi/ic_gryphon_white.png
new file mode 100644
index 000000000..580e97d7f
Binary files /dev/null and b/common/src/main/res/drawable-mdpi/ic_gryphon_white.png differ
diff --git a/common/src/main/res/drawable-mdpi/ic_gryphon_white.webp b/common/src/main/res/drawable-mdpi/ic_gryphon_white.webp
deleted file mode 100644
index 24145a0aa..000000000
Binary files a/common/src/main/res/drawable-mdpi/ic_gryphon_white.webp and /dev/null differ
diff --git a/common/src/main/res/drawable-xhdpi/ic_gryphon_white.png b/common/src/main/res/drawable-xhdpi/ic_gryphon_white.png
new file mode 100644
index 000000000..7b847d1d7
Binary files /dev/null and b/common/src/main/res/drawable-xhdpi/ic_gryphon_white.png differ
diff --git a/common/src/main/res/drawable-xhdpi/ic_gryphon_white.webp b/common/src/main/res/drawable-xhdpi/ic_gryphon_white.webp
deleted file mode 100644
index ffb6eddd6..000000000
Binary files a/common/src/main/res/drawable-xhdpi/ic_gryphon_white.webp and /dev/null differ
diff --git a/common/src/main/res/drawable-xxhdpi/ic_gryphon_white.png b/common/src/main/res/drawable-xxhdpi/ic_gryphon_white.png
new file mode 100644
index 000000000..2648df11c
Binary files /dev/null and b/common/src/main/res/drawable-xxhdpi/ic_gryphon_white.png differ
diff --git a/common/src/main/res/drawable-xxhdpi/ic_gryphon_white.webp b/common/src/main/res/drawable-xxhdpi/ic_gryphon_white.webp
deleted file mode 100644
index 4159a8720..000000000
Binary files a/common/src/main/res/drawable-xxhdpi/ic_gryphon_white.webp and /dev/null differ
diff --git a/common/src/main/res/drawable-xxxhdpi/ic_gryphon_white.png b/common/src/main/res/drawable-xxxhdpi/ic_gryphon_white.png
new file mode 100644
index 000000000..9badec523
Binary files /dev/null and b/common/src/main/res/drawable-xxxhdpi/ic_gryphon_white.png differ