fix sprite substitution

This commit is contained in:
Phillip Thelen 2024-02-14 18:39:32 +01:00
parent 52d7348151
commit 5e429d7572
34 changed files with 322 additions and 179 deletions

View file

@ -1,176 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/material_card_background_color">
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/bottom_sheet_background"
app:behavior_hideable="true">
<ImageView
android:layout_width="22dp"
android:layout_height="3dp"
android:layout_gravity="center_horizontal"
android:layout_margin="@dimen/spacing_large"
android:importantForAccessibility="no"
android:src="@color/offset_background" />
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="50dp"
app:elevation="0dp">
<LinearLayout
android:id="@+id/bottom_sheet"
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/material_card_background_color"
android:backgroundTint="@color/material_card_background_color"
android:minHeight="?attr/actionBarSize"
android:theme="@style/Toolbar"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"
app:theme="@style/ReportMessageToolbar"
app:title=""
android:paddingStart="24dp"
android:paddingEnd="8dp"
app:titleTextColor="@color/text_primary">
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="36dp"
android:fontFamily="sans-serif-medium"
android:text="@string/report_violation"
android:textColor="@color/text_primary"
android:textSize="20sp" />
<Button
android:id="@+id/report_button"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginEnd="8dp"
android:enabled="false"
android:text="@string/report"
android:textAllCaps="false"
android:textColor="@color/text_dimmed"
android:textSize="18sp" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:behavior_hideable="true">
android:layout_marginBottom="0dp">
<ImageView
android:layout_width="22dp"
android:layout_height="3dp"
android:layout_gravity="center_horizontal"
android:layout_margin="@dimen/spacing_large"
android:src="@color/offset_background"
android:importantForAccessibility="no" />
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="50dp"
app:elevation="0dp">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/material_card_background_color"
android:backgroundTint="@color/material_card_background_color"
android:minHeight="?attr/actionBarSize"
android:theme="@style/Toolbar"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"
app:theme="@style/ReportMessageToolbar"
app:title=""
app:titleTextColor="@color/text_primary">
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="36dp"
android:fontFamily="sans-serif-medium"
android:text="@string/report_violation"
android:textColor="@color/text_primary"
android:textSize="20sp" />
<Button
android:id="@+id/report_button"
style="@style/Widget.AppCompat.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginEnd="8dp"
android:text="@string/report"
android:textAllCaps="false"
android:textColor="@color/red_100"
android:textSize="18sp" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
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">
<LinearLayout
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="0dp"
android:focusableInTouchMode="true"
android:orientation="vertical"
android:paddingStart="24dp"
android:paddingTop="16dp"
android:paddingEnd="24dp"
android:paddingBottom="25dp">
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/material_card_background_color"
app:cardCornerRadius="8dp"
app:strokeColor="@color/gray200_gray400"
app:strokeWidth="1dp">
<TextView
android:id="@+id/message_text_view"
style="@style/Body2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:lineSpacingExtra="4sp"
android:paddingStart="13dp"
android:paddingTop="11dp"
android:paddingEnd="13dp"
android:paddingBottom="11dp"
android:textColor="@color/text_primary"
tools:text="This is the message that is reported" />
</com.google.android.material.card.MaterialCardView>
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/material_card_background_color"
app:cardCornerRadius="8dp"
app:strokeColor="@color/gray200_gray400"
app:strokeWidth="1dp">
<TextView
android:id="@+id/report_reason_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_large"
android:layout_marginBottom="@dimen/spacing_small"
android:fontFamily="sans-serif-medium"
android:id="@+id/message_text_view"
style="@style/Body2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:lineSpacingExtra="4sp"
android:paddingStart="13dp"
android:paddingTop="11dp"
android:paddingEnd="13dp"
android:paddingBottom="11dp"
android:textColor="@color/text_primary"
android:textSize="16sp" />
tools:text="This is the message that is reported" />
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/report_reason_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_large"
android:layout_marginBottom="@dimen/spacing_small"
android:fontFamily="sans-serif-medium"
android:textColor="@color/text_primary"
android:textSize="16sp" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_small"
android:layout_marginBottom="@dimen/spacing_small"
app:cardBackgroundColor="@color/gray600_gray10"
app:cardCornerRadius="8dp"
app:strokeWidth="0dp">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/additional_info_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/transparent"
android:fontFamily="sans-serif"
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" />
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/additional_explanation_textview"
style="@style/Caption3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/spacing_medium"
android:fontFamily="sans-serif-medium"
android:gravity="start"
android:textColor="@color/text_ternary"
android:textColorLink="?colorAccent"
android:textSize="14sp"
android:textStyle="bold"
android:visibility="gone"
tools:text="@string/report_user_description" />
<TextView
android:id="@+id/report_explanation_textview"
style="@style/Caption3"
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_small"
android:layout_marginBottom="@dimen/spacing_small"
app:cardBackgroundColor="@color/gray600_gray10"
app:cardCornerRadius="8dp"
app:strokeWidth="0dp">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/additional_info_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/transparent"
android:fontFamily="sans-serif"
android:gravity="start"
android:textColor="@color/text_ternary"
android:textColorLink="@color/purple400_purple500"
android:textSize="14sp"
tools:text="@string/report_message_explanation" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
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" />
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/additional_explanation_textview"
style="@style/Caption3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/spacing_medium"
android:fontFamily="sans-serif-medium"
android:gravity="start"
android:textColor="@color/text_ternary"
android:textColorLink="?colorAccent"
android:textSize="14sp"
android:textStyle="bold"
android:visibility="gone"
tools:text="@string/report_user_description" />
<TextView
android:id="@+id/report_explanation_textview"
style="@style/Caption3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif"
android:gravity="start"
android:textColor="@color/text_ternary"
android:textColorLink="@color/purple400_purple500"
android:textSize="14sp"
tools:text="@string/report_message_explanation" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View file

