New sensitive media design

This commit is contained in:
Grishka 2023-03-24 00:33:02 +03:00
parent 4492e940e5
commit e873dd7d0a
14 changed files with 180 additions and 137 deletions

View File

@ -74,6 +74,7 @@ public class AccountTimelineFragment extends StatusListFragment{
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
view.setBackground(null); // prevents unnecessary overdraw
}
@Override

View File

@ -428,35 +428,6 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
}
public void onVisibilityIconClick(HeaderStatusDisplayItem.Holder holder){
Status status=holder.getItem().status;
status.spoilerRevealed=!status.spoilerRevealed;
if(!TextUtils.isEmpty(status.spoilerText)){
TextStatusDisplayItem.Holder text=findHolderOfType(holder.getItemID(), TextStatusDisplayItem.Holder.class);
if(text!=null){
adapter.notifyItemChanged(text.getAbsoluteAdapterPosition());
}
}
holder.rebind();
updateImagesSpoilerState(status, holder.getItemID());
}
protected void updateImagesSpoilerState(Status status, String itemID){
ArrayList<Integer> updatedPositions=new ArrayList<>();
MediaGridStatusDisplayItem.Holder mediaGrid=findHolderOfType(itemID, MediaGridStatusDisplayItem.Holder.class);
if(mediaGrid!=null){
mediaGrid.setRevealed(status.spoilerRevealed);
updatedPositions.add(mediaGrid.getAbsoluteAdapterPosition()-getMainAdapterOffset());
}
int i=0;
for(StatusDisplayItem item:displayItems){
if(itemID.equals(item.parentID) && item instanceof MediaGridStatusDisplayItem && !updatedPositions.contains(i)){
adapter.notifyItemChanged(i);
}
i++;
}
}
public void onGapClick(GapStatusDisplayItem.Holder item){}
public String getAccountID(){
@ -622,10 +593,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
private class StatusListItemDecoration extends RecyclerView.ItemDecoration{
private Paint dividerPaint=new Paint(), hiddenMediaPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
private Typeface mediumTypeface=Typeface.create("sans-serif-medium", Typeface.NORMAL);
private Layout mediaHiddenTitleLayout, mediaHiddenTextLayout, tapToRevealTextLayout;
private int currentMediaHiddenLayoutsWidth=0;
private Paint dividerPaint=new Paint();
{
dividerPaint.setColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Outline));
@ -646,73 +614,5 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
}
}
@Override
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state){
for(int i=0;i<parent.getChildCount();i++){
View child=parent.getChildAt(i);
RecyclerView.ViewHolder holder=parent.getChildViewHolder(child);
if(holder instanceof MediaGridStatusDisplayItem.Holder imgHolder){
if(!imgHolder.getItem().status.spoilerRevealed && TextUtils.isEmpty(imgHolder.getItem().status.spoilerText)){
hiddenMediaPaint.setColor(0x80000000);
c.drawRect(child.getX(), child.getY(), child.getX()+child.getWidth(), child.getY()+child.getHeight(), hiddenMediaPaint);
}
}
}
for(int i=0;i<parent.getChildCount();i++){
View child=parent.getChildAt(i);
RecyclerView.ViewHolder holder=parent.getChildViewHolder(child);
if(holder instanceof MediaGridStatusDisplayItem.Holder imgHolder){
if(!imgHolder.getItem().status.spoilerRevealed){
if(TextUtils.isEmpty(imgHolder.getItem().status.spoilerText)){
int listWidth=getListWidthForMediaLayout();
int width=Math.min(listWidth, V.dp(MediaGridLayout.MAX_WIDTH));
if(currentMediaHiddenLayoutsWidth!=width)
rebuildMediaHiddenLayouts(width-V.dp(32));
c.save();
float totalHeight;
boolean hiddenByAuthor=imgHolder.getItem().status.sensitive;
if(hiddenByAuthor)
totalHeight=mediaHiddenTitleLayout.getHeight()+mediaHiddenTextLayout.getHeight()+V.dp(8);
else
totalHeight=tapToRevealTextLayout.getHeight();
c.translate(child.getX()+V.dp(16), child.getY()+child.getHeight()/2f-totalHeight/2f);
if(hiddenByAuthor){
mediaHiddenTitleLayout.draw(c);
c.translate(0, mediaHiddenTitleLayout.getHeight()+V.dp(8));
mediaHiddenTextLayout.draw(c);
}else{
tapToRevealTextLayout.draw(c);
}
c.restore();
}
}
}
}
}
private void rebuildMediaHiddenLayouts(int width){
currentMediaHiddenLayoutsWidth=width;
String title=getString(R.string.sensitive_content);
TextPaint titlePaint=new TextPaint(Paint.ANTI_ALIAS_FLAG);
titlePaint.setColor(getResources().getColor(R.color.gray_50));
titlePaint.setTextSize(V.dp(22));
titlePaint.setTypeface(mediumTypeface);
mediaHiddenTitleLayout=StaticLayout.Builder.obtain(title, 0, title.length(), titlePaint, width)
.setAlignment(Layout.Alignment.ALIGN_CENTER)
.build();
String tapToReveal=getString(R.string.tap_to_reveal);
tapToRevealTextLayout=StaticLayout.Builder.obtain(tapToReveal, 0, tapToReveal.length(), titlePaint, width)
.setAlignment(Layout.Alignment.ALIGN_CENTER)
.build();
TextPaint textPaint=new TextPaint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(getResources().getColor(R.color.gray_200));
textPaint.setTextSize(V.dp(16));
String text=getString(R.string.sensitive_content_explain);
mediaHiddenTextLayout=StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, width)
.setAlignment(Layout.Alignment.ALIGN_CENTER)
.setLineSpacing(V.dp(5), 1f)
.build();
}
}
}

View File

@ -5,8 +5,11 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
@ -19,9 +22,11 @@ import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.PhotoLayoutHelper;
import org.joinmastodon.android.ui.drawables.SpoilerStripesDrawable;
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
import org.joinmastodon.android.ui.utils.MediaAttachmentViewController;
import org.joinmastodon.android.ui.views.FrameLayoutThatOnlyMeasuresFirstChild;
import org.joinmastodon.android.ui.views.MaxWidthFrameLayout;
import org.joinmastodon.android.ui.views.MediaGridLayout;
import org.joinmastodon.android.utils.TypedObjectPool;
@ -42,6 +47,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
private final List<Attachment> attachments;
private final ArrayList<ImageLoaderRequest> requests=new ArrayList<>();
public final Status status;
public boolean sensitiveRevealed;
public MediaGridStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, PhotoLayoutHelper.TiledLayoutResult tiledLayout, List<Attachment> attachments, Status status){
super(parentID, parentFragment);
@ -49,6 +55,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
this.viewPool=parentFragment.getAttachmentViewsPool();
this.attachments=attachments;
this.status=status;
sensitiveRevealed=!status.sensitive;
for(Attachment att:attachments){
requests.add(new UrlImageLoaderRequest(switch(att.type){
case IMAGE -> att.url;
@ -85,12 +92,18 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
private final View.OnClickListener clickListener=this::onViewClick, altTextClickListener=this::onAltTextClick;
private final ArrayList<MediaAttachmentViewController> controllers=new ArrayList<>();
private final MaxWidthFrameLayout overlays;
private final FrameLayout altTextWrapper;
private final TextView altTextButton;
private final View altTextScroller;
private final ImageButton altTextClose;
private final TextView altText;
private final View sensitiveOverlay;
private final LayerDrawable sensitiveOverlayBG;
private static final ColorDrawable drawableForWhenThereIsNoBlurhash=new ColorDrawable(0xffffffff);
private final TextView hideSensitiveButton;
private int altTextIndex=-1;
private Animator altTextAnimator;
@ -100,15 +113,34 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
layout=new MediaGridLayout(activity);
wrapper.addView(layout);
wrapper.setPadding(0, 0, 0, V.dp(8));
wrapper.setClipToPadding(false);
activity.getLayoutInflater().inflate(R.layout.overlay_image_alt_text, wrapper);
overlays=new MaxWidthFrameLayout(activity);
overlays.setMaxWidth(V.dp(MediaGridLayout.MAX_WIDTH));
wrapper.addView(overlays, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER_HORIZONTAL));
activity.getLayoutInflater().inflate(R.layout.overlay_image_alt_text, overlays);
altTextWrapper=findViewById(R.id.alt_text_wrapper);
altTextButton=findViewById(R.id.alt_button);
altTextScroller=findViewById(R.id.alt_text_scroller);
altTextClose=findViewById(R.id.alt_text_close);
altText=findViewById(R.id.alt_text);
altTextClose.setOnClickListener(this::onAltTextCloseClick);
wrapper.setClipToPadding(false);
hideSensitiveButton=(TextView) activity.getLayoutInflater().inflate(R.layout.alt_text_badge, overlays, false);
hideSensitiveButton.setText(R.string.hide);
FrameLayout.LayoutParams lp;
overlays.addView(hideSensitiveButton, lp=new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, V.dp(24), Gravity.END | Gravity.BOTTOM));
int margin=V.dp(8);
lp.setMargins(margin, margin, margin, margin);
activity.getLayoutInflater().inflate(R.layout.overlay_image_sensitive, overlays);
sensitiveOverlay=findViewById(R.id.sensitive_overlay);
sensitiveOverlayBG=(LayerDrawable) sensitiveOverlay.getBackground();
sensitiveOverlayBG.setDrawableByLayerId(R.id.left_drawable, new SpoilerStripesDrawable(false));
sensitiveOverlayBG.setDrawableByLayerId(R.id.right_drawable, new SpoilerStripesDrawable(true));
sensitiveOverlay.setOnClickListener(v->revealSensitive());
hideSensitiveButton.setOnClickListener(v->hideSensitive());
}
@Override
@ -148,6 +180,16 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
}
altTextWrapper.setVisibility(View.GONE);
altTextIndex=-1;
if(!item.sensitiveRevealed){
sensitiveOverlay.setVisibility(View.VISIBLE);
layout.setVisibility(View.INVISIBLE);
updateBlurhashInSensitiveOverlay();
}else{
sensitiveOverlay.setVisibility(View.GONE);
layout.setVisibility(View.VISIBLE);
}
hideSensitiveButton.setVisibility(item.status.sensitive ? View.VISIBLE : View.GONE);
}
@Override
@ -182,7 +224,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
int[] loc={0, 0};
v.getLocationInWindow(loc);
int btnL=loc[0], btnT=loc[1];
wrapper.getLocationInWindow(loc);
overlays.getLocationInWindow(loc);
btnL-=loc[0];
btnT-=loc[1];
@ -240,7 +282,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
int[] loc={0, 0};
btn.getLocationInWindow(loc);
int btnL=loc[0], btnT=loc[1];
wrapper.getLocationInWindow(loc);
overlays.getLocationInWindow(loc);
btnL-=loc[0];
btnT-=loc[1];
@ -276,12 +318,6 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
set.start();
}
public void setRevealed(boolean revealed){
for(MediaAttachmentViewController c:controllers){
c.setRevealed(revealed);
}
}
public MediaAttachmentViewController getViewController(int index){
return controllers.get(index);
}
@ -290,5 +326,25 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
layout.setClipChildren(clip);
wrapper.setClipChildren(clip);
}
private void updateBlurhashInSensitiveOverlay(){
Drawable d=item.attachments.get(0).blurhashPlaceholder;
sensitiveOverlayBG.setDrawableByLayerId(R.id.blurhash, d==null ? drawableForWhenThereIsNoBlurhash : d.mutate());
}
private void revealSensitive(){
if(item.sensitiveRevealed)
return;
item.sensitiveRevealed=true;
V.setVisibilityAnimated(sensitiveOverlay, View.GONE);
layout.setVisibility(View.VISIBLE);
}
private void hideSensitive(){
if(!item.sensitiveRevealed)
return;
item.sensitiveRevealed=false;
V.setVisibilityAnimated(sensitiveOverlay, View.VISIBLE, ()->layout.setVisibility(View.INVISIBLE));
}
}
}

