Implement new Material3 spec.

fork-5.53.8
Alex Hart 2022-05-26 17:32:52 -03:00 zatwierdzone przez Greyson Parrelli
rodzic 556e480b06
commit 1b471e163d
374 zmienionych plików z 3219 dodań i 3049 usunięć

Wyświetl plik

@ -10,12 +10,6 @@ apply plugin: 'kotlin-parcelize'
apply from: 'static-ips.gradle'
repositories {
maven {
url "https://raw.github.com/signalapp/maven/master/circular-progress-button/releases/"
content {
includeGroupByRegex "com\\.github\\.dmytrodanylyk\\.circular-progress-button\\.*"
}
}
maven {
url "https://raw.github.com/signalapp/maven/master/sqlcipher/release/"
content {
@ -508,7 +502,6 @@ dependencies {
implementation libs.lottie
implementation libs.stickyheadergrid
implementation libs.circular.progress.button
implementation libs.signal.android.database.sqlcipher
implementation libs.androidx.sqlite

Wyświetl plik

@ -58,9 +58,9 @@ import com.google.android.material.chip.ChipGroup;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.pnikosis.materialishprogress.ProgressWheel;
import org.signal.core.util.concurrent.SimpleTask;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.components.RecyclerViewFastScroller;
import org.thoughtcrime.securesms.components.recyclerview.ToolbarShadowAnimationHelper;
import org.thoughtcrime.securesms.contacts.AbstractContactsCursorLoader;
import org.thoughtcrime.securesms.contacts.ContactChip;
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter;
@ -85,7 +85,6 @@ import org.thoughtcrime.securesms.util.UsernameUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.adapter.FixedViewsAdapter;
import org.thoughtcrime.securesms.util.adapter.RecyclerViewConcatenateAdapterStickyHeader;
import org.signal.core.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import java.io.IOException;
@ -138,8 +137,7 @@ public final class ContactSelectionListFragment extends LoggingFragment
private HorizontalScrollView chipGroupScrollContainer;
private OnSelectionLimitReachedListener onSelectionLimitReachedListener;
private AbstractContactsCursorLoaderFactoryProvider cursorFactoryProvider;
private View shadowView;
private ToolbarShadowAnimationHelper toolbarShadowAnimationHelper;
private HeaderActionProvider headerActionProvider;
private TextView headerActionView;
@ -253,14 +251,10 @@ public final class ContactSelectionListFragment extends LoggingFragment
chipGroup = view.findViewById(R.id.chipGroup);
chipGroupScrollContainer = view.findViewById(R.id.chipGroupScrollContainer);
constraintLayout = view.findViewById(R.id.container);
shadowView = view.findViewById(R.id.toolbar_shadow);
headerActionView = view.findViewById(R.id.header_action);
toolbarShadowAnimationHelper = new ToolbarShadowAnimationHelper(shadowView);
final LinearLayoutManager layoutManager = new LinearLayoutManager(requireContext());
recyclerView.addOnScrollListener(toolbarShadowAnimationHelper);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator() {
@Override

Wyświetl plik

@ -125,10 +125,10 @@ public class MainActivity extends PassphraseRequiredActivity implements VoiceNot
private void updateTabVisibility() {
if (Stories.isFeatureEnabled()) {
findViewById(R.id.conversation_list_tabs).setVisibility(View.VISIBLE);
WindowUtil.setNavigationBarColor(getWindow(), ContextCompat.getColor(this, R.color.signal_colorSecondaryContainer));
WindowUtil.setNavigationBarColor(getWindow(), ContextCompat.getColor(this, R.color.signal_colorSurface2));
} else {
findViewById(R.id.conversation_list_tabs).setVisibility(View.GONE);
WindowUtil.setNavigationBarColor(getWindow(), ContextCompat.getColor(this, R.color.signal_background_primary));
WindowUtil.setNavigationBarColor(getWindow(), ContextCompat.getColor(this, R.color.signal_colorBackground));
conversationListTabsViewModel.onChatsSelected();
}
}

Wyświetl plik

@ -81,14 +81,7 @@ class AvatarPickerFragment : Fragment(R.layout.avatar_picker_fragment) {
}
clearButton.visible = state.canClear
val wasEnabled = saveButton.isEnabled
saveButton.isEnabled = state.canSave
if (wasEnabled != state.canSave) {
val alpha = if (state.canSave) 1f else 0.5f
saveButton.animate().cancel()
saveButton.animate().alpha(alpha)
}
saveButton.isClickable = state.canSave
val items = state.selectableAvatars.map { AvatarPickerItem.Model(it, it == state.currentAvatar) }
val selectedPosition = items.indexOfFirst { it.isSelected }
@ -104,6 +97,11 @@ class AvatarPickerFragment : Fragment(R.layout.avatar_picker_fragment) {
photoButton.setOnIconClickedListener { openGallery() }
textButton.setOnIconClickedListener { openTextEditor(null) }
saveButton.setOnClickListener { v ->
if (!saveButton.isEnabled) {
return@setOnClickListener
}
saveButton.isEnabled = false
viewModel.save(
{
setFragmentResult(

Wyświetl plik

@ -31,7 +31,7 @@ object ExpiredGiftSheetConfiguration {
textPref(
title = DSLSettingsText.from(
stringId = R.string.ExpiredGiftSheetConfiguration__your_gift_badge_has_expired,
DSLSettingsText.CenterModifier, DSLSettingsText.Title2BoldModifier
DSLSettingsText.CenterModifier, DSLSettingsText.TitleLargeModifier
)
)

Wyświetl plik

@ -58,7 +58,7 @@ class GiftThanksSheet : DSLSettingsBottomSheetFragment() {
private fun getConfiguration(recipient: Recipient): DSLConfiguration {
return configure {
textPref(
title = DSLSettingsText.from(R.string.SubscribeThanksForYourSupportBottomSheetDialogFragment__thanks_for_your_support, DSLSettingsText.Title2BoldModifier, DSLSettingsText.CenterModifier)
title = DSLSettingsText.from(R.string.SubscribeThanksForYourSupportBottomSheetDialogFragment__thanks_for_your_support, DSLSettingsText.TitleLargeModifier, DSLSettingsText.CenterModifier)
)
noPadTextPref(

Wyświetl plik

@ -158,7 +158,7 @@ class ViewReceivedGiftBottomSheet : DSLSettingsBottomSheetFragment() {
noPadTextPref(
title = DSLSettingsText.from(
charSequence = requireContext().getString(R.string.ViewReceivedGiftBottomSheet__s_sent_you_a_gift, state.recipient.getShortDisplayName(requireContext())),
DSLSettingsText.CenterModifier, DSLSettingsText.Title2BoldModifier
DSLSettingsText.CenterModifier, DSLSettingsText.TitleLargeModifier
)
)

Wyświetl plik

@ -66,7 +66,7 @@ class ViewSentGiftBottomSheet : DSLSettingsBottomSheetFragment() {
noPadTextPref(
title = DSLSettingsText.from(
stringId = R.string.ViewSentGiftBottomSheet__thanks_for_your_support,
DSLSettingsText.CenterModifier, DSLSettingsText.Title2BoldModifier
DSLSettingsText.CenterModifier, DSLSettingsText.TitleLargeModifier
)
)

Wyświetl plik

@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.badges.self.featured
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import org.thoughtcrime.securesms.R
@ -11,13 +12,12 @@ import org.thoughtcrime.securesms.badges.Badges
import org.thoughtcrime.securesms.badges.Badges.displayBadges
import org.thoughtcrime.securesms.badges.models.Badge
import org.thoughtcrime.securesms.badges.models.BadgePreview
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
import org.thoughtcrime.securesms.components.settings.configure
import org.thoughtcrime.securesms.util.LifecycleDisposable
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
/**
* Fragment which allows user to select one of their badges to be their "Featured" badge.
@ -46,8 +46,8 @@ class SelectFeaturedBadgeFragment : DSLSettingsFragment(
}
}
override fun getOnScrollAnimationHelper(toolbarShadow: View): OnScrollAnimationHelper {
return ToolbarShadowAnimationHelper(scrollShadow)
override fun getMaterial3OnScrollHelper(toolbar: Toolbar?): Material3OnScrollHelper? {
return Material3OnScrollHelper(requireActivity(), scrollShadow)
}
override fun bindAdapter(adapter: DSLSettingsAdapter) {

Wyświetl plik

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.badges.self.none
import android.content.Intent
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.viewModels
import org.signal.core.util.DimensionUnit
@ -40,7 +41,7 @@ class BecomeASustainerFragment : DSLSettingsBottomSheetFragment() {
title = DSLSettingsText.from(
R.string.BecomeASustainerFragment__get_badges,
DSLSettingsText.CenterModifier,
DSLSettingsText.Title2BoldModifier
DSLSettingsText.TitleLargeModifier
)
)
@ -49,13 +50,15 @@ class BecomeASustainerFragment : DSLSettingsBottomSheetFragment() {
noPadTextPref(
title = DSLSettingsText.from(
R.string.BecomeASustainerFragment__signal_is_a_non_profit,
DSLSettingsText.CenterModifier
DSLSettingsText.CenterModifier,
DSLSettingsText.TextAppearanceModifier(R.style.Signal_Text_BodyMedium),
DSLSettingsText.ColorModifier(ContextCompat.getColor(requireContext(), R.color.signal_colorOnSurfaceVariant))
)
)
space(DimensionUnit.DP.toPixels(77f).toInt())
space(DimensionUnit.DP.toPixels(32f).toInt())
primaryButton(
tonalButton(
text = DSLSettingsText.from(
R.string.BecomeASustainerMegaphone__become_a_sustainer
),
@ -65,7 +68,7 @@ class BecomeASustainerFragment : DSLSettingsBottomSheetFragment() {
}
)
space(DimensionUnit.DP.toPixels(8f).toInt())
space(DimensionUnit.DP.toPixels(32f).toInt())
}
}

Wyświetl plik

@ -171,6 +171,6 @@ public class BlockedUsersActivity extends PassphraseRequiredActivity implements
throw new IllegalArgumentException("Unsupported event type " + event);
}
Snackbar.make(view, getString(messageResId, displayName), Snackbar.LENGTH_SHORT).setTextColor(Color.WHITE).show();
Snackbar.make(view, getString(messageResId, displayName), Snackbar.LENGTH_SHORT).show();
}
}

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -61,8 +61,8 @@ public final class ContactChip extends Chip {
.placeholder(fallbackContactPhotoDrawable)
.fallback(fallbackContactPhotoDrawable)
.error(fallbackContactPhotoDrawable)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.circleCrop()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {

Wyświetl plik

@ -28,7 +28,7 @@ class LetterHeaderDecoration(private val context: Context, private val hideDecor
color = ContextCompat.getColor(context, R.color.signal_text_primary)
isAntiAlias = true
style = Paint.Style.FILL
typeface = Typeface.create("sans-serif-medium", Typeface.BOLD)
typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL)
textAlign = Paint.Align.LEFT
textSize = ViewUtil.spToPx(16f).toFloat()
}

Wyświetl plik

@ -0,0 +1,32 @@
package org.thoughtcrime.securesms.conversation
import androidx.core.view.doOnNextLayout
import androidx.recyclerview.widget.RecyclerView
import org.signal.core.util.DimensionUnit
/**
* Adds necessary padding to each side of the given RecyclerView in order to ensure that
* if all buttons can fit in the visible real-estate on screen, they are centered.
*/
class AttachmentButtonCenterHelper(private val recyclerView: RecyclerView) : RecyclerView.AdapterDataObserver() {
private val itemWidth: Float = DimensionUnit.DP.toPixels(88f)
private val defaultPadding: Float = DimensionUnit.DP.toPixels(16f)
override fun onChanged() {
val itemCount = recyclerView.adapter?.itemCount ?: return
val requiredSpace = itemWidth * itemCount
recyclerView.doOnNextLayout {
if (it.measuredWidth >= requiredSpace) {
val extraSpace = it.measuredWidth - requiredSpace
val availablePadding = extraSpace / 2f
it.post {
it.setPadding(availablePadding.toInt(), it.paddingTop, availablePadding.toInt(), it.paddingBottom)
}
} else {
it.setPadding(defaultPadding.toInt(), it.paddingTop, defaultPadding.toInt(), it.paddingBottom)
}
}
}
}

Wyświetl plik

@ -78,6 +78,8 @@ public class AttachmentKeyboard extends FrameLayout implements InputAwareLayout.
mediaList.setAdapter(mediaAdapter);
buttonList.setAdapter(buttonAdapter);
buttonAdapter.registerAdapterDataObserver(new AttachmentButtonCenterHelper(buttonList));
mediaList.setLayoutManager(new GridLayoutManager(context, 1, GridLayoutManager.HORIZONTAL, false));
buttonList.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));

Wyświetl plik

@ -7,11 +7,11 @@ import org.thoughtcrime.securesms.R;
public enum AttachmentKeyboardButton {
GALLERY(R.string.AttachmentKeyboard_gallery, R.drawable.ic_photo_album_outline_32),
FILE(R.string.AttachmentKeyboard_file, R.drawable.ic_file_outline_32),
PAYMENT(R.string.AttachmentKeyboard_payment, R.drawable.ic_payments_32),
CONTACT(R.string.AttachmentKeyboard_contact, R.drawable.ic_contact_circle_outline_32),
LOCATION(R.string.AttachmentKeyboard_location, R.drawable.ic_location_outline_32);
GALLERY(R.string.AttachmentKeyboard_gallery, R.drawable.ic_gallery_outline_24),
FILE(R.string.AttachmentKeyboard_file, R.drawable.ic_file_outline_24),
PAYMENT(R.string.AttachmentKeyboard_payment, R.drawable.ic_payments_24),
CONTACT(R.string.AttachmentKeyboard_contact, R.drawable.ic_contact_outline_24),
LOCATION(R.string.AttachmentKeyboard_location, R.drawable.ic_location_outline_24);
private final int titleRes;
private final int iconRes;

Wyświetl plik

@ -79,8 +79,8 @@ class AttachmentKeyboardButtonAdapter extends RecyclerView.Adapter<AttachmentKey
public ButtonViewHolder(@NonNull View itemView) {
super(itemView);
this.image = itemView.findViewById(R.id.attachment_button_image);
this.title = itemView.findViewById(R.id.attachment_button_title);
this.image = itemView.findViewById(R.id.icon);
this.title = itemView.findViewById(R.id.label);
}
void bind(@NonNull AttachmentKeyboardButton button, boolean wallpaperEnabled, @NonNull Listener listener) {
@ -88,12 +88,6 @@ class AttachmentKeyboardButtonAdapter extends RecyclerView.Adapter<AttachmentKey
title.setText(button.getTitleRes());
itemView.setOnClickListener(v -> listener.onClick(button));
if (wallpaperEnabled) {
itemView.setBackgroundResource(R.drawable.attachment_keyboard_button_wallpaper_background);
} else {
itemView.setBackgroundResource(R.drawable.attachment_keyboard_button_background);
}
}
void recycle() {

Wyświetl plik

@ -25,7 +25,6 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import androidx.annotation.AnyThread;
import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.LayoutRes;
@ -40,7 +39,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.exoplayer2.MediaItem;
import org.signal.core.util.ThreadUtil;
import org.signal.core.util.logging.Log;
import org.signal.paging.PagingController;
import org.thoughtcrime.securesms.BindableConversationItem;
@ -65,10 +63,8 @@ import org.thoughtcrime.securesms.util.ViewUtil;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@ -348,22 +344,22 @@ public class ConversationAdapter
if (type == HEADER_TYPE_POPOVER_DATE) {
if (hasWallpaper) {
viewHolder.setBackgroundRes(R.drawable.wallpaper_bubble_background_8);
viewHolder.setBackgroundRes(R.drawable.wallpaper_bubble_background_18);
} else {
viewHolder.setBackgroundRes(R.drawable.sticky_date_header_background);
}
} else if (type == HEADER_TYPE_INLINE_DATE) {
if (hasWallpaper) {
viewHolder.setBackgroundRes(R.drawable.wallpaper_bubble_background_8);
viewHolder.setBackgroundRes(R.drawable.wallpaper_bubble_background_18);
} else {
viewHolder.clearBackground();
}
}
if (hasWallpaper && ThemeUtil.isDarkTheme(context)) {
viewHolder.setTextColor(ContextCompat.getColor(context, R.color.core_grey_15));
viewHolder.setTextColor(ContextCompat.getColor(context, R.color.signal_colorNeutralInverse));
} else {
viewHolder.setTextColor(ContextCompat.getColor(context, R.color.signal_text_secondary));
viewHolder.setTextColor(ContextCompat.getColor(context, R.color.signal_colorOnSurfaceVariant));
}
}
@ -400,7 +396,7 @@ public class ConversationAdapter
viewHolder.setText(viewHolder.itemView.getContext().getResources().getQuantityString(R.plurals.ConversationAdapter_n_unread_messages, count, count));
if (hasWallpaper) {
viewHolder.setBackgroundRes(R.drawable.wallpaper_bubble_background_8);
viewHolder.setBackgroundRes(R.drawable.wallpaper_bubble_background_18);
viewHolder.setDividerColor(viewHolder.itemView.getResources().getColor(R.color.transparent_black_80));
} else {
viewHolder.clearBackground();

Wyświetl plik

@ -49,10 +49,12 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.WindowDecorActionBar;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.app.ActivityOptionsCompat;
import androidx.core.content.ContextCompat;
import androidx.core.text.HtmlCompat;
import androidx.core.view.ViewCompat;
import androidx.core.view.ViewKt;
@ -132,6 +134,7 @@ import org.thoughtcrime.securesms.jobs.MultiDeviceViewOnceOpenJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.longmessage.LongMessageFragment;
import org.thoughtcrime.securesms.main.Material3OnScrollHelperBinder;
import org.thoughtcrime.securesms.messagedetails.MessageDetailsFragment;
import org.thoughtcrime.securesms.messagerequests.MessageRequestState;
import org.thoughtcrime.securesms.messagerequests.MessageRequestViewModel;
@ -239,7 +242,6 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
private Animation mentionButtonOutAnimation;
private OnScrollListener conversationScrollListener;
private int lastSeenScrollOffset;
private View toolbarShadow;
private Stopwatch startupStopwatch;
private LayoutTransition layoutTransition;
private TransitionListener transitionListener;
@ -290,7 +292,6 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
scrollToBottomButton = view.findViewById(R.id.scroll_to_bottom);
scrollToMentionButton = view.findViewById(R.id.scroll_to_mention);
scrollDateHeader = view.findViewById(R.id.scroll_date_header);
toolbarShadow = requireActivity().findViewById(R.id.conversation_toolbar_shadow);
reactionsShade = view.findViewById(R.id.reactions_shade);
bottomActionBar = view.findViewById(R.id.conversation_bottom_action_bar);
@ -321,6 +322,8 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
list.addItemDecoration(multiselectItemDecoration);
list.setItemAnimator(conversationItemAnimator);
((Material3OnScrollHelperBinder) requireParentFragment()).bindScrollHelper(list);
getViewLifecycleOwner().getLifecycle().addObserver(multiselectItemDecoration);
snapToTopDataObserver = new ConversationSnapToTopDataObserver(list, new ConversationScrollRequestValidator());
@ -352,7 +355,12 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
this.messageCountsViewModel = new ViewModelProvider(getParentFragment()).get(MessageCountsViewModel.class);
this.conversationViewModel = new ViewModelProvider(getParentFragment(), new ConversationViewModel.Factory()).get(ConversationViewModel.class);
disposables.add(conversationViewModel.getChatColors().subscribe(recyclerViewColorizer::setChatColors));
disposables.add(conversationViewModel.getChatColors().subscribe(chatColors -> {
recyclerViewColorizer.setChatColors(chatColors);
scrollToMentionButton.setUnreadCountBackgroundTint(chatColors.asSingleColor());
scrollToBottomButton.setUnreadCountBackgroundTint(chatColors.asSingleColor());
}));
disposables.add(conversationViewModel.getMessageData().subscribe(messageData -> {
SignalLocalMetrics.ConversationOpen.onDataPostedToMain();
@ -428,7 +436,6 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
getChildFragmentManager().setFragmentResultListener(ViewReceivedGiftBottomSheet.REQUEST_KEY, getViewLifecycleOwner(), (key, bundle) -> {
if (bundle.getBoolean(ViewReceivedGiftBottomSheet.RESULT_NOT_NOW, false)) {
Snackbar.make(view.getRootView(), R.string.ConversationFragment__you_can_redeem_your_badge_later, Snackbar.LENGTH_SHORT)
.setTextColor(Color.WHITE)
.show();
}
});
@ -544,6 +551,13 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
}
public void onWallpaperChanged(@Nullable ChatWallpaper wallpaper) {
if (scrollDateHeader != null) {
scrollDateHeader.setBackgroundResource(wallpaper != null ? R.drawable.sticky_date_header_background_wallpaper
: R.drawable.sticky_date_header_background);
scrollDateHeader.setTextColor(ContextCompat.getColor(requireContext(), wallpaper != null ? R.color.sticky_header_foreground_wallpaper
: R.color.signal_colorOnSurfaceVariant));
}
if (list != null) {
ConversationAdapter adapter = getListAdapter();
@ -686,7 +700,6 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
conversationScrollListener = new ConversationScrollListener(requireContext());
list.addOnScrollListener(conversationScrollListener);
list.addOnScrollListener(new ShadowScrollListener());
if (oldThreadId != threadId) {
ApplicationDependencies.getTypingStatusRepository().getTypists(oldThreadId).removeObservers(getViewLifecycleOwner());
@ -694,10 +707,6 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
}
private void initializeListAdapter() {
if (threadId == -1) {
toolbarShadow.setVisibility(View.GONE);
}
if (this.recipient != null) {
if (getListAdapter() != null && getListAdapter().isForRecipientId(this.recipient.getId())) {
Log.d(TAG, "List adapter already initialized for " + this.recipient.getId());
@ -1069,7 +1078,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
}
private void handleDisplayDetails(ConversationMessage message) {
MessageDetailsFragment.create(message.getMessageRecord(), recipient.getId()).show(getChildFragmentManager(), null);
MessageDetailsFragment.create(message.getMessageRecord(), recipient.getId()).show(getParentFragment().getChildFragmentManager(), null);
}
private void handleForwardMessageParts(Set<MultiselectPart> multiselectParts) {
@ -1301,9 +1310,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
if (!TextSecurePreferences.hasSeenSwipeToReplyTooltip(requireContext())) {
int text = ViewUtil.isLtr(requireContext()) ? R.string.ConversationFragment_you_can_swipe_to_the_right_reply
: R.string.ConversationFragment_you_can_swipe_to_the_left_reply;
Snackbar.make(list, text, Snackbar.LENGTH_LONG)
.setTextColor(Color.WHITE)
.show();
Snackbar.make(list, text, Snackbar.LENGTH_LONG).show();
TextSecurePreferences.setHasSeenSwipeToReplyTooltip(requireContext(), true);
}
@ -1409,6 +1416,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
void setThreadId(long threadId);
void handleReplyMessage(ConversationMessage conversationMessage);
void onMessageActionToolbarOpened();
void onMessageActionToolbarClosed();
void onBottomActionBarVisibilityChanged(int visibility);
void onForwardClicked();
void onMessageRequest(@NonNull MessageRequestViewModel viewModel);
@ -1513,7 +1521,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
if (actionMode != null) return;
MessageRecord messageRecord = item.getConversationMessage().getMessageRecord();;
MessageRecord messageRecord = item.getConversationMessage().getMessageRecord();
if (messageRecord.isSecure() &&
!messageRecord.isRemoteDelete() &&
@ -2191,6 +2199,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
list.invalidateItemDecorations();
setBottomActionBarVisibility(false);
actionMode = null;
listener.onMessageActionToolbarClosed();
}
@Override
@ -2242,21 +2251,6 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
}
}
private class ShadowScrollListener extends RecyclerView.OnScrollListener {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (recyclerView.canScrollVertically(-1)) {
if (toolbarShadow.getVisibility() != View.VISIBLE) {
ViewUtil.fadeIn(toolbarShadow, 250);
}
} else {
if (toolbarShadow.getVisibility() != View.GONE) {
ViewUtil.fadeOut(toolbarShadow, 250);
}
}
}
}
private static final class TransitionListener implements Animator.AnimatorListener {
private final ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);

Wyświetl plik

@ -22,6 +22,7 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.Typeface;
@ -569,6 +570,10 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
if (conversationRecipient.getId().equals(modified.getId())) {
setBubbleState(messageRecord, modified, modified.hasWallpaper(), colorizer);
if (quoteView != null) {
quoteView.setWallpaperEnabled(modified.hasWallpaper());
}
if (audioViewStub.resolved()) {
setAudioViewTint(messageRecord);
}
@ -606,7 +611,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
}
private void initializeAttributes() {
defaultBubbleColor = ContextCompat.getColor(context, R.color.signal_background_secondary);
defaultBubbleColor = ContextCompat.getColor(context, R.color.signal_colorSurfaceVariant);
defaultBubbleColorForWallpaper = ContextCompat.getColor(context, R.color.conversation_item_wallpaper_bubble_color);
}
@ -728,8 +733,8 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
this.hasWallpaper = hasWallpaper;
ViewUtil.updateLayoutParams(bodyBubble, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
bodyText.setTextColor(ContextCompat.getColor(getContext(), R.color.signal_text_primary));
bodyText.setLinkTextColor(ContextCompat.getColor(getContext(), R.color.signal_text_primary));
bodyText.setTextColor(colorizer.getIncomingBodyTextColor(context, hasWallpaper));
bodyText.setLinkTextColor(colorizer.getIncomingBodyTextColor(context, hasWallpaper));
if (messageRecord.isOutgoing() && !messageRecord.isRemoteDelete()) {
bodyBubble.getBackground().setColorFilter(recipient.getChatColors().getChatBubbleColorFilter());
@ -751,9 +756,9 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
footer.setOnlyShowSendingStatus(messageRecord.isRemoteDelete(), messageRecord);
} else {
bodyBubble.getBackground().setColorFilter(getDefaultBubbleColor(hasWallpaper), PorterDuff.Mode.SRC_IN);
footer.setTextColor(ContextCompat.getColor(context, R.color.signal_text_secondary));
footer.setIconColor(ContextCompat.getColor(context, R.color.signal_text_secondary));
footer.setRevealDotColor(ContextCompat.getColor(context, R.color.signal_text_secondary));
footer.setTextColor(colorizer.getIncomingFooterTextColor(context, hasWallpaper));
footer.setIconColor(colorizer.getIncomingFooterIconColor(context, hasWallpaper));
footer.setRevealDotColor(colorizer.getIncomingFooterIconColor(context, hasWallpaper));
footer.setOnlyShowSendingStatus(false, messageRecord);
}
@ -788,15 +793,16 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
private void setAudioViewTint(MessageRecord messageRecord) {
if (hasAudio(messageRecord)) {
if (!messageRecord.isOutgoing()) {
audioViewStub.get().setTint(getContext().getResources().getColor(R.color.conversation_item_incoming_audio_foreground_tint));
if (hasWallpaper) {
audioViewStub.get().setTint(getContext().getResources().getColor(R.color.conversation_item_incoming_audio_foreground_tint_wallpaper));
audioViewStub.get().setProgressAndPlayBackgroundTint(getContext().getResources().getColor(R.color.conversation_item_incoming_audio_play_pause_background_tint_wallpaper));
} else {
audioViewStub.get().setTint(getContext().getResources().getColor(R.color.conversation_item_incoming_audio_foreground_tint_normal));
audioViewStub.get().setProgressAndPlayBackgroundTint(getContext().getResources().getColor(R.color.conversation_item_incoming_audio_play_pause_background_tint_normal));
}
} else {
audioViewStub.get().setTint(Color.WHITE);
audioViewStub.get().setProgressAndPlayBackgroundTint(getContext().getResources().getColor(R.color.transparent_white_20));
audioViewStub.get().setTint(getContext().getResources().getColor(R.color.conversation_item_outgoing_audio_foreground_tint));
audioViewStub.get().setProgressAndPlayBackgroundTint(getContext().getResources().getColor(R.color.signal_colorTransparent2));
}
}
}
@ -1089,6 +1095,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
linkPreviewStub.get().setOnClickListener(linkPreviewClickListener);
linkPreviewStub.get().setOnLongClickListener(passthroughClickListener);
linkPreviewStub.get().setBackgroundColor(getDefaultBubbleColor(hasWallpaper));
footer.setVisibility(VISIBLE);
} else if (hasAudio(messageRecord)) {
@ -1470,10 +1477,10 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
quote.getDisplayText(),
quote.isOriginalMissing(),
quote.getAttachment(),
chatColors,
isStoryReaction(current) ? current.getBody() : null,
quote.getQuoteType());
quoteView.setWallpaperEnabled(hasWallpaper);
quoteView.setVisibility(View.VISIBLE);
quoteView.setTextSize(TypedValue.COMPLEX_UNIT_SP, SignalStore.settings().getMessageFontSize());
quoteView.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
@ -1951,6 +1958,10 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
@Override
public @NonNull ProjectionList getColorizerProjections(@NonNull ViewGroup coordinateRoot) {
return getSnapshotProjections(coordinateRoot, true);
}
public @NonNull ProjectionList getSnapshotProjections(@NonNull ViewGroup coordinateRoot, boolean clipOutMedia) {
colorizerProjections.clear();
if (messageRecord.isOutgoing() &&
@ -1961,6 +1972,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
{
Projection bodyBubbleToRoot = Projection.relativeToParent(coordinateRoot, bodyBubble, bodyBubbleCorners).translateX(bodyBubble.getTranslationX());
Projection videoToBubble = bodyBubble.getVideoPlayerProjection();
Projection mediaThumb = clipOutMedia && mediaThumbnailStub.resolved() ? Projection.relativeToParent(coordinateRoot, mediaThumbnailStub.require(), null) : null;
float translationX = Util.halfOffsetFromScale(bodyBubble.getWidth(), bodyBubble.getScaleX());
float translationY = Util.halfOffsetFromScale(bodyBubble.getHeight(), bodyBubble.getScaleY());
@ -1981,6 +1993,13 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
}
colorizerProjections.addAll(projections);
} else if (hasThumbnail(messageRecord) && mediaThumb != null) {
colorizerProjections.add(
bodyBubbleToRoot.insetTop(mediaThumb.getHeight())
.scale(bodyBubble.getScaleX())
.translateX(translationX)
.translateY(translationY)
);
} else {
colorizerProjections.add(
bodyBubbleToRoot.scale(bodyBubble.getScaleX())
@ -1988,6 +2007,10 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
.translateY(translationY)
);
}
if (mediaThumb != null) {
mediaThumb.release();
}
}
if (messageRecord.isOutgoing() &&
@ -2007,21 +2030,6 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
}
}
if (!messageRecord.isOutgoing() &&
hasQuote(messageRecord) &&
quoteView != null &&
bodyBubble.getVisibility() == VISIBLE)
{
bodyBubble.setQuoteViewProjection(quoteView.getProjection(bodyBubble));
float bubbleOffsetFromScale = Util.halfOffsetFromScale(bodyBubble.getHeight(), bodyBubble.getScaleY());
Projection cProj = quoteView.getProjection(coordinateRoot)
.translateX(bodyBubble.getTranslationX() + this.getTranslationX() + Util.halfOffsetFromScale(quoteView.getWidth(), bodyBubble.getScaleX()))
.translateY(bubbleOffsetFromScale - quoteView.getY() + (quoteView.getY() * bodyBubble.getScaleY()))
.scale(bodyBubble.getScaleX());
colorizerProjections.add(cProj);
}
for (int i = 0; i < colorizerProjections.size(); i++) {
colorizerProjections.get(i).translateY(getTranslationY());
}

Wyświetl plik

@ -48,7 +48,7 @@ object ConversationItemSelection {
bodyBubble.scaleX = 1.0f
bodyBubble.scaleY = 1.0f
val projections = conversationItem.getColorizerProjections(list)
val projections = conversationItem.getSnapshotProjections(list, false)
val path = Path()

Wyświetl plik

@ -27,6 +27,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
@ -68,6 +69,7 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.ColorInt;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -81,11 +83,14 @@ import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.content.pm.ShortcutManagerCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.graphics.drawable.IconCompat;
import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;
import com.airbnb.lottie.SimpleColorFilter;
import com.annimon.stream.Collectors;
import com.annimon.stream.Stream;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
@ -212,6 +217,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel;
import org.thoughtcrime.securesms.main.Material3OnScrollHelperBinder;
import org.thoughtcrime.securesms.maps.PlacePickerActivity;
import org.thoughtcrime.securesms.mediaoverview.MediaOverviewActivity;
import org.thoughtcrime.securesms.mediasend.Media;
@ -282,6 +288,7 @@ import org.thoughtcrime.securesms.util.DrawableUtil;
import org.thoughtcrime.securesms.util.FullscreenHelper;
import org.thoughtcrime.securesms.util.IdentityUtil;
import org.thoughtcrime.securesms.util.LifecycleDisposable;
import org.thoughtcrime.securesms.util.Material3OnScrollHelper;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.MessageRecordUtil;
import org.thoughtcrime.securesms.util.MessageUtil;
@ -319,6 +326,8 @@ import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import kotlin.Unit;
import static org.thoughtcrime.securesms.TransportOption.Type;
import static org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
@ -349,7 +358,9 @@ public class ConversationParentFragment extends Fragment
GifKeyboardPageFragment.Host,
EmojiKeyboardPageFragment.Callback,
EmojiSearchFragment.Callback,
StickerKeyboardPageFragment.Callback
StickerKeyboardPageFragment.Callback,
Material3OnScrollHelperBinder,
MessageDetailsFragment.Callback
{
private static final int SHORTCUT_ICON_SIZE = Build.VERSION.SDK_INT >= 26 ? ViewUtil.dpToPx(72) : ViewUtil.dpToPx(48 + 16 * 2);
@ -419,6 +430,7 @@ public class ConversationParentFragment extends Fragment
private ImageView wallpaper;
private View wallpaperDim;
private Toolbar toolbar;
private View toolbarBackground;
private BroadcastReceiver pinnedShortcutReceiver;
private LinkPreviewViewModel linkPreviewViewModel;
@ -433,7 +445,7 @@ public class ConversationParentFragment extends Fragment
private DraftViewModel draftViewModel;
private VoiceNoteMediaController voiceNoteMediaController;
private VoiceNotePlayerView voiceNotePlayerView;
private Material3OnScrollHelper material3OnScrollHelper;
private LiveRecipient recipient;
private long threadId;
@ -1114,6 +1126,9 @@ public class ConversationParentFragment extends Fragment
}
super.onCreateOptionsMenu(menu, inflater);
int toolbarTextAndIconColor = getResources().getColor(wallpaper.getDrawable() != null ? R.color.signal_colorNeutralInverse : R.color.signal_colorOnSurface);
setToolbarActionItemTint(toolbar, toolbarTextAndIconColor);
}
public void invalidateOptionsMenu() {
@ -1743,7 +1758,10 @@ public class ConversationParentFragment extends Fragment
}
}
noLongerMemberBanner.setVisibility(leftGroup ? View.VISIBLE : View.GONE);
if (messageRequestBottomView.getVisibility() == View.GONE) {
noLongerMemberBanner.setVisibility(leftGroup ? View.VISIBLE : View.GONE);
}
requestingMemberBanner.setVisibility(canCancelRequest ? View.VISIBLE : View.GONE);
if (canCancelRequest) {
@ -2092,6 +2110,7 @@ public class ConversationParentFragment extends Fragment
private void initializeViews(View view) {
toolbar = view.findViewById(R.id.toolbar);
toolbarBackground = view.findViewById(R.id.toolbar_background);
titleView = view.findViewById(R.id.conversation_title_view);
buttonToggle = view.findViewById(R.id.button_toggle);
sendButton = view.findViewById(R.id.send_button);
@ -2124,7 +2143,6 @@ public class ConversationParentFragment extends Fragment
Stub<ConversationReactionOverlay> reactionOverlayStub = ViewUtil.findStubById(view, R.id.conversation_reaction_scrubber_stub);
reactionDelegate = new ConversationReactionDelegate(reactionOverlayStub);
noLongerMemberBanner = view.findViewById(R.id.conversation_no_longer_member_banner);
cannotSendInAnnouncementGroupBanner = ViewUtil.findStubById(view, R.id.conversation_cannot_send_announcement_stub);
requestingMemberBanner = view.findViewById(R.id.conversation_requesting_banner);
@ -2156,7 +2174,7 @@ public class ConversationParentFragment extends Fragment
linkPreviewViewModel.onTransportChanged(newTransport.isSms());
composeText.setTransport(newTransport);
buttonToggle.getBackground().setColorFilter(newTransport.getBackgroundColor(), PorterDuff.Mode.MULTIPLY);
buttonToggle.getBackground().setColorFilter(getButtonToggleBackgroundColor(newTransport), PorterDuff.Mode.MULTIPLY);
buttonToggle.getBackground().invalidateSelf();
if (manuallySelected) recordTransportPreference(newTransport);
@ -2200,6 +2218,18 @@ public class ConversationParentFragment extends Fragment
});
voiceNoteMediaController.getVoiceNotePlaybackState().observe(getViewLifecycleOwner(), inputPanel.getPlaybackStateObserver());
material3OnScrollHelper = new Material3OnScrollHelper(Collections.singletonList(toolbarBackground), Collections.emptyList(), this::updateStatusBarColor);
}
private @ColorInt int getButtonToggleBackgroundColor(TransportOption newTransport) {
if (newTransport.isSms()) {
return newTransport.getBackgroundColor();
} else if (recipient != null) {
return getRecipient().getChatColors().asSingleColor();
} else {
return newTransport.getBackgroundColor();
}
}
private @NonNull VoiceNotePlayerView requireVoiceNotePlayerView() {
@ -2221,12 +2251,12 @@ public class ConversationParentFragment extends Fragment
attachmentKeyboardStub.get().setWallpaperEnabled(true);
}
int toolbarColor = getResources().getColor(R.color.conversation_toolbar_color_wallpaper);
toolbar.setBackgroundColor(toolbarColor);
// TODO [alex] LargeScreenSupport -- statusBarBox
if (Build.VERSION.SDK_INT > 23) {
WindowUtil.setStatusBarColor(requireActivity().getWindow(), toolbarColor);
}
toolbarBackground.setBackgroundResource(R.color.material3_toolbar_background_wallpaper);
updateStatusBarColor(toolbarBackground.isActivated());
int toolbarTextAndIconColor = getResources().getColor(R.color.signal_colorNeutralInverse);
toolbar.setTitleTextColor(toolbarTextAndIconColor);
setToolbarActionItemTint(toolbar, toolbarTextAndIconColor);
} else {
wallpaper.setImageDrawable(null);
wallpaperDim.setVisibility(View.GONE);
@ -2235,14 +2265,56 @@ public class ConversationParentFragment extends Fragment
attachmentKeyboardStub.get().setWallpaperEnabled(false);
}
int toolbarColor = getResources().getColor(R.color.conversation_toolbar_color);
toolbar.setBackgroundColor(toolbarColor);
// TODO [alex] LargeScreenSupport -- statusBarBox
if (Build.VERSION.SDK_INT > 23) {
WindowUtil.setStatusBarColor(requireActivity().getWindow(), toolbarColor);
}
toolbarBackground.setBackgroundResource(R.color.material3_toolbar_background);
updateStatusBarColor(toolbarBackground.isActivated());
int toolbarTextAndIconColor = getResources().getColor(R.color.signal_colorOnSurface);
toolbar.setTitleTextColor(toolbarTextAndIconColor);
setToolbarActionItemTint(toolbar, toolbarTextAndIconColor);
}
fragment.onWallpaperChanged(chatWallpaper);
messageRequestBottomView.setWallpaperEnabled(chatWallpaper != null);
}
private Unit updateStatusBarColor(boolean isActive) {
// TODO [alex] LargeScreenSupport -- statusBarBox
if (Build.VERSION.SDK_INT > 23) {
boolean hasWallpaper = wallpaper.getDrawable() != null;
int toolbarColor = isActive ? getActiveToolbarColor(requireContext(), hasWallpaper)
: getInactiveToolbarColor(requireContext(), hasWallpaper);
WindowUtil.setStatusBarColor(requireActivity().getWindow(), toolbarColor);
}
return Unit.INSTANCE;
}
private static @ColorInt int getActiveToolbarColor(@NonNull Context context, boolean hasWallpaper) {
int colorRes = hasWallpaper ? R.color.conversation_toolbar_color_wallpaper_scrolled
: R.color.signal_colorSurface2;
return ContextCompat.getColor(context, colorRes);
}
private static @ColorInt int getInactiveToolbarColor(@NonNull Context context, boolean hasWallpaper) {
int colorRes = hasWallpaper ? R.color.conversation_toolbar_color_wallpaper
: R.color.signal_colorBackground;
return ContextCompat.getColor(context, colorRes);
}
private void setToolbarActionItemTint(@NonNull Toolbar toolbar, @ColorInt int tint) {
for (int i = 0; i < toolbar.getMenu().size(); i++) {
MenuItem menuItem = toolbar.getMenu().getItem(i);
MenuItemCompat.setIconTintList(menuItem, ColorStateList.valueOf(tint));
}
if (toolbar.getNavigationIcon() != null) {
toolbar.getNavigationIcon().setColorFilter(new SimpleColorFilter(tint));
}
if (toolbar.getOverflowIcon() != null) {
toolbar.getOverflowIcon().setColorFilter(new SimpleColorFilter(tint));
}
}
protected void initializeActionBar() {
@ -3547,6 +3619,16 @@ public class ConversationParentFragment extends Fragment
StickerSearchDialogFragment.show(getChildFragmentManager());
}
@Override
public void bindScrollHelper(@NonNull RecyclerView recyclerView) {
recyclerView.addOnScrollListener(material3OnScrollHelper);
}
@Override
public void onMessageDetailsFragmentDismissed() {
updateStatusBarColor(toolbarBackground.isActivated());
}
// Listeners
private final class DeleteCanceledVoiceNoteListener implements ListenableFuture.Listener<VoiceNoteDraft> {
@ -3950,6 +4032,12 @@ public class ConversationParentFragment extends Fragment
@Override
public void onMessageActionToolbarOpened() {
searchViewItem.collapseActionView();
toolbar.setVisibility(View.GONE);
}
@Override
public void onMessageActionToolbarClosed() {
toolbar.setVisibility(View.VISIBLE);
}
@Override
@ -4206,18 +4294,23 @@ public class ConversationParentFragment extends Fragment
{
Log.d(TAG, "[presentMessageRequestState] Have extra, so ignoring provided state.");
messageRequestBottomView.setVisibility(View.GONE);
inputPanel.setVisibility(View.VISIBLE);
} else if (isPushGroupV1Conversation() && !isActiveGroup()) {
Log.d(TAG, "[presentMessageRequestState] Inactive push group V1, so ignoring provided state.");
messageRequestBottomView.setVisibility(View.GONE);
inputPanel.setVisibility(View.VISIBLE);
} else if (messageData == null) {
Log.d(TAG, "[presentMessageRequestState] Null messageData. Ignoring.");
} else if (messageData.getMessageState() == MessageRequestState.NONE) {
Log.d(TAG, "[presentMessageRequestState] No message request necessary.");
messageRequestBottomView.setVisibility(View.GONE);
inputPanel.setVisibility(View.VISIBLE);
} else {
Log.d(TAG, "[presentMessageRequestState] " + messageData.getMessageState());
messageRequestBottomView.setMessageData(messageData);
messageRequestBottomView.setVisibility(View.VISIBLE);
noLongerMemberBanner.setVisibility(View.GONE);
inputPanel.setVisibility(View.GONE);
}
invalidateOptionsMenu();

Wyświetl plik

@ -13,8 +13,10 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.cardview.widget.CardView;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ColorStateListInflaterCompat;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
@ -175,14 +177,6 @@ public final class ConversationUpdateItem extends FrameLayout
textColor = ContextCompat.getColor(getContext(), R.color.core_grey_15);
}
if (!ThemeUtil.isDarkTheme(getContext())) {
if (hasWallpaper) {
actionButton.setStrokeColor(ColorStateList.valueOf(getResources().getColor(R.color.core_grey_45)));
} else {
actionButton.setStrokeColor(ColorStateList.valueOf(getResources().getColor(R.color.signal_button_secondary_stroke)));
}
}
UpdateDescription updateDescription = Objects.requireNonNull(messageRecord.getUpdateDisplayBody(getContext(), eventListener::onRecipientNameClicked));
LiveData<SpannableString> liveUpdateMessage = LiveUpdateMessage.fromMessageDescription(getContext(), updateDescription, textColor, true);
LiveData<SpannableString> spannableMessage = loading(liveUpdateMessage);
@ -195,6 +189,8 @@ public final class ConversationUpdateItem extends FrameLayout
shouldCollapse(messageRecord, nextMessageRecord),
hasWallpaper);
presentActionButton(hasWallpaper);
updateSelectedState();
}
@ -645,6 +641,16 @@ public final class ConversationUpdateItem extends FrameLayout
}
}
private void presentActionButton(boolean hasWallpaper) {
if (hasWallpaper) {
actionButton.setBackgroundTintList(AppCompatResources.getColorStateList(getContext(), R.color.conversation_update_item_button_background_wallpaper));
actionButton.setTextColor(AppCompatResources.getColorStateList(getContext(), R.color.conversation_update_item_button_text_color_wallpaper));
} else {
actionButton.setBackgroundTintList(AppCompatResources.getColorStateList(getContext(), R.color.conversation_update_item_button_background_normal));
actionButton.setTextColor(AppCompatResources.getColorStateList(getContext(), R.color.conversation_update_item_button_text_color_normal));
}
}
private static boolean isSameType(@NonNull MessageRecord current, @NonNull MessageRecord candidate) {
return (current.isGroupUpdate() && candidate.isGroupUpdate()) ||
(current.isProfileChange() && candidate.isProfileChange()) ||

Wyświetl plik

@ -16,7 +16,6 @@ import androidx.annotation.ColorInt
import com.google.common.base.Objects
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import org.signal.core.util.ColorUtil
import org.thoughtcrime.securesms.components.RotatableGradientDrawable
import org.thoughtcrime.securesms.database.model.databaseprotos.ChatColor
import org.thoughtcrime.securesms.util.customizeOnDraw
@ -77,10 +76,7 @@ class ChatColors(
}
if (linearGradient != null) {
val start = linearGradient.colors.first()
val end = linearGradient.colors.last()
return ColorUtil.blendARGB(start, end, 0.5f)
return linearGradient.colors.last()
}
throw AssertionError()

Wyświetl plik

@ -9,13 +9,9 @@ object ChatColorsPalette {
// region Default
@JvmField
val ULTRAMARINE = ChatColors.forGradient(
val ULTRAMARINE = ChatColors.forColor(
ChatColors.Id.BuiltIn,
ChatColors.LinearGradient(
180.0f,
intArrayOf(0xFF0552F0.toInt(), 0xFF2C6BED.toInt()),
floatArrayOf(0f, 1f)
)
0xFF315FF4.toInt()
)
// endregion

Wyświetl plik

@ -22,17 +22,44 @@ class Colorizer {
@ColorInt
fun getOutgoingBodyTextColor(context: Context): Int {
return ContextCompat.getColor(context, R.color.white)
return ContextCompat.getColor(context, R.color.conversation_outgoing_body_color)
}
@ColorInt
fun getOutgoingFooterTextColor(context: Context): Int {
return ContextCompat.getColor(context, R.color.conversation_item_outgoing_footer_fg)
return ContextCompat.getColor(context, R.color.conversation_outgoing_footer_color)
}
@ColorInt
fun getOutgoingFooterIconColor(context: Context): Int {
return ContextCompat.getColor(context, R.color.conversation_item_outgoing_footer_fg)
return ContextCompat.getColor(context, R.color.conversation_outgoing_footer_color)
}
@ColorInt
fun getIncomingBodyTextColor(context: Context, hasWallpaper: Boolean): Int {
return if (hasWallpaper) {
ContextCompat.getColor(context, R.color.signal_colorNeutralInverse)
} else {
ContextCompat.getColor(context, R.color.signal_colorOnSurface)
}
}
@ColorInt
fun getIncomingFooterTextColor(context: Context, hasWallpaper: Boolean): Int {
return if (hasWallpaper) {
ContextCompat.getColor(context, R.color.signal_colorNeutralVariantInverse)
} else {
ContextCompat.getColor(context, R.color.signal_colorOnSurfaceVariant)
}
}
@ColorInt
fun getIncomingFooterIconColor(context: Context, hasWallpaper: Boolean): Int {
return if (hasWallpaper) {
ContextCompat.getColor(context, R.color.signal_colorNeutralVariantInverse)
} else {
ContextCompat.getColor(context, R.color.signal_colorOnSurfaceVariant)
}
}
@ColorInt

Wyświetl plik

@ -37,7 +37,6 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton;
import org.thoughtcrime.securesms.database.SignalDatabase;
import org.thoughtcrime.securesms.util.ConversationUtil;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.task.SnackbarAsyncTask;
import org.thoughtcrime.securesms.util.views.Stub;
@ -72,14 +71,8 @@ public class ConversationListArchiveFragment extends ConversationListFragment im
coordinator = view.findViewById(R.id.coordinator);
list = view.findViewById(R.id.list);
emptyState = new Stub<>(view.findViewById(R.id.empty_state));
if (FeatureFlags.internalUser()) {
fab = view.findViewById(R.id.fab_new);
cameraFab = view.findViewById(R.id.camera_fab_new);
} else {
fab = view.findViewById(R.id.fab_old);
cameraFab = view.findViewById(R.id.camera_fab_old);
}
fab = view.findViewById(R.id.fab);
cameraFab = view.findViewById(R.id.camera_fab);
toolbar.get().setNavigationOnClickListener(v -> NavHostFragment.findNavController(this).popBackStack());
toolbar.get().setTitle(R.string.AndroidManifest_archived_conversations);

Wyświetl plik

@ -57,6 +57,7 @@ import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.Toolbar;
import androidx.appcompat.widget.TooltipCompat;
import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;
@ -76,6 +77,7 @@ import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.signal.core.util.DimensionUnit;
import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.concurrent.SimpleTask;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.MainFragment;
import org.thoughtcrime.securesms.MainNavigator;
@ -85,8 +87,8 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.badges.models.Badge;
import org.thoughtcrime.securesms.badges.self.expired.CantProcessSubscriptionPaymentBottomSheetDialogFragment;
import org.thoughtcrime.securesms.badges.self.expired.ExpiredBadgeBottomSheetDialogFragment;
import org.thoughtcrime.securesms.components.Material3SearchToolbar;
import org.thoughtcrime.securesms.components.RatingManager;
import org.thoughtcrime.securesms.components.SearchToolbar;
import org.thoughtcrime.securesms.components.UnreadPaymentsView;
import org.thoughtcrime.securesms.components.menu.ActionItem;
import org.thoughtcrime.securesms.components.menu.SignalBottomActionBar;
@ -117,6 +119,7 @@ import org.thoughtcrime.securesms.insights.InsightsLauncher;
import org.thoughtcrime.securesms.jobs.ServiceOutageDetectionJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.lock.v2.CreateKbsPinActivity;
import org.thoughtcrime.securesms.main.Material3OnScrollHelperBinder;
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity;
import org.thoughtcrime.securesms.megaphone.Megaphone;
import org.thoughtcrime.securesms.megaphone.MegaphoneActionController;
@ -143,7 +146,6 @@ import org.thoughtcrime.securesms.util.AppForegroundObserver;
import org.thoughtcrime.securesms.util.AppStartup;
import org.thoughtcrime.securesms.util.BottomSheetUtil;
import org.thoughtcrime.securesms.util.ConversationUtil;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.LifecycleDisposable;
import org.thoughtcrime.securesms.util.PlayStoreUtil;
import org.thoughtcrime.securesms.util.ServiceUtil;
@ -156,7 +158,6 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.WindowUtil;
import org.signal.core.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.task.SnackbarAsyncTask;
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import org.thoughtcrime.securesms.util.views.Stub;
@ -203,7 +204,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
private TextView searchEmptyState;
private PulsingFloatingActionButton fab;
private PulsingFloatingActionButton cameraFab;
private View toolbarShadow;
private ConversationListViewModel viewModel;
private RecyclerView.Adapter activeAdapter;
private ConversationListAdapter defaultAdapter;
@ -254,27 +254,20 @@ public class ConversationListFragment extends MainFragment implements ActionMode
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
coordinator = view.findViewById(R.id.coordinator);
list = view.findViewById(R.id.list);
searchEmptyState = view.findViewById(R.id.search_no_results);
toolbarShadow = view.findViewById(R.id.conversation_list_toolbar_shadow);
bottomActionBar = view.findViewById(R.id.conversation_list_bottom_action_bar);
reminderView = new Stub<>(view.findViewById(R.id.reminder));
emptyState = new Stub<>(view.findViewById(R.id.empty_state));
megaphoneContainer = new Stub<>(view.findViewById(R.id.megaphone_container));
paymentNotificationView = new Stub<>(view.findViewById(R.id.payments_notification));
voiceNotePlayerViewStub = new Stub<>(view.findViewById(R.id.voice_note_player));
coordinator = view.findViewById(R.id.coordinator);
list = view.findViewById(R.id.list);
searchEmptyState = view.findViewById(R.id.search_no_results);
bottomActionBar = view.findViewById(R.id.conversation_list_bottom_action_bar);
reminderView = new Stub<>(view.findViewById(R.id.reminder));
emptyState = new Stub<>(view.findViewById(R.id.empty_state));
megaphoneContainer = new Stub<>(view.findViewById(R.id.megaphone_container));
paymentNotificationView = new Stub<>(view.findViewById(R.id.payments_notification));
voiceNotePlayerViewStub = new Stub<>(view.findViewById(R.id.voice_note_player));
fab = view.findViewById(R.id.fab);
cameraFab = view.findViewById(R.id.camera_fab);
if (FeatureFlags.internalUser()) {
fab = view.findViewById(R.id.fab_new);
cameraFab = view.findViewById(R.id.camera_fab_new);
fab.setVisibility(View.VISIBLE);
cameraFab.setVisibility(View.VISIBLE);
} else {
fab = view.findViewById(R.id.fab_old);
cameraFab = view.findViewById(R.id.camera_fab_old);
}
fab.setVisibility(View.VISIBLE);
cameraFab.setVisibility(View.VISIBLE);
fab.show();
cameraFab.show();
@ -284,7 +277,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
list.setLayoutManager(new LinearLayoutManager(requireActivity()));
list.setItemAnimator(itemAnimator);
list.addOnScrollListener(new ScrollListener());
list.addItemDecoration(archiveDecoration);
snapToTopDataObserver = new SnapToTopDataObserver(list);
@ -331,14 +323,16 @@ public class ConversationListFragment extends MainFragment implements ActionMode
lifecycleDisposable.bindTo(getViewLifecycleOwner());
lifecycleDisposable.add(conversationListTabsViewModel.getTabClickEvents().filter(tab -> tab == ConversationListTab.CHATS)
.subscribe(unused -> {
LinearLayoutManager layoutManager = (LinearLayoutManager) list.getLayoutManager();
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
LinearLayoutManager layoutManager = (LinearLayoutManager) list.getLayoutManager();
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
if (firstVisibleItemPosition <= LIST_SMOOTH_SCROLL_TO_TOP_THRESHOLD) {
list.smoothScrollToPosition(0);
} else {
list.scrollToPosition(0);
}
}));
requireCallback().bindScrollHelper(list);
}
@Override
@ -346,7 +340,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
coordinator = null;
list = null;
searchEmptyState = null;
toolbarShadow = null;
bottomActionBar = null;
reminderView = null;
emptyState = null;
@ -377,7 +370,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
InsightsLauncher.showInsightsModal(requireContext(), requireFragmentManager());
}
if ((!requireCallback().getSearchToolbar().resolved() || !requireCallback().getSearchToolbar().get().isVisible()) && list.getAdapter() != defaultAdapter) {
if ((!requireCallback().getSearchToolbar().resolved() || !(requireCallback().getSearchToolbar().get().getVisibility() == View.VISIBLE)) && list.getAdapter() != defaultAdapter) {
list.removeItemDecoration(searchAdapterDecoration);
setAdapter(defaultAdapter);
}
@ -401,10 +394,11 @@ public class ConversationListFragment extends MainFragment implements ActionMode
long subscriptionFailureWatermark = SignalStore.donationsValues().getUnexpectedSubscriptionCancelationWatermark();
boolean isWatermarkPriorToTimestamp = subscriptionFailureWatermark < subscriptionFailureTimestamp;
if (unexpectedSubscriptionCancellation != null &&
if (unexpectedSubscriptionCancellation != null &&
!SignalStore.donationsValues().isUserManuallyCancelled() &&
SignalStore.donationsValues().showCantProcessDialog() &&
isWatermarkPriorToTimestamp) {
SignalStore.donationsValues().showCantProcessDialog() &&
isWatermarkPriorToTimestamp)
{
Log.w(TAG, "Displaying bottom sheet for unexpected cancellation: " + unexpectedSubscriptionCancellation, true);
new CantProcessSubscriptionPaymentBottomSheetDialogFragment().show(getChildFragmentManager(), BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG);
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationWatermark(subscriptionFailureTimestamp);
@ -469,20 +463,31 @@ public class ConversationListFragment extends MainFragment implements ActionMode
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case R.id.menu_new_group: handleCreateGroup(); return true;
case R.id.menu_settings: handleDisplaySettings(); return true;
case R.id.menu_clear_passphrase: handleClearPassphrase(); return true;
case R.id.menu_mark_all_read: handleMarkAllRead(); return true;
case R.id.menu_invite: handleInvite(); return true;
case R.id.menu_insights: handleInsights(); return true;
case R.id.menu_notification_profile: handleNotificationProfile(); return true;
case R.id.menu_new_group:
handleCreateGroup(); return true;
case R.id.menu_settings:
handleDisplaySettings(); return true;
case R.id.menu_clear_passphrase:
handleClearPassphrase(); return true;
case R.id.menu_mark_all_read:
handleMarkAllRead(); return true;
case R.id.menu_invite:
handleInvite(); return true;
case R.id.menu_insights:
handleInsights(); return true;
case R.id.menu_notification_profile:
handleNotificationProfile(); return true;
}
return false;
}
private boolean isSearchOpen() {
return (requireCallback().getSearchToolbar().resolved() && requireCallback().getSearchToolbar().get().isVisible()) || activeAdapter == searchAdapter;
return isSearchVisible() || activeAdapter == searchAdapter;
}
private boolean isSearchVisible() {
return (requireCallback().getSearchToolbar().resolved() && requireCallback().getSearchToolbar().get().getVisibility() == View.VISIBLE);
}
private boolean closeSearchIfOpen() {
@ -509,7 +514,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
}
if (requestCode == CreateKbsPinActivity.REQUEST_NEW_PIN) {
Snackbar.make(fab, R.string.ConfirmKbsPinFragment__pin_created, Snackbar.LENGTH_LONG).setTextColor(Color.WHITE).show();
Snackbar.make(fab, R.string.ConfirmKbsPinFragment__pin_created, Snackbar.LENGTH_LONG).show();
viewModel.onMegaphoneCompleted(Megaphones.Event.PINS_FOR_ALL);
}
}
@ -568,9 +573,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
@Override
public void onMegaphoneToastRequested(@NonNull String string) {
Snackbar.make(fab, string, Snackbar.LENGTH_LONG)
.setTextColor(Color.WHITE)
.show();
Snackbar.make(fab, string, Snackbar.LENGTH_LONG).show();
}
@Override
@ -616,7 +619,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
requireCallback().getSearchToolbar().get().display(requireCallback().getSearchAction().getX() + (requireCallback().getSearchAction().getWidth() / 2.0f),
requireCallback().getSearchAction().getY() + (requireCallback().getSearchAction().getHeight() / 2.0f));
requireCallback().getSearchToolbar().get().setListener(new SearchToolbar.SearchListener() {
requireCallback().getSearchToolbar().get().setListener(new Material3SearchToolbar.Listener() {
@Override
public void onSearchTextChange(String text) {
String trimmed = text.trim();
@ -748,7 +751,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
}
@Override
public void onBackground() { }
public void onBackground() {}
};
viewModel.getUnreadPaymentsLiveData().observe(getViewLifecycleOwner(), this::onUnreadPaymentsChanged);
@ -1027,7 +1030,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
Snackbar.make(fab,
getString(R.string.conversation_list__you_can_only_pin_up_to_d_chats, MAXIMUM_PINNED_CONVERSATIONS),
Snackbar.LENGTH_LONG)
.setTextColor(Color.WHITE)
.show();
endActionModeIfActive();
return;
@ -1273,16 +1275,16 @@ public class ConversationListFragment extends MainFragment implements ActionMode
viewModel.endSelection();
if (Build.VERSION.SDK_INT >= 21) {
TypedArray color = getActivity().getTheme().obtainStyledAttributes(new int[] {android.R.attr.statusBarColor});
TypedArray color = getActivity().getTheme().obtainStyledAttributes(new int[] { android.R.attr.statusBarColor });
WindowUtil.setStatusBarColor(getActivity().getWindow(), color.getColor(0, Color.BLACK));
color.recycle();
}
if (Build.VERSION.SDK_INT >= 23) {
TypedArray lightStatusBarAttr = getActivity().getTheme().obtainStyledAttributes(new int[] {android.R.attr.windowLightStatusBar});
TypedArray lightStatusBarAttr = getActivity().getTheme().obtainStyledAttributes(new int[] { android.R.attr.windowLightStatusBar });
int current = getActivity().getWindow().getDecorView().getSystemUiVisibility();
int statusBarMode = lightStatusBarAttr.getBoolean(0, false) ? current | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
: current & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
int statusBarMode = lightStatusBarAttr.getBoolean(0, false) ? current | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
: current & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
getActivity().getWindow().getDecorView().setSystemUiVisibility(statusBarMode);
@ -1507,10 +1509,10 @@ public class ConversationListFragment extends MainFragment implements ActionMode
@Override
public int getSwipeDirs(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
if (viewHolder.itemView instanceof ConversationListItemAction ||
if (viewHolder.itemView instanceof ConversationListItemAction ||
viewHolder instanceof ConversationListAdapter.HeaderViewHolder ||
actionMode != null ||
viewHolder.itemView.isSelected() ||
actionMode != null ||
viewHolder.itemView.isSelected() ||
activeAdapter == searchAdapter)
{
return 0;
@ -1543,8 +1545,8 @@ public class ConversationListFragment extends MainFragment implements ActionMode
}
private void onTrueSwipe(RecyclerView.ViewHolder viewHolder) {
final long threadId = ((ConversationListItem)viewHolder.itemView).getThreadId();
final int unreadCount = ((ConversationListItem)viewHolder.itemView).getUnreadCount();
final long threadId = ((ConversationListItem) viewHolder.itemView).getThreadId();
final int unreadCount = ((ConversationListItem) viewHolder.itemView).getUnreadCount();
onItemSwiped(threadId, unreadCount);
}
@ -1577,7 +1579,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
if (absoluteDx > 0) {
if (archiveDrawable == null) {
archiveDrawable = Objects.requireNonNull(AppCompatResources.getDrawable(requireContext(), getArchiveIconRes()));
archiveDrawable.setColorFilter(new SimpleColorFilter(Color.WHITE));
archiveDrawable.setColorFilter(new SimpleColorFilter(ContextCompat.getColor(requireContext(), R.color.signal_colorOnPrimary)));
archiveDrawable.setBounds(0, 0, archiveDrawable.getIntrinsicWidth(), archiveDrawable.getIntrinsicHeight());
}
@ -1628,21 +1630,6 @@ public class ConversationListFragment extends MainFragment implements ActionMode
}
}
private class ScrollListener extends RecyclerView.OnScrollListener {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (recyclerView.canScrollVertically(-1)) {
if (toolbarShadow.getVisibility() != View.VISIBLE) {
ViewUtil.fadeIn(toolbarShadow, 250);
}
} else {
if (toolbarShadow.getVisibility() != View.GONE) {
ViewUtil.fadeOut(toolbarShadow, 250);
}
}
}
}
private final class VoiceNotePlayerViewListener implements VoiceNotePlayerView.Listener {
@Override
@ -1673,18 +1660,27 @@ public class ConversationListFragment extends MainFragment implements ActionMode
}
}
public interface Callback {
public interface Callback extends Material3OnScrollHelperBinder {
@NonNull Toolbar getToolbar();
@NonNull ImageView getSearchAction();
@NonNull Stub<SearchToolbar> getSearchToolbar();
@NonNull Stub<Material3SearchToolbar> getSearchToolbar();
@NonNull View getUnreadPaymentsDot();
@NonNull Stub<Toolbar> getBasicToolbar();
void updateNotificationProfileStatus(@NonNull List<NotificationProfile> notificationProfiles);
void updateProxyStatus(@NonNull WebSocketConnectionState state);
void onSearchOpened();
void onSearchClosed();
void onMultiSelectStarted();
void onMultiSelectFinished();
}
}

Wyświetl plik

@ -149,7 +149,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
this.checkContainer = findViewById(R.id.conversation_list_item_check_container);
this.uncheckedView = findViewById(R.id.conversation_list_item_unchecked);
this.checkedView = findViewById(R.id.conversation_list_item_checked);
this.thumbSize = (int) DimensionUnit.SP.toPixels(20f);
this.thumbSize = (int) DimensionUnit.SP.toPixels(16f);
this.thumbTarget = new GlideLiveDataTarget(thumbSize, thumbSize);
getLayoutTransition().setDuration(150);
@ -622,7 +622,7 @@ public final class ConversationListItem extends ConstraintLayout implements Bind
RoundedDrawable drawable = RoundedDrawable.fromBitmap(bitmap);
drawable.setBounds(0, 0, thumbSize, thumbSize);
drawable.setCornerRadius(DimensionUnit.DP.toPixels(4));
drawable.setCornerRadius(DimensionUnit.DP.toPixels(2));
drawable.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
CharSequence thumbnailSpan = SpanUtil.buildCenteredImageSpan(drawable);

Wyświetl plik

@ -224,10 +224,10 @@ public class DeleteAccountFragment extends Fragment {
private void handleEvent(@NonNull DeleteAccountEvent deleteAccountEvent) {
switch (deleteAccountEvent.getType()) {
case NO_COUNTRY_CODE:
Snackbar.make(requireView(), R.string.DeleteAccountFragment__no_country_code, Snackbar.LENGTH_SHORT).setTextColor(Color.WHITE).show();
Snackbar.make(requireView(), R.string.DeleteAccountFragment__no_country_code, Snackbar.LENGTH_SHORT).show();
break;
case NO_NATIONAL_NUMBER:
Snackbar.make(requireView(), R.string.DeleteAccountFragment__no_number, Snackbar.LENGTH_SHORT).setTextColor(Color.WHITE).show();
Snackbar.make(requireView(), R.string.DeleteAccountFragment__no_number, Snackbar.LENGTH_SHORT).show();
break;
case NOT_A_MATCH:
new AlertDialog.Builder(requireContext())

Wyświetl plik

@ -13,7 +13,6 @@ import androidx.lifecycle.ViewModelProviders;
import com.annimon.stream.Collectors;
import com.annimon.stream.Stream;
import com.dd.CircularProgressButton;
import org.thoughtcrime.securesms.MainActivity;
import org.thoughtcrime.securesms.PassphraseRequiredActivity;
@ -27,6 +26,7 @@ import org.thoughtcrime.securesms.groups.ui.GroupMemberListView;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import java.util.Objects;
@ -34,10 +34,10 @@ public final class ChooseNewAdminActivity extends PassphraseRequiredActivity {
private static final String EXTRA_GROUP_ID = "group_id";
private ChooseNewAdminViewModel viewModel;
private GroupMemberListView groupList;
private CircularProgressButton done;
private GroupId.V2 groupId;
private ChooseNewAdminViewModel viewModel;
private GroupMemberListView groupList;
private CircularProgressMaterialButton done;
private GroupId.V2 groupId;
private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme();
@ -70,7 +70,6 @@ public final class ChooseNewAdminActivity extends PassphraseRequiredActivity {
groupList = findViewById(R.id.choose_new_admin_group_list);
done = findViewById(R.id.choose_new_admin_done);
done.setIndeterminateProgressMode(true);
initializeViewModel();
@ -80,8 +79,7 @@ public final class ChooseNewAdminActivity extends PassphraseRequiredActivity {
.collect(Collectors.toSet())));
done.setOnClickListener(v -> {
done.setClickable(false);
done.setProgress(50);
done.setSpinning();
viewModel.updateAdminsAndLeave(this::handleUpdateAndLeaveResult);
});
}
@ -116,8 +114,7 @@ public final class ChooseNewAdminActivity extends PassphraseRequiredActivity {
startActivity(MainActivity.clearTop(this));
finish();
} else {
done.setClickable(true);
done.setProgress(0);
done.cancelSpinning();
//noinspection ConstantConditions
Toast.makeText(this, GroupErrors.getUserDisplayMessage(updateResult.getFailureReason()), Toast.LENGTH_LONG).show();
}

Wyświetl plik

@ -1,17 +1,18 @@
package org.thoughtcrime.securesms.groups.ui.creategroup;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import org.signal.core.util.concurrent.SimpleTask;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.ContactSelectionActivity;
import org.thoughtcrime.securesms.ContactSelectionListFragment;
@ -25,8 +26,6 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.Stopwatch;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.signal.core.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import java.io.IOException;
@ -42,9 +41,8 @@ public class CreateGroupActivity extends ContactSelectionActivity {
private static final short REQUEST_CODE_ADD_DETAILS = 17275;
private ExtendedFloatingActionButton next;
private ValueAnimator padStart;
private ValueAnimator padEnd;
private MaterialButton skip;
private FloatingActionButton next;
public static Intent newIntent(@NonNull Context context) {
Intent intent = new Intent(context, CreateGroupActivity.class);
@ -67,9 +65,11 @@ public class CreateGroupActivity extends ContactSelectionActivity {
assert getSupportActionBar() != null;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
skip = findViewById(R.id.skip);
next = findViewById(R.id.next);
extendSkip();
skip.setOnClickListener(v -> handleNextPressed());
next.setOnClickListener(v -> handleNextPressed());
}
@ -125,33 +125,13 @@ public class CreateGroupActivity extends ContactSelectionActivity {
}
private void extendSkip() {
next.setIconGravity(MaterialButton.ICON_GRAVITY_END);
next.extend();
animatePadding(24, 18);
skip.setVisibility(View.VISIBLE);
next.setVisibility(View.GONE);
}
private void shrinkSkip() {
next.setIconGravity(MaterialButton.ICON_GRAVITY_START);
next.shrink();
animatePadding(16, 16);
}
private void animatePadding(int startDp, int endDp) {
if (padStart != null) padStart.cancel();
padStart = ValueAnimator.ofInt(next.getPaddingStart(), ViewUtil.dpToPx(startDp)).setDuration(200);
padStart.addUpdateListener(animation -> {
ViewUtil.setPaddingStart(next, (Integer) animation.getAnimatedValue());
});
padStart.start();
if (padEnd != null) padEnd.cancel();
padEnd = ValueAnimator.ofInt(next.getPaddingEnd(), ViewUtil.dpToPx(endDp)).setDuration(200);
padEnd.addUpdateListener(animation -> {
ViewUtil.setPaddingEnd(next, (Integer) animation.getAnimatedValue());
});
padEnd.start();
skip.setVisibility(View.GONE);
next.setVisibility(View.VISIBLE);
}
private void handleNextPressed() {

Wyświetl plik

@ -19,14 +19,15 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.ViewModelProviders;
import androidx.navigation.Navigation;
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
import com.airbnb.lottie.SimpleColorFilter;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.dd.CircularProgressButton;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.signal.core.util.EditTextUtil;
@ -49,7 +50,7 @@ import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
import org.thoughtcrime.securesms.util.text.AfterTextChanged;
import org.thoughtcrime.securesms.util.views.LearnMoreTextView;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import java.util.Arrays;
import java.util.List;
@ -60,13 +61,13 @@ public class AddGroupDetailsFragment extends LoggingFragment {
private static final int AVATAR_PLACEHOLDER_INSET_DP = 18;
private static final short REQUEST_DISAPPEARING_TIMER = 28621;
private CircularProgressButton create;
private Callback callback;
private AddGroupDetailsViewModel viewModel;
private Drawable avatarPlaceholder;
private EditText name;
private Toolbar toolbar;
private View disappearingMessagesRow;
private CircularProgressMaterialButton create;
private Callback callback;
private AddGroupDetailsViewModel viewModel;
private Drawable avatarPlaceholder;
private EditText name;
private Toolbar toolbar;
private View disappearingMessagesRow;
@Override
public void onAttach(@NonNull Context context) {
@ -94,17 +95,17 @@ public class AddGroupDetailsFragment extends LoggingFragment {
toolbar = view.findViewById(R.id.toolbar);
disappearingMessagesRow = view.findViewById(R.id.group_disappearing_messages_row);
setCreateEnabled(false, false);
setCreateEnabled(false);
GroupMemberListView members = view.findViewById(R.id.member_list);
ImageView avatar = view.findViewById(R.id.group_avatar);
View mmsWarning = view.findViewById(R.id.mms_warning);
LearnMoreTextView gv2Warning = view.findViewById(R.id.gv2_warning);
View addLater = view.findViewById(R.id.add_later);
TextView disappearingMessageValue = view.findViewById(R.id.group_disappearing_messages_value);
members.initializeAdapter(getViewLifecycleOwner());
avatarPlaceholder = VectorDrawableCompat.create(getResources(), R.drawable.ic_camera_outline_32_ultramarine, requireActivity().getTheme());
avatarPlaceholder = Objects.requireNonNull(VectorDrawableCompat.create(getResources(), R.drawable.ic_camera_outline_24, requireActivity().getTheme()));
avatarPlaceholder.setColorFilter(new SimpleColorFilter(ContextCompat.getColor(requireContext(), R.color.signal_icon_tint_primary)));
if (savedInstanceState == null) {
avatar.setImageDrawable(new InsetDrawable(avatarPlaceholder, ViewUtil.dpToPx(AVATAR_PLACEHOLDER_INSET_DP)));
@ -122,7 +123,7 @@ public class AddGroupDetailsFragment extends LoggingFragment {
addLater.setVisibility(list.isEmpty() ? View.VISIBLE : View.GONE);
members.setMembers(list);
});
viewModel.getCanSubmitForm().observe(getViewLifecycleOwner(), isFormValid -> setCreateEnabled(isFormValid, true));
viewModel.getCanSubmitForm().observe(getViewLifecycleOwner(), this::setCreateEnabled);
viewModel.getIsMms().observe(getViewLifecycleOwner(), isMms -> {
disappearingMessagesRow.setVisibility(isMms ? View.GONE : View.VISIBLE);
mmsWarning.setVisibility(isMms ? View.VISIBLE : View.GONE);
@ -205,9 +206,11 @@ public class AddGroupDetailsFragment extends LoggingFragment {
}
private void handleCreateClicked() {
create.setClickable(false);
create.setIndeterminateProgressMode(true);
create.setProgress(50);
if (!create.isClickable()) {
return;
}
create.setSpinning();
viewModel.create();
}
@ -254,15 +257,12 @@ public class AddGroupDetailsFragment extends LoggingFragment {
.show();
}
private void setCreateEnabled(boolean isEnabled, boolean animate) {
if (create.isEnabled() == isEnabled) {
private void setCreateEnabled(boolean isEnabled) {
if (create.isClickable() == isEnabled) {
return;
}
create.setEnabled(isEnabled);
create.animate()
.setDuration(animate ? 300 : 0)
.alpha(isEnabled ? 1f : 0.5f);
create.setClickable(isEnabled);
}
private void showAvatarPicker() {

Wyświetl plik

@ -10,6 +10,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.SwitchCompat;
import androidx.constraintlayout.widget.Group;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProviders;
@ -35,8 +36,8 @@ public final class GroupLinkInviteFriendsBottomSheetDialogFragment extends Botto
private Button groupLinkEnableAndShareButton;
private Button groupLinkShareButton;
private View memberApprovalRow;
private View memberApprovalRow2;
private Group controlGroup;
private View controlOutline;
private SwitchCompat memberApprovalSwitch;
private SimpleProgressDialog.DismissibleDialog busyDialog;
@ -68,8 +69,8 @@ public final class GroupLinkInviteFriendsBottomSheetDialogFragment extends Botto
groupLinkEnableAndShareButton = view.findViewById(R.id.group_link_enable_and_share_button);
groupLinkShareButton = view.findViewById(R.id.group_link_share_button);
memberApprovalRow = view.findViewById(R.id.group_link_enable_and_share_approve_new_members_row);
memberApprovalRow2 = view.findViewById(R.id.group_link_enable_and_share_approve_new_members_row2);
controlGroup = view.findViewById(R.id.control_group);
controlOutline = view.findViewById(R.id.group_link_enable_and_share_approve_outline);
memberApprovalSwitch = view.findViewById(R.id.group_link_enable_and_share_approve_new_members_switch);
view.findViewById(R.id.group_link_enable_and_share_cancel_button).setOnClickListener(v -> dismiss());
@ -91,20 +92,17 @@ public final class GroupLinkInviteFriendsBottomSheetDialogFragment extends Botto
if (groupLinkUrlAndStatus.isEnabled()) {
groupLinkShareButton.setVisibility(View.VISIBLE);
groupLinkEnableAndShareButton.setVisibility(View.INVISIBLE);
memberApprovalRow.setVisibility(View.GONE);
memberApprovalRow2.setVisibility(View.GONE);
controlGroup.setVisibility(View.GONE);
groupLinkShareButton.setOnClickListener(v -> shareGroupLinkAndDismiss(groupId));
} else {
memberApprovalRow.setVisibility(View.VISIBLE);
memberApprovalRow2.setVisibility(View.VISIBLE);
controlGroup.setVisibility(View.VISIBLE);
groupLinkEnableAndShareButton.setVisibility(View.VISIBLE);
groupLinkShareButton.setVisibility(View.INVISIBLE);
}
});
memberApprovalRow.setOnClickListener(v -> viewModel.toggleMemberApproval());
controlOutline.setOnClickListener(v -> viewModel.toggleMemberApproval());
viewModel.getMemberApproval()
.observe(getViewLifecycleOwner(), enabled -> memberApprovalSwitch.setChecked(enabled));

Wyświetl plik

@ -21,7 +21,6 @@ import androidx.annotation.StringRes;
import androidx.lifecycle.ViewModelProviders;
import com.annimon.stream.Stream;
import com.dd.CircularProgressButton;
import org.signal.core.util.ResourceUtil;
import org.thoughtcrime.securesms.LoggingFragment;
@ -31,6 +30,7 @@ import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.SupportEmailUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.text.AfterTextChanged;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import java.util.ArrayList;
import java.util.List;
@ -41,16 +41,16 @@ public class HelpFragment extends LoggingFragment {
public static final int PAYMENT_INDEX = 6;
public static final int DONATION_INDEX = 7;
private EditText problem;
private CheckBox includeDebugLogs;
private View debugLogInfo;
private View faq;
private CircularProgressButton next;
private View toaster;
private List<EmojiImageView> emoji;
private HelpViewModel helpViewModel;
private Spinner categorySpinner;
private ArrayAdapter<CharSequence> categoryAdapter;
private EditText problem;
private CheckBox includeDebugLogs;
private View debugLogInfo;
private View faq;
private CircularProgressMaterialButton next;
private View toaster;
private List<EmojiImageView> emoji;
private HelpViewModel helpViewModel;
private Spinner categorySpinner;
private ArrayAdapter<CharSequence> categoryAdapter;
@Override
public @Nullable View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@ -69,7 +69,7 @@ public class HelpFragment extends LoggingFragment {
public void onResume() {
super.onResume();
cancelSpinning(next);
next.cancelSpinning();
problem.setEnabled(true);
}
@ -161,7 +161,7 @@ public class HelpFragment extends LoggingFragment {
}
private void submitForm() {
setSpinning(next);
next.setSpinning();
problem.setEnabled(false);
helpViewModel.onSubmitClicked(includeDebugLogs.isChecked()).observe(getViewLifecycleOwner(), result -> {
@ -220,22 +220,6 @@ public class HelpFragment extends LoggingFragment {
suffix.toString());
}
private static void setSpinning(@Nullable CircularProgressButton button) {
if (button != null) {
button.setClickable(false);
button.setIndeterminateProgressMode(true);
button.setProgress(50);
}
}
private static void cancelSpinning(@Nullable CircularProgressButton button) {
if (button != null) {
button.setProgress(0);
button.setIndeterminateProgressMode(false);
button.setClickable(true);
}
}
private enum Feeling {
ECSTATIC(R.id.help_fragment_emoji_5, R.string.HelpFragment__emoji_5, "\ud83d\ude00"),
HAPPY(R.id.help_fragment_emoji_4, R.string.HelpFragment__emoji_4, "\ud83d\ude42"),

Wyświetl plik

@ -20,8 +20,6 @@ import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.dd.CircularProgressButton;
import org.thoughtcrime.securesms.BaseActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.DynamicTheme;
@ -29,6 +27,7 @@ import org.thoughtcrime.securesms.util.LongClickCopySpan;
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import org.thoughtcrime.securesms.util.views.SimpleProgressDialog;
import java.util.List;
@ -39,12 +38,12 @@ public class SubmitDebugLogActivity extends BaseActivity implements SubmitDebugL
private SubmitDebugLogAdapter adapter;
private SubmitDebugLogViewModel viewModel;
private View warningBanner;
private View editBanner;
private CircularProgressButton submitButton;
private AlertDialog loadingDialog;
private View scrollToBottomButton;
private View scrollToTopButton;
private View warningBanner;
private View editBanner;
private CircularProgressMaterialButton submitButton;
private AlertDialog loadingDialog;
private View scrollToBottomButton;
private View scrollToTopButton;
private MenuItem editMenuItem;
private MenuItem doneMenuItem;
@ -263,9 +262,7 @@ public class SubmitDebugLogActivity extends BaseActivity implements SubmitDebugL
}
private void onSubmitClicked() {
submitButton.setClickable(false);
submitButton.setIndeterminateProgressMode(true);
submitButton.setProgress(50);
submitButton.setSpinning();
viewModel.onSubmitClicked().observe(this, result -> {
if (result.isPresent()) {
@ -274,9 +271,7 @@ public class SubmitDebugLogActivity extends BaseActivity implements SubmitDebugL
Toast.makeText(this, R.string.SubmitDebugLogActivity_failed_to_submit_logs, Toast.LENGTH_LONG).show();
}
submitButton.setClickable(true);
submitButton.setIndeterminateProgressMode(false);
submitButton.setProgress(0);
submitButton.cancelSpinning();
});
}
}

Wyświetl plik

@ -17,12 +17,13 @@ import androidx.navigation.NavDestination
import androidx.navigation.Navigator
import androidx.navigation.findNavController
import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.recyclerview.widget.RecyclerView
import org.signal.core.util.concurrent.SimpleTask
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.MainActivity
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.badges.BadgeImageView
import org.thoughtcrime.securesms.components.SearchToolbar
import org.thoughtcrime.securesms.components.Material3SearchToolbar
import org.thoughtcrime.securesms.components.TooltipPopup
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
import org.thoughtcrime.securesms.components.settings.app.notifications.manual.NotificationProfileSelectionFragment
@ -36,6 +37,7 @@ import org.thoughtcrime.securesms.stories.tabs.ConversationListTabsState
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabsViewModel
import org.thoughtcrime.securesms.util.AvatarUtil
import org.thoughtcrime.securesms.util.BottomSheetUtil
import org.thoughtcrime.securesms.util.Material3OnScrollHelper
import org.thoughtcrime.securesms.util.TopToastPopup
import org.thoughtcrime.securesms.util.TopToastPopup.Companion.show
import org.thoughtcrime.securesms.util.Util
@ -45,7 +47,7 @@ import org.thoughtcrime.securesms.util.views.Stub
import org.thoughtcrime.securesms.util.visible
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState
class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_fragment), ConversationListFragment.Callback {
class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_fragment), ConversationListFragment.Callback, Material3OnScrollHelperBinder {
companion object {
private val TAG = Log.tag(MainActivityListHostFragment::class.java)
@ -53,11 +55,12 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
private val conversationListTabsViewModel: ConversationListTabsViewModel by viewModels(ownerProducer = { requireActivity() })
private lateinit var _toolbarBackground: View
private lateinit var _toolbar: Toolbar
private lateinit var _basicToolbar: Stub<Toolbar>
private lateinit var notificationProfileStatus: ImageView
private lateinit var proxyStatus: ImageView
private lateinit var _searchToolbar: Stub<SearchToolbar>
private lateinit var _searchToolbar: Stub<Material3SearchToolbar>
private lateinit var _searchAction: ImageView
private lateinit var _unreadPaymentsDot: View
@ -72,6 +75,7 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
_toolbarBackground = view.findViewById(R.id.toolbar_background)
_toolbar = view.findViewById(R.id.toolbar)
_basicToolbar = Stub(view.findViewById(R.id.toolbar_basic_stub))
notificationProfileStatus = view.findViewById(R.id.conversation_list_notification_profile_status)
@ -101,8 +105,8 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
if (state.tab == ConversationListTab.CHATS) {
return
} else {
val cameraFab = requireView().findViewById<View>(R.id.camera_fab_new)
val newConvoFab = requireView().findViewById<View>(R.id.fab_new)
val cameraFab = requireView().findViewById<View>(R.id.camera_fab)
val newConvoFab = requireView().findViewById<View>(R.id.fab)
val extras: Navigator.Extras? = if (cameraFab == null || newConvoFab == null) {
null
@ -187,7 +191,7 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
return _searchAction
}
override fun getSearchToolbar(): Stub<SearchToolbar> {
override fun getSearchToolbar(): Stub<Material3SearchToolbar> {
return _searchToolbar
}
@ -208,10 +212,12 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
}
override fun onMultiSelectStarted() {
_toolbar.visible = false
conversationListTabsViewModel.onMultiSelectStarted()
}
override fun onMultiSelectFinished() {
_toolbar.visible = true
conversationListTabsViewModel.onMultiSelectFinished()
}
@ -313,4 +319,14 @@ class MainActivityListHostFragment : Fragment(R.layout.main_activity_list_host_f
}
}
}
override fun bindScrollHelper(recyclerView: RecyclerView) {
recyclerView.addOnScrollListener(
Material3OnScrollHelper(
requireActivity(),
listOf(_toolbarBackground),
listOf(_searchToolbar, _basicToolbar)
)
)
}
}

Wyświetl plik

@ -0,0 +1,7 @@
package org.thoughtcrime.securesms.main
import androidx.recyclerview.widget.RecyclerView
interface Material3OnScrollHelperBinder {
fun bindScrollHelper(recyclerView: RecyclerView)
}

Wyświetl plik

@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.messagedetails;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.FrameLayout;
@ -12,7 +13,6 @@ import androidx.recyclerview.widget.RecyclerView;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.FullScreenDialogFragment;
import org.thoughtcrime.securesms.components.recyclerview.ToolbarShadowAnimationHelper;
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
import org.thoughtcrime.securesms.conversation.colors.RecyclerViewColorizer;
import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog;
@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.messagedetails.MessageDetailsViewModel.Factory
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.Material3OnScrollHelper;
import java.util.ArrayList;
import java.util.Collection;
@ -87,6 +88,17 @@ public final class MessageDetailsFragment extends FullScreenDialogFragment {
adapter.pauseMessageExpirationTimer();
}
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
super.onDismiss(dialog);
if (getActivity() instanceof Callback) {
((Callback) getActivity()).onMessageDetailsFragmentDismissed();
} else if (getParentFragment() instanceof Callback) {
((Callback) getParentFragment()).onMessageDetailsFragmentDismissed();
}
}
private void initializeList(@NonNull View view) {
RecyclerView list = view.findViewById(R.id.message_details_list);
View toolbarShadow = view.findViewById(R.id.toolbar_shadow);
@ -97,7 +109,7 @@ public final class MessageDetailsFragment extends FullScreenDialogFragment {
list.setAdapter(adapter);
list.setItemAnimator(null);
list.addOnScrollListener(new ToolbarShadowAnimationHelper(toolbarShadow));
list.addOnScrollListener(new Material3OnScrollHelper(requireActivity(), toolbarShadow));
}
private void initializeViewModel() {
@ -161,4 +173,8 @@ public final class MessageDetailsFragment extends FullScreenDialogFragment {
private void onErrorClicked(@NonNull MessageRecord messageRecord) {
SafetyNumberChangeDialog.show(requireContext(), getChildFragmentManager(), messageRecord);
}
public interface Callback {
void onMessageDetailsFragmentDismissed();
}
}

Wyświetl plik

@ -0,0 +1,45 @@
package org.thoughtcrime.securesms.messagerequests
import android.content.Context
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import org.thoughtcrime.securesms.R
enum class MessageRequestBarColorTheme(
private val containerBackgroundColor: Int,
private val buttonBackgroundColor: Int,
private val buttonForegroundDenyColor: Int,
private val buttonForegroundAcceptColor: Int
) {
WALLPAPER(
R.color.message_request_bar_container_background_wallpaper,
R.color.message_request_bar_background_wallpaper,
R.color.message_request_bar_denyForeground_wallpaper,
R.color.message_request_bar_acceptForeground_wallpaper
),
NORMAL(
R.color.message_request_bar_container_background_normal,
R.color.message_request_bar_background_normal,
R.color.message_request_bar_denyForeground_normal,
R.color.message_request_bar_acceptForeground_normal
);
@ColorInt
fun getContainerButtonBackgroundColor(context: Context): Int = ContextCompat.getColor(context, containerBackgroundColor)
@ColorInt
fun getButtonBackgroundColor(context: Context): Int = ContextCompat.getColor(context, buttonBackgroundColor)
@ColorInt
fun getButtonForegroundDenyColor(context: Context): Int = ContextCompat.getColor(context, buttonForegroundDenyColor)
@ColorInt
fun getButtonForegroundAcceptColor(context: Context): Int = ContextCompat.getColor(context, buttonForegroundAcceptColor)
companion object {
@JvmStatic
fun resolveTheme(hasWallpaper: Boolean): MessageRequestBarColorTheme {
return if (hasWallpaper) WALLPAPER else NORMAL
}
}
}

Wyświetl plik

@ -1,6 +1,7 @@
package org.thoughtcrime.securesms.messagerequests;
import android.content.Context;
import android.content.res.ColorStateList;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
@ -10,6 +11,8 @@ import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.Group;
import androidx.core.text.HtmlCompat;
import com.google.android.material.button.MaterialButton;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.CommunicationActions;
@ -18,17 +21,19 @@ import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.HtmlUtil;
import org.thoughtcrime.securesms.util.views.LearnMoreTextView;
import java.util.stream.Stream;
public class MessageRequestsBottomView extends ConstraintLayout {
private final Debouncer showProgressDebouncer = new Debouncer(250);
private LearnMoreTextView question;
private Button accept;
private Button gv1Continue;
private View block;
private View delete;
private View bigDelete;
private View bigUnblock;
private MaterialButton accept;
private MaterialButton gv1Continue;
private MaterialButton block;
private MaterialButton delete;
private MaterialButton bigDelete;
private MaterialButton bigUnblock;
private View busyIndicator;
private Group normalButtons;
@ -65,6 +70,8 @@ public class MessageRequestsBottomView extends ConstraintLayout {
blockedButtons = findViewById(R.id.message_request_blocked_buttons);
gv1MigrationButtons = findViewById(R.id.message_request_gv1_migration_buttons);
busyIndicator = findViewById(R.id.message_request_busy_indicator);
setWallpaperEnabled(false);
}
public void setMessageData(@NonNull MessageRequestViewModel.MessageData messageData) {
@ -162,6 +169,24 @@ public class MessageRequestsBottomView extends ConstraintLayout {
}
}
public void setWallpaperEnabled(boolean isEnabled) {
MessageRequestBarColorTheme theme = MessageRequestBarColorTheme.resolveTheme(isEnabled);
Stream.of(delete, bigDelete, block, bigUnblock, accept, gv1Continue).forEach(button -> {
button.setBackgroundTintList(ColorStateList.valueOf(theme.getButtonBackgroundColor(getContext())));
});
Stream.of(delete, bigDelete, block).forEach(button -> {
button.setTextColor(theme.getButtonForegroundDenyColor(getContext()));
});
Stream.of(accept, bigUnblock, gv1Continue).forEach(button -> {
button.setTextColor(theme.getButtonForegroundAcceptColor(getContext()));
});
setBackgroundColor(theme.getContainerButtonBackgroundColor(getContext()));
}
public void setAcceptOnClickListener(OnClickListener acceptOnClickListener) {
accept.setOnClickListener(acceptOnClickListener);
}

Wyświetl plik

@ -155,7 +155,6 @@ public class PaymentsHomeFragment extends LoggingFragment {
return;
case DEACTIVATED:
Snackbar.make(requireView(), R.string.PaymentsHomeFragment__payments_deactivated, Snackbar.LENGTH_SHORT)
.setTextColor(Color.WHITE)
.show();
return;
case DEACTIVATE_WITHOUT_BALANCE:

Wyświetl plik

@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.permissions;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
@ -18,13 +17,15 @@ import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
public class RationaleDialog {
public static AlertDialog.Builder createFor(@NonNull Context context, @NonNull String message, @DrawableRes int... drawables) {
public static MaterialAlertDialogBuilder createFor(@NonNull Context context, @NonNull String message, @DrawableRes int... drawables) {
View view = LayoutInflater.from(context).inflate(R.layout.permissions_rationale_dialog, null);
ViewGroup header = view.findViewById(R.id.header_container);
TextView text = view.findViewById(R.id.message);
@ -54,8 +55,10 @@ public class RationaleDialog {
text.setText(message);
return new AlertDialog.Builder(context, ThemeUtil.isDarkTheme(context) ? R.style.Theme_Signal_AlertDialog_Dark_Cornered : R.style.Theme_Signal_AlertDialog_Light_Cornered)
.setView(view);
return new MaterialAlertDialogBuilder(context,
ThemeUtil.isDarkTheme(context) ? R.style.Theme_Signal_AlertDialog_Dark_Cornered
: R.style.Theme_Signal_AlertDialog_Light_Cornered)
.setView(view);
}
}

Wyświetl plik

@ -21,8 +21,6 @@ import androidx.core.view.ViewCompat;
import androidx.lifecycle.ViewModelProviders;
import androidx.navigation.Navigation;
import com.dd.CircularProgressButton;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.MainActivity;
@ -42,19 +40,20 @@ import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.SupportEmailUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
public class PinRestoreEntryFragment extends LoggingFragment {
private static final String TAG = Log.tag(PinRestoreActivity.class);
private static final int MINIMUM_PIN_LENGTH = 4;
private EditText pinEntry;
private View helpButton;
private View skipButton;
private CircularProgressButton pinButton;
private TextView errorLabel;
private TextView keyboardToggle;
private PinRestoreViewModel viewModel;
private EditText pinEntry;
private View helpButton;
private View skipButton;
private CircularProgressMaterialButton pinButton;
private TextView errorLabel;
private TextView keyboardToggle;
private PinRestoreViewModel viewModel;
@Override
public @Nullable View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@ -153,18 +152,18 @@ public class PinRestoreEntryFragment extends LoggingFragment {
break;
case EMPTY_PIN:
Toast.makeText(requireContext(), R.string.RegistrationActivity_you_must_enter_your_registration_lock_PIN, Toast.LENGTH_LONG).show();
cancelSpinning(pinButton);
pinButton.cancelSpinning();
pinEntry.getText().clear();
enableAndFocusPinEntry();
break;
case PIN_TOO_SHORT:
Toast.makeText(requireContext(), getString(R.string.RegistrationActivity_your_pin_has_at_least_d_digits_or_characters, MINIMUM_PIN_LENGTH), Toast.LENGTH_LONG).show();
cancelSpinning(pinButton);
pinButton.cancelSpinning();
pinEntry.getText().clear();
enableAndFocusPinEntry();
break;
case PIN_INCORRECT:
cancelSpinning(pinButton);
pinButton.cancelSpinning();
pinEntry.getText().clear();
enableAndFocusPinEntry();
break;
@ -173,7 +172,7 @@ public class PinRestoreEntryFragment extends LoggingFragment {
break;
case NETWORK_ERROR:
Toast.makeText(requireContext(), R.string.RegistrationActivity_error_connecting_to_service, Toast.LENGTH_LONG).show();
cancelSpinning(pinButton);
pinButton.cancelSpinning();
pinEntry.setEnabled(true);
enableAndFocusPinEntry();
break;
@ -189,7 +188,7 @@ public class PinRestoreEntryFragment extends LoggingFragment {
private void onPinSubmitted() {
pinEntry.setEnabled(false);
viewModel.onPinSubmitted(pinEntry.getText().toString(), getPinEntryKeyboardType());
setSpinning(pinButton);
pinButton.setSpinning();
}
private void onNeedHelpClicked() {
@ -232,7 +231,7 @@ public class PinRestoreEntryFragment extends LoggingFragment {
}
private void handleSuccess() {
cancelSpinning(pinButton);
pinButton.cancelSpinning();
SignalStore.onboarding().clearAll();
Activity activity = requireActivity();
@ -277,20 +276,4 @@ public class PinRestoreEntryFragment extends LoggingFragment {
ServiceUtil.getInputMethodManager(pinEntry.getContext()).showSoftInput(pinEntry, 0);
}
}
private static void setSpinning(@Nullable CircularProgressButton button) {
if (button != null) {
button.setClickable(false);
button.setIndeterminateProgressMode(true);
button.setProgress(50);
}
}
private static void cancelSpinning(@Nullable CircularProgressButton button) {
if (button != null) {
button.setProgress(0);
button.setIndeterminateProgressMode(false);
button.setClickable(true);
}
}
}

Wyświetl plik

@ -42,7 +42,7 @@ public class AdvancedPinPreferenceFragment extends ListSummaryPreferenceFragment
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == CreateKbsPinActivity.REQUEST_NEW_PIN && resultCode == CreateKbsPinActivity.RESULT_OK) {
Snackbar.make(requireView(), R.string.ApplicationPreferencesActivity_pin_created, Snackbar.LENGTH_LONG).setTextColor(Color.WHITE).show();
Snackbar.make(requireView(), R.string.ApplicationPreferencesActivity_pin_created, Snackbar.LENGTH_LONG).show();
}
}
@ -99,7 +99,7 @@ public class AdvancedPinPreferenceFragment extends ListSummaryPreferenceFragment
PinOptOutDialog.show(requireContext(),
() -> {
updatePreferenceState();
Snackbar.make(requireView(), R.string.ApplicationPreferencesActivity_pin_disabled, Snackbar.LENGTH_SHORT).setTextColor(Color.WHITE).show();
Snackbar.make(requireView(), R.string.ApplicationPreferencesActivity_pin_disabled, Snackbar.LENGTH_SHORT).show();
});
} else {
startActivityForResult(CreateKbsPinActivity.getIntentForPinCreate(requireContext()), CreateKbsPinActivity.REQUEST_NEW_PIN);

Wyświetl plik

@ -16,8 +16,6 @@ import androidx.core.app.ShareCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;
import com.dd.CircularProgressButton;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
@ -25,6 +23,7 @@ import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.SignalProxyUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import org.thoughtcrime.securesms.util.views.LearnMoreTextView;
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState;
import org.whispersystems.signalservice.internal.configuration.SignalProxy;
@ -33,13 +32,13 @@ import java.util.Optional;
public class EditProxyFragment extends Fragment {
private SwitchCompat proxySwitch;
private EditText proxyText;
private TextView proxyTitle;
private TextView proxyStatus;
private View shareButton;
private CircularProgressButton saveButton;
private EditProxyViewModel viewModel;
private SwitchCompat proxySwitch;
private EditText proxyText;
private TextView proxyTitle;
private TextView proxyStatus;
private View shareButton;
private CircularProgressMaterialButton saveButton;
private EditProxyViewModel viewModel;
public static EditProxyFragment newInstance() {
return new EditProxyFragment();
@ -173,14 +172,10 @@ public class EditProxyFragment extends Fragment {
private void presentSaveState(@NonNull EditProxyViewModel.SaveState state) {
switch (state) {
case IDLE:
saveButton.setClickable(true);
saveButton.setIndeterminateProgressMode(false);
saveButton.setProgress(0);
saveButton.cancelSpinning();
break;
case IN_PROGRESS:
saveButton.setClickable(false);
saveButton.setIndeterminateProgressMode(true);
saveButton.setProgress(50);
saveButton.setSpinning();
break;
}
}

Wyświetl plik

@ -25,7 +25,6 @@ import androidx.navigation.Navigation;
import com.airbnb.lottie.SimpleColorFilter;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.dd.CircularProgressButton;
import org.signal.core.util.EditTextUtil;
import org.signal.core.util.StreamUtil;
@ -45,6 +44,7 @@ import org.thoughtcrime.securesms.util.FeatureFlags;
import org.signal.core.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
import org.thoughtcrime.securesms.util.text.AfterTextChanged;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import org.thoughtcrime.securesms.util.views.LearnMoreTextView;
import java.io.IOException;
@ -62,16 +62,16 @@ public class EditProfileFragment extends LoggingFragment {
private static final int MAX_DESCRIPTION_GLYPHS = 480;
private static final int MAX_DESCRIPTION_BYTES = 8192;
private Toolbar toolbar;
private View title;
private ImageView avatar;
private CircularProgressButton finishButton;
private EditText givenName;
private EditText familyName;
private View reveal;
private TextView preview;
private ImageView avatarPreviewBackground;
private ImageView avatarPreview;
private Toolbar toolbar;
private View title;
private ImageView avatar;
private CircularProgressMaterialButton finishButton;
private EditText givenName;
private EditText familyName;
private View reveal;
private TextView preview;
private ImageView avatarPreviewBackground;
private ImageView avatarPreview;
private Intent nextIntent;
@ -223,8 +223,7 @@ public class EditProfileFragment extends LoggingFragment {
}
this.finishButton.setOnClickListener(v -> {
this.finishButton.setIndeterminateProgressMode(true);
this.finishButton.setProgress(50);
this.finishButton.setSpinning();
handleUpload();
});
@ -313,7 +312,7 @@ public class EditProfileFragment extends LoggingFragment {
}
private void handleFinishedLegacy() {
finishButton.setProgress(0);
finishButton.cancelSpinning();
if (nextIntent != null) startActivity(nextIntent);
controller.onProfileNameUploadCompleted();
@ -341,7 +340,7 @@ public class EditProfileFragment extends LoggingFragment {
@Override
public void onAnimationEnd(Animator animation) {
finishButton.setProgress(0);
finishButton.cancelSpinning();
if (nextIntent != null && getActivity() != null) {
startActivity(nextIntent);
}

Wyświetl plik

@ -22,8 +22,6 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;
import com.dd.CircularProgressButton;
import org.signal.core.util.BreakIteratorCompat;
import org.signal.core.util.EditTextUtil;
import org.thoughtcrime.securesms.R;
@ -34,6 +32,7 @@ import org.signal.core.util.StringUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.adapter.AlwaysChangedDiffUtil;
import org.thoughtcrime.securesms.util.text.AfterTextChanged;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import org.whispersystems.signalservice.api.crypto.ProfileCipher;
import java.util.Arrays;
@ -60,11 +59,11 @@ public class EditAboutFragment extends Fragment implements ManageProfileActivity
new AboutPreset("\uD83D\uDE80", R.string.EditAboutFragment_working_on_something_new)
);
private ImageView emojiView;
private EditText bodyView;
private TextView countView;
private CircularProgressButton saveButton;
private EditAboutViewModel viewModel;
private ImageView emojiView;
private EditText bodyView;
private TextView countView;
private CircularProgressMaterialButton saveButton;
private EditAboutViewModel viewModel;
private String selectedEmoji;
@ -167,14 +166,10 @@ public class EditAboutFragment extends Fragment implements ManageProfileActivity
private void presentSaveState(@NonNull EditAboutViewModel.SaveState state) {
switch (state) {
case IDLE:
saveButton.setClickable(true);
saveButton.setIndeterminateProgressMode(false);
saveButton.setProgress(0);
saveButton.cancelSpinning();
break;
case IN_PROGRESS:
saveButton.setClickable(false);
saveButton.setIndeterminateProgressMode(true);
saveButton.setProgress(50);
saveButton.setSpinning();
break;
case DONE:
saveButton.setClickable(false);

Wyświetl plik

@ -16,8 +16,6 @@ import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProviders;
import androidx.navigation.Navigation;
import com.dd.CircularProgressButton;
import org.signal.core.util.EditTextUtil;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.profiles.ProfileName;
@ -25,6 +23,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.signal.core.util.StringUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.text.AfterTextChanged;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
/**
* Simple fragment to edit your profile name.
@ -33,10 +32,10 @@ public class EditProfileNameFragment extends Fragment {
public static final int NAME_MAX_GLYPHS = 26;
private EditText givenName;
private EditText familyName;
private CircularProgressButton saveButton;
private EditProfileNameViewModel viewModel;
private EditText givenName;
private EditText familyName;
private CircularProgressMaterialButton saveButton;
private EditProfileNameViewModel viewModel;
@Override
public @NonNull View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@ -92,17 +91,13 @@ public class EditProfileNameFragment extends Fragment {
setEditTextEnabled(familyName, true);
break;
case IDLE:
saveButton.setClickable(true);
saveButton.setIndeterminateProgressMode(false);
saveButton.setProgress(0);
saveButton.cancelSpinning();
saveButton.setAlpha(1);
setEditTextEnabled(givenName, true);
setEditTextEnabled(familyName, true);
break;
case IN_PROGRESS:
saveButton.setClickable(false);
saveButton.setIndeterminateProgressMode(true);
saveButton.setProgress(50);
saveButton.setSpinning();
saveButton.setAlpha(1);
setEditTextEnabled(givenName, false);
setEditTextEnabled(familyName, false);

Wyświetl plik

@ -16,13 +16,12 @@ import androidx.lifecycle.ViewModelProviders;
import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment;
import com.dd.CircularProgressButton;
import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.UsernameUtil;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
public class UsernameEditFragment extends LoggingFragment {
@ -30,10 +29,10 @@ public class UsernameEditFragment extends LoggingFragment {
private UsernameEditViewModel viewModel;
private EditText usernameInput;
private TextView usernameSubtext;
private CircularProgressButton submitButton;
private CircularProgressButton deleteButton;
private EditText usernameInput;
private TextView usernameSubtext;
private CircularProgressMaterialButton submitButton;
private CircularProgressMaterialButton deleteButton;
public static UsernameEditFragment newInstance() {
return new UsernameEditFragment();
@ -84,42 +83,42 @@ public class UsernameEditFragment extends LoggingFragment {
switch (state.getButtonState()) {
case SUBMIT:
cancelSpinning(submitButton);
submitButton.cancelSpinning();
submitButton.setVisibility(View.VISIBLE);
submitButton.setEnabled(true);
submitButton.setAlpha(1);
deleteButton.setVisibility(View.GONE);
break;
case SUBMIT_DISABLED:
cancelSpinning(submitButton);
submitButton.cancelSpinning();
submitButton.setVisibility(View.VISIBLE);
submitButton.setEnabled(false);
submitButton.setAlpha(DISABLED_ALPHA);
deleteButton.setVisibility(View.GONE);
break;
case SUBMIT_LOADING:
setSpinning(submitButton);
submitButton.setSpinning();
submitButton.setVisibility(View.VISIBLE);
submitButton.setAlpha(1);
deleteButton.setVisibility(View.GONE);
usernameInput.setEnabled(false);
break;
case DELETE:
cancelSpinning(deleteButton);
deleteButton.cancelSpinning();
deleteButton.setVisibility(View.VISIBLE);
deleteButton.setEnabled(true);
deleteButton.setAlpha(1);
submitButton.setVisibility(View.GONE);
break;
case DELETE_DISABLED:
cancelSpinning(deleteButton);
deleteButton.cancelSpinning();
deleteButton.setVisibility(View.VISIBLE);
deleteButton.setEnabled(false);
deleteButton.setAlpha(DISABLED_ALPHA);
submitButton.setVisibility(View.GONE);
break;
case DELETE_LOADING:
setSpinning(deleteButton);
deleteButton.setSpinning();
deleteButton.setVisibility(View.VISIBLE);
deleteButton.setAlpha(1);
submitButton.setVisibility(View.GONE);
@ -180,16 +179,4 @@ public class UsernameEditFragment extends LoggingFragment {
break;
}
}
private static void setSpinning(@NonNull CircularProgressButton button) {
button.setClickable(false);
button.setIndeterminateProgressMode(true);
button.setProgress(50);
}
private static void cancelSpinning(@NonNull CircularProgressButton button) {
button.setProgress(0);
button.setIndeterminateProgressMode(false);
button.setClickable(true);
}
}

Wyświetl plik

@ -14,14 +14,15 @@ import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProviders;
import com.dd.CircularProgressButton;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.preferences.EditProxyViewModel;
import org.thoughtcrime.securesms.util.BottomSheetUtil;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
/**
* A bottom sheet shown in response to a deep link. Allows a user to set a proxy.
@ -32,10 +33,10 @@ public final class ProxyBottomSheetFragment extends BottomSheetDialogFragment {
private static final String ARG_PROXY_LINK = "proxy_link";
private TextView proxyText;
private View cancelButton;
private CircularProgressButton useProxyButton;
private EditProxyViewModel viewModel;
private TextView proxyText;
private View cancelButton;
private CircularProgressMaterialButton useProxyButton;
private EditProxyViewModel viewModel;
public static void showForProxy(@NonNull FragmentManager manager, @NonNull String proxyLink) {
ProxyBottomSheetFragment fragment = new ProxyBottomSheetFragment();
@ -86,14 +87,10 @@ public final class ProxyBottomSheetFragment extends BottomSheetDialogFragment {
private void presentSaveState(@NonNull EditProxyViewModel.SaveState state) {
switch (state) {
case IDLE:
useProxyButton.setClickable(true);
useProxyButton.setIndeterminateProgressMode(false);
useProxyButton.setProgress(0);
useProxyButton.cancelSpinning();
break;
case IN_PROGRESS:
useProxyButton.setClickable(false);
useProxyButton.setIndeterminateProgressMode(true);
useProxyButton.setProgress(50);
useProxyButton.setSpinning();
break;
}
}
@ -105,7 +102,7 @@ public final class ProxyBottomSheetFragment extends BottomSheetDialogFragment {
dismiss();
break;
case PROXY_FAILURE:
new AlertDialog.Builder(requireContext())
new MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.preferences_failed_to_connect)
.setMessage(R.string.preferences_couldnt_connect_to_the_proxy)
.setPositiveButton(android.R.string.ok, (d, i) -> d.dismiss())

Wyświetl plik

@ -14,7 +14,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import com.dd.CircularProgressButton;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.signal.core.util.logging.Log;
@ -26,6 +25,7 @@ import org.thoughtcrime.securesms.registration.viewmodel.BaseRegistrationViewMod
import org.thoughtcrime.securesms.util.LifecycleDisposable;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import java.util.concurrent.TimeUnit;
@ -33,8 +33,6 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.Disposable;
import static org.thoughtcrime.securesms.registration.fragments.RegistrationViewDelegate.setDebugLogSubmitMultiTapView;
import static org.thoughtcrime.securesms.util.CircularProgressButtonUtil.cancelSpinning;
import static org.thoughtcrime.securesms.util.CircularProgressButtonUtil.setSpinning;
/**
* Base fragment used by registration and change number flow to deal with a registration locked account.
@ -48,12 +46,12 @@ public abstract class BaseRegistrationLockFragment extends LoggingFragment {
*/
private static final int MINIMUM_PIN_LENGTH = 4;
private EditText pinEntry;
private View forgotPin;
protected CircularProgressButton pinButton;
private TextView errorLabel;
private TextView keyboardToggle;
private long timeRemaining;
private EditText pinEntry;
private View forgotPin;
protected CircularProgressMaterialButton pinButton;
private TextView errorLabel;
private TextView keyboardToggle;
private long timeRemaining;
private BaseRegistrationViewModel viewModel;
@ -171,7 +169,7 @@ public abstract class BaseRegistrationLockFragment extends LoggingFragment {
return;
}
setSpinning(pinButton);
pinButton.setSpinning();
Disposable verify = viewModel.verifyCodeAndRegisterAccountWithRegistrationLock(pin)
.observeOn(AndroidSchedulers.mainThread())
@ -194,7 +192,7 @@ public abstract class BaseRegistrationLockFragment extends LoggingFragment {
}
public void onIncorrectKbsRegistrationLockPin(@NonNull TokenData tokenData) {
cancelSpinning(pinButton);
pinButton.cancelSpinning();
pinEntry.getText().clear();
enableAndFocusPinEntry();
@ -227,7 +225,7 @@ public abstract class BaseRegistrationLockFragment extends LoggingFragment {
}
public void onRateLimited() {
cancelSpinning(pinButton);
pinButton.cancelSpinning();
enableAndFocusPinEntry();
new MaterialAlertDialogBuilder(requireContext())
@ -242,7 +240,7 @@ public abstract class BaseRegistrationLockFragment extends LoggingFragment {
}
public void onError() {
cancelSpinning(pinButton);
pinButton.cancelSpinning();
enableAndFocusPinEntry();
Toast.makeText(requireContext(), R.string.RegistrationActivity_error_connecting_to_service, Toast.LENGTH_LONG).show();

Wyświetl plik

@ -22,7 +22,6 @@ import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment;
import com.dd.CircularProgressButton;
import com.google.android.gms.auth.api.phone.SmsRetriever;
import com.google.android.gms.auth.api.phone.SmsRetrieverClient;
import com.google.android.gms.common.ConnectionResult;
@ -50,26 +49,25 @@ import org.thoughtcrime.securesms.util.PlayServicesUtil;
import org.thoughtcrime.securesms.util.SupportEmailUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.Disposable;
import static org.thoughtcrime.securesms.registration.fragments.RegistrationViewDelegate.setDebugLogSubmitMultiTapView;
import static org.thoughtcrime.securesms.registration.fragments.RegistrationViewDelegate.showConfirmNumberDialogIfTranslated;
import static org.thoughtcrime.securesms.util.CircularProgressButtonUtil.cancelSpinning;
import static org.thoughtcrime.securesms.util.CircularProgressButtonUtil.setSpinning;
public final class EnterPhoneNumberFragment extends LoggingFragment implements RegistrationNumberInputController.Callbacks {
private static final String TAG = Log.tag(EnterPhoneNumberFragment.class);
private LabeledEditText countryCode;
private LabeledEditText number;
private CircularProgressButton register;
private Spinner countrySpinner;
private View cancel;
private ScrollView scrollView;
private RegistrationViewModel viewModel;
private LabeledEditText countryCode;
private LabeledEditText number;
private CircularProgressMaterialButton register;
private Spinner countrySpinner;
private View cancel;
private ScrollView scrollView;
private RegistrationViewModel viewModel;
private final LifecycleDisposable disposables = new LifecycleDisposable();
@ -179,7 +177,7 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
}
private void handleRequestVerification(@NonNull Context context, boolean fcmSupported) {
setSpinning(register);
register.setSpinning();
disableAllEntries();
if (fcmSupported) {
@ -247,7 +245,7 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
Toast.makeText(register.getContext(), R.string.RegistrationActivity_unable_to_connect_to_service, Toast.LENGTH_LONG).show();
}
cancelSpinning(register);
register.cancelSpinning();
enableAllEntries();
});

Wyświetl plik

@ -4,6 +4,7 @@ import androidx.annotation.NonNull;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import org.signal.core.util.concurrent.SimpleTask;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
@ -16,14 +17,11 @@ import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.Stopwatch;
import org.thoughtcrime.securesms.util.SupportEmailUtil;
import org.signal.core.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import static org.thoughtcrime.securesms.util.CircularProgressButtonUtil.cancelSpinning;
public final class RegistrationLockFragment extends BaseRegistrationLockFragment {
private static final String TAG = Log.tag(RegistrationLockFragment.class);
@ -68,7 +66,7 @@ public final class RegistrationLockFragment extends BaseRegistrationLockFragment
return null;
}, none -> {
cancelSpinning(pinButton);
pinButton.cancelSpinning();
SafeNavigation.safeNavigate(Navigation.findNavController(requireView()), RegistrationLockFragmentDirections.actionSuccessfulRegistration());
});
}

Wyświetl plik

@ -31,8 +31,6 @@ import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation;
import com.dd.CircularProgressButton;
import net.zetetic.database.sqlcipher.SQLiteDatabase;
import org.greenrobot.eventbus.EventBus;
@ -58,25 +56,24 @@ import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.Util;
import org.signal.core.util.concurrent.SimpleTask;
import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import java.io.IOException;
import java.util.Locale;
import static org.thoughtcrime.securesms.registration.fragments.RegistrationViewDelegate.setDebugLogSubmitMultiTapView;
import static org.thoughtcrime.securesms.util.CircularProgressButtonUtil.cancelSpinning;
import static org.thoughtcrime.securesms.util.CircularProgressButtonUtil.setSpinning;
public final class RestoreBackupFragment extends LoggingFragment {
private static final String TAG = Log.tag(RestoreBackupFragment.class);
private static final short OPEN_DOCUMENT_TREE_RESULT_CODE = 13782;
private TextView restoreBackupSize;
private TextView restoreBackupTime;
private TextView restoreBackupProgress;
private CircularProgressButton restoreButton;
private View skipRestoreButton;
private RegistrationViewModel viewModel;
private TextView restoreBackupSize;
private TextView restoreBackupTime;
private TextView restoreBackupProgress;
private CircularProgressMaterialButton restoreButton;
private View skipRestoreButton;
private RegistrationViewModel viewModel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -261,7 +258,7 @@ public final class RestoreBackupFragment extends LoggingFragment {
InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(prompt.getWindowToken(), 0);
setSpinning(restoreButton);
restoreButton.setSpinning();
skipRestoreButton.setVisibility(View.INVISIBLE);
String passphrase = prompt.getText().toString();
@ -315,7 +312,7 @@ public final class RestoreBackupFragment extends LoggingFragment {
@Override
protected void onPostExecute(@NonNull BackupImportResult result) {
viewModel.markBackupCompleted();
cancelSpinning(restoreButton);
restoreButton.cancelSpinning();
skipRestoreButton.setVisibility(View.VISIBLE);
restoreBackupProgress.setText("");
@ -365,7 +362,7 @@ public final class RestoreBackupFragment extends LoggingFragment {
restoreBackupProgress.setText(getString(R.string.RegistrationActivity_d_messages_so_far, count));
}
setSpinning(restoreButton);
restoreButton.setSpinning();
skipRestoreButton.setVisibility(View.INVISIBLE);
if (event.getType() == FullBackupBase.BackupEvent.Type.FINISHED) {

Wyświetl plik

@ -22,7 +22,6 @@ import androidx.navigation.ActivityNavigator;
import androidx.navigation.Navigation;
import androidx.navigation.fragment.NavHostFragment;
import com.dd.CircularProgressButton;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
@ -40,12 +39,11 @@ import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import java.util.Optional;
import static org.thoughtcrime.securesms.registration.fragments.RegistrationViewDelegate.setDebugLogSubmitMultiTapView;
import static org.thoughtcrime.securesms.util.CircularProgressButtonUtil.cancelSpinning;
import static org.thoughtcrime.securesms.util.CircularProgressButtonUtil.setSpinning;
public final class WelcomeFragment extends LoggingFragment {
@ -74,8 +72,8 @@ public final class WelcomeFragment extends LoggingFragment {
private static final int[] HEADERS = { R.drawable.ic_contacts_white_48dp, R.drawable.ic_folder_white_48dp };
private static final int[] HEADERS_API_29 = { R.drawable.ic_contacts_white_48dp };
private CircularProgressButton continueButton;
private RegistrationViewModel viewModel;
private CircularProgressMaterialButton continueButton;
private RegistrationViewModel viewModel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -164,7 +162,7 @@ public final class WelcomeFragment extends LoggingFragment {
}
private void gatherInformationAndContinue(@NonNull View view) {
setSpinning(continueButton);
continueButton.setSpinning();
RestoreBackupFragment.searchForBackup(backup -> {
Context context = getContext();
@ -177,7 +175,7 @@ public final class WelcomeFragment extends LoggingFragment {
initializeNumber();
cancelSpinning(continueButton);
continueButton.cancelSpinning();
if (backup == null) {
Log.i(TAG, "Skipping backup. No backup found, or no permission to look.");

Wyświetl plik

@ -11,7 +11,6 @@ import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;
import com.annimon.stream.Stream;
import com.dd.CircularProgressButton;
import org.thoughtcrime.securesms.PassphraseRequiredActivity;
import org.thoughtcrime.securesms.R;
@ -28,6 +27,7 @@ import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.text.AfterTextChanged;
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
import java.util.Objects;
@ -39,12 +39,12 @@ public class ShareInterstitialActivity extends PassphraseRequiredActivity {
private static final String ARGS = "args";
private ShareInterstitialViewModel viewModel;
private LinkPreviewViewModel linkPreviewViewModel;
private CircularProgressButton confirm;
private RecyclerView contactsRecycler;
private Toolbar toolbar;
private LinkPreviewView preview;
private ShareInterstitialViewModel viewModel;
private LinkPreviewViewModel linkPreviewViewModel;
private CircularProgressMaterialButton confirm;
private RecyclerView contactsRecycler;
private Toolbar toolbar;
private LinkPreviewView preview;
private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme();
private final ShareInterstitialSelectionAdapter adapter = new ShareInterstitialSelectionAdapter();
@ -171,9 +171,7 @@ public class ShareInterstitialActivity extends PassphraseRequiredActivity {
}
private void onConfirm() {
confirm.setClickable(false);
confirm.setIndeterminateProgressMode(true);
confirm.setProgress(50);
confirm.setSpinning();
viewModel.send(results -> {
MultiShareDialogs.displayResultDialog(this, results, () -> {

Wyświetl plik

@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.stories.landing
import android.Manifest
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.transition.TransitionInflater
@ -36,6 +35,7 @@ import org.thoughtcrime.securesms.conversation.mutiselect.forward.MultiselectFor
import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.main.Material3OnScrollHelperBinder
import org.thoughtcrime.securesms.mediasend.v2.MediaSelectionActivity
import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.stories.StoryTextPostModel
@ -48,6 +48,7 @@ import org.thoughtcrime.securesms.stories.tabs.ConversationListTab
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabsViewModel
import org.thoughtcrime.securesms.stories.viewer.StoryViewerActivity
import org.thoughtcrime.securesms.util.LifecycleDisposable
import org.thoughtcrime.securesms.util.fragments.requireListener
import org.thoughtcrime.securesms.util.visible
import java.util.concurrent.TimeUnit
@ -97,6 +98,8 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
MyStoriesItem.register(adapter)
ExpandHeader.register(adapter)
requireListener<Material3OnScrollHelperBinder>().bindScrollHelper(recyclerView!!)
lifecycleDisposable.bindTo(viewLifecycleOwner)
emptyNotice = requireView().findViewById(R.id.empty_notice)
cameraFab = requireView().findViewById(R.id.camera_fab)
@ -105,7 +108,7 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
setEnterSharedElementCallback(object : SharedElementCallback() {
override fun onSharedElementStart(sharedElementNames: MutableList<String>?, sharedElements: MutableList<View>?, sharedElementSnapshots: MutableList<View>?) {
if (sharedElementNames?.contains("camera_fab") == true) {
cameraFab.setImageResource(R.drawable.ic_compose_24)
cameraFab.setImageResource(R.drawable.ic_compose_outline_24)
lifecycleDisposable += Single.timer(200, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy {
@ -279,7 +282,6 @@ class StoriesLandingFragment : DSLSettingsFragment(layoutId = R.layout.stories_l
.setPositiveButton(R.string.StoriesLandingFragment__hide) { _, _ ->
viewModel.setHideStory(model.data.storyRecipient, true).subscribe {
Snackbar.make(cameraFab, R.string.StoriesLandingFragment__story_hidden, Snackbar.LENGTH_SHORT)
.setTextColor(Color.WHITE)
.setAnchorView(cameraFab)
.setAnimationMode(BaseTransientBottomBar.ANIMATION_MODE_FADE)
.show()

Wyświetl plik

@ -11,13 +11,13 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import com.airbnb.lottie.SimpleColorFilter
import com.dd.CircularProgressButton
import com.google.android.material.textfield.TextInputLayout
import io.reactivex.rxjava3.kotlin.subscribeBy
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.database.model.DistributionListId
import org.thoughtcrime.securesms.util.LifecycleDisposable
import org.thoughtcrime.securesms.util.ViewUtil
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
class EditStoryNameFragment : Fragment(R.layout.stories_edit_story_name_fragment) {
@ -35,7 +35,7 @@ class EditStoryNameFragment : Fragment(R.layout.stories_edit_story_name_fragment
private val lifecycleDisposable = LifecycleDisposable()
private lateinit var saveButton: CircularProgressButton
private lateinit var saveButton: CircularProgressMaterialButton
private lateinit var storyName: EditText
private lateinit var storyNameWrapper: TextInputLayout

Wyświetl plik

@ -107,7 +107,6 @@ class StoryReplyComposer @JvmOverloads constructor(
false,
messageRecord.slideDeck,
null,
null,
QuoteModel.Type.NORMAL
)

Wyświetl plik

@ -203,7 +203,7 @@ object StoryGroupReplyItem {
val actions = mutableListOf<ActionItem>()
if (model.onCopyClick != null) {
actions += ActionItem(R.drawable.ic_copy_24_solid_tinted, context.getString(R.string.StoryGroupReplyItem__copy)) {
actions += ActionItem(R.drawable.ic_copy_24_tinted, context.getString(R.string.StoryGroupReplyItem__copy)) {
val toCopy: CharSequence = when (model) {
is TextModel -> model.text.message.getDisplayBody(context)
else -> model.messageRecord.getDisplayBody(context)
@ -211,7 +211,7 @@ object StoryGroupReplyItem {
model.onCopyClick.invoke(toCopy)
}
}
actions += ActionItem(R.drawable.ic_trash_24_solid_tinted, context.getString(R.string.StoryGroupReplyItem__delete)) { model.onDeleteClick(model.messageRecord) }
actions += ActionItem(R.drawable.ic_trash_24, context.getString(R.string.StoryGroupReplyItem__delete)) { model.onDeleteClick(model.messageRecord) }
SignalContextMenu.Builder(itemView, itemView.rootView as ViewGroup)
.preferredHorizontalPosition(SignalContextMenu.HorizontalPosition.START)

Wyświetl plik

@ -1,24 +0,0 @@
package org.thoughtcrime.securesms.util
import com.dd.CircularProgressButton
object CircularProgressButtonUtil {
@JvmStatic
fun setSpinning(button: CircularProgressButton?) {
button?.apply {
isClickable = false
isIndeterminateProgressMode = true
progress = 50
}
}
@JvmStatic
fun cancelSpinning(button: CircularProgressButton?) {
button?.apply {
progress = 0
isIndeterminateProgressMode = false
isClickable = true
}
}
}

Wyświetl plik

@ -0,0 +1,56 @@
package org.thoughtcrime.securesms.util
import android.app.Activity
import android.os.Build
import android.view.View
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.views.Stub
/**
* Sets the view's isActivated state when the content of the attached recycler can scroll up.
* This can be used to appropriately tint toolbar backgrounds. Also can emit the state change
* for other purposes.
*/
class Material3OnScrollHelper(
private val views: List<View>,
private val viewStubs: List<Stub<out View>> = emptyList(),
private val onActiveStateChanged: (Boolean) -> Unit
) : RecyclerView.OnScrollListener() {
constructor(activity: Activity, views: List<View>, viewStubs: List<Stub<out View>>) : this(views, viewStubs, { updateStatusBarColor(activity, it) })
constructor(activity: Activity, view: View) : this(listOf(view), emptyList(), { updateStatusBarColor(activity, it) })
private var active: Boolean? = null
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
updateActiveState(recyclerView.canScrollVertically(-1))
}
private fun updateActiveState(isActive: Boolean) {
if (active == isActive) {
return
}
active = isActive
views.forEach { it.isActivated = isActive }
viewStubs.filter { it.resolved() }.forEach { it.get().isActivated = isActive }
onActiveStateChanged(isActive)
}
companion object {
fun updateStatusBarColor(activity: Activity, isActive: Boolean) {
if (Build.VERSION.SDK_INT > 21) {
if (isActive) {
WindowUtil.setStatusBarColor(activity.window, ContextCompat.getColor(activity, R.color.signal_colorSurface2))
} else {
WindowUtil.setStatusBarColor(activity.window, ContextCompat.getColor(activity, R.color.signal_colorBackground))
}
}
}
}
}

Wyświetl plik

@ -122,6 +122,15 @@ public final class Projection {
return set(x, y, (int) (width * scale), (int) (height * scale), newCorners);
}
public @NonNull Projection insetTop(int boundary) {
Corners newCorners = this.corners == null ? null : new Corners(0,
0,
this.corners.bottomRight,
this.corners.bottomLeft);
return set(x, y + boundary, width, height - boundary, newCorners);
}
public static @NonNull Projection relativeToParent(@NonNull ViewGroup parent, @NonNull View view, @Nullable Corners corners) {
Rect viewBounds = new Rect();

Wyświetl plik

@ -75,8 +75,6 @@ public abstract class SnackbarAsyncTask<Params>
Snackbar.make(view, snackbarText, snackbarDuration)
.setAction(snackbarActionText, this)
.setActionTextColor(snackbarActionColor)
.setTextColor(Color.WHITE)
.show();
}

Wyświetl plik

@ -0,0 +1,149 @@
package org.thoughtcrime.securesms.util.views
import android.animation.Animator
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.util.AttributeSet
import android.view.ViewAnimationUtils
import android.widget.FrameLayout
import androidx.annotation.StringRes
import androidx.core.animation.doOnEnd
import androidx.core.content.withStyledAttributes
import com.google.android.material.button.MaterialButton
import com.google.android.material.theme.overlay.MaterialThemeOverlay
import org.thoughtcrime.securesms.R
import kotlin.math.max
/**
* Drop-In replacement for CircularProgressButton that better supports material design.
*/
class CircularProgressMaterialButton @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : FrameLayout(MaterialThemeOverlay.wrap(context, attrs, 0, 0), attrs, 0) {
init {
inflate(getContext(), R.layout.circular_progress_material_button, this)
}
private var currentState: State = State.BUTTON
private var requestedState: State = State.BUTTON
private var animator: Animator? = null
private val materialButton: MaterialButton = findViewById(R.id.button)
var text: CharSequence?
get() = materialButton.text
set(value) {
materialButton.text = value
}
init {
getContext().withStyledAttributes(attrs, R.styleable.CircularProgressMaterialButton) {
val label = getString(R.styleable.CircularProgressMaterialButton_circularProgressMaterialButton__label)
materialButton.text = label
}
}
fun setText(@StringRes resId: Int) {
materialButton.setText(resId)
}
override fun onSaveInstanceState(): Parcelable {
return Bundle().apply {
putParcelable(SUPER_STATE, super.onSaveInstanceState())
putInt(STATE, if (requestedState != currentState) requestedState.code else currentState.code)
}
}
override fun onRestoreInstanceState(state: Parcelable) {
val stateBundle = state as Bundle
val superState: Parcelable? = stateBundle.getParcelable(SUPER_STATE)
super.onRestoreInstanceState(superState)
currentState = if (materialButton.visibility == INVISIBLE) State.PROGRESS else State.BUTTON
requestedState = State.fromCode(stateBundle.getInt(STATE))
ensureRequestedState(false)
}
override fun setOnClickListener(onClickListener: OnClickListener?) {
materialButton.setOnClickListener(onClickListener)
}
fun setSpinning() {
transformTo(State.PROGRESS, true)
}
fun cancelSpinning() {
transformTo(State.BUTTON, true)
}
private fun transformTo(state: State, animate: Boolean) {
requestedState = state
if (animator?.isRunning == true) {
return
}
if (!animate || Build.VERSION.SDK_INT < 21) {
materialButton.visibility = state.materialButtonVisibility
currentState = state
return
}
currentState = state
if (state == State.BUTTON) {
materialButton.visibility = VISIBLE
}
val buttonShrunkRadius = 0f
val buttonExpandedRadius = max(measuredWidth, measuredHeight).toFloat()
animator = ViewAnimationUtils.createCircularReveal(
materialButton,
materialButton.measuredWidth / 2,
materialButton.measuredHeight / 2,
if (state == State.BUTTON) buttonShrunkRadius else buttonExpandedRadius,
if (state == State.PROGRESS) buttonShrunkRadius else buttonExpandedRadius
).apply {
duration = ANIMATION_DURATION
doOnEnd {
materialButton.visibility = state.materialButtonVisibility
ensureRequestedState(true)
}
start()
}
}
private fun ensureRequestedState(animate: Boolean) {
if (requestedState == currentState || !isAttachedToWindow) {
return
}
transformTo(requestedState, animate)
}
enum class State(val code: Int, val materialButtonVisibility: Int) {
BUTTON(0, VISIBLE),
PROGRESS(1, INVISIBLE);
companion object {
fun fromCode(code: Int): State {
return when (code) {
0 -> BUTTON
1 -> PROGRESS
else -> error("Unexpected code $code")
}
}
}
}
companion object {
private val ANIMATION_DURATION = 300L
private val SUPER_STATE = "super_state"
private val STATE = "state"
}
}

Wyświetl plik

@ -4,14 +4,24 @@ import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Dimension;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import com.google.android.material.snackbar.Snackbar;
import org.signal.core.util.DimensionUnit;
public class SlideUpWithSnackbarBehavior extends CoordinatorLayout.Behavior<View> {
@Dimension(unit = Dimension.DP)
private static final float PAD_TOP_OF_SNACKBAR_DP = 16f;
@Px
private final float padTopOfSnackbar = DimensionUnit.DP.toPixels(PAD_TOP_OF_SNACKBAR_DP);
public SlideUpWithSnackbarBehavior(@NonNull Context context, @Nullable AttributeSet attributeSet) {
super(context, attributeSet);
}
@ -21,7 +31,7 @@ public class SlideUpWithSnackbarBehavior extends CoordinatorLayout.Behavior<View
@NonNull View child,
@NonNull View dependency)
{
float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
float translationY = Math.min(0, dependency.getTranslationY() - (dependency.getHeight() + padTopOfSnackbar));
child.setTranslationY(translationY);
return true;

Wyświetl plik

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/signal_colorTransparent2" android:state_enabled="true"/>
<item android:alpha="@dimen/material_emphasis_disabled_background" android:color="@color/signal_colorOnSecondaryContainer"/>
</selector>

Wyświetl plik

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/signal_colorNeutralVariantInverse" android:state_enabled="true"/>
<item android:alpha="@dimen/material_emphasis_disabled" android:color="@color/signal_colorNeutralVariantInverse"/>
</selector>

Wyświetl plik

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/signal_colorSurface1" android:state_enabled="true"/>
<item android:alpha="@dimen/material_emphasis_disabled_background" android:color="@color/signal_colorOnSurfaceVariant"/>
</selector>

Wyświetl plik

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/signal_colorTransparent4" android:state_enabled="true"/>
<item android:alpha="@dimen/material_emphasis_disabled_background" android:color="@color/signal_colorOnSecondaryContainer"/>
</selector>

Some files were not shown because too many files have changed in this diff Show More