@ -14,4 +14,6 @@
<item
android:id="@+id/action_share"
android:title="@string/share"/>
<item android:id="@+id/action_report"
android:title="@string/report_challenge" />
</menu>

View file

@ -811,11 +811,13 @@
<string name="report_message_title">Report %s for violation:</string>
<string name="report_message_explanation">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.</string>
<string name="report_user_explanation">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.</string>
<string name="report_challenge_explanation">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.</string>
<string name="report_player_title">Report %s?</string>
<string name="report_player">Report Player</string>
<string name="report_hint">Reason for report</string>
<string name="report_reason_title_message">Why are you reporting this message?</string>
<string name="report_reason_title_player">Why are you reporting this player?</string>
<string name="report_reason_title_challenge">Why are you reporting this challenge?</string>
<string name="report_formatted_name">%1$s\n@%2$s</string>
<string name="report_user_description">This will also block @%s</string>
<string name="report_message_hint">Reason for report</string>
@ -1476,6 +1478,7 @@
<string name="error_loading_member">Unable to find player</string>
<string name="error_loading_member_body">There was an error when loading this player\'s data. Please make sure you typed their @username correctly.</string>
<string name="preference_email_content_release">Content releases + Events</string>
<string name="report_challenge">Report Challenge</string>
<plurals name="you_x_others">

View file

@ -484,4 +484,7 @@ interface ApiService {
@GET("looking-for-party")
suspend fun retrievePartySeekingUsers(@Query("page") page: Int): HabitResponse<List<Member>>
@POST("challenges/{challengeId}/flag")
suspend fun reportChallenge(@Query("challengeId") challengeid: String, @Body updateData: Map<String, String>): HabitResponse<Void>
}

View file

@ -284,4 +284,5 @@ interface ApiClient {
suspend fun retrievePartySeekingUsers(page: Int): List<Member>?
suspend fun getGroupInvites(groupId: String, includeAllPublicFields: Boolean?): List<Member>?
suspend fun syncUserStats(): User?
suspend fun reportChallenge(challengeid: String, updateData: Map<String, String>): Void?
}

