mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-23 18:30:20 +01:00
Implement new Material3 spec.
This commit is contained in:
committed by
Greyson Parrelli
parent
556e480b06
commit
1b471e163d
@@ -3,9 +3,6 @@ package org.thoughtcrime.securesms.components;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
@@ -42,7 +39,6 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment;
|
||||
import org.thoughtcrime.securesms.util.AvatarUtil;
|
||||
import org.thoughtcrime.securesms.util.BlurTransformation;
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
@@ -58,24 +54,8 @@ public final class AvatarImageView extends AppCompatImageView {
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = Log.tag(AvatarImageView.class);
|
||||
|
||||
private static final Paint LIGHT_THEME_OUTLINE_PAINT = new Paint();
|
||||
private static final Paint DARK_THEME_OUTLINE_PAINT = new Paint();
|
||||
|
||||
static {
|
||||
LIGHT_THEME_OUTLINE_PAINT.setColor(Color.argb((int) (255 * 0.2), 0, 0, 0));
|
||||
LIGHT_THEME_OUTLINE_PAINT.setStyle(Paint.Style.STROKE);
|
||||
LIGHT_THEME_OUTLINE_PAINT.setStrokeWidth(1);
|
||||
LIGHT_THEME_OUTLINE_PAINT.setAntiAlias(true);
|
||||
|
||||
DARK_THEME_OUTLINE_PAINT.setColor(Color.argb((int) (255 * 0.2), 255, 255, 255));
|
||||
DARK_THEME_OUTLINE_PAINT.setStyle(Paint.Style.STROKE);
|
||||
DARK_THEME_OUTLINE_PAINT.setStrokeWidth(1);
|
||||
DARK_THEME_OUTLINE_PAINT.setAntiAlias(true);
|
||||
}
|
||||
|
||||
private int size;
|
||||
private boolean inverted;
|
||||
private Paint outlinePaint;
|
||||
private OnClickListener listener;
|
||||
private Recipient.FallbackPhotoProvider fallbackPhotoProvider;
|
||||
private boolean blurred;
|
||||
@@ -105,8 +85,6 @@ public final class AvatarImageView extends AppCompatImageView {
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
outlinePaint = ThemeUtil.isDarkTheme(context) ? DARK_THEME_OUTLINE_PAINT : LIGHT_THEME_OUTLINE_PAINT;
|
||||
|
||||
unknownRecipientDrawable = new ResourceContactPhoto(R.drawable.ic_profile_outline_40, R.drawable.ic_profile_outline_20).asDrawable(context, AvatarColor.UNKNOWN, inverted);
|
||||
blurred = false;
|
||||
chatColors = null;
|
||||
@@ -117,20 +95,6 @@ public final class AvatarImageView extends AppCompatImageView {
|
||||
super.setClipBounds(clipBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
float width = getWidth() - getPaddingRight() - getPaddingLeft();
|
||||
float height = getHeight() - getPaddingBottom() - getPaddingTop();
|
||||
float cx = width / 2f;
|
||||
float cy = height / 2f;
|
||||
float radius = Math.min(cx, cy) - (outlinePaint.getStrokeWidth() / 2f);
|
||||
|
||||
canvas.translate(getPaddingLeft(), getPaddingTop());
|
||||
canvas.drawCircle(cx, cy, radius, outlinePaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnClickListener(OnClickListener listener) {
|
||||
this.listener = listener;
|
||||
|
||||
@@ -11,7 +11,6 @@ import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
@@ -31,7 +30,6 @@ public class ConversationItemThumbnail extends FrameLayout {
|
||||
private ImageView shade;
|
||||
private ConversationItemFooter footer;
|
||||
private CornerMask cornerMask;
|
||||
private Outliner outliner;
|
||||
private Outliner pulseOutliner;
|
||||
private boolean borderless;
|
||||
private int[] normalBounds;
|
||||
@@ -61,9 +59,6 @@ public class ConversationItemThumbnail extends FrameLayout {
|
||||
this.shade = findViewById(R.id.conversation_thumbnail_shade);
|
||||
this.footer = findViewById(R.id.conversation_thumbnail_footer);
|
||||
this.cornerMask = new CornerMask(this);
|
||||
this.outliner = new Outliner();
|
||||
|
||||
outliner.setColor(ContextCompat.getColor(getContext(), R.color.signal_inverse_transparent_20));
|
||||
|
||||
int gifWidth = ViewUtil.dpToPx(260);
|
||||
if (attrs != null) {
|
||||
@@ -98,10 +93,6 @@ public class ConversationItemThumbnail extends FrameLayout {
|
||||
|
||||
if (!borderless) {
|
||||
cornerMask.mask(canvas);
|
||||
|
||||
if (album.getVisibility() != VISIBLE) {
|
||||
outliner.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
if (pulseOutliner != null) {
|
||||
@@ -150,7 +141,6 @@ public class ConversationItemThumbnail extends FrameLayout {
|
||||
|
||||
public void setCorners(int topLeft, int topRight, int bottomRight, int bottomLeft) {
|
||||
cornerMask.setRadii(topLeft, topRight, bottomRight, bottomLeft);
|
||||
outliner.setRadii(topLeft, topRight, bottomRight, bottomLeft);
|
||||
}
|
||||
|
||||
public void setMinimumThumbnailWidth(int width) {
|
||||
|
||||
@@ -7,9 +7,12 @@ import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.airbnb.lottie.SimpleColorFilter;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
public final class ConversationScrollToView extends FrameLayout {
|
||||
@@ -43,6 +46,10 @@ public final class ConversationScrollToView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
public void setUnreadCountBackgroundTint(@ColorInt int tint) {
|
||||
unreadCount.getBackground().setColorFilter(new SimpleColorFilter(tint));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnClickListener(@Nullable OnClickListener l) {
|
||||
scrollButton.setOnClickListener(l);
|
||||
|
||||
@@ -4,8 +4,6 @@ import android.content.Context;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.CharacterStyle;
|
||||
import android.util.AttributeSet;
|
||||
@@ -49,13 +47,11 @@ public class FromTextView extends SimpleEmojiTextView {
|
||||
|
||||
public void setText(Recipient recipient, @Nullable CharSequence fromString, boolean read, @Nullable String suffix) {
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||
SpannableString fromSpan = new SpannableString(fromString);
|
||||
fromSpan.setSpan(getFontSpan(!read), 0, fromSpan.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
|
||||
if (recipient.isSelf()) {
|
||||
builder.append(getContext().getString(R.string.note_to_self));
|
||||
} else {
|
||||
builder.append(fromSpan);
|
||||
builder.append(fromString);
|
||||
}
|
||||
|
||||
if (suffix != null) {
|
||||
@@ -85,8 +81,4 @@ public class FromTextView extends SimpleEmojiTextView {
|
||||
|
||||
return mutedDrawable;
|
||||
}
|
||||
|
||||
private CharacterStyle getFontSpan(boolean isBold) {
|
||||
return isBold ? SpanUtil.getBoldSpan() : SpanUtil.getNormalSpan();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationSet;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
@@ -77,8 +78,8 @@ public class InputPanel extends LinearLayout
|
||||
private LinkPreviewView linkPreview;
|
||||
private EmojiToggle mediaKeyboard;
|
||||
private ComposeText composeText;
|
||||
private View quickCameraToggle;
|
||||
private View quickAudioToggle;
|
||||
private ImageButton quickCameraToggle;
|
||||
private ImageButton quickAudioToggle;
|
||||
private AnimatingToggle buttonToggle;
|
||||
private SendButton sendButton;
|
||||
private View recordingContainer;
|
||||
@@ -182,7 +183,7 @@ public class InputPanel extends LinearLayout
|
||||
@NonNull SlideDeck attachments,
|
||||
@NonNull QuoteModel.Type quoteType)
|
||||
{
|
||||
this.quoteView.setQuote(glideRequests, id, author, body, false, attachments, null, null, quoteType);
|
||||
this.quoteView.setQuote(glideRequests, id, author, body, false, attachments, null, quoteType);
|
||||
|
||||
int originalHeight = this.quoteView.getVisibility() == VISIBLE ? this.quoteView.getMeasuredHeight()
|
||||
: 0;
|
||||
@@ -322,13 +323,34 @@ public class InputPanel extends LinearLayout
|
||||
}
|
||||
|
||||
public void setWallpaperEnabled(boolean enabled) {
|
||||
final int iconTint;
|
||||
final int textColor;
|
||||
final int textHintColor;
|
||||
|
||||
if (enabled) {
|
||||
iconTint = getContext().getResources().getColor(R.color.signal_colorNeutralInverse);
|
||||
textColor = getContext().getResources().getColor(R.color.signal_colorNeutralInverse);
|
||||
textHintColor = getContext().getResources().getColor(R.color.signal_colorNeutralVariantInverse);
|
||||
|
||||
setBackground(new ColorDrawable(getContext().getResources().getColor(R.color.wallpaper_compose_background)));
|
||||
composeContainer.setBackground(Objects.requireNonNull(ContextCompat.getDrawable(getContext(), R.drawable.compose_background_wallpaper)));
|
||||
quickAudioToggle.setColorFilter(iconTint);
|
||||
quickCameraToggle.setColorFilter(iconTint);
|
||||
} else {
|
||||
setBackground(new ColorDrawable(getContext().getResources().getColor(R.color.signal_background_primary)));
|
||||
iconTint = getContext().getResources().getColor(R.color.signal_colorOnSurface);
|
||||
textColor = getContext().getResources().getColor(R.color.signal_colorOnSurface);
|
||||
textHintColor = getContext().getResources().getColor(R.color.signal_colorOnSurfaceVariant);
|
||||
|
||||
setBackground(new ColorDrawable(getContext().getResources().getColor(R.color.signal_colorSurface)));
|
||||
composeContainer.setBackground(Objects.requireNonNull(ContextCompat.getDrawable(getContext(), R.drawable.compose_background)));
|
||||
}
|
||||
|
||||
mediaKeyboard.setColorFilter(iconTint);
|
||||
quickAudioToggle.setColorFilter(iconTint);
|
||||
quickCameraToggle.setColorFilter(iconTint);
|
||||
composeText.setTextColor(textColor);
|
||||
composeText.setHintTextColor(textHintColor);
|
||||
quoteView.setWallpaperEnabled(enabled);
|
||||
}
|
||||
|
||||
public void setHideForGroupState(boolean hideForGroupState) {
|
||||
|
||||
@@ -13,7 +13,6 @@ import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
||||
@@ -51,7 +50,6 @@ public class LinkPreviewView extends FrameLayout {
|
||||
private int type;
|
||||
private int defaultRadius;
|
||||
private CornerMask cornerMask;
|
||||
private Outliner outliner;
|
||||
private CloseClickedListener closeClickedListener;
|
||||
|
||||
public LinkPreviewView(Context context) {
|
||||
@@ -78,9 +76,6 @@ public class LinkPreviewView extends FrameLayout {
|
||||
noPreview = findViewById(R.id.linkpreview_no_preview);
|
||||
defaultRadius = getResources().getDimensionPixelSize(R.dimen.thumbnail_default_radius);
|
||||
cornerMask = new CornerMask(this);
|
||||
outliner = new Outliner();
|
||||
|
||||
outliner.setColor(ContextCompat.getColor(getContext(), R.color.signal_inverse_transparent_20));
|
||||
|
||||
if (attrs != null) {
|
||||
TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.LinkPreviewView, 0, 0);
|
||||
@@ -112,7 +107,6 @@ public class LinkPreviewView extends FrameLayout {
|
||||
if (type == TYPE_COMPOSE) return;
|
||||
|
||||
cornerMask.mask(canvas);
|
||||
outliner.draw(canvas);
|
||||
}
|
||||
|
||||
public void setLoading() {
|
||||
@@ -185,11 +179,9 @@ public class LinkPreviewView extends FrameLayout {
|
||||
public void setCorners(int topStart, int topEnd) {
|
||||
if (ViewUtil.isRtl(this)) {
|
||||
cornerMask.setRadii(topEnd, topStart, 0, 0);
|
||||
outliner.setRadii(topEnd, topStart, 0, 0);
|
||||
thumbnail.setCorners(defaultRadius, topEnd, defaultRadius, defaultRadius);
|
||||
} else {
|
||||
cornerMask.setRadii(topStart, topEnd, 0, 0);
|
||||
outliner.setRadii(topStart, topEnd, 0, 0);
|
||||
thumbnail.setCorners(topStart, defaultRadius, defaultRadius, defaultRadius);
|
||||
}
|
||||
postInvalidate();
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.thoughtcrime.securesms.components
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.PointF
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.ViewAnimationUtils
|
||||
import android.widget.EditText
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
|
||||
/**
|
||||
* Search Toolbar following the Signal Material3 design spec.
|
||||
*/
|
||||
class Material3SearchToolbar @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : ConstraintLayout(context, attrs) {
|
||||
|
||||
var listener: Listener? = null
|
||||
|
||||
private val input: EditText
|
||||
|
||||
private val circularRevealPoint = PointF()
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.material3_serarch_toolbar, this)
|
||||
|
||||
input = findViewById(R.id.search_input)
|
||||
|
||||
val close = findViewById<View>(R.id.search_close)
|
||||
val clear = findViewById<View>(R.id.search_clear)
|
||||
|
||||
close.setOnClickListener { collapse() }
|
||||
clear.setOnClickListener { input.setText("") }
|
||||
|
||||
input.addTextChangedListener(afterTextChanged = {
|
||||
clear.visible = !it.isNullOrBlank()
|
||||
listener?.onSearchTextChange(it?.toString() ?: "")
|
||||
})
|
||||
}
|
||||
|
||||
fun display(x: Float, y: Float) {
|
||||
if (Build.VERSION.SDK_INT < 21) {
|
||||
visibility = VISIBLE
|
||||
ViewUtil.focusAndShowKeyboard(input)
|
||||
} else if (!visible) {
|
||||
circularRevealPoint.set(x, y)
|
||||
|
||||
val animator = ViewAnimationUtils.createCircularReveal(this, x.toInt(), y.toInt(), 0f, width.toFloat())
|
||||
animator.duration = 400
|
||||
|
||||
visibility = VISIBLE
|
||||
ViewUtil.focusAndShowKeyboard(input)
|
||||
animator.start()
|
||||
}
|
||||
}
|
||||
|
||||
fun collapse() {
|
||||
if (visibility == VISIBLE) {
|
||||
listener?.onSearchClosed()
|
||||
ViewUtil.hideKeyboard(context, input)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
val animator = ViewAnimationUtils.createCircularReveal(this, circularRevealPoint.x.toInt(), circularRevealPoint.y.toInt(), width.toFloat(), 0f)
|
||||
animator.duration = 400
|
||||
|
||||
animator.addListener(onEnd = {
|
||||
visibility = INVISIBLE
|
||||
})
|
||||
animator.start()
|
||||
} else {
|
||||
visibility = INVISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun onSearchTextChange(text: String)
|
||||
fun onSearchClosed()
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ package org.thoughtcrime.securesms.components;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
@@ -17,7 +16,6 @@ import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
@@ -30,7 +28,7 @@ import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiImageView;
|
||||
import org.thoughtcrime.securesms.components.mention.MentionAnnotation;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors;
|
||||
import org.thoughtcrime.securesms.components.quotes.QuoteViewColorTheme;
|
||||
import org.thoughtcrime.securesms.database.model.Mention;
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
@@ -43,7 +41,6 @@ import org.thoughtcrime.securesms.recipients.RecipientForeverObserver;
|
||||
import org.thoughtcrime.securesms.stories.StoryTextPostModel;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Projection;
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -103,6 +100,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
private int smallCornerRadius;
|
||||
private CornerMask cornerMask;
|
||||
private QuoteModel.Type quoteType;
|
||||
private boolean isWallpaperEnabled;
|
||||
|
||||
private int thumbHeight;
|
||||
private int thumbWidth;
|
||||
@@ -151,19 +149,12 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
cornerMask = new CornerMask(this);
|
||||
|
||||
if (attrs != null) {
|
||||
TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.QuoteView, 0, 0);
|
||||
int primaryColor = typedArray.getColor(R.styleable.QuoteView_quote_colorPrimary, Color.BLACK);
|
||||
int secondaryColor = typedArray.getColor(R.styleable.QuoteView_quote_colorSecondary, Color.BLACK);
|
||||
TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.QuoteView, 0, 0);
|
||||
|
||||
messageType = MessageType.fromCode(typedArray.getInt(R.styleable.QuoteView_message_type, 0));
|
||||
typedArray.recycle();
|
||||
|
||||
dismissView.setVisibility(messageType == MessageType.PREVIEW ? VISIBLE : GONE);
|
||||
|
||||
authorView.setTextColor(primaryColor);
|
||||
bodyView.setTextColor(primaryColor);
|
||||
attachmentNameView.setTextColor(primaryColor);
|
||||
mediaDescriptionText.setTextColor(secondaryColor);
|
||||
missingLinkText.setTextColor(primaryColor);
|
||||
}
|
||||
|
||||
setMessageType(messageType);
|
||||
@@ -211,7 +202,6 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
@Nullable CharSequence body,
|
||||
boolean originalMissing,
|
||||
@NonNull SlideDeck attachments,
|
||||
@Nullable ChatColors chatColors,
|
||||
@Nullable String storyReaction,
|
||||
@NonNull QuoteModel.Type quoteType)
|
||||
{
|
||||
@@ -228,12 +218,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
setQuoteText(resolveBody(body, quoteType), attachments, originalMissing, storyReaction);
|
||||
setQuoteAttachment(glideRequests, body, attachments, originalMissing);
|
||||
setQuoteMissingFooter(originalMissing);
|
||||
|
||||
if (Build.VERSION.SDK_INT < 21 && messageType == MessageType.INCOMING && chatColors != null) {
|
||||
this.setBackgroundColor(chatColors.asSingleColor());
|
||||
} else {
|
||||
this.setBackground(null);
|
||||
}
|
||||
applyColorTheme();
|
||||
}
|
||||
|
||||
private @Nullable CharSequence resolveBody(@Nullable CharSequence body, @NonNull QuoteModel.Type quoteType) {
|
||||
@@ -255,6 +240,11 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
setVisibility(GONE);
|
||||
}
|
||||
|
||||
public void setWallpaperEnabled(boolean isWallpaperEnabled) {
|
||||
this.isWallpaperEnabled = isWallpaperEnabled;
|
||||
applyColorTheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecipientChanged(@NonNull Recipient recipient) {
|
||||
setQuoteAuthor(recipient);
|
||||
@@ -269,9 +259,6 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
}
|
||||
|
||||
private void setQuoteAuthor(@NonNull Recipient author) {
|
||||
boolean outgoing = messageType != MessageType.INCOMING && messageType != MessageType.STORY_REPLY_INCOMING;
|
||||
boolean preview = messageType == MessageType.PREVIEW || messageType == MessageType.STORY_REPLY_PREVIEW;
|
||||
|
||||
if (isStoryReply()) {
|
||||
authorView.setText(author.isSelf() ? getContext().getString(R.string.QuoteView_your_story)
|
||||
: getContext().getString(R.string.QuoteView_s_story, author.getDisplayName(getContext())));
|
||||
@@ -279,19 +266,6 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
authorView.setText(author.isSelf() ? getContext().getString(R.string.QuoteView_you)
|
||||
: author.getDisplayName(getContext()));
|
||||
}
|
||||
|
||||
quoteBarView.setBackgroundColor(ContextCompat.getColor(getContext(), outgoing || isStoryReply() ? R.color.core_white : android.R.color.transparent));
|
||||
|
||||
int mainViewColor;
|
||||
if (preview) {
|
||||
mainViewColor = R.color.quote_preview_background;
|
||||
} else if (!outgoing && isStoryReply()) {
|
||||
mainViewColor = R.color.quote_incoming_story_background;
|
||||
} else {
|
||||
mainViewColor = R.color.quote_view_background;
|
||||
}
|
||||
|
||||
mainView.setBackgroundColor(ContextCompat.getColor(getContext(), mainViewColor));
|
||||
}
|
||||
|
||||
private boolean isStoryReply() {
|
||||
@@ -450,15 +424,10 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
attachmentContainerView.setVisibility(GONE);
|
||||
dismissView.setBackgroundDrawable(null);
|
||||
}
|
||||
|
||||
if (ThemeUtil.isDarkTheme(getContext())) {
|
||||
dismissView.setBackgroundResource(R.drawable.circle_alpha);
|
||||
}
|
||||
}
|
||||
|
||||
private void setQuoteMissingFooter(boolean missing) {
|
||||
footerView.setVisibility(missing && !isStoryReply() ? VISIBLE : GONE);
|
||||
footerView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.quote_view_background));
|
||||
}
|
||||
|
||||
private @Nullable StoryTextPostModel getStoryTextPost(@Nullable CharSequence body) {
|
||||
@@ -515,4 +484,20 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private void applyColorTheme() {
|
||||
boolean isOutgoing = messageType != MessageType.INCOMING && messageType != MessageType.STORY_REPLY_INCOMING;
|
||||
boolean isPreview = messageType == MessageType.PREVIEW || messageType == MessageType.STORY_REPLY_PREVIEW;
|
||||
|
||||
QuoteViewColorTheme quoteViewColorTheme = QuoteViewColorTheme.resolveTheme(isOutgoing, isPreview, isWallpaperEnabled);
|
||||
|
||||
quoteBarView.setBackgroundColor(quoteViewColorTheme.getBarColor(getContext()));
|
||||
mainView.setBackgroundColor(quoteViewColorTheme.getBackgroundColor(getContext()));
|
||||
authorView.setTextColor(quoteViewColorTheme.getForegroundColor(getContext()));
|
||||
bodyView.setTextColor(quoteViewColorTheme.getForegroundColor(getContext()));
|
||||
attachmentNameView.setTextColor(quoteViewColorTheme.getForegroundColor(getContext()));
|
||||
mediaDescriptionText.setTextColor(quoteViewColorTheme.getForegroundColor(getContext()));
|
||||
missingLinkText.setTextColor(quoteViewColorTheme.getForegroundColor(getContext()));
|
||||
footerView.setBackgroundColor(quoteViewColorTheme.getBackgroundColor(getContext()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,17 +26,17 @@ public class EmojiToggle extends AppCompatImageButton implements MediaKeyboard.M
|
||||
|
||||
public EmojiToggle(Context context) {
|
||||
super(context);
|
||||
initialize(null);
|
||||
initialize();
|
||||
}
|
||||
|
||||
public EmojiToggle(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initialize(attrs);
|
||||
initialize();
|
||||
}
|
||||
|
||||
public EmojiToggle(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
initialize(attrs);
|
||||
initialize();
|
||||
}
|
||||
|
||||
public void setToMedia() {
|
||||
@@ -47,18 +47,11 @@ public class EmojiToggle extends AppCompatImageButton implements MediaKeyboard.M
|
||||
setImageDrawable(imeToggle);
|
||||
}
|
||||
|
||||
private void initialize(@Nullable AttributeSet attrs) {
|
||||
boolean forceOutline = false;
|
||||
if (attrs != null) {
|
||||
TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.EmojiToggle, 0, 0);
|
||||
forceOutline = typedArray.getBoolean(R.styleable.EmojiToggle_force_outline, false);
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
this.emojiToggle = ContextUtil.requireDrawable(getContext(), forceOutline ? R.drawable.ic_emoji_outline : R.drawable.ic_emoji);
|
||||
private void initialize() {
|
||||
this.emojiToggle = ContextUtil.requireDrawable(getContext(), R.drawable.ic_emoji);
|
||||
this.stickerToggle = ContextUtil.requireDrawable(getContext(), R.drawable.ic_sticker_24);
|
||||
this.gifToggle = ContextUtil.requireDrawable(getContext(), R.drawable.ic_gif_24);
|
||||
this.imeToggle = ContextUtil.requireDrawable(getContext(), forceOutline ? R.drawable.ic_keyboard_outline_24 : R.drawable.ic_keyboard_24);
|
||||
this.imeToggle = ContextUtil.requireDrawable(getContext(), R.drawable.ic_keyboard_24);
|
||||
this.mediaToggle = emojiToggle;
|
||||
|
||||
setToMedia();
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.thoughtcrime.securesms.components.quotes
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import org.thoughtcrime.securesms.R
|
||||
|
||||
enum class QuoteViewColorTheme(
|
||||
private val backgroundColorRes: Int,
|
||||
private val barColorRes: Int,
|
||||
private val foregroundColorRes: Int
|
||||
) {
|
||||
|
||||
INCOMING_WALLPAPER(
|
||||
R.color.quote_view_background_incoming_wallpaper,
|
||||
R.color.quote_view_bar_incoming_wallpaper,
|
||||
R.color.quote_view_foreground_incoming_wallpaper
|
||||
),
|
||||
INCOMING_NORMAL(
|
||||
R.color.quote_view_background_incoming_normal,
|
||||
R.color.quote_view_bar_incoming_normal,
|
||||
R.color.quote_view_foreground_incoming_normal
|
||||
),
|
||||
OUTGOING_WALLPAPER(
|
||||
R.color.quote_view_background_outgoing_wallpaper,
|
||||
R.color.quote_view_bar_outgoing_wallpaper,
|
||||
R.color.quote_view_foreground_outgoing_wallpaper
|
||||
),
|
||||
OUTGOING_NORMAL(
|
||||
R.color.quote_view_background_outgoing_normal,
|
||||
R.color.quote_view_bar_outgoing_normal,
|
||||
R.color.quote_view_foreground_outgoing_normal
|
||||
);
|
||||
|
||||
fun getBackgroundColor(context: Context) = ContextCompat.getColor(context, backgroundColorRes)
|
||||
fun getBarColor(context: Context) = ContextCompat.getColor(context, barColorRes)
|
||||
fun getForegroundColor(context: Context) = ContextCompat.getColor(context, foregroundColorRes)
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun resolveTheme(isOutgoing: Boolean, isPreview: Boolean, hasWallpaper: Boolean): QuoteViewColorTheme {
|
||||
return when {
|
||||
isPreview && hasWallpaper -> INCOMING_WALLPAPER
|
||||
isPreview && !hasWallpaper -> INCOMING_NORMAL
|
||||
isOutgoing && hasWallpaper -> OUTGOING_WALLPAPER
|
||||
!isOutgoing && hasWallpaper -> INCOMING_WALLPAPER
|
||||
isOutgoing && !hasWallpaper -> OUTGOING_NORMAL
|
||||
else -> INCOMING_NORMAL
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,13 @@ import android.util.AttributeSet;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CallMeCountDownView extends androidx.appcompat.widget.AppCompatButton {
|
||||
public class CallMeCountDownView extends MaterialButton {
|
||||
|
||||
private long countDownToTime;
|
||||
@Nullable
|
||||
|
||||
@@ -15,8 +15,7 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.recyclerview.OnScrollAnimationHelper
|
||||
import org.thoughtcrime.securesms.components.recyclerview.ToolbarShadowAnimationHelper
|
||||
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
|
||||
|
||||
abstract class DSLSettingsFragment(
|
||||
@StringRes private val titleId: Int = -1,
|
||||
@@ -28,12 +27,9 @@ abstract class DSLSettingsFragment(
|
||||
protected var recyclerView: RecyclerView? = null
|
||||
private set
|
||||
|
||||
private var scrollAnimationHelper: OnScrollAnimationHelper? = null
|
||||
|
||||
@CallSuper
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val toolbar: Toolbar? = view.findViewById(R.id.toolbar)
|
||||
val toolbarShadow: View? = view.findViewById(R.id.toolbar_shadow)
|
||||
|
||||
if (titleId != -1) {
|
||||
toolbar?.setTitle(titleId)
|
||||
@@ -48,10 +44,6 @@ abstract class DSLSettingsFragment(
|
||||
toolbar?.setOnMenuItemClickListener { onOptionsItemSelected(it) }
|
||||
}
|
||||
|
||||
if (toolbarShadow != null) {
|
||||
scrollAnimationHelper = getOnScrollAnimationHelper(toolbarShadow)
|
||||
}
|
||||
|
||||
val settingsAdapter = DSLSettingsAdapter()
|
||||
|
||||
recyclerView = view.findViewById<RecyclerView>(R.id.recycler).apply {
|
||||
@@ -59,23 +51,25 @@ abstract class DSLSettingsFragment(
|
||||
layoutManager = layoutManagerProducer(requireContext())
|
||||
adapter = settingsAdapter
|
||||
|
||||
val helper = scrollAnimationHelper
|
||||
if (helper != null) {
|
||||
addOnScrollListener(helper)
|
||||
getMaterial3OnScrollHelper(toolbar)?.let {
|
||||
addOnScrollListener(it)
|
||||
}
|
||||
}
|
||||
|
||||
bindAdapter(settingsAdapter)
|
||||
}
|
||||
|
||||
open fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper? {
|
||||
if (toolbar == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
return Material3OnScrollHelper(requireActivity(), toolbar)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
recyclerView = null
|
||||
scrollAnimationHelper = null
|
||||
}
|
||||
|
||||
protected open fun getOnScrollAnimationHelper(toolbarShadow: View): OnScrollAnimationHelper {
|
||||
return ToolbarShadowAnimationHelper(toolbarShadow)
|
||||
}
|
||||
|
||||
abstract fun bindAdapter(adapter: DSLSettingsAdapter)
|
||||
|
||||
@@ -65,7 +65,7 @@ sealed class DSLSettingsText {
|
||||
}
|
||||
}
|
||||
|
||||
object Title2BoldModifier : TextAppearanceModifier(R.style.TextAppearance_Signal_Title2_Bold)
|
||||
object TitleLargeModifier : TextAppearanceModifier(R.style.Signal_Text_TitleLarge)
|
||||
object Body1BoldModifier : TextAppearanceModifier(R.style.TextAppearance_Signal_Body1_Bold)
|
||||
|
||||
open class TextAppearanceModifier(@StyleRes private val textAppearance: Int) : Modifier {
|
||||
|
||||
@@ -101,7 +101,7 @@ class AppSettingsFragment : DSLSettingsFragment(R.string.text_secure_normal__men
|
||||
|
||||
clickPref(
|
||||
title = DSLSettingsText.from(R.string.preferences_chats__chats),
|
||||
icon = DSLSettingsIcon.from(R.drawable.ic_message_tinted_bitmap_24),
|
||||
icon = DSLSettingsIcon.from(R.drawable.ic_chat_message_24),
|
||||
onClick = {
|
||||
findNavController().safeNavigate(R.id.action_appSettingsFragment_to_chatsSettingsFragment)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.components.settings.app.account
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.Typeface
|
||||
import android.text.InputType
|
||||
import android.util.DisplayMetrics
|
||||
@@ -42,7 +41,7 @@ class AccountSettingsFragment : DSLSettingsFragment(R.string.AccountSettingsFrag
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == CreateKbsPinActivity.REQUEST_NEW_PIN && resultCode == CreateKbsPinActivity.RESULT_OK) {
|
||||
Snackbar.make(requireView(), R.string.ConfirmKbsPinFragment__pin_created, Snackbar.LENGTH_LONG).setTextColor(Color.WHITE).show()
|
||||
Snackbar.make(requireView(), R.string.ConfirmKbsPinFragment__pin_created, Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.lock.PinHashing
|
||||
import org.thoughtcrime.securesms.registration.fragments.BaseRegistrationLockFragment
|
||||
import org.thoughtcrime.securesms.registration.viewmodel.BaseRegistrationViewModel
|
||||
import org.thoughtcrime.securesms.util.CircularProgressButtonUtil.cancelSpinning
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||
import org.thoughtcrime.securesms.util.SupportEmailUtil
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
@@ -45,7 +44,7 @@ class ChangeNumberRegistrationLockFragment : BaseRegistrationLockFragment(R.layo
|
||||
override fun handleSuccessfulPinEntry(pin: String) {
|
||||
val pinsDiffer: Boolean = SignalStore.kbsValues().localPinHash?.let { !PinHashing.verifyLocalPinHash(it, pin) } ?: false
|
||||
|
||||
cancelSpinning(pinButton)
|
||||
pinButton.cancelSpinning()
|
||||
|
||||
if (pinsDiffer) {
|
||||
findNavController().safeNavigate(ChangeNumberRegistrationLockFragmentDirections.actionChangeNumberRegistrationLockToChangeNumberPinDiffers())
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
package org.thoughtcrime.securesms.components.settings.app.notifications.profiles
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.dd.CircularProgressButton
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.thoughtcrime.securesms.R
|
||||
@@ -22,6 +19,7 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
|
||||
|
||||
/**
|
||||
* Show and allow addition of recipients to a profile during the create flow.
|
||||
@@ -37,7 +35,7 @@ class AddAllowedMembersFragment : DSLSettingsFragment(layoutId = R.layout.fragme
|
||||
|
||||
lifecycleDisposable.bindTo(viewLifecycleOwner.lifecycle)
|
||||
|
||||
view.findViewById<CircularProgressButton>(R.id.add_allowed_members_profile_next).apply {
|
||||
view.findViewById<CircularProgressMaterialButton>(R.id.add_allowed_members_profile_next).apply {
|
||||
setOnClickListener {
|
||||
findNavController().safeNavigate(AddAllowedMembersFragmentDirections.actionAddAllowedMembersFragmentToEditNotificationProfileScheduleFragment(profileId, true))
|
||||
}
|
||||
@@ -87,8 +85,6 @@ class AddAllowedMembersFragment : DSLSettingsFragment(layoutId = R.layout.fragme
|
||||
view?.let { view ->
|
||||
Snackbar.make(view, getString(R.string.NotificationProfileDetails__s_removed, removed.getDisplayName(requireContext())), Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.NotificationProfileDetails__undo) { undoRemove(id) }
|
||||
.setActionTextColor(ContextCompat.getColor(requireContext(), R.color.core_ultramarine_light))
|
||||
.setTextColor(Color.WHITE)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import androidx.appcompat.widget.Toolbar
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.dd.CircularProgressButton
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.signal.core.util.BreakIteratorCompat
|
||||
@@ -24,11 +23,11 @@ import org.thoughtcrime.securesms.components.settings.app.notifications.profiles
|
||||
import org.thoughtcrime.securesms.components.settings.app.notifications.profiles.models.NotificationProfileNamePreset
|
||||
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiBottomSheetDialogFragment
|
||||
import org.thoughtcrime.securesms.util.BottomSheetUtil
|
||||
import org.thoughtcrime.securesms.util.CircularProgressButtonUtil
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.text.AfterTextChanged
|
||||
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
|
||||
|
||||
/**
|
||||
* Dual use Edit/Create notification profile fragment. Use to create in the create profile flow,
|
||||
@@ -58,7 +57,7 @@ class EditNotificationProfileFragment : DSLSettingsFragment(layoutId = R.layout.
|
||||
|
||||
val title: TextView = view.findViewById(R.id.edit_notification_profile_title)
|
||||
val countView: TextView = view.findViewById(R.id.edit_notification_profile_count)
|
||||
val saveButton: CircularProgressButton = view.findViewById(R.id.edit_notification_profile_save)
|
||||
val saveButton: CircularProgressMaterialButton = view.findViewById(R.id.edit_notification_profile_save)
|
||||
val emojiView: ImageView = view.findViewById(R.id.edit_notification_profile_emoji)
|
||||
val nameView: EditText = view.findViewById(R.id.edit_notification_profile_name)
|
||||
val nameTextWrapper: TextInputLayout = view.findViewById(R.id.edit_notification_profile_name_wrapper)
|
||||
@@ -90,8 +89,8 @@ class EditNotificationProfileFragment : DSLSettingsFragment(layoutId = R.layout.
|
||||
}
|
||||
|
||||
lifecycleDisposable += viewModel.save(nameView.text.toString())
|
||||
.doOnSubscribe { CircularProgressButtonUtil.setSpinning(saveButton) }
|
||||
.doAfterTerminate { CircularProgressButtonUtil.cancelSpinning(saveButton) }
|
||||
.doOnSubscribe { saveButton.setSpinning() }
|
||||
.doAfterTerminate { saveButton.cancelSpinning() }
|
||||
.subscribeBy(
|
||||
onSuccess = { saveResult ->
|
||||
when (saveResult) {
|
||||
|
||||
@@ -15,7 +15,6 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.dd.CircularProgressButton
|
||||
import com.google.android.material.switchmaterial.SwitchMaterial
|
||||
import com.google.android.material.timepicker.MaterialTimePicker
|
||||
import com.google.android.material.timepicker.TimeFormat
|
||||
@@ -28,6 +27,7 @@ import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.formatHours
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.orderOfDaysInWeek
|
||||
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalTime
|
||||
@@ -75,7 +75,7 @@ class EditNotificationProfileScheduleFragment : LoggingFragment(R.layout.fragmen
|
||||
val startTime: TextView = view.findViewById(R.id.edit_notification_profile_schedule_start_time)
|
||||
val endTime: TextView = view.findViewById(R.id.edit_notification_profile_schedule_end_time)
|
||||
|
||||
val next: CircularProgressButton = view.findViewById(R.id.edit_notification_profile_schedule__next)
|
||||
val next: CircularProgressMaterialButton = view.findViewById(R.id.edit_notification_profile_schedule__next)
|
||||
next.setOnClickListener {
|
||||
lifecycleDisposable += viewModel.save(createMode)
|
||||
.subscribeBy(
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.thoughtcrime.securesms.components.settings.app.notifications.profiles
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
@@ -147,8 +146,6 @@ class NotificationProfileDetailsFragment : DSLSettingsFragment() {
|
||||
view?.let { view ->
|
||||
Snackbar.make(view, getString(R.string.NotificationProfileDetails__s_removed, removed.getDisplayName(requireContext())), Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.NotificationProfileDetails__undo) { undoRemove(id) }
|
||||
.setActionTextColor(ContextCompat.getColor(requireContext(), R.color.core_ultramarine_light))
|
||||
.setTextColor(Color.WHITE)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import androidx.appcompat.widget.Toolbar
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.dd.CircularProgressButton
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.thoughtcrime.securesms.ContactSelectionListFragment
|
||||
import org.thoughtcrime.securesms.LoggingFragment
|
||||
@@ -17,10 +16,10 @@ import org.thoughtcrime.securesms.components.ContactFilterView
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader
|
||||
import org.thoughtcrime.securesms.groups.SelectionLimits
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.CircularProgressButtonUtil
|
||||
import org.thoughtcrime.securesms.util.LifecycleDisposable
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
|
||||
import java.util.Optional
|
||||
import java.util.function.Consumer
|
||||
|
||||
@@ -32,7 +31,7 @@ class SelectRecipientsFragment : LoggingFragment(), ContactSelectionListFragment
|
||||
private val viewModel: SelectRecipientsViewModel by viewModels(factoryProducer = this::createFactory)
|
||||
private val lifecycleDisposable = LifecycleDisposable()
|
||||
|
||||
private var addToProfile: CircularProgressButton? = null
|
||||
private var addToProfile: CircularProgressMaterialButton? = null
|
||||
|
||||
private fun createFactory(): ViewModelProvider.Factory {
|
||||
val args = SelectRecipientsFragmentArgs.fromBundle(requireArguments())
|
||||
@@ -86,8 +85,8 @@ class SelectRecipientsFragment : LoggingFragment(), ContactSelectionListFragment
|
||||
addToProfile = view.findViewById(R.id.select_recipients_add)
|
||||
addToProfile?.setOnClickListener {
|
||||
lifecycleDisposable += viewModel.updateAllowedMembers()
|
||||
.doOnSubscribe { CircularProgressButtonUtil.setSpinning(addToProfile) }
|
||||
.doOnTerminate { CircularProgressButtonUtil.cancelSpinning(addToProfile) }
|
||||
.doOnSubscribe { addToProfile?.setSpinning() }
|
||||
.doOnTerminate { addToProfile?.cancelSpinning() }
|
||||
.subscribeBy(onSuccess = { findNavController().navigateUp() })
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import android.widget.Toast
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.dd.CircularProgressButton
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
@@ -22,6 +21,7 @@ import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.livedata.ProcessState
|
||||
import org.thoughtcrime.securesms.util.livedata.distinctUntilChanged
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
|
||||
|
||||
/**
|
||||
* Depending on the arguments, can be used to set the universal expire timer, set expire timer
|
||||
@@ -32,7 +32,7 @@ class ExpireTimerSettingsFragment : DSLSettingsFragment(
|
||||
layoutId = R.layout.expire_timer_settings_fragment
|
||||
) {
|
||||
|
||||
private lateinit var save: CircularProgressButton
|
||||
private lateinit var save: CircularProgressMaterialButton
|
||||
private lateinit var viewModel: ExpireTimerSettingsViewModel
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
@@ -62,9 +62,7 @@ class ExpireTimerSettingsFragment : DSLSettingsFragment(
|
||||
viewModel.state.distinctUntilChanged(ExpireTimerSettingsState::saveState).observe(viewLifecycleOwner) { state ->
|
||||
when (val saveState: ProcessState<Int> = state.saveState) {
|
||||
is ProcessState.Working -> {
|
||||
save.isClickable = false
|
||||
save.isIndeterminateProgressMode = true
|
||||
save.progress = 50
|
||||
save.setSpinning()
|
||||
}
|
||||
is ProcessState.Success -> {
|
||||
if (state.isGroupCreate) {
|
||||
@@ -79,9 +77,7 @@ class ExpireTimerSettingsFragment : DSLSettingsFragment(
|
||||
viewModel.resetError()
|
||||
}
|
||||
else -> {
|
||||
save.isClickable = true
|
||||
save.isIndeterminateProgressMode = false
|
||||
save.progress = 0
|
||||
save.cancelSpinning()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ class BoostFragment : DSLSettingsBottomSheetFragment(
|
||||
sectionHeaderPref(
|
||||
title = DSLSettingsText.from(
|
||||
R.string.BoostFragment__give_signal_a_boost,
|
||||
DSLSettingsText.CenterModifier, DSLSettingsText.Title2BoldModifier
|
||||
DSLSettingsText.CenterModifier, DSLSettingsText.TitleLargeModifier
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ class ManageDonationsFragment : DSLSettingsFragment(), ExpiredGiftSheet.Callback
|
||||
sectionHeaderPref(
|
||||
title = DSLSettingsText.from(
|
||||
R.string.SubscribeFragment__signal_is_powered_by_people_like_you,
|
||||
DSLSettingsText.CenterModifier, DSLSettingsText.Title2BoldModifier
|
||||
DSLSettingsText.CenterModifier, DSLSettingsText.TitleLargeModifier
|
||||
)
|
||||
)
|
||||
|
||||
@@ -215,7 +215,7 @@ class ManageDonationsFragment : DSLSettingsFragment(), ExpiredGiftSheet.Callback
|
||||
|
||||
space(DimensionUnit.DP.toPixels(16f).toInt())
|
||||
|
||||
primaryButton(
|
||||
tonalButton(
|
||||
text = DSLSettingsText.from(R.string.ManageDonationsFragment__make_a_monthly_donation),
|
||||
onClick = {
|
||||
findNavController().safeNavigate(R.id.action_manageDonationsFragment_to_subscribeFragment)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.thoughtcrime.securesms.components.settings.app.subscription.subscribe
|
||||
|
||||
import android.content.DialogInterface
|
||||
import android.graphics.Color
|
||||
import android.text.SpannableStringBuilder
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
@@ -138,7 +137,7 @@ class SubscribeFragment : DSLSettingsFragment(
|
||||
sectionHeaderPref(
|
||||
title = DSLSettingsText.from(
|
||||
R.string.SubscribeFragment__signal_is_powered_by_people_like_you,
|
||||
DSLSettingsText.CenterModifier, DSLSettingsText.Title2BoldModifier
|
||||
DSLSettingsText.CenterModifier, DSLSettingsText.TitleLargeModifier
|
||||
)
|
||||
)
|
||||
|
||||
@@ -300,9 +299,7 @@ class SubscribeFragment : DSLSettingsFragment(
|
||||
}
|
||||
|
||||
private fun onSubscriptionCancelled() {
|
||||
Snackbar.make(requireView(), R.string.SubscribeFragment__your_subscription_has_been_cancelled, Snackbar.LENGTH_LONG)
|
||||
.setTextColor(Color.WHITE)
|
||||
.show()
|
||||
Snackbar.make(requireView(), R.string.SubscribeFragment__your_subscription_has_been_cancelled, Snackbar.LENGTH_LONG).show()
|
||||
|
||||
requireActivity().finish()
|
||||
requireActivity().startActivity(AppSettingsActivity.home(requireContext()))
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.components.settings.conversation
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.PorterDuffColorFilter
|
||||
import android.graphics.Rect
|
||||
@@ -24,6 +23,7 @@ import app.cash.exhaustive.Exhaustive
|
||||
import com.google.android.flexbox.FlexboxLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import org.signal.core.util.DimensionUnit
|
||||
import org.thoughtcrime.securesms.AvatarPreviewActivity
|
||||
import org.thoughtcrime.securesms.BlockUnblockDialog
|
||||
import org.thoughtcrime.securesms.InviteActivity
|
||||
@@ -38,7 +38,6 @@ import org.thoughtcrime.securesms.badges.models.Badge
|
||||
import org.thoughtcrime.securesms.badges.view.ViewBadgeBottomSheetDialogFragment
|
||||
import org.thoughtcrime.securesms.components.AvatarImageView
|
||||
import org.thoughtcrime.securesms.components.recyclerview.OnScrollAnimationHelper
|
||||
import org.thoughtcrime.securesms.components.recyclerview.ToolbarShadowAnimationHelper
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
@@ -83,7 +82,6 @@ import org.thoughtcrime.securesms.util.CommunicationActions
|
||||
import org.thoughtcrime.securesms.util.ContextUtil
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil
|
||||
import org.thoughtcrime.securesms.util.ViewUtil
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog
|
||||
@@ -161,6 +159,8 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
}
|
||||
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
recyclerView?.addOnScrollListener(ConversationSettingsOnUserScrolledAnimationHelper(toolbarAvatarContainer, toolbarTitle, toolbarBackground))
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
@@ -179,10 +179,6 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getOnScrollAnimationHelper(toolbarShadow: View): OnScrollAnimationHelper {
|
||||
return ConversationSettingsOnUserScrolledAnimationHelper(toolbarAvatarContainer, toolbarTitle, toolbarBackground, toolbarShadow)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return if (item.itemId == R.id.action_edit) {
|
||||
val args = ConversationSettingsFragmentArgs.fromBundle(requireArguments())
|
||||
@@ -767,19 +763,18 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
showMembersAdded.membersAddedCount
|
||||
)
|
||||
|
||||
Snackbar.make(requireView(), string, Snackbar.LENGTH_SHORT).setTextColor(Color.WHITE).show()
|
||||
Snackbar.make(requireView(), string, Snackbar.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
private class ConversationSettingsOnUserScrolledAnimationHelper(
|
||||
private val toolbarAvatar: View,
|
||||
private val toolbarTitle: View,
|
||||
private val toolbarBackground: View,
|
||||
toolbarShadow: View
|
||||
) : ToolbarShadowAnimationHelper(toolbarShadow) {
|
||||
private val toolbarBackground: View
|
||||
) : OnScrollAnimationHelper() {
|
||||
|
||||
override val duration: Long = 200L
|
||||
|
||||
private val actionBarSize = ThemeUtil.getThemedDimen(toolbarShadow.context, R.attr.actionBarSize)
|
||||
private val actionBarSize = DimensionUnit.DP.toPixels(64f)
|
||||
private val rect = Rect()
|
||||
|
||||
override fun getAnimationState(recyclerView: RecyclerView): AnimationState {
|
||||
@@ -805,8 +800,6 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
}
|
||||
|
||||
override fun show(duration: Long) {
|
||||
super.show(duration)
|
||||
|
||||
toolbarAvatar
|
||||
.animate()
|
||||
.setDuration(duration)
|
||||
@@ -826,8 +819,6 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
||||
}
|
||||
|
||||
override fun hide(duration: Long) {
|
||||
super.hide(duration)
|
||||
|
||||
toolbarAvatar
|
||||
.animate()
|
||||
.setDuration(duration)
|
||||
|
||||
@@ -158,6 +158,15 @@ class DSLConfiguration {
|
||||
children.add(preference)
|
||||
}
|
||||
|
||||
fun tonalButton(
|
||||
text: DSLSettingsText,
|
||||
isEnabled: Boolean = true,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
val preference = Button.Model.Tonal(text, null, isEnabled, onClick)
|
||||
children.add(preference)
|
||||
}
|
||||
|
||||
fun secondaryButtonNoOutline(
|
||||
text: DSLSettingsText,
|
||||
icon: DSLSettingsIcon? = null,
|
||||
|
||||
@@ -14,6 +14,7 @@ object Button {
|
||||
|
||||
fun register(mappingAdapter: MappingAdapter) {
|
||||
mappingAdapter.registerFactory(Model.Primary::class.java, LayoutFactory({ ViewHolder(it) }, R.layout.dsl_button_primary))
|
||||
mappingAdapter.registerFactory(Model.Tonal::class.java, LayoutFactory({ ViewHolder(it) }, R.layout.dsl_button_tonal))
|
||||
mappingAdapter.registerFactory(Model.SecondaryNoOutline::class.java, LayoutFactory({ ViewHolder(it) }, R.layout.dsl_button_secondary))
|
||||
}
|
||||
|
||||
@@ -34,6 +35,13 @@ object Button {
|
||||
onClick: () -> Unit
|
||||
) : Model<Primary>(title, icon, isEnabled, onClick)
|
||||
|
||||
class Tonal(
|
||||
title: DSLSettingsText?,
|
||||
icon: DSLSettingsIcon?,
|
||||
isEnabled: Boolean,
|
||||
onClick: () -> Unit
|
||||
) : Model<Tonal>(title, icon, isEnabled, onClick)
|
||||
|
||||
class SecondaryNoOutline(
|
||||
title: DSLSettingsText?,
|
||||
icon: DSLSettingsIcon?,
|
||||
@@ -44,7 +52,7 @@ object Button {
|
||||
|
||||
class ViewHolder<T : Model<T>>(itemView: View) : MappingViewHolder<T>(itemView) {
|
||||
|
||||
private val button: MaterialButton = itemView as MaterialButton
|
||||
private val button: MaterialButton = itemView.findViewById(R.id.button)
|
||||
|
||||
override fun bind(model: T) {
|
||||
button.text = model.title?.resolve(context)
|
||||
|
||||
@@ -93,7 +93,7 @@ class VoiceNotePlayerView @JvmOverloads constructor(
|
||||
playPauseToggleView.addValueCallback(
|
||||
KeyPath("**"),
|
||||
LottieProperty.COLOR_FILTER,
|
||||
LottieValueCallback(SimpleColorFilter(ContextCompat.getColor(context, R.color.signal_icon_tint_primary)))
|
||||
LottieValueCallback(SimpleColorFilter(ContextCompat.getColor(context, R.color.signal_colorOnSurface)))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user