diff --git a/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt index d31ff1d3c..28056f921 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt @@ -22,9 +22,12 @@ import android.content.Context import android.content.Intent import android.content.res.ColorStateList import android.graphics.Color +import android.graphics.Typeface import android.graphics.drawable.LayerDrawable import android.os.Bundle +import android.text.SpannableStringBuilder import android.text.TextWatcher +import android.text.style.StyleSpan import android.view.Menu import android.view.MenuInflater import android.view.MenuItem @@ -32,10 +35,12 @@ import android.view.View import android.view.ViewGroup import androidx.activity.viewModels import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes import androidx.annotation.Px import androidx.appcompat.app.AlertDialog import androidx.appcompat.content.res.AppCompatResources import androidx.core.app.ActivityOptionsCompat +import androidx.core.graphics.ColorUtils import androidx.core.view.MenuProvider import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat @@ -48,6 +53,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.viewpager2.widget.MarginPageTransformer import com.bumptech.glide.Glide import com.google.android.material.appbar.AppBarLayout +import com.google.android.material.chip.Chip import com.google.android.material.color.MaterialColors import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.shape.MaterialShapeDrawable @@ -475,10 +481,10 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide accountFieldAdapter.notifyDataSetChanged() binding.accountLockedImageView.visible(account.locked) - binding.accountBadgeTextView.visible(account.bot) updateAccountAvatar() updateToolbar() + updateBadges() updateMovedAccount() updateRemoteAccount() updateAccountJoinedDate() @@ -491,6 +497,33 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide } } + private fun updateBadges() { + binding.accountBadgeContainer.removeAllViews() + + val isLight = resources.getBoolean(R.bool.lightNavigationBar) + + if (loadedAccount?.bot == true) { + val badgeView = getBadge(getColor(R.color.tusky_grey_50), R.drawable.ic_bot_24dp, getString(R.string.profile_badge_bot_text), isLight) + binding.accountBadgeContainer.addView(badgeView) + } + + loadedAccount?.roles?.forEach { role -> + val badgeColor = if (role.color.isNotBlank()) { + Color.parseColor(role.color) + } else { + // sometimes the color is not set for a role, in this case fall back to our default blue + getColor(R.color.tusky_blue) + } + + val sb = SpannableStringBuilder("${role.name} ${viewModel.domain}") + sb.setSpan(StyleSpan(Typeface.BOLD), 0, role.name.length, 0) + + val badgeView = getBadge(badgeColor, R.drawable.profile_badge_person_24dp, sb, isLight) + + binding.accountBadgeContainer.addView(badgeView) + } + } + private fun updateAccountJoinedDate() { loadedAccount?.let { account -> try { @@ -1003,6 +1036,46 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide } } + private fun getBadge( + @ColorInt baseColor: Int, + @DrawableRes icon: Int, + text: CharSequence, + isLight: Boolean + ): Chip { + val badge = Chip(this) + + // text color with maximum contrast + val textColor = if (isLight) Color.BLACK else Color.WHITE + // badge color with 50% transparency so it blends in with the theme background + val backgroundColor = Color.argb(128, Color.red(baseColor), Color.green(baseColor), Color.blue(baseColor)) + // a color between the text color and the badge color + val outlineColor = ColorUtils.blendARGB(textColor, baseColor, 0.7f) + + // configure the badge + badge.text = text + badge.setTextColor(textColor) + badge.chipStrokeWidth = resources.getDimension(R.dimen.profile_badge_stroke_width) + badge.chipStrokeColor = ColorStateList.valueOf(outlineColor) + badge.setChipIconResource(icon) + badge.isChipIconVisible = true + badge.chipIconSize = resources.getDimension(R.dimen.profile_badge_icon_size) + badge.chipIconTint = ColorStateList.valueOf(outlineColor) + badge.chipBackgroundColor = ColorStateList.valueOf(backgroundColor) + + // badge isn't clickable, so disable all related behavior + badge.isClickable = false + badge.isFocusable = false + badge.setEnsureMinTouchTargetSize(false) + + // reset some chip defaults so it looks better for our badge usecase + badge.iconStartPadding = resources.getDimension(R.dimen.profile_badge_icon_start_padding) + badge.iconEndPadding = resources.getDimension(R.dimen.profile_badge_icon_end_padding) + badge.minHeight = resources.getDimensionPixelSize(R.dimen.profile_badge_min_height) + badge.chipMinHeight = resources.getDimension(R.dimen.profile_badge_min_height) + badge.updatePadding(top = 0, bottom = 0) + return badge + } + override fun androidInjector() = dispatchingAndroidInjector companion object { diff --git a/app/src/main/java/com/keylesspalace/tusky/components/account/AccountViewModel.kt b/app/src/main/java/com/keylesspalace/tusky/components/account/AccountViewModel.kt index b12e3923d..2cd4171a3 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/account/AccountViewModel.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/account/AccountViewModel.kt @@ -42,6 +42,9 @@ class AccountViewModel @Inject constructor( lateinit var accountId: String var isSelf = false + /** the domain of the viewed account **/ + var domain = "" + /** True if the viewed account has the same domain as the active account */ var isFromOwnDomain = false @@ -68,11 +71,12 @@ class AccountViewModel @Inject constructor( mastodonApi.account(accountId) .fold( { account -> + domain = getDomain(account.url) + isFromOwnDomain = domain == activeAccount.domain + accountData.postValue(Success(account)) isDataLoading = false isRefreshing.postValue(false) - - isFromOwnDomain = getDomain(account.url) == activeAccount.domain }, { t -> Log.w(TAG, "failed obtaining account", t) diff --git a/app/src/main/java/com/keylesspalace/tusky/entity/Account.kt b/app/src/main/java/com/keylesspalace/tusky/entity/Account.kt index 43b9bd9c9..4bb2b52e8 100644 --- a/app/src/main/java/com/keylesspalace/tusky/entity/Account.kt +++ b/app/src/main/java/com/keylesspalace/tusky/entity/Account.kt @@ -36,8 +36,8 @@ data class Account( val bot: Boolean = false, val emojis: List? = emptyList(), // nullable for backward compatibility val fields: List? = emptyList(), // nullable for backward compatibility - val moved: Account? = null - + val moved: Account? = null, + val roles: List? = emptyList() ) { val name: String @@ -68,3 +68,8 @@ data class StringField( val name: String, val value: String ) + +data class Role( + val name: String, + val color: String +) diff --git a/app/src/main/res/drawable/profile_badge_background.xml b/app/src/main/res/drawable/profile_badge_background.xml deleted file mode 100644 index be4bcf3ef..000000000 --- a/app/src/main/res/drawable/profile_badge_background.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/profile_badge_person_24dp.xml b/app/src/main/res/drawable/profile_badge_person_24dp.xml new file mode 100644 index 000000000..628c29de0 --- /dev/null +++ b/app/src/main/res/drawable/profile_badge_person_24dp.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/activity_account.xml b/app/src/main/res/layout/activity_account.xml index 2e92acc08..04b04baab 100644 --- a/app/src/main/res/layout/activity_account.xml +++ b/app/src/main/res/layout/activity_account.xml @@ -34,8 +34,8 @@ android:layout_height="180dp" android:layout_alignTop="@+id/account_header_info" android:background="?attr/colorPrimaryDark" - android:scaleType="centerCrop" android:contentDescription="@string/label_header" + android:scaleType="centerCrop" app:layout_collapseMode="parallax" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" @@ -154,40 +154,42 @@ app:tint="?android:textColorSecondary" tools:visibility="visible" /> - - + app:chipSpacingVertical="4dp" + app:layout_constraintStart_toEndOf="@id/accountUsernameTextView" + app:layout_constraintTop_toBottomOf="@id/accountFollowsYouTextView" + app:layout_goneMarginStart="0dp" /> + app:constraint_referenced_ids="accountFollowsYouTextView,accountBadgeContainer" /> + tools:text="April, 1971" /> @@ -287,16 +290,16 @@ tools:text="Account has moved" /> @@ -471,8 +474,8 @@ android:layout_width="@dimen/account_activity_avatar_size" android:layout_height="@dimen/account_activity_avatar_size" android:layout_marginStart="16dp" - android:padding="3dp" android:contentDescription="@string/label_avatar" + android:padding="3dp" app:layout_anchor="@+id/accountHeaderInfoContainer" app:layout_anchorGravity="top" app:layout_scrollFlags="scroll" diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 3caf111c2..ece334708 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -66,4 +66,11 @@ 48dp 48dp + + 1dp + 24dp + 16dp + 8dp + 0dp +