View file

@ -44,4 +44,5 @@ interface ChallengeRepository : BaseRepository {
fun getChallengepMembership(id: String): Flow<ChallengeMembership>
fun getChallengeMemberships(): Flow<List<ChallengeMembership>>
fun isChallengeMember(challengeID: String): Flow<Boolean>
suspend fun reportChallenge(challengeid: String, updateData: Map<String, String>): Void?
}

View file

@ -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<String, String>
): Void? {
return process { apiService.reportChallenge(challengeid, updateData) }
}
override suspend fun getContent(language: String?): ContentResult? {
return process { apiService.getContent(language ?: this.languageCode) }

View file

@ -23,6 +23,13 @@ class ChallengeRepositoryImpl(
return localRepository.isChallengeMember(currentUserID, challengeID)
}
override suspend fun reportChallenge(
challengeid: String,
updateData: Map<String, String>
): Void? {
return apiClient.reportChallenge(challengeid, updateData)
}
override fun getChallengepMembership(id: String): Flow<ChallengeMembership> {
return localRepository.getChallengeMembership(currentUserID, id)
}

View file

@ -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)
}
}

View file

@ -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
)
}
}

View file

@ -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)

View file

@ -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) {
(
{

View file

@ -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 =

View file

@ -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)

View file

@ -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<FragmentChallengeDetailBinding>
R.id.action_end_challenge -> {
showEndChallengeDialog()
}
R.id.action_report -> {
showReportChallengeBottomSheet()
}
}
return super.onOptionsItemSelected(item)
@ -217,6 +221,17 @@ class ChallengeDetailFragment : BaseMainFragment<FragmentChallengeDetailBinding>
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({

View file

@ -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<FragmentPartyDetailBinding>() {
@Inject
lateinit var inventoryRepository: InventoryRepository
@Inject
lateinit var appConfigManager: AppConfigManager
override fun onDestroyView() {
inventoryRepository.close()
super.onDestroyView()
@ -136,6 +140,7 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
isInvited = true,
showHeader = true,
showExtendedInfo = false,
configManager = appConfigManager,
onInvite = {
viewModel.rescindInvite(invitedMember)
}

View file

@ -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<PagingData<Member>>
@ -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)

View file

@ -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<Member>? = 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<User, Team
.background(HabiticaTheme.colors.contentBackground)
.padding(8.dp),
onMemberRowClicked = { },
onClassSelectionClicked = { }
onClassSelectionClicked = { },
configManager = AppConfigManager(null)
)
}
}

View file

@ -27,6 +27,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
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.auth.LocalAuthentication
import com.habitrpg.android.habitica.models.members.Member
import com.habitrpg.android.habitica.models.social.Group
@ -42,7 +43,8 @@ import kotlin.random.Random
fun GroupPlanMemberList(
members: List<Member>?,
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<Member> {
@Composable
@Preview
private fun Preview(@PreviewParameter(MemberProvider::class) member: Member) {
MemberItem(member = member, role = "Manager", onMemberClicked = {})
MemberItem(member = member, role = "Manager", onMemberClicked = {}, AppConfigManager(null))
}

View file

@ -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)

View file

@ -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<Member> {
@Preview
@Composable
private fun Preview(@PreviewParameter(MemberProvider::class) data: Member) {
PartySeekingListItem(user = data, onInvite = {})
PartySeekingListItem(user = data, onInvite = {}, configManager = AppConfigManager(null))
}

View file

@ -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<Member>,
assignedMembers: List<String>,
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)

View file

@ -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) {

View file

@ -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<LayerType, String>? = null
var configManager: AppConfigManager? = null
private val layerMap: Map<LayerType, String>
get() {
val avatar = this.avatar ?: return emptyMap()
@ -57,7 +60,8 @@ class AvatarView : FrameLayout {
private var spriteSubstitutions: Map<String, Map<String, String>> = 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

View file

@ -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) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 674 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB