Merge remote-tracking branch 'upstream/master'

This commit is contained in:
sk
2023-01-30 23:55:03 +01:00
33 changed files with 1390 additions and 77 deletions

View File

@@ -602,7 +602,7 @@ public class TabLayout extends HorizontalScrollView {
* <p>If the tab indicator color is not {@code Color.TRANSPARENT}, the indicator will be wrapped
* and tinted right before it is drawn by {@link SlidingTabIndicator#draw(Canvas)}. If you'd like
* the inherent color or the tinted color of a custom drawable to be used, make sure this color is
* set to {@code Color.TRANSPARENT} to avoid your color/tint being overriden.
* set to {@code Color.TRANSPARENT} to avoid your color/tint being overridden.
*
* @param color color to use for the indicator
* @attr ref com.google.android.material.R.styleable#TabLayout_tabIndicatorColor

View File

@@ -16,6 +16,10 @@ public class LinkSpan extends CharacterStyle {
private String accountID;
private String text;
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID){
this(link, listener, type, accountID, null);
}
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID, String text){
this.listener=listener;
this.link=link;
@@ -38,6 +42,7 @@ public class LinkSpan extends CharacterStyle {
case URL -> UiUtils.openURL(context, accountID, link);
case MENTION -> UiUtils.openProfileByID(context, accountID, link);
case HASHTAG -> UiUtils.openHashtagTimeline(context, accountID, link, null);
case CUSTOM -> listener.onLinkClick(this);
}
}
@@ -64,6 +69,7 @@ public class LinkSpan extends CharacterStyle {
public enum Type{
URL,
MENTION,
HASHTAG
HASHTAG,
CUSTOM
}
}

View File

@@ -28,6 +28,9 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.os.ext.SdkExtensions;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
@@ -664,6 +667,38 @@ public class UiUtils {
}).exec(accountID);
}
public static void setRelationshipToActionButtonM3(Relationship relationship, Button button){
boolean secondaryStyle;
if(relationship.blocking){
button.setText(R.string.button_blocked);
secondaryStyle=true;
}else if(relationship.blockedBy){
button.setText(R.string.button_follow);
secondaryStyle=false;
}else if(relationship.requested){
button.setText(R.string.button_follow_pending);
secondaryStyle=true;
}else if(!relationship.following){
button.setText(relationship.followedBy ? R.string.follow_back : R.string.button_follow);
secondaryStyle=false;
}else{
button.setText(R.string.button_following);
secondaryStyle=true;
}
button.setEnabled(!relationship.blockedBy);
int styleRes=secondaryStyle ? R.style.Widget_Mastodon_M3_Button_Tonal : R.style.Widget_Mastodon_M3_Button_Filled;
TypedArray ta=button.getContext().obtainStyledAttributes(styleRes, new int[]{android.R.attr.background});
button.setBackground(ta.getDrawable(0));
ta.recycle();
ta=button.getContext().obtainStyledAttributes(styleRes, new int[]{android.R.attr.textColor});
if(relationship.blocking)
button.setTextColor(button.getResources().getColorStateList(R.color.error_600));
else
button.setTextColor(ta.getColorStateList(0));
ta.recycle();
}
public static void performAccountAction(Activity activity, Account account, String accountID, Relationship relationship, Button button, Consumer<Boolean> progressCallback, Consumer<Relationship> resultCallback) {
if (relationship.blocking) {
confirmToggleBlockUser(activity, accountID, account, true, resultCallback);
@@ -1176,4 +1211,63 @@ public class UiUtils {
// fucking finally
return container;
}
/**
* Check to see if Android platform photopicker is available on the device\
*
* @return whether the device supports photopicker intents.
*/
@SuppressLint("NewApi")
public static boolean isPhotoPickerAvailable(){
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.TIRAMISU){
return true;
}else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.R){
return SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R)>=2;
}else
return false;
}
@SuppressLint("InlinedApi")
public static Intent getMediaPickerIntent(String[] mimeTypes, int maxCount){
Intent intent;
if(isPhotoPickerAvailable()){
intent=new Intent(MediaStore.ACTION_PICK_IMAGES);
if(maxCount>1)
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxCount);
}else{
intent=new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
}
if(mimeTypes.length>1){
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
}else if(mimeTypes.length==1){
intent.setType(mimeTypes[0]);
}else{
intent.setType("*/*");
}
if(maxCount>1)
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
return intent;
}
/**
* Wraps a View.OnClickListener to filter multiple clicks in succession.
* Useful for buttons that perform some action that changes their state asynchronously.
* @param l
* @return
*/
public static View.OnClickListener rateLimitedClickListener(View.OnClickListener l){
return new View.OnClickListener(){
private long lastClickTime;
@Override
public void onClick(View v){
if(SystemClock.uptimeMillis()-lastClickTime>500L){
lastClickTime=SystemClock.uptimeMillis();
l.onClick(v);
}
}
};
}
}