View File

@ -11,6 +11,7 @@ import org.joinmastodon.android.MastodonApp;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import me.grishka.appkit.utils.V;
public class SpoilerStripesDrawable extends Drawable{
private Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
@ -33,6 +34,8 @@ public class SpoilerStripesDrawable extends Drawable{
canvas.translate(bounds.left, bounds.top);
canvas.clipRect(0, 0, bounds.width(), bounds.height());
float scale=MastodonApp.context.getResources().getDisplayMetrics().density;
if(bounds.width()>V.dp(10))
scale*=2;
canvas.scale(scale, scale, 0, 0);
float height=bounds.height()/scale;

View File

@ -50,4 +50,10 @@ public class BlurHashDrawable extends Drawable{
public int getIntrinsicHeight(){
return height;
}
@NonNull
@Override
public Drawable mutate(){
return new BlurHashDrawable(bitmap, width, height);
}
}

View File

@ -52,7 +52,7 @@ public class MediaAttachmentViewController{
this.status=status;
crossfadeDrawable.setSize(attachment.getWidth(), attachment.getHeight());
crossfadeDrawable.setBlurhashDrawable(attachment.blurhashPlaceholder);
crossfadeDrawable.setCrossfadeAlpha(status.spoilerRevealed ? 0f : 1f);
crossfadeDrawable.setCrossfadeAlpha(0f);
photo.setImageDrawable(null);
photo.setImageDrawable(crossfadeDrawable);
photo.setContentDescription(TextUtils.isEmpty(attachment.description) ? context.getString(R.string.media_no_description) : attachment.description);
@ -67,7 +67,7 @@ public class MediaAttachmentViewController{
public void setImage(Drawable drawable){
crossfadeDrawable.setImageDrawable(drawable);
if(didClear && status.spoilerRevealed)
if(didClear)
crossfadeDrawable.animateAlpha(0f);
}
@ -76,8 +76,4 @@ public class MediaAttachmentViewController{
crossfadeDrawable.setImageDrawable(null);
didClear=true;
}
public void setRevealed(boolean revealed){
crossfadeDrawable.animateAlpha(revealed ? 0f : 1f);
}
}

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/blurhash">
<color android:color="#fff"/>
</item>
<item>
<color android:color="?colorSensitiveOverlay"/>
</item>
<item android:gravity="left" android:width="12dp">
<shape>
<gradient android:type="linear" android:angle="270" android:startColor="#FEC84B" android:endColor="#F79009"/>
</shape>
</item>
<item android:id="@+id/left_drawable" android:width="12dp" android:gravity="left">
<color android:color="#0f0"/>
</item>
<item android:gravity="right" android:width="12dp">
<shape>
<gradient android:type="linear" android:angle="270" android:startColor="#FEC84B" android:endColor="#F79009"/>
</shape>
</item>
<item android:id="@+id/right_drawable" android:width="12dp" android:gravity="right">
<color android:color="#0f0"/>
</item>
</layer-list>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M16.1,13.3 L14.65,11.85Q14.875,10.675 13.975,9.65Q13.075,8.625 11.65,8.85L10.2,7.4Q10.625,7.2 11.062,7.1Q11.5,7 12,7Q13.875,7 15.188,8.312Q16.5,9.625 16.5,11.5Q16.5,12 16.4,12.438Q16.3,12.875 16.1,13.3ZM19.3,16.45 L17.85,15.05Q18.8,14.325 19.538,13.462Q20.275,12.6 20.8,11.5Q19.55,8.975 17.212,7.487Q14.875,6 12,6Q11.275,6 10.575,6.1Q9.875,6.2 9.2,6.4L7.65,4.85Q8.675,4.425 9.75,4.212Q10.825,4 12,4Q15.775,4 18.725,6.087Q21.675,8.175 23,11.5Q22.425,12.975 21.488,14.238Q20.55,15.5 19.3,16.45ZM19.8,22.6 L15.6,18.45Q14.725,18.725 13.838,18.863Q12.95,19 12,19Q8.225,19 5.275,16.913Q2.325,14.825 1,11.5Q1.525,10.175 2.325,9.037Q3.125,7.9 4.15,7L1.4,4.2L2.8,2.8L21.2,21.2ZM5.55,8.4Q4.825,9.05 4.225,9.825Q3.625,10.6 3.2,11.5Q4.45,14.025 6.787,15.512Q9.125,17 12,17Q12.5,17 12.975,16.938Q13.45,16.875 13.95,16.8L13.05,15.85Q12.775,15.925 12.525,15.962Q12.275,16 12,16Q10.125,16 8.812,14.688Q7.5,13.375 7.5,11.5Q7.5,11.225 7.537,10.975Q7.575,10.725 7.65,10.45ZM13.525,10.725Q13.525,10.725 13.525,10.725Q13.525,10.725 13.525,10.725Q13.525,10.725 13.525,10.725Q13.525,10.725 13.525,10.725Q13.525,10.725 13.525,10.725Q13.525,10.725 13.525,10.725ZM9.75,12.6Q9.75,12.6 9.75,12.6Q9.75,12.6 9.75,12.6Q9.75,12.6 9.75,12.6Q9.75,12.6 9.75,12.6Q9.75,12.6 9.75,12.6Q9.75,12.6 9.75,12.6Z"/>
</vector>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:layout_gravity="start|bottom"
android:layout_margin="8dp"
android:importantForAccessibility="no"
android:textAppearance="@style/m3_label_large"
android:textColor="#FFF"
android:gravity="center"
android:includeFontPadding="false"
android:background="@drawable/bg_image_alt_overlay"
android:text="ALT"
tools:ignore="HardcodedText"
tools:showIn="@layout/display_item_photo" />

View File

@ -12,21 +12,7 @@
android:scaleType="centerCrop"/>
<!-- This is hidden from screenreaders because that same alt text is set as content description on the ImageView -->
<TextView
android:id="@+id/alt_button"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:layout_gravity="start|bottom"
android:layout_margin="8dp"
android:importantForAccessibility="no"
android:textAppearance="@style/m3_label_large"
android:textColor="#FFF"
android:gravity="center"
android:includeFontPadding="false"
android:background="@drawable/bg_image_alt_overlay"
android:text="ALT"
tools:ignore="HardcodedText" />
<include layout="@layout/alt_text_badge"
android:id="@+id/alt_button"/>
</FrameLayout>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sensitive_overlay"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="32dp"
android:paddingRight="32dp"
android:background="@drawable/bg_spoiler_overlay"
android:layerType="hardware"
android:gravity="center">
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:tint="?colorM3OnSurfaceVariant"
android:importantForAccessibility="no"
android:src="@drawable/ic_visibility_off_24px"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:gravity="center_horizontal"
android:maxLines="2"
android:textAppearance="@style/m3_body_large"
android:textColor="?colorM3OnSurfaceVariant"
android:text="@string/sensitive_content_explain"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="20dp"
android:textAppearance="@style/m3_label_large"
android:textColor="?colorM3Primary"
android:gravity="center_vertical"
android:text="@string/show"/>
</LinearLayout>

View File

@ -42,6 +42,7 @@
<attr name="colorM3ErrorContainer" format="color"/>
<attr name="colorM3OnErrorContainer" format="color"/>
<attr name="colorM3PrimaryInverse" format="color"/>
<attr name="colorSensitiveOverlay" format="color"/>
<attr name="primaryLargeButtonStyle" format="reference"/>
<attr name="secondaryLargeButtonStyle" format="reference"/>

View File

@ -268,8 +268,7 @@
<string name="settings_app_version">Mastodon for Android v%1$s (%2$d)</string>
<string name="media_cache_cleared">Media cache cleared</string>
<string name="confirm_log_out">Are you sure you want to sign out?</string>
<string name="sensitive_content">Sensitive content</string>
<string name="sensitive_content_explain">The author marked this media as sensitive. Tap to reveal.</string>
<string name="sensitive_content_explain">The author marked this media as sensitive.</string>
<string name="media_hidden">Tap to reveal</string>
<string name="avatar_description">Go to %s\'s profile</string>
<string name="more_options">More options</string>
@ -448,4 +447,6 @@
<string name="view_all">View all</string>
<string name="profile_endorsed_accounts">Accounts</string>
<string name="verified_link">Verified link</string>
<string name="show">Show</string>
<string name="hide">Hide</string>
</resources>

View File

@ -71,7 +71,8 @@
<item name="android:statusBarColor">?colorM3Background</item>
<item name="android:navigationBarColor">@color/navigation_bar_bg_light</item>
<item name="android:colorAccent">?colorM3Primary</item>
<item name="android:colorControlHighlight">@color/m3_primary_overlay</item>
<item name="android:colorControlHighlight">@color/m3_on_surface_overlay</item>
<item name="colorSensitiveOverlay">#a6ffffff</item>
</style>
<style name="Theme.Mastodon.Dark" parent="Theme.AppKit">
@ -147,7 +148,8 @@
<item name="android:statusBarColor">?colorM3Background</item>
<item name="android:navigationBarColor">?colorM3Background</item>
<item name="android:colorAccent">?colorM3Primary</item>
<item name="android:colorControlHighlight">@color/m3_primary_overlay</item>
<item name="android:colorControlHighlight">@color/m3_on_surface_overlay</item>
<item name="colorSensitiveOverlay">#80000000</item>
</style>
<style name="Theme.Mastodon.Dark.TrueBlack">