Add polish to voice note bubbles.
This commit is contained in:
parent
b4b1e5b605
commit
ac54b5cbdf
24 changed files with 272 additions and 46 deletions
|
@ -61,6 +61,7 @@ public final class AudioView extends FrameLayout {
|
|||
|
||||
@ColorInt private final int waveFormPlayedBarsColor;
|
||||
@ColorInt private final int waveFormUnplayedBarsColor;
|
||||
@ColorInt private final int waveFormThumbTint;
|
||||
|
||||
@Nullable private SlideClickListener downloadListener;
|
||||
private int backwardsCounter;
|
||||
|
@ -107,6 +108,9 @@ public final class AudioView extends FrameLayout {
|
|||
|
||||
this.waveFormPlayedBarsColor = typedArray.getColor(R.styleable.AudioView_waveformPlayedBarsColor, Color.WHITE);
|
||||
this.waveFormUnplayedBarsColor = typedArray.getColor(R.styleable.AudioView_waveformUnplayedBarsColor, Color.WHITE);
|
||||
this.waveFormThumbTint = typedArray.getColor(R.styleable.AudioView_waveformThumbTint, Color.WHITE);
|
||||
|
||||
progressAndPlay.getBackground().setColorFilter(typedArray.getColor(R.styleable.AudioView_progressAndPlayTint, Color.BLACK), PorterDuff.Mode.SRC_IN);
|
||||
} finally {
|
||||
if (typedArray != null) {
|
||||
typedArray.recycle();
|
||||
|
@ -132,10 +136,15 @@ public final class AudioView extends FrameLayout {
|
|||
|
||||
public void setAudio(final @NonNull AudioSlide audio,
|
||||
final @Nullable Callbacks callbacks,
|
||||
final boolean showControls)
|
||||
final boolean showControls,
|
||||
final boolean forceHideDuration)
|
||||
{
|
||||
this.callbacks = callbacks;
|
||||
|
||||
if (duration != null) {
|
||||
duration.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (seekBar instanceof WaveFormSeekBarView) {
|
||||
if (audioSlide != null && !Objects.equals(audioSlide.getUri(), audio.getUri())) {
|
||||
WaveFormSeekBarView waveFormView = (WaveFormSeekBarView) seekBar;
|
||||
|
@ -150,9 +159,11 @@ public final class AudioView extends FrameLayout {
|
|||
seekBar.setEnabled(false);
|
||||
downloadButton.setOnClickListener(new DownloadClickedListener(audio));
|
||||
if (circleProgress.isSpinning()) circleProgress.stopSpinning();
|
||||
circleProgress.setVisibility(View.GONE);
|
||||
} else if (showControls && audio.getTransferState() == AttachmentDatabase.TRANSFER_PROGRESS_STARTED) {
|
||||
controlToggle.displayQuick(progressAndPlay);
|
||||
seekBar.setEnabled(false);
|
||||
circleProgress.setVisibility(View.VISIBLE);
|
||||
circleProgress.spin();
|
||||
} else {
|
||||
seekBar.setEnabled(true);
|
||||
|
@ -164,13 +175,13 @@ public final class AudioView extends FrameLayout {
|
|||
|
||||
if (seekBar instanceof WaveFormSeekBarView) {
|
||||
WaveFormSeekBarView waveFormView = (WaveFormSeekBarView) seekBar;
|
||||
waveFormView.setColors(waveFormPlayedBarsColor, waveFormUnplayedBarsColor);
|
||||
waveFormView.setColors(waveFormPlayedBarsColor, waveFormUnplayedBarsColor, waveFormThumbTint);
|
||||
if (android.os.Build.VERSION.SDK_INT >= 23) {
|
||||
new AudioWaveForm(getContext(), audio).getWaveForm(
|
||||
data -> {
|
||||
if (duration != null) {
|
||||
durationMillis = data.getDuration(TimeUnit.MILLISECONDS);
|
||||
updateProgress(0, 0);
|
||||
durationMillis = data.getDuration(TimeUnit.MILLISECONDS);
|
||||
updateProgress(0, 0);
|
||||
if (!forceHideDuration && duration != null) {
|
||||
duration.setVisibility(VISIBLE);
|
||||
}
|
||||
waveFormView.setWaveData(data.getWaveForm());
|
||||
|
@ -183,12 +194,21 @@ public final class AudioView extends FrameLayout {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (forceHideDuration && duration != null) {
|
||||
duration.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDownloadClickListener(@Nullable SlideClickListener listener) {
|
||||
this.downloadListener = listener;
|
||||
}
|
||||
|
||||
public @Nullable Uri getAudioSlideUri() {
|
||||
if (audioSlide != null) return audioSlide.getUri();
|
||||
else return null;
|
||||
}
|
||||
|
||||
private void onPlaybackState(@NonNull VoiceNotePlaybackState voiceNotePlaybackState) {
|
||||
onStart(voiceNotePlaybackState.getUri(), voiceNotePlaybackState.isAutoReset());
|
||||
onProgress(voiceNotePlaybackState.getUri(),
|
||||
|
@ -274,6 +294,10 @@ public final class AudioView extends FrameLayout {
|
|||
}
|
||||
|
||||
private void updateProgress(float progress, long millis) {
|
||||
if (callbacks != null) {
|
||||
callbacks.onProgressUpdated(durationMillis, millis);
|
||||
}
|
||||
|
||||
if (duration != null && durationMillis > 0) {
|
||||
long remainingSecs = TimeUnit.MILLISECONDS.toSeconds(durationMillis - millis);
|
||||
duration.setText(getResources().getString(R.string.AudioView_duration, remainingSecs / 60, remainingSecs % 60));
|
||||
|
@ -336,7 +360,7 @@ public final class AudioView extends FrameLayout {
|
|||
if (!smallView || seekBar.getProgress() == 0) {
|
||||
circleProgress.setInstantProgress(1);
|
||||
}
|
||||
circleProgress.setVisibility(VISIBLE);
|
||||
circleProgress.setVisibility(GONE);
|
||||
playPauseButton.setVisibility(VISIBLE);
|
||||
controlToggle.displayQuick(progressAndPlay);
|
||||
}
|
||||
|
@ -435,5 +459,6 @@ public final class AudioView extends FrameLayout {
|
|||
void onPause(@NonNull Uri audioUri);
|
||||
void onSeekTo(@NonNull Uri audioUri, double progress);
|
||||
void onStopAndReset(@NonNull Uri audioUri);
|
||||
void onProgressUpdated(long durationMillis, long playheadMillis);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.annotation.SuppressLint;
|
|||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.os.AsyncTask;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
@ -15,18 +16,26 @@ import android.widget.TextView;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
import com.airbnb.lottie.LottieProperty;
|
||||
import com.airbnb.lottie.model.KeyPath;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.dualsim.SubscriptionInfoCompat;
|
||||
import org.thoughtcrime.securesms.util.dualsim.SubscriptionManagerCompat;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ConversationItemFooter extends LinearLayout {
|
||||
|
||||
|
@ -36,6 +45,9 @@ public class ConversationItemFooter extends LinearLayout {
|
|||
private ImageView insecureIndicatorView;
|
||||
private DeliveryStatusView deliveryStatusView;
|
||||
private boolean onlyShowSendingStatus;
|
||||
private View audioSpace;
|
||||
private TextView audioDuration;
|
||||
private LottieAnimationView revealDot;
|
||||
|
||||
public ConversationItemFooter(Context context) {
|
||||
super(context);
|
||||
|
@ -60,11 +72,15 @@ public class ConversationItemFooter extends LinearLayout {
|
|||
timerView = findViewById(R.id.footer_expiration_timer);
|
||||
insecureIndicatorView = findViewById(R.id.footer_insecure_indicator);
|
||||
deliveryStatusView = findViewById(R.id.footer_delivery_status);
|
||||
audioDuration = findViewById(R.id.footer_audio_duration);
|
||||
audioSpace = findViewById(R.id.footer_audio_duration_space);
|
||||
revealDot = findViewById(R.id.footer_revealed_dot);
|
||||
|
||||
if (attrs != null) {
|
||||
TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.ConversationItemFooter, 0, 0);
|
||||
setTextColor(typedArray.getInt(R.styleable.ConversationItemFooter_footer_text_color, getResources().getColor(R.color.core_white)));
|
||||
setIconColor(typedArray.getInt(R.styleable.ConversationItemFooter_footer_icon_color, getResources().getColor(R.color.core_white)));
|
||||
setRevealDotColor(typedArray.getInt(R.styleable.ConversationItemFooter_footer_reveal_dot_color, getResources().getColor(R.color.core_white)));
|
||||
typedArray.recycle();
|
||||
}
|
||||
}
|
||||
|
@ -81,11 +97,18 @@ public class ConversationItemFooter extends LinearLayout {
|
|||
presentTimer(messageRecord);
|
||||
presentInsecureIndicator(messageRecord);
|
||||
presentDeliveryStatus(messageRecord);
|
||||
hideAudioDurationViews();
|
||||
}
|
||||
|
||||
public void setAudioDuration(long totalDurationMillis, long currentPostionMillis) {
|
||||
long remainingSecs = TimeUnit.MILLISECONDS.toSeconds(totalDurationMillis - currentPostionMillis);
|
||||
audioDuration.setText(getResources().getString(R.string.AudioView_duration, remainingSecs / 60, remainingSecs % 60));
|
||||
}
|
||||
|
||||
public void setTextColor(int color) {
|
||||
dateView.setTextColor(color);
|
||||
simView.setTextColor(color);
|
||||
audioDuration.setTextColor(color);
|
||||
}
|
||||
|
||||
public void setIconColor(int color) {
|
||||
|
@ -94,6 +117,14 @@ public class ConversationItemFooter extends LinearLayout {
|
|||
deliveryStatusView.setTint(color);
|
||||
}
|
||||
|
||||
public void setRevealDotColor(int color) {
|
||||
revealDot.addValueCallback(
|
||||
new KeyPath("**"),
|
||||
LottieProperty.COLOR_FILTER,
|
||||
frameInfo -> new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)
|
||||
);
|
||||
}
|
||||
|
||||
public void setOnlyShowSendingStatus(boolean onlyShowSending, MessageRecord messageRecord) {
|
||||
this.onlyShowSendingStatus = onlyShowSending;
|
||||
presentDeliveryStatus(messageRecord);
|
||||
|
@ -204,4 +235,64 @@ public class ConversationItemFooter extends LinearLayout {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void presentAudioDuration(@NonNull MessageRecord messageRecord) {
|
||||
if (messageRecord.isMms()) {
|
||||
MmsMessageRecord mmsMessageRecord = (MmsMessageRecord) messageRecord;
|
||||
|
||||
if (mmsMessageRecord.getSlideDeck().getAudioSlide() != null) {
|
||||
if (messageRecord.isOutgoing()) {
|
||||
moveAudioViewsForOutgoing();
|
||||
} else {
|
||||
moveAudioViewsForIncoming();
|
||||
}
|
||||
showAudioDurationViews();
|
||||
} else {
|
||||
hideAudioDurationViews();
|
||||
}
|
||||
} else {
|
||||
hideAudioDurationViews();
|
||||
}
|
||||
}
|
||||
|
||||
private void moveAudioViewsForOutgoing() {
|
||||
removeView(audioSpace);
|
||||
removeView(audioDuration);
|
||||
removeView(revealDot);
|
||||
addView(audioSpace, 0);
|
||||
addView(revealDot, 0);
|
||||
addView(audioDuration, 0);
|
||||
|
||||
int padStart = ViewUtil.dpToPx(60);
|
||||
int padLeft = getLayoutDirection() == LAYOUT_DIRECTION_LTR ? padStart : 0;
|
||||
int padRight = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? padStart : 0;
|
||||
|
||||
audioDuration.setPadding(padLeft, 0, padRight, 0);
|
||||
}
|
||||
|
||||
private void moveAudioViewsForIncoming() {
|
||||
removeView(audioSpace);
|
||||
removeView(audioDuration);
|
||||
removeView(revealDot);
|
||||
addView(audioSpace);
|
||||
addView(revealDot);
|
||||
addView(audioDuration);
|
||||
|
||||
audioDuration.setPadding(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
private void showAudioDurationViews() {
|
||||
audioSpace.setVisibility(View.VISIBLE);
|
||||
audioDuration.setVisibility(View.VISIBLE);
|
||||
|
||||
if (FeatureFlags.viewedReceipts()) {
|
||||
revealDot.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void hideAudioDurationViews() {
|
||||
audioSpace.setVisibility(View.GONE);
|
||||
audioDuration.setVisibility(View.GONE);
|
||||
revealDot.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.components;
|
|||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.animation.Interpolator;
|
||||
|
@ -13,6 +14,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Px;
|
||||
import androidx.appcompat.widget.AppCompatSeekBar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
|
@ -65,9 +67,12 @@ public final class WaveFormSeekBarView extends AppCompatSeekBar {
|
|||
barWidth = getResources().getDimensionPixelSize(R.dimen.wave_form_bar_width);
|
||||
}
|
||||
|
||||
public void setColors(@ColorInt int playedBarColor, @ColorInt int unplayedBarColor) {
|
||||
public void setColors(@ColorInt int playedBarColor, @ColorInt int unplayedBarColor, @ColorInt int thumbTint) {
|
||||
this.playedBarColor = playedBarColor;
|
||||
this.unplayedBarColor = unplayedBarColor;
|
||||
|
||||
getThumb().setColorFilter(thumbTint, PorterDuff.Mode.SRC_IN);
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,8 @@ final class VoiceNotePlaybackPreparer implements MediaSessionConnector.PlaybackP
|
|||
|
||||
@Override
|
||||
public void onPrepareFromUri(final Uri uri, Bundle extras) {
|
||||
Log.d(TAG, "onPrepareFromUri: " + uri);
|
||||
|
||||
long messageId = extras.getLong(VoiceNoteMediaController.EXTRA_MESSAGE_ID);
|
||||
double progress = extras.getDouble(VoiceNoteMediaController.EXTRA_PROGRESS, 0);
|
||||
boolean singlePlayback = extras.getBoolean(VoiceNoteMediaController.EXTRA_PLAY_SINGLE, false);
|
||||
|
|
|
@ -10,6 +10,7 @@ import android.os.Bundle;
|
|||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.support.v4.media.MediaBrowserCompat;
|
||||
import android.support.v4.media.MediaDescriptionCompat;
|
||||
import android.support.v4.media.session.MediaControllerCompat;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
|
@ -162,7 +163,16 @@ public class VoiceNotePlaybackService extends MediaBrowserServiceCompat {
|
|||
|
||||
@Override
|
||||
public void onPositionDiscontinuity(int reason) {
|
||||
int currentWindowIndex = player.getCurrentWindowIndex();
|
||||
int currentWindowIndex = player.getCurrentWindowIndex();
|
||||
if (currentWindowIndex == C.INDEX_UNSET) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reason == Player.DISCONTINUITY_REASON_PERIOD_TRANSITION) {
|
||||
MediaDescriptionCompat mediaDescriptionCompat = queueDataAdapter.getMediaDescription(currentWindowIndex);
|
||||
Log.d(TAG, "onPositionDiscontinuity: current window uri: " + mediaDescriptionCompat.getMediaUri());
|
||||
}
|
||||
|
||||
boolean isWithinThreshold = currentWindowIndex < LOAD_MORE_THRESHOLD ||
|
||||
currentWindowIndex + LOAD_MORE_THRESHOLD >= queueDataAdapter.size();
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@ import org.thoughtcrime.securesms.jobs.SmsSendJob;
|
|||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.AudioSlide;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.ImageSlide;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
|
@ -112,6 +113,7 @@ import org.thoughtcrime.securesms.util.DateUtils;
|
|||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.InterceptableLongClickCopyLinkSpan;
|
||||
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
|
||||
import org.thoughtcrime.securesms.util.MessageRecordUtil;
|
||||
import org.thoughtcrime.securesms.util.SearchUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||
|
@ -127,6 +129,7 @@ import java.util.Collections;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.thoughtcrime.securesms.util.ThemeUtil.isDarkTheme;
|
||||
|
@ -408,6 +411,7 @@ public class ConversationItem extends LinearLayout implements BindableConversati
|
|||
}
|
||||
cancelPulseOutlinerAnimation();
|
||||
if (eventListener != null && audioViewStub.resolved()) {
|
||||
Log.d(TAG, "unbind: unregistering voice note callbacks for audio slide " + audioViewStub.get().getAudioSlideUri());
|
||||
eventListener.onUnregisterVoiceNoteCallbacks(audioViewStub.get().getPlaybackStateObserver());
|
||||
}
|
||||
}
|
||||
|
@ -659,6 +663,7 @@ public class ConversationItem extends LinearLayout implements BindableConversati
|
|||
boolean showControls = !messageRecord.isFailed();
|
||||
|
||||
if (eventListener != null && audioViewStub.resolved()) {
|
||||
Log.d(TAG, "setMediaAttributes: unregistering voice note callbacks for audio slide " + audioViewStub.get().getAudioSlideUri());
|
||||
eventListener.onUnregisterVoiceNoteCallbacks(audioViewStub.get().getPlaybackStateObserver());
|
||||
}
|
||||
|
||||
|
@ -744,13 +749,15 @@ public class ConversationItem extends LinearLayout implements BindableConversati
|
|||
if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE);
|
||||
if (revealableStub.resolved()) revealableStub.get().setVisibility(View.GONE);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
audioViewStub.get().setAudio(((MediaMmsMessageRecord) messageRecord).getSlideDeck().getAudioSlide(), new AudioViewCallbacks(), showControls);
|
||||
audioViewStub.get().setAudio(Objects.requireNonNull(((MediaMmsMessageRecord) messageRecord).getSlideDeck().getAudioSlide()), new AudioViewCallbacks(), showControls, false);
|
||||
audioViewStub.get().setDownloadClickListener(singleDownloadClickListener);
|
||||
audioViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
|
||||
if (eventListener != null) {
|
||||
Log.d(TAG, "setMediaAttributes: registered listener for audio slide " + audioViewStub.get().getAudioSlideUri());
|
||||
eventListener.onRegisterVoiceNoteCallbacks(audioViewStub.get().getPlaybackStateObserver());
|
||||
} else {
|
||||
Log.w(TAG, "setMediaAttributes: could not register listener for audio slide " + audioViewStub.get().getAudioSlideUri());
|
||||
}
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
|
@ -1572,6 +1579,11 @@ public class ConversationItem extends LinearLayout implements BindableConversati
|
|||
public void onStopAndReset(@NonNull Uri audioUri) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressUpdated(long durationMillis, long playheadMillis) {
|
||||
footer.setAudioDuration(durationMillis, playheadMillis);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMessageApproval() {
|
||||
|
|
|
@ -440,7 +440,7 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
long mmsId = Objects.requireNonNull(mediaRecord.getAttachment()).getMmsId();
|
||||
|
||||
audioItemListener.unregisterPlaybackStateObserver(audioView.getPlaybackStateObserver());
|
||||
audioView.setAudio((AudioSlide) slide, new AudioViewCallbacksAdapter(audioItemListener, mmsId), true);
|
||||
audioView.setAudio((AudioSlide) slide, new AudioViewCallbacksAdapter(audioItemListener, mmsId), true, true);
|
||||
audioItemListener.registerPlaybackStateObserver(audioView.getPlaybackStateObserver());
|
||||
|
||||
audioView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
|
||||
|
@ -520,6 +520,10 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
public void onStopAndReset(@NonNull Uri audioUri) {
|
||||
audioItemListener.onStopAndReset(audioUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressUpdated(long durationMillis, long playheadMillis) {
|
||||
}
|
||||
}
|
||||
|
||||
interface ItemClickListener {
|
||||
|
|
|
@ -277,7 +277,7 @@ public class AttachmentManager {
|
|||
attachmentViewStub.get().setVisibility(View.VISIBLE);
|
||||
|
||||
if (slide.hasAudio()) {
|
||||
audioView.setAudio((AudioSlide) slide, null, false);
|
||||
audioView.setAudio((AudioSlide) slide, null, false, false);
|
||||
removableMediaView.display(audioView, false);
|
||||
result.set(true);
|
||||
} else if (slide.hasDocument()) {
|
||||
|
|
|
@ -59,6 +59,7 @@ public final class FeatureFlags {
|
|||
private static final String CLIENT_EXPIRATION = "android.clientExpiration";
|
||||
public static final String RESEARCH_MEGAPHONE_1 = "research.megaphone.1";
|
||||
public static final String MODERN_PROFILE_SHARING = "android.modernProfileSharing";
|
||||
private static final String VIEWED_RECEIPTS = "android.viewed.receipts";
|
||||
|
||||
/**
|
||||
* We will only store remote values for flags in this set. If you want a flag to be controllable
|
||||
|
@ -75,7 +76,8 @@ public final class FeatureFlags {
|
|||
VERIFY_V2,
|
||||
CLIENT_EXPIRATION,
|
||||
RESEARCH_MEGAPHONE_1,
|
||||
MODERN_PROFILE_SHARING
|
||||
MODERN_PROFILE_SHARING,
|
||||
VIEWED_RECEIPTS
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -243,6 +245,13 @@ public final class FeatureFlags {
|
|||
return getBoolean(MODERN_PROFILE_SHARING, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the user should display the content revealed dot in voice notes.
|
||||
*/
|
||||
public static boolean viewedReceipts() {
|
||||
return getBoolean(VIEWED_RECEIPTS, false);
|
||||
}
|
||||
|
||||
/** Only for rendering debug info. */
|
||||
public static synchronized @NonNull Map<String, Object> getMemoryValues() {
|
||||
return new TreeMap<>(REMOTE_VALUES);
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<size android:height="6dp" android:width="6dp" />
|
||||
<solid android:color="@color/white" />
|
||||
</shape>
|
9
app/src/main/res/drawable/audio_wave_thumb.xml
Normal file
9
app/src/main/res/drawable/audio_wave_thumb.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle"
|
||||
android:thickness="2dp"
|
||||
android:useLevel="false">
|
||||
<size android:width="2dp" android:height="28dp" />
|
||||
<corners android:radius="30dp" />
|
||||
<solid android:color="@color/white" />
|
||||
</shape>
|
|
@ -18,9 +18,10 @@
|
|||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="10dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:thumb="@drawable/audio_wave_thumb"
|
||||
tools:progress="50" />
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:padding="2dp"
|
||||
android:gravity="center"
|
||||
tools:showIn="@layout/audio_view">
|
||||
|
||||
<FrameLayout
|
||||
android:background="@drawable/circle_tintable"
|
||||
android:id="@+id/progress_and_play"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
@ -25,8 +27,8 @@
|
|||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/play"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/circle_touch_highlight_background"
|
||||
android:contentDescription="@string/audio_view__play_pause_accessibility_description"
|
||||
|
|
|
@ -1,65 +1,93 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical|end"
|
||||
android:orientation="horizontal"
|
||||
tools:parentTag="org.thoughtcrime.securesms.components.ConversationItemFooter">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/footer_audio_duration"
|
||||
style="@style/Signal.Text.Caption.MessageSent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
tools:text="0:00"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/footer_revealed_dot"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:visibility="gone"
|
||||
app:lottie_rawRes="@raw/lottie_played"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Space
|
||||
android:id="@+id/footer_audio_duration_space"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/footer_date"
|
||||
android:autoLink="none"
|
||||
style="@style/Signal.Text.Caption.MessageSent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="none"
|
||||
android:linksClickable="false"
|
||||
style="@style/Signal.Text.Caption.MessageSent"
|
||||
android:textColor="?conversation_item_sent_text_secondary_color"
|
||||
tools:text="30m"/>
|
||||
tools:text="30m" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.ExpirationTimerView
|
||||
android:id="@+id/footer_expiration_timer"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="12dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="4dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/footer_sim_info"
|
||||
android:autoLink="none"
|
||||
style="@style/Signal.Text.Caption.MessageSent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="4dp"
|
||||
android:autoLink="none"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:linksClickable="false"
|
||||
android:maxWidth="140dp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:linksClickable="false"
|
||||
style="@style/Signal.Text.Caption.MessageSent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
tools:text="to SIM1" />
|
||||
tools:text="to SIM1"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/footer_insecure_indicator"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="11dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="4dp"
|
||||
android:contentDescription="@string/conversation_item__secure_message_description"
|
||||
android:src="@drawable/ic_unlocked_white_18dp"
|
||||
android:visibility="gone"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:contentDescription="@string/conversation_item__secure_message_description"
|
||||
tools:visibility="visible"/>
|
||||
tools:visibility="visible" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.DeliveryStatusView
|
||||
android:id="@+id/footer_delivery_status"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="4dp" />
|
||||
|
||||
</merge>
|
||||
|
|
|
@ -11,4 +11,5 @@
|
|||
app:backgroundTintColor="@color/blue_500"
|
||||
app:waveformPlayedBarsColor="@color/core_white"
|
||||
app:waveformUnplayedBarsColor="@color/transparent_white_40"
|
||||
app:progressAndPlayTint="@color/transparent_white_20"
|
||||
tools:visibility="visible"/>
|
||||
|
|
|
@ -203,6 +203,7 @@
|
|||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:alpha="0.7"
|
||||
app:footer_reveal_dot_color="@color/core_white"
|
||||
app:footer_text_color="?conversation_item_received_text_secondary_color"
|
||||
app:footer_icon_color="?conversation_item_received_text_secondary_color"/>
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
android:layout_height="wrap_content"
|
||||
app:foregroundTintColor="@color/grey_500"
|
||||
app:backgroundTintColor="@color/white"
|
||||
app:waveformPlayedBarsColor="@color/core_ultramarine_light"
|
||||
app:waveformUnplayedBarsColor="@color/core_grey_25"
|
||||
app:waveformThumbTint="?attr/audio_seek_bar_sent_played_color"
|
||||
app:waveformPlayedBarsColor="?attr/audio_seek_bar_sent_played_color"
|
||||
app:waveformUnplayedBarsColor="?attr/audio_seek_bar_sent_unplayed_color"
|
||||
app:progressAndPlayTint="?attr/audio_play_pause_sent_background_tint"
|
||||
android:visibility="gone"/>
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:gravity="end"
|
||||
app:footer_reveal_dot_color="?attr/conversation_footer_sent_reveal_dot_color"
|
||||
app:footer_icon_color="?attr/conversation_item_sent_icon_color"
|
||||
app:footer_text_color="?attr/conversation_item_sent_text_secondary_color" />
|
||||
|
||||
|
|
1
app/src/main/res/raw/lottie_played.json
Normal file
1
app/src/main/res/raw/lottie_played.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"v":"5.7.1","fr":29.9700012207031,"ip":0,"op":40.0000016292334,"w":16,"h":16,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[8,8,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[37.5,37.5,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":18,"s":[56.25,56.25,100]},{"t":29.0000011811942,"s":[0,0,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[16.002,16.002],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0.032,0.001],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"bm":0}],"markers":[{"tm":63.0000025660426,"cm":"1","dr":0}]}
|
|
@ -11,6 +11,4 @@
|
|||
<dimen name="album_5_total_height">250dp</dimen>
|
||||
<dimen name="album_5_cell_size_big">149dp</dimen>
|
||||
<dimen name="album_5_cell_size_small">99dp</dimen>
|
||||
|
||||
<dimen name="message_audio_width">260dp</dimen>
|
||||
</resources>
|
|
@ -94,6 +94,7 @@
|
|||
<attr name="conversation_number_picker_text_color_selected" format="reference|color"/>
|
||||
<attr name="conversation_sticker_footer_text_color" format="reference|color"/>
|
||||
<attr name="conversation_sticker_footer_icon_color" format="reference|color"/>
|
||||
<attr name="conversation_footer_sent_reveal_dot_color" format="color" />
|
||||
<attr name="conversation_sticker_author_color" format="reference|color"/>
|
||||
<attr name="conversation_popup_theme" format="reference"/>
|
||||
<attr name="conversation_title_color" format="reference" />
|
||||
|
@ -141,6 +142,10 @@
|
|||
|
||||
<attr name="compose_icon_tint" />
|
||||
|
||||
<attr name="audio_seek_bar_sent_played_color" format="color" />
|
||||
<attr name="audio_seek_bar_sent_unplayed_color" format="color" />
|
||||
<attr name="audio_play_pause_sent_background_tint" format="color" />
|
||||
|
||||
<attr name="conversation_item_background" format="reference"/>
|
||||
<attr name="conversation_item_bubble_background" format="reference|color"/>
|
||||
<attr name="conversation_item_sent_text_primary_color" format="reference|color"/>
|
||||
|
@ -387,8 +392,10 @@
|
|||
<declare-styleable name="AudioView">
|
||||
<attr name="foregroundTintColor" format="color" />
|
||||
<attr name="backgroundTintColor" format="color" />
|
||||
<attr name="waveformThumbTint" format="color" />
|
||||
<attr name="waveformPlayedBarsColor" format="color" />
|
||||
<attr name="waveformUnplayedBarsColor" format="color" />
|
||||
<attr name="progressAndPlayTint" format="color" />
|
||||
<attr name="small" format="boolean" />
|
||||
<attr name="autoRewind" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
@ -486,6 +493,7 @@
|
|||
<declare-styleable name="ConversationItemFooter">
|
||||
<attr name="footer_text_color" format="color" />
|
||||
<attr name="footer_icon_color" format="color" />
|
||||
<attr name="footer_reveal_dot_color" format="color" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="ConversationItemThumbnail">
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<dimen name="media_bubble_min_height">100dp</dimen>
|
||||
<dimen name="media_bubble_max_height">320dp</dimen>
|
||||
<dimen name="media_bubble_sticker_dimens">175dp</dimen>
|
||||
<dimen name="message_audio_width">210dp</dimen>
|
||||
<dimen name="message_audio_width">242dp</dimen>
|
||||
|
||||
<dimen name="media_picker_folder_width">175dp</dimen>
|
||||
<dimen name="media_picker_item_width">85dp</dimen>
|
||||
|
|
|
@ -1505,7 +1505,7 @@
|
|||
<string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string>
|
||||
|
||||
<!-- AudioView -->
|
||||
<string name="AudioView_duration" translatable="false">%1$02d:%2$02d</string>
|
||||
<string name="AudioView_duration" translatable="false">%1$d:%2$02d</string>
|
||||
|
||||
<!-- MessageDisplayHelper -->
|
||||
<string name="MessageDisplayHelper_bad_encrypted_message">Bad encrypted message</string>
|
||||
|
|
|
@ -167,6 +167,10 @@
|
|||
<item name="backup_enable_dialog_divider_background">@color/core_grey_20</item>
|
||||
<item name="backup_enable_subhead_color">@color/core_grey_65</item>
|
||||
|
||||
<item name="audio_seek_bar_sent_played_color">@color/core_grey_60</item>
|
||||
<item name="audio_seek_bar_sent_unplayed_color">@color/core_grey_25</item>
|
||||
<item name="audio_play_pause_sent_background_tint">@color/core_white</item>
|
||||
|
||||
<item name="insight_modal_background">@drawable/insights_modal_background</item>
|
||||
<item name="insight_modal_button_background">@color/core_grey_10</item>
|
||||
<item name="insight_title">@color/core_grey_90</item>
|
||||
|
@ -272,6 +276,7 @@
|
|||
<item name="conversation_number_picker_text_color_selected">@color/black</item>
|
||||
<item name="conversation_sticker_footer_text_color">@color/core_grey_60</item>
|
||||
<item name="conversation_sticker_footer_icon_color">@color/core_grey_60</item>
|
||||
<item name="conversation_footer_sent_reveal_dot_color">@color/core_grey_60</item>
|
||||
<item name="conversation_sticker_author_color">@color/core_grey_95</item>
|
||||
<item name="conversation_popup_theme">@style/ThemeOverlay.AppCompat.Light</item>
|
||||
<item name="conversation_title_color">@color/white</item>
|
||||
|
@ -502,6 +507,10 @@
|
|||
<item name="backup_enable_dialog_divider_background">@color/core_grey_60</item>
|
||||
<item name="backup_enable_subhead_color">@color/core_grey_25</item>
|
||||
|
||||
<item name="audio_seek_bar_sent_played_color">@color/core_grey_15</item>
|
||||
<item name="audio_seek_bar_sent_unplayed_color">@color/core_grey_60</item>
|
||||
<item name="audio_play_pause_sent_background_tint">@color/core_grey_60</item>
|
||||
|
||||
<item name="insight_modal_background">@drawable/insights_modal_background_dark</item>
|
||||
<item name="insight_modal_button_background">@color/core_grey_60</item>
|
||||
<item name="insight_title">@color/core_grey_25</item>
|
||||
|
@ -661,6 +670,7 @@
|
|||
<item name="conversation_number_picker_text_color_selected">@color/white</item>
|
||||
<item name="conversation_sticker_footer_text_color">@color/core_grey_25</item>
|
||||
<item name="conversation_sticker_footer_icon_color">@color/core_grey_25</item>
|
||||
<item name="conversation_footer_sent_reveal_dot_color">@color/core_grey_25</item>
|
||||
<item name="conversation_sticker_author_color">@color/core_grey_05</item>
|
||||
<item name="conversation_popup_theme">@style/ThemeOverlay.AppCompat.Dark</item>
|
||||
<item name="conversation_title_color">@color/transparent_white_90</item>
|
||||
|
|
Loading…
Add table
Reference in a new issue