View File

@@ -20,6 +20,7 @@ import android.text.Editable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.EditText;
@@ -47,6 +48,7 @@ public class FloatingHintEditTextLayout extends FrameLayout{
private RectF tmpRect=new RectF();
private ColorStateList labelColors, origHintColors;
private boolean errorState;
private TextView errorView;
public FloatingHintEditTextLayout(Context context){
this(context, null);
@@ -95,12 +97,22 @@ public class FloatingHintEditTextLayout extends FrameLayout{
label.setAlpha(0f);
edit.addTextChangedListener(new SimpleTextWatcher(this::onTextChanged));
errorView=new LinkedTextView(getContext());
errorView.setTextAppearance(R.style.m3_body_small);
errorView.setTextColor(UiUtils.getThemeColor(getContext(), R.attr.colorM3OnSurfaceVariant));
errorView.setLinkTextColor(UiUtils.getThemeColor(getContext(), R.attr.colorM3Primary));
errorView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
errorView.setPadding(V.dp(16), V.dp(4), V.dp(16), 0);
errorView.setVisibility(View.GONE);
addView(errorView);
}
private void onTextChanged(Editable text){
if(errorState){
errorView.setVisibility(View.GONE);
errorState=false;
setForeground(getResources().getDrawable(R.drawable.bg_m3_outlined_text_field));
setForeground(getResources().getDrawable(R.drawable.bg_m3_outlined_text_field, getContext().getTheme()));
refreshDrawableState();
}
boolean newHintVisible=text.length()==0;
@@ -211,12 +223,34 @@ public class FloatingHintEditTextLayout extends FrameLayout{
label.setTextColor(color.getColorForState(getDrawableState(), 0xff00ff00));
}
public void setErrorState(){
public void setErrorState(CharSequence error){
if(errorState)
return;
errorState=true;
setForeground(getResources().getDrawable(R.drawable.bg_m3_outlined_text_field_error, getContext().getTheme()));
label.setTextColor(UiUtils.getThemeColor(getContext(), R.attr.colorM3Error));
errorView.setVisibility(VISIBLE);
errorView.setText(error);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
if(errorView.getVisibility()!=GONE){
int width=MeasureSpec.getSize(widthMeasureSpec)-getPaddingLeft()-getPaddingRight();
LayoutParams editLP=(LayoutParams) edit.getLayoutParams();
width-=editLP.leftMargin+editLP.rightMargin;
errorView.measure(width | MeasureSpec.EXACTLY, MeasureSpec.UNSPECIFIED);
LayoutParams lp=(LayoutParams) errorView.getLayoutParams();
lp.width=width;
lp.height=errorView.getMeasuredHeight();
lp.gravity=Gravity.LEFT | Gravity.BOTTOM;
lp.leftMargin=editLP.leftMargin;
editLP.bottomMargin=errorView.getMeasuredHeight();
}else{
LayoutParams editLP=(LayoutParams) edit.getLayoutParams();
editLP.bottomMargin=0;
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private class PaddedForegroundDrawable extends Drawable{
@@ -313,8 +347,8 @@ public class FloatingHintEditTextLayout extends FrameLayout{
@Override
protected void onBoundsChange(@NonNull Rect bounds){
super.onBoundsChange(bounds);
LayoutParams lp=(LayoutParams) edit.getLayoutParams();
wrapped.setBounds(bounds.left+lp.leftMargin-V.dp(12), bounds.top, bounds.right-lp.rightMargin+V.dp(12), bounds.bottom);
int offset=V.dp(12);
wrapped.setBounds(edit.getLeft()-offset, edit.getTop()-offset, edit.getRight()+offset, edit.getBottom()+offset);
}
}
}