Messaging: Let there be lambdas

Change-Id: Iee1fc46c92ea9159abb10d92d34baee937bdee0c
This commit is contained in:
Michael W
2024-12-26 14:55:12 +01:00
parent c1b4aa4dfe
commit d43b6ff1c4
84 changed files with 991 additions and 1697 deletions
@@ -85,7 +85,7 @@ public class AsyncImageView extends ImageView implements MediaResourceLoadListen
// setting is null (no placeholder).
private final Drawable mPlaceholderDrawable;
protected ImageResource mImageResource;
private final Runnable mDisposeRunnable = new Runnable() {
private final Runnable mDisposeRunnable = () -> new Runnable() {
@Override
public void run() {
if (mImageRequestBinding.isBound()) {
@@ -71,35 +71,22 @@ public class AttachmentPreview extends ScrollView implements OnAttachmentClickLi
protected void onFinishInflate() {
super.onFinishInflate();
mCloseButton = (ImageButton) findViewById(R.id.close_button);
mCloseButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {
mComposeMessageView.clearAttachments();
}
});
mCloseButton.setOnClickListener(view -> mComposeMessageView.clearAttachments());
mAttachmentView = (FrameLayout) findViewById(R.id.attachment_view);
// The attachment preview is a scroll view so that it can show the bottom portion of the
// attachment whenever the space is tight (e.g. when in landscape mode). Per design
// request we'd like to make the attachment view always scrolled to the bottom.
addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(final View v, final int left, final int top, final int right,
final int bottom, final int oldLeft, final int oldTop, final int oldRight,
final int oldBottom) {
post(new Runnable() {
@Override
public void run() {
final int childCount = getChildCount();
if (childCount > 0) {
final View lastChild = getChildAt(childCount - 1);
scrollTo(getScrollX(), lastChild.getBottom() - getHeight());
}
}
});
addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
oldBottom) -> post(() ->
{
final int childCount = getChildCount();
if (childCount > 0) {
final View lastChild = getChildAt(childCount - 1);
scrollTo(getScrollX(), lastChild.getBottom() - getHeight());
}
});
}));
mPendingFirstUpdate = true;
}
@@ -129,18 +116,14 @@ public class AttachmentPreview extends ScrollView implements OnAttachmentClickLi
mPendingHideCanceled = false;
final View viewToHide = mAttachmentView.getChildCount() > 1 ?
mAttachmentView : mAttachmentView.getChildAt(0);
UiUtils.revealOrHideViewWithAnimation(viewToHide, INVISIBLE,
new Runnable() {
@Override
public void run() {
// Only hide if we are didn't get overruled by showing
if (!mPendingHideCanceled) {
stopPopupAnimation();
mAttachmentView.removeAllViews();
setVisibility(GONE);
}
}
});
UiUtils.revealOrHideViewWithAnimation(viewToHide, INVISIBLE, () -> {
// Only hide if we are didn't get overruled by showing
if (!mPendingHideCanceled) {
stopPopupAnimation();
mAttachmentView.removeAllViews();
setVisibility(GONE);
}
});
} else {
mAttachmentView.removeAllViews();
setVisibility(GONE);
@@ -164,14 +147,11 @@ public class AttachmentPreview extends ScrollView implements OnAttachmentClickLi
.getQuantityString(R.plurals.attachment_preview_close_content_description,
combinedAttachmentCount));
if (combinedAttachmentCount == 0) {
mHideRunnable = new Runnable() {
@Override
public void run() {
mHideRunnable = null;
// Only start the hiding if there are still no attachments
if (attachments.size() + pendingAttachments.size() == 0) {
hideAttachmentPreview();
}
mHideRunnable = () -> {
mHideRunnable = null;
// Only start the hiding if there are still no attachments
if (attachments.size() + pendingAttachments.size() == 0) {
hideAttachmentPreview();
}
};
if (draftMessageData.isSending()) {
@@ -196,13 +176,11 @@ public class AttachmentPreview extends ScrollView implements OnAttachmentClickLi
if (!isFirstUpdate) {
// Reveal the close button after the view animates in.
mCloseButton.setVisibility(INVISIBLE);
ThreadUtil.getMainThreadHandler().postDelayed(new Runnable() {
@Override
public void run() {
ThreadUtil.getMainThreadHandler().postDelayed(() ->
UiUtils.revealOrHideViewWithAnimation(mCloseButton, VISIBLE,
null /* onFinishRunnable */);
}
}, UiUtils.MEDIAPICKER_TRANSITION_DURATION + CLOSE_BUTTON_REVEAL_STAGGER_MILLIS);
null /* onFinishRunnable */),
UiUtils.MEDIAPICKER_TRANSITION_DURATION +
CLOSE_BUTTON_REVEAL_STAGGER_MILLIS);
}
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,8 +24,6 @@ import androidx.annotation.Nullable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.FrameLayout.LayoutParams;
import android.widget.ImageView;
@@ -93,22 +92,16 @@ public class AttachmentPreviewFactory {
}
if (attachmentView != null && clickListener != null) {
attachmentView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {
final Rect bounds = UiUtils.getMeasuredBoundsOnScreen(view);
clickListener.onAttachmentClick(attachmentData, bounds,
false /* longPress */);
}
});
attachmentView.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(final View view) {
final Rect bounds = UiUtils.getMeasuredBoundsOnScreen(view);
return clickListener.onAttachmentClick(attachmentData, bounds,
true /* longPress */);
}
});
attachmentView.setOnClickListener(view -> {
final Rect bounds = UiUtils.getMeasuredBoundsOnScreen(view);
clickListener.onAttachmentClick(attachmentData, bounds,
false /* longPress */);
});
attachmentView.setOnLongClickListener(view -> {
final Rect bounds = UiUtils.getMeasuredBoundsOnScreen(view);
return clickListener.onAttachmentClick(attachmentData, bounds,
true /* longPress */);
});
}
return attachmentView;
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,9 +23,6 @@ import android.graphics.Path;
import android.graphics.RectF;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.SystemClock;
import android.text.TextUtils;
@@ -106,32 +104,29 @@ public class AudioAttachmentView extends LinearLayout {
mPlayPauseButton = (AudioAttachmentPlayPauseButton) findViewById(R.id.play_pause_button);
mChronometer = (PausableChronometer) findViewById(R.id.timer);
mProgressBar = (AudioPlaybackProgressBar) findViewById(R.id.progress);
mPlayPauseButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
// Has the MediaPlayer already been prepared?
if (mMediaPlayer != null && mPrepared) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
mChronometer.pause();
mProgressBar.pause();
} else {
playAudio();
}
mPlayPauseButton.setOnClickListener(v -> {
// Has the MediaPlayer already been prepared?
if (mMediaPlayer != null && mPrepared) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
mChronometer.pause();
mProgressBar.pause();
} else {
// Either eager preparation is still going on (the user must have clicked
// the Play button immediately after the view is bound) or this is lazy
// preparation.
if (mStartPlayAfterPrepare) {
// The user is (starting and) pausing before the MediaPlayer is prepared
mStartPlayAfterPrepare = false;
} else {
mStartPlayAfterPrepare = true;
setupMediaPlayer();
}
playAudio();
}
} else {
// Either eager preparation is still going on (the user must have clicked
// the Play button immediately after the view is bound) or this is lazy
// preparation.
if (mStartPlayAfterPrepare) {
// The user is (starting and) pausing before the MediaPlayer is prepared
mStartPlayAfterPrepare = false;
} else {
mStartPlayAfterPrepare = true;
setupMediaPlayer();
}
updatePlayPauseButtonState();
}
updatePlayPauseButtonState();
});
updatePlayPauseButtonState();
initializeViewsForMode();
@@ -217,47 +212,38 @@ public class AudioAttachmentView extends LinearLayout {
try {
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setDataSource(Factory.get().getApplicationContext(), mDataSourceUri);
mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(final MediaPlayer mp) {
updatePlayPauseButtonState();
mChronometer.reset();
mChronometer.setBase(SystemClock.elapsedRealtime() -
mMediaPlayer.getDuration());
updateChronometerVisibility(false /* playing */);
mProgressBar.reset();
mMediaPlayer.setOnCompletionListener(mp -> {
updatePlayPauseButtonState();
mChronometer.reset();
mChronometer.setBase(SystemClock.elapsedRealtime() -
mMediaPlayer.getDuration());
updateChronometerVisibility(false /* playing */);
mProgressBar.reset();
mPlaybackFinished = true;
}
mPlaybackFinished = true;
});
mMediaPlayer.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(final MediaPlayer mp) {
// Set base on the chronometer so we can show the full length of the audio.
mChronometer.setBase(SystemClock.elapsedRealtime() -
mMediaPlayer.getDuration());
mProgressBar.setDuration(mMediaPlayer.getDuration());
mMediaPlayer.seekTo(0);
mPrepared = true;
mMediaPlayer.setOnPreparedListener(mp -> {
// Set base on the chronometer so we can show the full length of the audio.
mChronometer.setBase(SystemClock.elapsedRealtime() -
mMediaPlayer.getDuration());
mProgressBar.setDuration(mMediaPlayer.getDuration());
mMediaPlayer.seekTo(0);
mPrepared = true;
if (mStartPlayAfterPrepare) {
mStartPlayAfterPrepare = false;
playAudio();
updatePlayPauseButtonState();
}
}
});
mMediaPlayer.setOnErrorListener(new OnErrorListener() {
@Override
public boolean onError(final MediaPlayer mp, final int what, final int extra) {
if (mStartPlayAfterPrepare) {
mStartPlayAfterPrepare = false;
onAudioReplayError(what, extra, null);
return true;
playAudio();
updatePlayPauseButtonState();
}
});
mMediaPlayer.setOnErrorListener((mp, what, extra) -> {
mStartPlayAfterPrepare = false;
onAudioReplayError(what, extra, null);
return true;
});
mMediaPlayer.prepareAsync();
} catch (final Exception exception) {
onAudioReplayError(0, 0, exception);
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +18,6 @@ package com.android.messaging.ui;
import android.animation.ObjectAnimator;
import android.animation.TimeAnimator;
import android.animation.TimeAnimator.TimeListener;
import android.content.Context;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.Drawable;
@@ -41,18 +41,14 @@ public class AudioPlaybackProgressBar extends ProgressBar implements PlaybackSta
mUpdateAnimator = new TimeAnimator();
mUpdateAnimator.setRepeatCount(ObjectAnimator.INFINITE);
mUpdateAnimator.setTimeListener(new TimeListener() {
@Override
public void onTimeUpdate(final TimeAnimator animation, final long totalTime,
final long deltaTime) {
int progress = 0;
if (mDurationInMillis > 0) {
progress = (int) (((mCumulativeTime + SystemClock.elapsedRealtime() -
mCurrentPlayStartTime) * 1.0f / mDurationInMillis) * 100);
progress = Math.max(Math.min(progress, 100), 0);
}
setProgress(progress);
mUpdateAnimator.setTimeListener((animation, totalTime, deltaTime) -> {
int progress = 0;
if (mDurationInMillis > 0) {
progress = (int) (((mCumulativeTime + SystemClock.elapsedRealtime() -
mCurrentPlayStartTime) * 1.0f / mDurationInMillis) * 100);
progress = Math.max(Math.min(progress, 100), 0);
}
setProgress(progress);
});
updateAppearance();
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +20,6 @@ import android.content.Context;
import androidx.core.text.BidiFormatter;
import androidx.core.text.TextDirectionHeuristicsCompat;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -44,12 +44,7 @@ public class BlockedParticipantListItemView extends LinearLayout {
protected void onFinishInflate() {
mNameTextView = (TextView) findViewById(R.id.name);
mContactIconView = (ContactIconView) findViewById(R.id.contact_icon);
setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
mData.unblock(getContext());
}
});
setOnClickListener(v -> mData.unblock(getContext()));
}
public void bind(final ParticipantListItemData data) {
@@ -20,7 +20,6 @@ package com.android.messaging.ui;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle;
@@ -188,21 +187,15 @@ public class ClassZeroActivity extends Activity {
}
}
private final OnClickListener mCancelListener = new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int whichButton) {
dialog.dismiss();
processNextMessage();
}
private final OnClickListener mCancelListener = (dialog, whichButton) -> {
dialog.dismiss();
processNextMessage();
};
private final OnClickListener mSaveListener = new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int whichButton) {
mRead = true;
saveMessage();
dialog.dismiss();
processNextMessage();
}
private final OnClickListener mSaveListener = (dialog, whichButton) -> {
mRead = true;
saveMessage();
dialog.dismiss();
processNextMessage();
};
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +23,6 @@ import android.net.Uri;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.android.messaging.R;
import com.android.messaging.datamodel.data.ParticipantData;
@@ -134,13 +134,8 @@ public class ContactIconView extends AsyncImageView {
&& !TextUtils.isEmpty(mContactLookupKey)) ||
!TextUtils.isEmpty(mNormalizedDestination)) {
if (!mDisableClickHandler) {
setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
ContactUtil.showOrAddContact(view, mContactId, mContactLookupKey,
mAvatarUri, mNormalizedDestination);
}
});
setOnClickListener(view -> ContactUtil.showOrAddContact(view, mContactId,
mContactLookupKey, mAvatarUri, mNormalizedDestination));
}
} else {
// This should happen when the phone number is not in the user's contacts or it is a
@@ -24,7 +24,6 @@ import android.os.Bundle;
import android.os.SystemClock;
import android.provider.Settings;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -57,29 +56,16 @@ public class PermissionCheckActivity extends Activity {
setContentView(R.layout.permission_check_activity);
UiUtils.setStatusBarColor(this, getColor(R.color.permission_check_activity_background));
findViewById(R.id.exit).setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {
finish();
}
});
findViewById(R.id.exit).setOnClickListener(view -> finish());
mNextView = (TextView) findViewById(R.id.next);
mNextView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {
tryRequestPermission();
}
});
mNextView.setOnClickListener(view -> tryRequestPermission());
mSettingsView = (TextView) findViewById(R.id.settings);
mSettingsView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {
final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.parse(PACKAGE_URI_PREFIX + getPackageName()));
startActivity(intent);
}
mSettingsView.setOnClickListener(view -> {
final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.parse(PACKAGE_URI_PREFIX + getPackageName()));
startActivity(intent);
});
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -168,22 +169,16 @@ public class PersonItemView extends LinearLayout implements PersonItemDataListen
if (mListener == null) {
return;
}
setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
if (mListener != null && mBinding.isBound()) {
mListener.onPersonClicked(mBinding.getData());
}
setOnClickListener(v -> {
if (mListener != null && mBinding.isBound()) {
mListener.onPersonClicked(mBinding.getData());
}
});
final OnLongClickListener onLongClickListener = new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (mListener != null && mBinding.isBound()) {
return mListener.onPersonLongClicked(mBinding.getData());
}
return false;
final OnLongClickListener onLongClickListener = v -> {
if (mListener != null && mBinding.isBound()) {
return mListener.onPersonLongClicked(mBinding.getData());
}
return false;
};
setOnLongClickListener(onLongClickListener);
mContactIconView.setOnLongClickListener(onLongClickListener);
@@ -28,7 +28,6 @@ import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
@@ -108,12 +107,7 @@ public class SmsStorageLowWarningFragment extends Fragment {
builder.setTitle(R.string.sms_storage_low_title)
.setView(dialogLayout)
.setNegativeButton(R.string.ignore, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
.setNegativeButton(R.string.ignore, (dialog, id) -> dialog.cancel());
final Dialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
@@ -145,12 +139,9 @@ public class SmsStorageLowWarningFragment extends Fragment {
final String action = getItem(position);
actionItemView.setText(action);
actionItemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {
dismiss();
((SmsStorageLowWarningFragment) getTargetFragment()).confirm(position);
}
actionItemView.setOnClickListener(view1 -> {
dismiss();
((SmsStorageLowWarningFragment) getTargetFragment()).confirm(position);
});
return actionItemView;
}
@@ -191,25 +182,15 @@ public class SmsStorageLowWarningFragment extends Fragment {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.sms_storage_low_title)
.setMessage(getConfirmDialogMessage(actionIndex))
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog,
final int button) {
dismiss();
((SmsStorageLowWarningFragment) getTargetFragment()).cancel();
}
.setNegativeButton(android.R.string.cancel, (dialog, button) -> {
dismiss();
((SmsStorageLowWarningFragment) getTargetFragment()).cancel();
})
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog,
final int button) {
dismiss();
handleAction(actionIndex);
getActivity().finish();
SmsStorageStatusManager.cancelStorageLowNotification();
}
.setPositiveButton(android.R.string.ok, (dialog, button) -> {
dismiss();
handleAction(actionIndex);
getActivity().finish();
SmsStorageStatusManager.cancelStorageLowNotification();
});
return builder.create();
}
+4 -8
View File
@@ -22,7 +22,6 @@ import androidx.annotation.Nullable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -292,13 +291,10 @@ public class SnackBar {
} else {
mActionTextView.setVisibility(View.VISIBLE);
mActionTextView.setText(mAction.getActionLabel());
mActionTextView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
mAction.getActionRunnable().run();
if (mListener != null) {
mListener.onActionClick();
}
mActionTextView.setOnClickListener(v -> {
mAction.getActionRunnable().run();
if (mListener != null) {
mListener.onActionClick();
}
});
}
@@ -23,7 +23,6 @@ import android.os.Handler;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnAttachStateChangeListener;
@@ -34,7 +33,6 @@ import android.view.ViewPropertyAnimator;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
import android.widget.PopupWindow;
import android.widget.PopupWindow.OnDismissListener;
import androidx.annotation.NonNull;
@@ -66,28 +64,15 @@ public class SnackBarManager {
return sInstance;
}
private final Runnable mDismissRunnable = new Runnable() {
@Override
public void run() {
dismiss();
}
private final Runnable mDismissRunnable = this::dismiss;
private final OnTouchListener mDismissOnTouchListener = (view, event) -> {
// Dismiss the {@link SnackBar} but don't consume the event.
dismiss();
return false;
};
private final OnTouchListener mDismissOnTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(final View view, final MotionEvent event) {
// Dismiss the {@link SnackBar} but don't consume the event.
dismiss();
return false;
}
};
private final SnackBarListener mDismissOnUserTapListener = new SnackBarListener() {
@Override
public void onActionClick() {
dismiss();
}
};
private final SnackBarListener mDismissOnUserTapListener = this::dismiss;
private final OnAttachStateChangeListener mAttachStateChangeListener =
new OnAttachStateChangeListener() {
@@ -184,20 +169,12 @@ public class SnackBarManager {
// You'd expect PopupWindow.showAsDropDown to ensure the popup moves with the anchor
// view, which it does for scrolling, but not layout changes, so we have to manually
// update while the snackbar is showing
final OnGlobalLayoutListener listener = new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
final OnGlobalLayoutListener listener = () ->
mPopupWindow.update(anchorView, 0, getRelativeOffset(snackBar),
anchorView.getWidth(), LayoutParams.WRAP_CONTENT);
}
};
anchorView.getViewTreeObserver().addOnGlobalLayoutListener(listener);
mPopupWindow.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss() {
anchorView.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}
});
mPopupWindow.setOnDismissListener(() ->
anchorView.getViewTreeObserver().removeOnGlobalLayoutListener(listener));
mPopupWindow.showAsDropDown(anchorView, 0, getRelativeOffset(snackBar));
}
@@ -205,23 +182,20 @@ public class SnackBarManager {
// Animate the toast bar into view.
placeSnackBarOffScreen(snackBar);
animateSnackBarOnScreen(snackBar).withEndAction(new Runnable() {
@Override
public void run() {
mCurrentSnackBar.setEnabled(true);
makeCurrentSnackBarDismissibleOnTouch();
// Fire an accessibility event as needed
String snackBarText = snackBar.getMessageText();
if (!TextUtils.isEmpty(snackBarText) &&
TextUtils.getTrimmedLength(snackBarText) > 0) {
snackBarText = snackBarText.trim();
final String snackBarActionText = snackBar.getActionLabel();
if (!TextUtil.isAllWhitespace(snackBarActionText)) {
snackBarText = Joiner.on(", ").join(snackBarText, snackBarActionText);
}
AccessibilityUtil.announceForAccessibilityCompat(snackBar.getSnackBarView(),
null /*accessibilityManager*/, snackBarText);
animateSnackBarOnScreen(snackBar).withEndAction(() -> {
mCurrentSnackBar.setEnabled(true);
makeCurrentSnackBarDismissibleOnTouch();
// Fire an accessibility event as needed
String snackBarText = snackBar.getMessageText();
if (!TextUtils.isEmpty(snackBarText) &&
TextUtils.getTrimmedLength(snackBarText) > 0) {
snackBarText = snackBarText.trim();
final String snackBarActionText = snackBar.getActionLabel();
if (!TextUtil.isAllWhitespace(snackBarActionText)) {
snackBarText = Joiner.on(", ").join(snackBarText, snackBarActionText);
}
AccessibilityUtil.announceForAccessibilityCompat(snackBar.getSnackBarView(),
null /*accessibilityManager*/, snackBarText);
}
});
@@ -249,28 +223,25 @@ public class SnackBarManager {
// Animate the toast bar down.
final View rootView = snackBar.getRootView();
animateSnackBarOffScreen(snackBar).withEndAction(new Runnable() {
@Override
public void run() {
rootView.setVisibility(View.GONE);
try {
mPopupWindow.dismiss();
} catch (IllegalArgumentException e) {
// PopupWindow.dismiss() will fire an IllegalArgumentException if the activity
// has already ended while we were animating
}
snackBar.getParentView()
.removeOnAttachStateChangeListener(mAttachStateChangeListener);
animateSnackBarOffScreen(snackBar).withEndAction(() -> {
rootView.setVisibility(View.GONE);
try {
mPopupWindow.dismiss();
} catch (IllegalArgumentException e) {
// PopupWindow.dismiss() will fire an IllegalArgumentException if the activity
// has already ended while we were animating
}
snackBar.getParentView()
.removeOnAttachStateChangeListener(mAttachStateChangeListener);
mCurrentSnackBar = null;
mIsCurrentlyDismissing = false;
mCurrentSnackBar = null;
mIsCurrentlyDismissing = false;
// Show the next toast if one is waiting.
if (mNextSnackBar != null) {
final SnackBar localNextSnackBar = mNextSnackBar;
mNextSnackBar = null;
show(localNextSnackBar);
}
// Show the next toast if one is waiting.
if (mNextSnackBar != null) {
final SnackBar localNextSnackBar = mNextSnackBar;
mNextSnackBar = null;
show(localNextSnackBar);
}
});
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,11 +26,9 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import com.android.messaging.R;
import com.android.messaging.datamodel.DataModel;
@@ -73,34 +72,27 @@ public class VCardDetailFragment extends Fragment implements PersonItemDataListe
Assert.notNull(mVCardUri);
final View view = inflater.inflate(R.layout.vcard_detail_fragment, container, false);
mListView = (ExpandableListView) view.findViewById(R.id.list);
mListView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(final View v, final int left, final int top, final int right,
final int bottom, final int oldLeft, final int oldTop, final int oldRight,
final int oldBottom) {
mListView.setIndicatorBounds(mListView.getWidth() - getResources()
.getDimensionPixelSize(R.dimen.vcard_detail_group_indicator_width),
mListView.getWidth());
}
mListView.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
oldBottom) -> {
mListView.setIndicatorBounds(mListView.getWidth() - getResources().
getDimensionPixelSize(R.dimen.vcard_detail_group_indicator_width),
mListView.getWidth());
});
mListView.setOnChildClickListener(new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView expandableListView, View clickedView,
int groupPosition, int childPosition, long childId) {
if (!(clickedView instanceof PersonItemView)) {
return false;
}
final Intent intent = ((PersonItemView) clickedView).getClickIntent();
if (intent != null) {
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
return false;
}
return true;
}
mListView.setOnChildClickListener((expandableListView, clickedView, groupPosition,
childPosition, childId) -> {
if (!(clickedView instanceof PersonItemView)) {
return false;
}
final Intent intent = ((PersonItemView) clickedView).getClickIntent();
if (intent != null) {
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
return false;
}
return true;
}
return false;
});
mBinding.bind(DataModel.get().createVCardContactItemData(getActivity(), mVCardUri));
mBinding.getData().setListener(this);
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -95,15 +96,12 @@ public class VideoThumbnailView extends FrameLayout {
mVideoView.clearFocus();
addView(mVideoView, 0, new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(final MediaPlayer mediaPlayer) {
mVideoLoaded = true;
mVideoWidth = mediaPlayer.getVideoWidth();
mVideoHeight = mediaPlayer.getVideoHeight();
mediaPlayer.setLooping(loop);
trySwitchToVideo();
}
mVideoView.setOnPreparedListener(mediaPlayer -> {
mVideoLoaded = true;
mVideoWidth = mediaPlayer.getVideoWidth();
mVideoHeight = mediaPlayer.getVideoHeight();
mediaPlayer.setLooping(loop);
trySwitchToVideo();
});
mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
@@ -111,12 +109,7 @@ public class VideoThumbnailView extends FrameLayout {
mPlayButton.setVisibility(View.VISIBLE);
}
});
mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(final MediaPlayer mediaPlayer, final int i, final int i2) {
return true;
}
});
mVideoView.setOnErrorListener((mediaPlayer, i, i2) -> true);
} else {
mVideoView = null;
}
@@ -125,28 +118,22 @@ public class VideoThumbnailView extends FrameLayout {
if (loop) {
mPlayButton.setVisibility(View.GONE);
} else {
mPlayButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {
if (mVideoSource == null) {
return;
}
mPlayButton.setOnClickListener(view -> {
if (mVideoSource == null) {
return;
}
if (mMode == MODE_PLAYABLE_VIDEO) {
mVideoView.seekTo(0);
start();
} else {
UIIntents.get().launchFullScreenVideoViewer(getContext(), mVideoSource);
}
if (mMode == MODE_PLAYABLE_VIDEO) {
mVideoView.seekTo(0);
start();
} else {
UIIntents.get().launchFullScreenVideoViewer(getContext(), mVideoSource);
}
});
mPlayButton.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(final View view) {
// Button prevents long click from propagating up, do it manually
VideoThumbnailView.this.performLongClick();
return true;
}
mPlayButton.setOnLongClickListener(view -> {
// Button prevents long click from propagating up, do it manually
VideoThumbnailView.this.performLongClick();
return true;
});
}
@@ -157,12 +157,7 @@ public class ViewPagerTabs extends HorizontalScrollView implements ViewPager.OnP
textView.setText(tabTitle);
textView.setBackgroundResource(R.drawable.contact_picker_tab_background_selector);
textView.setGravity(Gravity.CENTER);
textView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mPager.setCurrentItem(getRtlPosition(position));
}
});
textView.setOnClickListener(v -> mPager.setCurrentItem(getRtlPosition(position)));
// Assign various text appearance related attributes to child views.
if (mTextStyle > 0) {
@@ -112,12 +112,8 @@ public class PopupTransitionAnimation extends Animation {
}
private final StringBuilder mEvents = new StringBuilder();
private final Runnable mCleanupRunnable = new Runnable() {
@Override
public void run() {
private final Runnable mCleanupRunnable = () ->
LogUtil.w(LogUtil.BUGLE_TAG, "PopupTransitionAnimation: " + mEvents);
}
};
/**
* Ensures the animation is ready before starting the animation.
@@ -210,17 +206,14 @@ public class PopupTransitionAnimation extends Animation {
mViewToAnimate.setVisibility(View.VISIBLE);
// Delay dismissing the popup window to let mViewToAnimate draw under it and reduce the
// flash
ThreadUtil.getMainThreadHandler().post(new Runnable() {
@Override
public void run() {
try {
mPopupWindow.dismiss();
} catch (IllegalArgumentException e) {
// PopupWindow.dismiss() will fire an IllegalArgumentException if the activity
// has already ended while we were animating
}
ThreadUtil.getMainThreadHandler().removeCallbacks(mCleanupRunnable);
ThreadUtil.getMainThreadHandler().post(() -> {
try {
mPopupWindow.dismiss();
} catch (IllegalArgumentException e) {
// PopupWindow.dismiss() will fire an IllegalArgumentException if the activity
// has already ended while we were animating
}
ThreadUtil.getMainThreadHandler().removeCallbacks(mCleanupRunnable);
});
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -168,17 +169,14 @@ public class ViewGroupItemVerticalExplodeAnimation {
expandLayer.animate().scaleY(scale)
.setDuration(mDuration)
.setInterpolator(UiUtils.EASE_IN_INTERPOLATOR)
.withEndAction(new Runnable() {
@Override
public void run() {
// Clean up the views added to overlay on animation finish.
overlay.remove(shadowContainerLayer);
mViewToAnimate.setBackground(oldBackground);
if (mViewBitmap != null) {
mViewBitmap.recycle();
}
.withEndAction(() -> {
// Clean up the views added to overlay on animation finish.
overlay.remove(shadowContainerLayer);
mViewToAnimate.setBackground(oldBackground);
if (mViewBitmap != null) {
mViewBitmap.recycle();
}
});
});
}
}
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +20,6 @@ import android.app.AlertDialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RadioButton;
import com.android.messaging.R;
@@ -70,18 +70,8 @@ public class GroupMmsSettingDialog {
rootView.findViewById(R.id.disable_group_mms_button);
final RadioButton enableButton = (RadioButton)
rootView.findViewById(R.id.enable_group_mms_button);
disableButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
changeGroupMmsSettings(false);
}
});
enableButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
changeGroupMmsSettings(true);
}
});
disableButton.setOnClickListener(view -> changeGroupMmsSettings(false));
enableButton.setOnClickListener(view -> changeGroupMmsSettings(true));
final boolean mmsEnabled = BuglePrefs.getSubscriptionPrefs(mSubId).getBoolean(
mContext.getString(R.string.group_mms_pref_key),
mContext.getResources().getBoolean(R.bool.group_mms_pref_default));
@@ -125,12 +125,9 @@ public class PerSubscriptionSettingsActivity extends BugleActionBarActivity {
// is being sent, making sure we will have a self number for group mms.
mmsCategory.removePreference(mGroupMmsPreference);
} else {
mGroupMmsPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference pref) {
GroupMmsSettingDialog.showDialog(getActivity(), mSubId);
return true;
}
mGroupMmsPreference.setOnPreferenceClickListener(pref -> {
GroupMmsSettingDialog.showDialog(getActivity(), mSubId);
return true;
});
updateGroupMmsPrefSummary();
}
@@ -27,7 +27,6 @@ import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
@@ -155,24 +154,21 @@ public class SettingsActivity extends BugleActionBarActivity {
} else {
subtitleTextView.setVisibility(View.GONE);
}
itemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
switch (item.getType()) {
case SettingsItem.TYPE_GENERAL_SETTINGS:
UIIntents.get().launchApplicationSettingsActivity(getActivity(),
false /* topLevel */);
break;
itemView.setOnClickListener(view -> {
switch (item.getType()) {
case SettingsItem.TYPE_GENERAL_SETTINGS:
UIIntents.get().launchApplicationSettingsActivity(getActivity(),
false /* topLevel */);
break;
case SettingsItem.TYPE_PER_SUBSCRIPTION_SETTINGS:
UIIntents.get().launchPerSubscriptionSettingsActivity(getActivity(),
item.getSubId(), item.getActivityTitle());
break;
case SettingsItem.TYPE_PER_SUBSCRIPTION_SETTINGS:
UIIntents.get().launchPerSubscriptionSettingsActivity(getActivity(),
item.getSubId(), item.getActivityTitle());
break;
default:
Assert.fail("unrecognized setting type!");
break;
}
default:
Assert.fail("unrecognized setting type!");
break;
}
});
return itemView;
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,30 +56,19 @@ public class AttachmentGridItemView extends FrameLayout {
super.onFinishInflate();
mAttachmentViewContainer = (FrameLayout) findViewById(R.id.attachment_container);
mCheckBox = (CheckBox) findViewById(R.id.checkbox);
mCheckBox.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
mHostInterface.onItemCheckedChanged(AttachmentGridItemView.this, mAttachmentData);
}
});
setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
mHostInterface.onItemClicked(AttachmentGridItemView.this, mAttachmentData);
}
});
addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
// Enlarge the clickable region for the checkbox.
final int touchAreaIncrease = getResources().getDimensionPixelOffset(
R.dimen.attachment_grid_checkbox_area_increase);
final Rect region = new Rect();
mCheckBox.getHitRect(region);
region.inset(-touchAreaIncrease, -touchAreaIncrease);
setTouchDelegate(new TouchDelegate(region, mCheckBox));
}
mCheckBox.setOnClickListener(v -> mHostInterface.onItemCheckedChanged(
AttachmentGridItemView.this, mAttachmentData));
setOnClickListener(v -> mHostInterface.onItemClicked(AttachmentGridItemView.this,
mAttachmentData));
addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
oldBottom) -> {
// Enlarge the clickable region for the checkbox.
final int touchAreaIncrease = getResources().getDimensionPixelOffset(
R.dimen.attachment_grid_checkbox_area_increase);
final Rect region = new Rect();
mCheckBox.getHitRect(region);
region.inset(-touchAreaIncrease, -touchAreaIncrease);
setTouchDelegate(new TouchDelegate(region, mCheckBox));
});
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,7 +37,6 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import com.android.messaging.R;
@@ -182,12 +182,7 @@ public class ContactPickerFragment extends Fragment implements ContactPickerData
mToolbar = (Toolbar) view.findViewById(R.id.toolbar);
mToolbar.setNavigationIcon(R.drawable.ic_arrow_back_light);
mToolbar.setNavigationContentDescription(R.string.back);
mToolbar.setNavigationOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
mHost.onBackButtonPressed();
}
});
mToolbar.setNavigationOnClickListener(v -> mHost.onBackButtonPressed());
mToolbar.inflateMenu(R.menu.compose_menu);
mToolbar.setOnMenuItemClickListener(this);
@@ -325,13 +320,10 @@ public class ContactPickerFragment extends Fragment implements ContactPickerData
// showImeKeyboard() won't work until the layout is ready, so wait until layout is complete
// before showing the soft keyboard.
UiUtils.doOnceAfterLayoutChange(mRootView, new Runnable() {
@Override
public void run() {
final Activity activity = getActivity();
if (activity != null) {
ImeUtil.get().showImeKeyboard(activity, mRecipientTextView);
}
UiUtils.doOnceAfterLayoutChange(mRootView, () -> {
final Activity activity = getActivity();
if (activity != null) {
ImeUtil.get().showImeKeyboard(activity, mRecipientTextView);
}
});
mRecipientTextView.invalidate();
@@ -541,19 +533,13 @@ public class ContactPickerFragment extends Fragment implements ContactPickerData
mCustomHeaderViewPager.animate().alpha(show ? 1F : 0F)
.setStartDelay(!show ? UiUtils.COMPOSE_TRANSITION_DURATION : 0)
.withStartAction(new Runnable() {
@Override
public void run() {
mCustomHeaderViewPager.setVisibility(View.VISIBLE);
mCustomHeaderViewPager.setAlpha(show ? 0F : 1F);
}
.withStartAction(() -> {
mCustomHeaderViewPager.setVisibility(View.VISIBLE);
mCustomHeaderViewPager.setAlpha(show ? 0F : 1F);
})
.withEndAction(new Runnable() {
@Override
public void run() {
mCustomHeaderViewPager.setVisibility(show ? View.VISIBLE : View.GONE);
mCustomHeaderViewPager.setAlpha(1F);
}
.withEndAction(() -> {
mCustomHeaderViewPager.setVisibility(show ? View.VISIBLE : View.GONE);
mCustomHeaderViewPager.setAlpha(1F);
});
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -59,38 +60,35 @@ public class ContactRecipientPhotoManager implements PhotoManager {
public void populatePhotoBytesAsync(final RecipientEntry entry,
final PhotoManagerCallback callback) {
// Post all media resource request to the main thread.
ThreadUtil.getMainThreadHandler().post(new Runnable() {
@Override
public void run() {
final Uri avatarUri = AvatarUriUtil.createAvatarUri(
ParticipantData.getFromRecipientEntry(entry));
final AvatarRequestDescriptor descriptor =
new AvatarRequestDescriptor(avatarUri, mIconSize, mIconSize);
final BindableMediaRequest<ImageResource> req = descriptor.buildAsyncMediaRequest(
mContext,
new MediaResourceLoadListener<ImageResource>() {
@Override
public void onMediaResourceLoaded(final MediaRequest<ImageResource> request,
final ImageResource resource, final boolean isCached) {
entry.setPhotoBytes(resource.getBytes());
callback.onPhotoBytesAsynchronouslyPopulated();
}
ThreadUtil.getMainThreadHandler().post(() -> {
final Uri avatarUri = AvatarUriUtil.createAvatarUri(
ParticipantData.getFromRecipientEntry(entry));
final AvatarRequestDescriptor descriptor =
new AvatarRequestDescriptor(avatarUri, mIconSize, mIconSize);
final BindableMediaRequest<ImageResource> req = descriptor.buildAsyncMediaRequest(
mContext,
new MediaResourceLoadListener<ImageResource>() {
@Override
public void onMediaResourceLoaded(final MediaRequest<ImageResource> request,
final ImageResource resource, final boolean isCached) {
entry.setPhotoBytes(resource.getBytes());
callback.onPhotoBytesAsynchronouslyPopulated();
}
@Override
public void onMediaResourceLoadError(final MediaRequest<ImageResource> request,
final Exception exception) {
LogUtil.e(LogUtil.BUGLE_TAG, "Photo bytes loading failed due to " +
exception + " request key=" + request.getKey());
@Override
public void onMediaResourceLoadError(final MediaRequest<ImageResource> request,
final Exception exception) {
LogUtil.e(LogUtil.BUGLE_TAG, "Photo bytes loading failed due to " +
exception + " request key=" + request.getKey());
// Fall back to the default avatar image.
callback.onPhotoBytesAsyncLoadFailed();
}});
// Fall back to the default avatar image.
callback.onPhotoBytesAsyncLoadFailed();
}});
// Statically bind the request since it's not bound to any specific piece of UI.
req.bind(IMAGE_BYTES_REQUEST_STATIC_BINDING_ID);
// Statically bind the request since it's not bound to any specific piece of UI.
req.bind(IMAGE_BYTES_REQUEST_STATIC_BINDING_ID);
Factory.get().getMediaResourceManager().requestMediaResourceAsync(req);
}
Factory.get().getMediaResourceManager().requestMediaResourceAsync(req);
});
}
}
@@ -51,7 +51,6 @@ import com.android.messaging.datamodel.data.ConversationData.ConversationDataLis
import com.android.messaging.datamodel.data.ConversationData.SimpleConversationDataListener;
import com.android.messaging.datamodel.data.DraftMessageData;
import com.android.messaging.datamodel.data.DraftMessageData.CheckDraftForSendTask;
import com.android.messaging.datamodel.data.DraftMessageData.CheckDraftTaskCallback;
import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageDataListener;
import com.android.messaging.datamodel.data.MessageData;
import com.android.messaging.datamodel.data.MessagePartData;
@@ -197,20 +196,14 @@ public class ComposeMessageView extends LinearLayout
R.id.compose_message_text);
mComposeEditText.setOnEditorActionListener(this);
mComposeEditText.addTextChangedListener(this);
mComposeEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(final View v, final boolean hasFocus) {
if (v == mComposeEditText && hasFocus) {
mHost.onComposeEditTextFocused();
}
mComposeEditText.setOnFocusChangeListener((v, hasFocus) -> {
if (v == mComposeEditText && hasFocus) {
mHost.onComposeEditTextFocused();
}
});
mComposeEditText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (mHost.shouldHideAttachmentsWhenSimSelectorShown()) {
hideSimSelector();
}
mComposeEditText.setOnClickListener(arg0 -> {
if (mHost.shouldHideAttachmentsWhenSimSelectorShown()) {
hideSimSelector();
}
});
@@ -221,26 +214,20 @@ public class ComposeMessageView extends LinearLayout
.getMaxTextLimit()) });
mSelfSendIcon = (SimIconView) findViewById(R.id.self_send_icon);
mSelfSendIcon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mSelfSendIcon.setOnClickListener(v -> {
boolean shown = mInputManager.toggleSimSelector(true /* animate */,
getSelfSubscriptionListEntry());
hideAttachmentsWhenShowingSims(shown);
});
mSelfSendIcon.setOnLongClickListener(v -> {
if (mHost.shouldShowSubjectEditor()) {
showSubjectEditor();
} else {
boolean shown = mInputManager.toggleSimSelector(true /* animate */,
getSelfSubscriptionListEntry());
hideAttachmentsWhenShowingSims(shown);
}
});
mSelfSendIcon.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(final View v) {
if (mHost.shouldShowSubjectEditor()) {
showSubjectEditor();
} else {
boolean shown = mInputManager.toggleSimSelector(true /* animate */,
getSelfSubscriptionListEntry());
hideAttachmentsWhenShowingSims(shown);
}
return true;
}
return true;
});
mComposeSubjectText = (PlainTextEditText) findViewById(
@@ -255,35 +242,25 @@ public class ComposeMessageView extends LinearLayout
.getMaxSubjectLength())});
mDeleteSubjectButton = (ImageButton) findViewById(R.id.delete_subject_button);
mDeleteSubjectButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View clickView) {
hideSubjectEditor();
mComposeSubjectText.setText(null);
mBinding.getData().setMessageSubject(null);
}
mDeleteSubjectButton.setOnClickListener(clickView -> {
hideSubjectEditor();
mComposeSubjectText.setText(null);
mBinding.getData().setMessageSubject(null);
});
mSubjectView = findViewById(R.id.subject_view);
mSendButton = (ImageButton) findViewById(R.id.send_message_button);
mSendButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View clickView) {
sendMessageInternal(true /* checkMessageSize */);
}
});
mSendButton.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(final View arg0) {
boolean shown = mInputManager.toggleSimSelector(true /* animate */,
getSelfSubscriptionListEntry());
hideAttachmentsWhenShowingSims(shown);
if (mHost.shouldShowSubjectEditor()) {
showSubjectEditor();
}
return true;
mSendButton.setOnClickListener(clickView ->
sendMessageInternal(true /* checkMessageSize */));
mSendButton.setOnLongClickListener(arg0 -> {
boolean shown = mInputManager.toggleSimSelector(true /* animate */,
getSelfSubscriptionListEntry());
hideAttachmentsWhenShowingSims(shown);
if (mHost.shouldShowSubjectEditor()) {
showSubjectEditor();
}
return true;
});
mSendButton.setAccessibilityDelegate(new AccessibilityDelegate() {
@Override
@@ -306,12 +283,9 @@ public class ComposeMessageView extends LinearLayout
mAttachMediaButton =
(ImageButton) findViewById(R.id.attach_media_button);
mAttachMediaButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View clickView) {
// Showing the media picker is treated as starting to compose the message.
mInputManager.showHideMediaPicker(true /* show */, true /* animate */);
}
mAttachMediaButton.setOnClickListener(clickView -> {
// Showing the media picker is treated as starting to compose the message.
mInputManager.showHideMediaPicker(true /* show */, true /* animate */);
});
mAttachmentPreview = (AttachmentPreview) findViewById(R.id.attachment_draft_view);
@@ -394,69 +368,60 @@ public class ComposeMessageView extends LinearLayout
mBinding.getData().setMessageSubject(subject);
// Asynchronously check the draft against various requirements before sending.
mBinding.getData().checkDraftForAction(checkMessageSize,
mHost.getConversationSelfSubId(), new CheckDraftTaskCallback() {
@Override
public void onDraftChecked(DraftMessageData data, int result) {
mBinding.ensureBound(data);
switch (result) {
case CheckDraftForSendTask.RESULT_PASSED:
// Continue sending after check succeeded.
final MessageData message = mBinding.getData()
.prepareMessageForSending(mBinding);
if (message != null && message.hasContent()) {
playSentSound();
mHost.sendMessage(message);
hideSubjectEditor();
if (AccessibilityUtil.isTouchExplorationEnabled(getContext())) {
AccessibilityUtil.announceForAccessibilityCompat(
ComposeMessageView.this, null,
R.string.sending_message);
mHost.getConversationSelfSubId(), (data, result) -> {
mBinding.ensureBound(data);
switch (result) {
case CheckDraftForSendTask.RESULT_PASSED:
// Continue sending after check succeeded.
final MessageData message = mBinding.getData()
.prepareMessageForSending(mBinding);
if (message != null && message.hasContent()) {
playSentSound();
mHost.sendMessage(message);
hideSubjectEditor();
if (AccessibilityUtil.isTouchExplorationEnabled(getContext())) {
AccessibilityUtil.announceForAccessibilityCompat(
ComposeMessageView.this, null,
R.string.sending_message);
}
}
}
break;
break;
case CheckDraftForSendTask.RESULT_HAS_PENDING_ATTACHMENTS:
// Cannot send while there's still attachment(s) being loaded.
UiUtils.showToastAtBottom(
R.string.cant_send_message_while_loading_attachments);
break;
case CheckDraftForSendTask.RESULT_HAS_PENDING_ATTACHMENTS:
// Cannot send while there's still attachment(s) being loaded.
UiUtils.showToastAtBottom(
R.string.cant_send_message_while_loading_attachments);
break;
case CheckDraftForSendTask.RESULT_NO_SELF_PHONE_NUMBER_IN_GROUP_MMS:
mHost.promptForSelfPhoneNumber();
break;
case CheckDraftForSendTask.RESULT_NO_SELF_PHONE_NUMBER_IN_GROUP_MMS:
mHost.promptForSelfPhoneNumber();
break;
case CheckDraftForSendTask.RESULT_MESSAGE_OVER_LIMIT:
Assert.isTrue(checkMessageSize);
mHost.warnOfExceedingMessageLimit(
true /*sending*/, false /* tooManyVideos */);
break;
case CheckDraftForSendTask.RESULT_MESSAGE_OVER_LIMIT:
Assert.isTrue(checkMessageSize);
mHost.warnOfExceedingMessageLimit(
true /*sending*/, false /* tooManyVideos */);
break;
case CheckDraftForSendTask.RESULT_VIDEO_ATTACHMENT_LIMIT_EXCEEDED:
Assert.isTrue(checkMessageSize);
mHost.warnOfExceedingMessageLimit(
true /*sending*/, true /* tooManyVideos */);
break;
case CheckDraftForSendTask.RESULT_VIDEO_ATTACHMENT_LIMIT_EXCEEDED:
Assert.isTrue(checkMessageSize);
mHost.warnOfExceedingMessageLimit(
true /*sending*/, true /* tooManyVideos */);
break;
case CheckDraftForSendTask.RESULT_SIM_NOT_READY:
// Cannot send if there is no active subscription
UiUtils.showToastAtBottom(
R.string.cant_send_message_without_active_subscription);
break;
case CheckDraftForSendTask.RESULT_SIM_NOT_READY:
// Cannot send if there is no active subscription
UiUtils.showToastAtBottom(
R.string.cant_send_message_without_active_subscription);
break;
default:
break;
}
}
}, mBinding);
} else {
mHost.warnOfMissingActionConditions(true /*sending*/,
new Runnable() {
@Override
public void run() {
sendMessageInternal(checkMessageSize);
default:
break;
}
});
}, mBinding);
} else {
mHost.warnOfMissingActionConditions(true /*sending*/, () ->
sendMessageInternal(checkMessageSize));
}
}
@@ -110,12 +110,9 @@ public class ConversationFastScroller extends RecyclerView.OnScrollListener impl
private AnimatorSet mHideAnimation;
private ObjectAnimator mHidePreviewAnimation;
private final Runnable mHideTrackRunnable = new Runnable() {
@Override
public void run() {
hide(true /* animate */);
mPendingHide = false;
}
private final Runnable mHideTrackRunnable = () -> {
hide(true /* animate */);
mPendingHide = false;
};
private ConversationFastScroller(RecyclerView rv, int position) {
@@ -28,10 +28,6 @@ import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
@@ -420,19 +416,13 @@ public class ConversationFragment extends Fragment implements ConversationDataLi
mAdapter = new ConversationMessageAdapter(getActivity(), null, this,
null,
// Sets the item click listener on the Recycler item views.
new View.OnClickListener() {
@Override
public void onClick(final View v) {
final ConversationMessageView messageView = (ConversationMessageView) v;
handleMessageClick(messageView);
}
v -> {
final ConversationMessageView messageView = (ConversationMessageView) v;
handleMessageClick(messageView);
},
new View.OnLongClickListener() {
@Override
public boolean onLongClick(final View view) {
selectMessage((ConversationMessageView) view);
return true;
}
view -> {
selectMessage((ConversationMessageView) view);
return true;
}
);
}
@@ -555,23 +545,17 @@ public class ConversationFragment extends Fragment implements ConversationDataLi
view.setAlpha(0);
mPopupTransitionAnimation = new PopupTransitionAnimation(startRect, view);
mPopupTransitionAnimation.setOnStartCallback(new Runnable() {
@Override
public void run() {
final int startWidth = composeBubbleRect.width();
attachmentView.onMessageAnimationStart();
messageBubble.kickOffMorphAnimation(startWidth,
messageBubble.findViewById(R.id.message_text_and_info)
.getMeasuredWidth());
}
});
mPopupTransitionAnimation.setOnStopCallback(new Runnable() {
@Override
public void run() {
view.setAlpha(1);
dispatchAddFinished(holder);
}
});
mPopupTransitionAnimation.setOnStartCallback(() -> {
final int startWidth = composeBubbleRect.width();
attachmentView.onMessageAnimationStart();
messageBubble.kickOffMorphAnimation(startWidth,
messageBubble.findViewById(R.id.message_text_and_info)
.getMeasuredWidth());
});
mPopupTransitionAnimation.setOnStopCallback(() -> {
view.setAlpha(1);
dispatchAddFinished(holder);
});
mPopupTransitionAnimation.startAfterLayoutComplete();
mAddAnimations.add(holder);
return true;
@@ -827,13 +811,7 @@ public class ConversationFragment extends Fragment implements ConversationDataLi
.setTitle(getResources().getQuantityString(
R.plurals.delete_conversations_confirmation_dialog_title, 1))
.setPositiveButton(R.string.delete_conversation_confirmation_button,
new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog,
final int button) {
deleteConversation();
}
})
(dialog, button) -> deleteConversation())
.setNegativeButton(R.string.delete_conversation_decline_button, null)
.show();
} else {
@@ -894,12 +872,9 @@ public class ConversationFragment extends Fragment implements ConversationDataLi
UiUtils.showSnackBarWithCustomAction(getActivity(),
getView().getRootView(),
getString(R.string.in_conversation_notify_new_message_text),
SnackBar.Action.createCustomAction(new Runnable() {
@Override
public void run() {
scrollToBottom(true /* smoothScroll */);
mComposeMessageView.hideAllComposeInputs(false /* animate */);
}
SnackBar.Action.createCustomAction(() -> {
scrollToBottom(true /* smoothScroll */);
mComposeMessageView.hideAllComposeInputs(false /* animate */);
},
getString(R.string.in_conversation_notify_new_message_action)),
null /* interactions */,
@@ -1036,13 +1011,7 @@ public class ConversationFragment extends Fragment implements ConversationDataLi
LogUtil.w(LogUtil.BUGLE_TAG, "Message can't be sent: conv participants not loaded");
}
} else {
warnOfMissingActionConditions(true /*sending*/,
new Runnable() {
@Override
public void run() {
sendMessage(message);
}
});
warnOfMissingActionConditions(true /*sending*/, () -> sendMessage(message));
}
}
@@ -1137,14 +1106,7 @@ public class ConversationFragment extends Fragment implements ConversationDataLi
mBinding.getData().resendMessage(mBinding, messageId);
}
} else {
warnOfMissingActionConditions(true /*sending*/,
new Runnable() {
@Override
public void run() {
retrySend(messageId);
}
});
warnOfMissingActionConditions(true /*sending*/, () -> retrySend(messageId));
}
}
@@ -1154,12 +1116,8 @@ public class ConversationFragment extends Fragment implements ConversationDataLi
.setTitle(R.string.delete_message_confirmation_dialog_title)
.setMessage(R.string.delete_message_confirmation_dialog_text)
.setPositiveButton(R.string.delete_message_confirmation_button,
new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
mBinding.getData().deleteMessage(mBinding, messageId);
}
})
(dialog, which) ->
mBinding.getData().deleteMessage(mBinding, messageId))
.setNegativeButton(android.R.string.cancel, null);
builder.setOnDismissListener(dialog -> mHost.dismissActionMode());
builder.create().show();
@@ -1506,19 +1464,11 @@ public class ConversationFragment extends Fragment implements ConversationDataLi
} else {
builder.setMessage(R.string.attachment_limit_reached_dialog_message_when_sending)
.setNegativeButton(R.string.attachment_limit_reached_send_anyway,
new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog,
final int which) {
composeMessageView.sendMessageIgnoreMessageSizeLimit();
}
});
(dialog, which) ->
composeMessageView.sendMessageIgnoreMessageSizeLimit());
}
builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
showAttachmentChooser(conversationId, activity);
}});
builder.setPositiveButton(android.R.string.ok, (dialog, which) ->
showAttachmentChooser(conversationId, activity));
} else {
builder.setMessage(R.string.attachment_limit_reached_dialog_message_when_composing)
.setPositiveButton(android.R.string.ok, null);
@@ -1557,12 +1507,7 @@ public class ConversationFragment extends Fragment implements ConversationDataLi
final LayoutInflater inflator = (LayoutInflater)
getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
customView = inflator.inflate(R.layout.action_bar_conversation_name, null);
customView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
onBackPressed();
}
});
customView.setOnClickListener(v -> onBackPressed());
actionBar.setCustomView(customView);
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -123,12 +124,9 @@ public class ConversationMessageView extends FrameLayout implements View.OnClick
@Override
protected void onFinishInflate() {
mContactIconView = (ContactIconView) findViewById(R.id.conversation_icon);
mContactIconView.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(final View view) {
ConversationMessageView.this.performLongClick();
return true;
}
mContactIconView.setOnLongClickListener(view -> {
ConversationMessageView.this.performLongClick();
return true;
});
mMessageAttachmentsView = (LinearLayout) findViewById(R.id.message_attachments);
@@ -1044,40 +1042,13 @@ public class ConversationMessageView extends FrameLayout implements View.OnClick
}
// Sort photos in MultiAttachLayout in the same order as the ConversationImagePartsView
static final Comparator<MessagePartData> sImageComparator = new Comparator<MessagePartData>(){
@Override
public int compare(final MessagePartData x, final MessagePartData y) {
return x.getPartId().compareTo(y.getPartId());
}
};
static final Comparator<MessagePartData> sImageComparator =
Comparator.comparing(MessagePartData::getPartId);
static final Predicate<MessagePartData> sVideoFilter = new Predicate<MessagePartData>() {
@Override
public boolean apply(final MessagePartData part) {
return part.isVideo();
}
};
static final Predicate<MessagePartData> sAudioFilter = new Predicate<MessagePartData>() {
@Override
public boolean apply(final MessagePartData part) {
return part.isAudio();
}
};
static final Predicate<MessagePartData> sVCardFilter = new Predicate<MessagePartData>() {
@Override
public boolean apply(final MessagePartData part) {
return part.isVCard();
}
};
static final Predicate<MessagePartData> sImageFilter = new Predicate<MessagePartData>() {
@Override
public boolean apply(final MessagePartData part) {
return part.isImage();
}
};
static final Predicate<MessagePartData> sVideoFilter = MessagePartData::isVideo;
static final Predicate<MessagePartData> sAudioFilter = MessagePartData::isAudio;
static final Predicate<MessagePartData> sVCardFilter = MessagePartData::isVCard;
static final Predicate<MessagePartData> sImageFilter = MessagePartData::isImage;
interface AttachmentViewBinder {
void bindView(View view, MessagePartData attachment);
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,13 +49,10 @@ abstract class ConversationSimSelector extends ConversationInput {
if (mPendingShow != null && mDataReady) {
final boolean show = mPendingShow.first;
final boolean animate = mPendingShow.second;
ThreadUtil.getMainThreadHandler().post(new Runnable() {
@Override
public void run() {
// This will No-Op if we are no longer attached to the host.
mConversationInputBase.showHideInternal(ConversationSimSelector.this,
show, animate);
}
ThreadUtil.getMainThreadHandler().post(() -> {
// This will No-Op if we are no longer attached to the host.
mConversationInputBase.showHideInternal(ConversationSimSelector.this,
show, animate);
});
mPendingShow = null;
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +20,6 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
@@ -53,30 +53,18 @@ public class EnterSelfPhoneNumberDialog extends DialogFragment {
builder.setTitle(R.string.enter_phone_number_title)
.setMessage(R.string.enter_phone_number_text)
.setView(mEditText)
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog,
final int button) {
dismiss();
}
})
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog,
final int button) {
final String newNumber = mEditText.getText().toString();
dismiss();
if (!TextUtils.isEmpty(newNumber)) {
savePhoneNumberInPrefs(newNumber);
// TODO: Remove this toast and just auto-send
// the message instead
UiUtils.showToast(
R.string
.toast_after_setting_default_sms_app_for_message_send);
}
}
.setNegativeButton(android.R.string.cancel, (dialog, button) -> dismiss())
.setPositiveButton(android.R.string.ok, (dialog, button) -> {
final String newNumber = mEditText.getText().toString();
dismiss();
if (!TextUtils.isEmpty(newNumber)) {
savePhoneNumberInPrefs(newNumber);
// TODO: Remove this toast and just auto-send
// the message instead
UiUtils.showToast(
R.string
.toast_after_setting_default_sms_app_for_message_send);
}
});
return builder.create();
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +19,6 @@ package com.android.messaging.ui.conversation;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -49,12 +49,7 @@ public class SimSelectorItemView extends LinearLayout {
mNameTextView = (TextView) findViewById(R.id.name);
mDetailsTextView = (TextView) findViewById(R.id.details);
mSimIconView = (SimIconView) findViewById(R.id.sim_icon);
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mHost.onSimItemClicked(mData);
}
});
setOnClickListener(v -> mHost.onSimItemClicked(mData));
}
public void bind(final SubscriptionListEntry simEntry) {
@@ -64,12 +64,7 @@ public class SimSelectorView extends FrameLayout implements SimSelectorItemView.
mSimListView.setAdapter(mAdapter);
// Clicking anywhere outside the switcher list should dismiss.
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showOrHide(false, true);
}
});
setOnClickListener(v -> showOrHide(false, true));
}
public void bind(final SubscriptionListData data) {
@@ -102,12 +97,9 @@ public class SimSelectorView extends FrameLayout implements SimSelectorItemView.
setAlpha(mShow ? 0.0f : 1.0f);
animate().alpha(mShow ? 1.0f : 0.0f)
.setDuration(UiUtils.REVEAL_ANIMATION_DURATION)
.withEndAction(new Runnable() {
@Override
public void run() {
setAlpha(1.0f);
setVisibility(mShow ? VISIBLE : GONE);
}
.withEndAction(() -> {
setAlpha(1.0f);
setVisibility(mShow ? VISIBLE : GONE);
});
} else {
setVisibility(mShow ? VISIBLE : GONE);
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +20,6 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
@@ -118,14 +118,11 @@ public abstract class AbstractConversationListActivity extends BugleActionBarAc
UiUtils.showSnackBarWithCustomAction(this,
getWindow().getDecorView().getRootView(),
getString(R.string.requires_default_sms_app),
SnackBar.Action.createCustomAction(new Runnable() {
@Override
public void run() {
final Intent intent =
UIIntents.get().getChangeDefaultSmsAppIntent(activity);
startActivityForResult(intent, REQUEST_SET_DEFAULT_SMS_APP);
}
},
SnackBar.Action.createCustomAction(() -> {
final Intent intent =
UIIntents.get().getChangeDefaultSmsAppIntent(activity);
startActivityForResult(intent, REQUEST_SET_DEFAULT_SMS_APP);
},
getString(R.string.requires_default_sms_change_button)),
null /* interactions */,
null /* placement */);
@@ -137,18 +134,14 @@ public abstract class AbstractConversationListActivity extends BugleActionBarAc
R.plurals.delete_conversations_confirmation_dialog_title,
conversations.size()))
.setPositiveButton(R.string.delete_conversation_confirmation_button,
new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog,
final int button) {
for (final SelectedConversation conversation : conversations) {
DeleteConversationAction.deleteConversation(
conversation.conversationId,
conversation.timestamp);
}
exitMultiSelectState();
(dialog, button) -> {
for (final SelectedConversation conversation : conversations) {
DeleteConversationAction.deleteConversation(
conversation.conversationId,
conversation.timestamp);
}
})
exitMultiSelectState();
})
.setNegativeButton(R.string.delete_conversation_decline_button, null)
.show();
}
@@ -167,15 +160,12 @@ public abstract class AbstractConversationListActivity extends BugleActionBarAc
}
}
final Runnable undoRunnable = new Runnable() {
@Override
public void run() {
for (final String conversationId : conversationIds) {
if (isToArchive) {
UpdateConversationArchiveStatusAction.unarchiveConversation(conversationId);
} else {
UpdateConversationArchiveStatusAction.archiveConversation(conversationId);
}
final Runnable undoRunnable = () -> {
for (final String conversationId : conversationIds) {
if (isToArchive) {
UpdateConversationArchiveStatusAction.unarchiveConversation(conversationId);
} else {
UpdateConversationArchiveStatusAction.archiveConversation(conversationId);
}
}
};
@@ -211,36 +201,29 @@ public abstract class AbstractConversationListActivity extends BugleActionBarAc
conversation.otherParticipantNormalizedDestination))
.setMessage(res.getString(R.string.block_confirmation_message))
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface arg0, final int arg1) {
final Context context = AbstractConversationListActivity.this;
final View listView = findViewById(android.R.id.list);
final List<SnackBarInteraction> interactions =
mConversationListFragment.getSnackBarInteractions();
final UpdateDestinationBlockedAction.UpdateDestinationBlockedActionListener
undoListener =
new UpdateDestinationBlockedActionSnackBar(
context, listView, null /* undoRunnable */,
interactions);
final Runnable undoRunnable = new Runnable() {
@Override
public void run() {
UpdateDestinationBlockedAction.updateDestinationBlocked(
conversation.otherParticipantNormalizedDestination, false,
conversation.conversationId,
undoListener);
}
};
final UpdateDestinationBlockedAction.UpdateDestinationBlockedActionListener
listener = new UpdateDestinationBlockedActionSnackBar(
context, listView, undoRunnable, interactions);
UpdateDestinationBlockedAction.updateDestinationBlocked(
conversation.otherParticipantNormalizedDestination, true,
conversation.conversationId,
listener);
exitMultiSelectState();
}
.setPositiveButton(android.R.string.ok, (arg0, arg1) -> {
final Context context = AbstractConversationListActivity.this;
final View listView = findViewById(android.R.id.list);
final List<SnackBarInteraction> interactions =
mConversationListFragment.getSnackBarInteractions();
final UpdateDestinationBlockedAction.UpdateDestinationBlockedActionListener
undoListener =
new UpdateDestinationBlockedActionSnackBar(
context, listView, null /* undoRunnable */,
interactions);
final Runnable undoRunnable = () ->
UpdateDestinationBlockedAction.updateDestinationBlocked(
conversation.otherParticipantNormalizedDestination, false,
conversation.conversationId,
undoListener);
final UpdateDestinationBlockedAction.UpdateDestinationBlockedActionListener
listener = new UpdateDestinationBlockedActionSnackBar(
context, listView, undoRunnable, interactions);
UpdateDestinationBlockedAction.updateDestinationBlocked(
conversation.otherParticipantNormalizedDestination, true,
conversation.conversationId,
listener);
exitMultiSelectState();
})
.create()
.show();
@@ -35,7 +35,6 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.ViewPropertyAnimator;
@@ -229,12 +228,8 @@ public class ConversationListFragment extends Fragment implements ConversationLi
mStartNewConversationButton.setVisibility(View.GONE);
} else {
mStartNewConversationButton.setVisibility(View.VISIBLE);
mStartNewConversationButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View clickView) {
mHost.onCreateConversationClick();
}
});
mStartNewConversationButton.setOnClickListener(clickView ->
mHost.onCreateConversationClick());
}
ViewCompat.setTransitionName(mStartNewConversationButton, BugleAnimationTags.TAG_FABICON);
@@ -415,12 +410,9 @@ public class ConversationListFragment extends Fragment implements ConversationLi
}
public ViewPropertyAnimator showFab() {
return getNormalizedFabAnimator().translationX(0).withEndAction(new Runnable() {
@Override
public void run() {
// Re-enable clicks after the animation.
mStartNewConversationButton.setEnabled(true);
}
return getNormalizedFabAnimator().translationX(0).withEndAction(() -> {
// Re-enable clicks after the animation.
mStartNewConversationButton.setEnabled(true);
});
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -552,12 +553,8 @@ public class ConversationListItemView extends FrameLayout implements OnClickList
return;
}
UpdateConversationArchiveStatusAction.archiveConversation(conversationId);
final Runnable undoRunnable = new Runnable() {
@Override
public void run() {
final Runnable undoRunnable = () ->
UpdateConversationArchiveStatusAction.unarchiveConversation(conversationId);
}
};
final String message = getResources().getString(R.string.archived_toast_message, 1);
UiUtils.showSnackBar(getContext(), getRootView(), message, undoRunnable,
SnackBar.Action.SNACK_BAR_UNDO,
@@ -22,7 +22,6 @@ import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.database.Cursor;
import android.os.Bundle;
import androidx.recyclerview.widget.LinearLayoutManager;
@@ -92,13 +91,10 @@ public class ShareIntentFragment extends DialogFragment implements ConversationL
final Bundle arguments = getArguments();
if (arguments == null || !arguments.getBoolean(HIDE_NEW_CONVERSATION_BUTTON_KEY)) {
dialogBuilder.setPositiveButton(R.string.share_new_message, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mDismissed = true;
mHost.onCreateConversationClick();
}
});
dialogBuilder.setPositiveButton(R.string.share_new_message, (dialog, which) -> {
mDismissed = true;
mHost.onCreateConversationClick();
});
}
return dialogBuilder.setNegativeButton(R.string.share_cancel, null)
.create();
@@ -21,7 +21,6 @@ import android.app.AlertDialog;
import android.app.Fragment;
import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
@@ -156,14 +155,10 @@ public class PeopleAndOptionsFragment extends Fragment
item.getOtherParticipant().getDisplayDestination()))
.setMessage(res.getString(R.string.block_confirmation_message))
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
mBinding.getData().setDestinationBlocked(mBinding, true);
activity.setResult(ConversationActivity.FINISH_RESULT_CODE);
activity.finish();
}
.setPositiveButton(android.R.string.ok, (arg0, arg1) -> {
mBinding.getData().setDestinationBlocked(mBinding, true);
activity.setResult(ConversationActivity.FINISH_RESULT_CODE);
activity.finish();
})
.create()
.show();
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +21,6 @@ import android.database.Cursor;
import androidx.appcompat.widget.SwitchCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -55,12 +55,7 @@ public class PeopleOptionsItemView extends LinearLayout {
@Override
protected void onFinishInflate () {
mTitle = (TextView) findViewById(R.id.title);
setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
mHostInterface.onOptionsItemViewClicked(mData);
}
});
setOnClickListener(v -> mHostInterface.onOptionsItemViewClicked(mData));
}
public void bind(final Cursor cursor, final int columnIndex, ParticipantData otherParticipant,
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +19,6 @@ package com.android.messaging.ui.debug;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.View;
@@ -115,14 +115,11 @@ public class DebugMmsConfigItemView extends LinearLayout implements OnClickListe
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, null)
.create();
dialog.setOnShowListener(new OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
mEditText.requestFocus();
mEditText.selectAll();
((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE))
.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
}
dialog.setOnShowListener(dialog1 -> {
mEditText.requestFocus();
mEditText.selectAll();
((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE))
.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0);
});
dialog.show();
}
@@ -29,7 +29,6 @@ import android.os.Environment;
import android.telephony.SmsMessage;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
@@ -113,15 +112,12 @@ public class DebugSmsMmsFromDumpFileDialogFragment extends DialogFragment {
final String file = getItem(position);
actionItemView.setText(file);
actionItemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View view) {
dismiss();
if (ACTION_LOAD.equals(mAction)) {
receiveFromDumpFile(file);
} else if (ACTION_EMAIL.equals(mAction)) {
emailDumpFile(file);
}
actionItemView.setOnClickListener(view1 -> {
dismiss();
if (ACTION_LOAD.equals(mAction)) {
receiveFromDumpFile(file);
} else if (ACTION_EMAIL.equals(mAction)) {
emailDumpFile(file);
}
});
return actionItemView;
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -121,23 +122,20 @@ public class AudioRecordView extends FrameLayout implements
mHintTextView = (TextView) findViewById(R.id.hint_text);
mTimerTextView = (PausableChronometer) findViewById(R.id.timer_text);
mSoundLevels.setLevelSource(mMediaRecorder.getLevelSource());
mRecordButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(final View v, final MotionEvent event) {
final int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
onRecordButtonTouchDown();
mRecordButton.setOnTouchListener((v, event) -> {
final int action = event.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
onRecordButtonTouchDown();
// Don't let the record button handle the down event to let it fall through
// so that we can handle it for the entire panel in onTouchEvent(). This is
// done so that: 1) the user taps on the record button to start recording
// 2) the entire panel owns the touch event so we'd keep recording even
// if the user moves outside the button region.
return false;
}
return false;
// Don't let the record button handle the down event to let it fall through
// so that we can handle it for the entire panel in onTouchEvent(). This is
// done so that: 1) the user taps on the record button to start recording
// 2) the entire panel owns the touch event so we'd keep recording even
// if the user moves outside the button region.
return false;
}
return false;
});
}
@@ -242,18 +240,15 @@ public class AudioRecordView extends FrameLayout implements
boolean onRecordButtonTouchDown() {
if (!mMediaRecorder.isRecording() && mCurrentMode == MODE_IDLE) {
setMode(MODE_STARTING);
playAudioStartSound(new OnCompletionListener() {
@Override
public void onCompletion() {
// Double-check the current mode before recording since the user may have
// lifted finger from the button before the beeping sound is played through.
final int maxSize = MmsConfig.get(mHostInterface.getConversationSelfSubId())
.getMaxMessageSize();
if (mCurrentMode == MODE_STARTING &&
mMediaRecorder.startRecording(AudioRecordView.this,
AudioRecordView.this, maxSize)) {
setMode(MODE_RECORDING);
}
playAudioStartSound(() -> {
// Double-check the current mode before recording since the user may have
// lifted finger from the button before the beeping sound is played through.
final int maxSize = MmsConfig.get(mHostInterface.getConversationSelfSubId())
.getMaxMessageSize();
if (mCurrentMode == MODE_STARTING &&
mMediaRecorder.startRecording(AudioRecordView.this,
AudioRecordView.this, maxSize)) {
setMode(MODE_RECORDING);
}
});
mAudioRecordStartTimeMillis = System.currentTimeMillis();
@@ -270,25 +265,17 @@ public class AudioRecordView extends FrameLayout implements
// "tap+hold" to record audio.
final Uri outputUri = stopRecording();
if (outputUri != null) {
SafeAsyncTask.executeOnThreadPool(new Runnable() {
@Override
public void run() {
SafeAsyncTask.executeOnThreadPool(() ->
Factory.get().getApplicationContext().getContentResolver().delete(
outputUri, null, null);
}
});
outputUri, null, null));
}
setMode(MODE_IDLE);
mHintTextView.setTypeface(null, Typeface.BOLD);
} else if (isRecording()) {
// Record for some extra time to ensure the ending part is saved.
setMode(MODE_STOPPING);
ThreadUtil.getMainThreadHandler().postDelayed(new Runnable() {
@Override
public void run() {
onFinishedRecording();
}
}, AUDIO_RECORD_ENDING_BUFFER_MILLIS);
ThreadUtil.getMainThreadHandler().postDelayed(this::onFinishedRecording,
AUDIO_RECORD_ENDING_BUFFER_MILLIS);
} else {
setMode(MODE_IDLE);
}
@@ -35,7 +35,6 @@ import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import com.android.messaging.datamodel.data.DraftMessageData.DraftMessageSubscriptionDataProvider;
@@ -268,18 +267,15 @@ class CameraManager implements FocusOverlayManager.Listener {
if (preview != null) {
Assert.isTrue(preview.isValid());
preview.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(final View view, final MotionEvent motionEvent) {
if ((motionEvent.getActionMasked() & MotionEvent.ACTION_UP) ==
MotionEvent.ACTION_UP) {
mFocusOverlayManager.setPreviewSize(view.getWidth(), view.getHeight());
mFocusOverlayManager.onSingleTapUp(
(int) motionEvent.getX() + view.getLeft(),
(int) motionEvent.getY() + view.getTop());
}
return true;
preview.setOnTouchListener((view, motionEvent) -> {
if ((motionEvent.getActionMasked() & MotionEvent.ACTION_UP) ==
MotionEvent.ACTION_UP) {
mFocusOverlayManager.setPreviewSize(view.getWidth(), view.getHeight());
mFocusOverlayManager.onSingleTapUp(
(int) motionEvent.getX() + view.getLeft(),
(int) motionEvent.getY() + view.getTop());
}
return true;
});
}
mCameraPreview = preview;
@@ -542,36 +538,33 @@ class CameraManager implements FocusOverlayManager.Listener {
callback.onMediaFailed(null);
return;
}
final Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(final byte[] bytes, final Camera camera) {
mTakingPicture = false;
if (mCamera != camera) {
// This may happen if the camera was changed between front/back while the
// picture is being taken.
callback.onMediaInfo(MediaCallback.MEDIA_CAMERA_CHANGED);
return;
}
if (bytes == null) {
callback.onMediaInfo(MediaCallback.MEDIA_NO_DATA);
return;
}
final Camera.Size size = camera.getParameters().getPictureSize();
int width;
int height;
if (mRotation == 90 || mRotation == 270) {
width = size.height;
height = size.width;
} else {
width = size.width;
height = size.height;
}
new ImagePersistTask(
width, height, heightPercent, bytes, mCameraPreview.getContext(), callback)
.executeOnThreadPool();
final Camera.PictureCallback jpegCallback = (bytes, camera) -> {
mTakingPicture = false;
if (mCamera != camera) {
// This may happen if the camera was changed between front/back while the
// picture is being taken.
callback.onMediaInfo(MediaCallback.MEDIA_CAMERA_CHANGED);
return;
}
if (bytes == null) {
callback.onMediaInfo(MediaCallback.MEDIA_NO_DATA);
return;
}
final Camera.Size size = camera.getParameters().getPictureSize();
int width;
int height;
if (mRotation == 90 || mRotation == 270) {
width = size.height;
height = size.width;
} else {
width = size.width;
height = size.height;
}
new ImagePersistTask(
width, height, heightPercent, bytes, mCameraPreview.getContext(), callback)
.executeOnThreadPool();
};
mTakingPicture = true;
@@ -757,12 +750,8 @@ class CameraManager implements FocusOverlayManager.Listener {
mCamera.setParameters(params);
mCameraPreview.startPreview(mCamera);
mCamera.startPreview();
mCamera.setAutoFocusMoveCallback(new Camera.AutoFocusMoveCallback() {
@Override
public void onAutoFocusMoving(final boolean start, final Camera camera) {
mFocusOverlayManager.onAutoFocusMoving(start);
}
});
mCamera.setAutoFocusMoveCallback((start, camera) ->
mFocusOverlayManager.onAutoFocusMoving(start));
mFocusOverlayManager.setParameters(mCamera.getParameters());
mFocusOverlayManager.setMirror(mCameraInfo.facing == CameraInfo.CAMERA_FACING_BACK);
mFocusOverlayManager.onPreviewStarted();
@@ -830,24 +819,17 @@ class CameraManager implements FocusOverlayManager.Listener {
return;
}
mMediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
@Override
public void onError(final MediaRecorder mediaRecorder, final int what,
final int extra) {
if (mListener != null) {
mListener.onCameraError(ERROR_RECORDING_VIDEO, null);
}
restoreRequestedOrientation();
mMediaRecorder.setOnErrorListener((mediaRecorder, what, extra) -> {
if (mListener != null) {
mListener.onCameraError(ERROR_RECORDING_VIDEO, null);
}
restoreRequestedOrientation();
});
mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
@Override
public void onInfo(final MediaRecorder mediaRecorder, final int what, final int extra) {
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED ||
what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
stopVideo();
}
mMediaRecorder.setOnInfoListener((mediaRecorder, what, extra) -> {
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED ||
what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
stopVideo();
}
});
@@ -1094,12 +1076,8 @@ class CameraManager implements FocusOverlayManager.Listener {
}
try {
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(final boolean success, final Camera camera) {
mFocusOverlayManager.onAutoFocus(success, false /* shutterDown */);
}
});
mCamera.autoFocus((success, camera) -> mFocusOverlayManager.onAutoFocus(success,
false /* shutterDown */));
} catch (final RuntimeException e) {
LogUtil.e(TAG, "RuntimeException in CameraManager.autoFocus", e);
// If autofocus fails, the camera should have called the callback with success=false,
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +25,6 @@ import android.hardware.Camera;
import android.net.Uri;
import android.os.SystemClock;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
@@ -92,120 +92,98 @@ class CameraMediaChooser extends MediaChooser implements
false /* attachToRoot */);
mCameraPreviewHost = (CameraPreview.CameraPreviewHost) view.findViewById(
R.id.camera_preview);
mCameraPreviewHost.getView().setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(final View view, final MotionEvent motionEvent) {
if (CameraManager.get().isVideoMode()) {
// Prevent the swipe down in video mode because video is always captured in
// full screen
return true;
}
return false;
mCameraPreviewHost.getView().setOnTouchListener((view1, motionEvent) -> {
if (CameraManager.get().isVideoMode()) {
// Prevent the swipe down in video mode because video is always captured in
// full screen
return true;
}
return false;
});
final View shutterVisual = view.findViewById(R.id.camera_shutter_visual);
mFullScreenButton = (ImageButton) view.findViewById(R.id.camera_fullScreen_button);
mFullScreenButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
mMediaPicker.setFullScreen(true);
}
});
mFullScreenButton.setOnClickListener(view12 -> mMediaPicker.setFullScreen(true));
mSwapCameraButton = (ImageButton) view.findViewById(R.id.camera_swapCamera_button);
mSwapCameraButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
CameraManager.get().swapCamera();
}
});
mSwapCameraButton.setOnClickListener(view13 -> CameraManager.get().swapCamera());
mCaptureButton = (ImageButton) view.findViewById(R.id.camera_capture_button);
mCaptureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
final float heightPercent = Math.min(mMediaPicker.getViewPager().getHeight() /
(float) mCameraPreviewHost.getView().getHeight(), 1);
mCaptureButton.setOnClickListener(v -> {
final float heightPercent = Math.min(mMediaPicker.getViewPager().getHeight() /
(float) mCameraPreviewHost.getView().getHeight(), 1);
if (CameraManager.get().isRecording()) {
CameraManager.get().stopVideo();
} else {
final CameraManager.MediaCallback callback = new CameraManager.MediaCallback() {
@Override
public void onMediaReady(
final Uri uriToVideo, final String contentType,
final int width, final int height) {
mVideoCounter.stop();
if (mVideoCancelled || uriToVideo == null) {
mVideoCancelled = false;
} else {
final Rect startRect = new Rect();
// It's possible to throw out the chooser while taking the
// picture/video. In that case, still use the attachment, just
// skip the startRect
if (mView != null) {
mView.getGlobalVisibleRect(startRect);
}
mMediaPicker.dispatchItemsSelected(
new MediaPickerMessagePartData(startRect, contentType,
uriToVideo, width, height),
true /* dismissMediaPicker */);
if (CameraManager.get().isRecording()) {
CameraManager.get().stopVideo();
} else {
final MediaCallback callback = new MediaCallback() {
@Override
public void onMediaReady(
final Uri uriToVideo, final String contentType,
final int width, final int height) {
mVideoCounter.stop();
if (mVideoCancelled || uriToVideo == null) {
mVideoCancelled = false;
} else {
final Rect startRect = new Rect();
// It's possible to throw out the chooser while taking the
// picture/video. In that case, still use the attachment, just
// skip the startRect
if (mView != null) {
mView.getGlobalVisibleRect(startRect);
}
updateViewState();
mMediaPicker.dispatchItemsSelected(
new MediaPickerMessagePartData(startRect, contentType,
uriToVideo, width, height),
true /* dismissMediaPicker */);
}
@Override
public void onMediaFailed(final Exception exception) {
UiUtils.showToastAtBottom(R.string.camera_media_failure);
updateViewState();
}
@Override
public void onMediaInfo(final int what) {
if (what == MediaCallback.MEDIA_NO_DATA) {
UiUtils.showToastAtBottom(R.string.camera_media_failure);
}
updateViewState();
}
};
if (CameraManager.get().isVideoMode()) {
CameraManager.get().startVideo(callback);
mVideoCounter.setBase(SystemClock.elapsedRealtime());
mVideoCounter.start();
updateViewState();
} else {
showShutterEffect(shutterVisual);
CameraManager.get().takePicture(heightPercent, callback);
updateViewState();
}
@Override
public void onMediaFailed(final Exception exception) {
UiUtils.showToastAtBottom(R.string.camera_media_failure);
updateViewState();
}
@Override
public void onMediaInfo(final int what) {
if (what == MediaCallback.MEDIA_NO_DATA) {
UiUtils.showToastAtBottom(R.string.camera_media_failure);
}
updateViewState();
}
};
if (CameraManager.get().isVideoMode()) {
CameraManager.get().startVideo(callback);
mVideoCounter.setBase(SystemClock.elapsedRealtime());
mVideoCounter.start();
updateViewState();
} else {
showShutterEffect(shutterVisual);
CameraManager.get().takePicture(heightPercent, callback);
updateViewState();
}
}
});
mSwapModeButton = (ImageButton) view.findViewById(R.id.camera_swap_mode_button);
mSwapModeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
final boolean isSwitchingToVideo = !CameraManager.get().isVideoMode();
if (isSwitchingToVideo && !OsUtil.hasRecordAudioPermission()) {
requestRecordAudioPermission();
} else {
onSwapMode();
}
mSwapModeButton.setOnClickListener(view14 -> {
final boolean isSwitchingToVideo = !CameraManager.get().isVideoMode();
if (isSwitchingToVideo && !OsUtil.hasRecordAudioPermission()) {
requestRecordAudioPermission();
} else {
onSwapMode();
}
});
mCancelVideoButton = (ImageButton) view.findViewById(R.id.camera_cancel_button);
mCancelVideoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
mVideoCancelled = true;
CameraManager.get().stopVideo();
mMediaPicker.dismiss(true);
}
mCancelVideoButton.setOnClickListener(view15 -> {
mVideoCancelled = true;
CameraManager.get().stopVideo();
mMediaPicker.dismiss(true);
});
mVideoCounter = (Chronometer) view.findViewById(R.id.camera_video_counter);
@@ -83,23 +83,20 @@ public class CameraMediaChooserView extends FrameLayout implements PersistentIns
if (!canvas.isHardwareAccelerated() && !mIsSoftwareFallbackActive) {
mIsSoftwareFallbackActive = true;
// Post modifying the tree since we can't modify the view tree during a draw pass
ThreadUtil.getMainThreadHandler().post(new Runnable() {
@Override
public void run() {
final HardwareCameraPreview cameraPreview =
(HardwareCameraPreview) findViewById(R.id.camera_preview);
if (cameraPreview == null) {
return;
}
final ViewGroup parent = ((ViewGroup) cameraPreview.getParent());
final int index = parent.indexOfChild(cameraPreview);
final SoftwareCameraPreview softwareCameraPreview =
new SoftwareCameraPreview(getContext());
// Be sure to remove the hardware view before adding the software view to
// prevent having 2 camera previews active at the same time
parent.removeView(cameraPreview);
parent.addView(softwareCameraPreview, index);
ThreadUtil.getMainThreadHandler().post(() -> {
final HardwareCameraPreview cameraPreview =
(HardwareCameraPreview) findViewById(R.id.camera_preview);
if (cameraPreview == null) {
return;
}
final ViewGroup parent = ((ViewGroup) cameraPreview.getParent());
final int index = parent.indexOfChild(cameraPreview);
final SoftwareCameraPreview softwareCameraPreview =
new SoftwareCameraPreview(getContext());
// Be sure to remove the hardware view before adding the software view to
// prevent having 2 camera previews active at the same time
parent.removeView(cameraPreview);
parent.addView(softwareCameraPreview, index);
});
}
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -77,14 +78,10 @@ class ContactMediaChooser extends MediaChooser {
false /* attachToRoot */);
mEnabledView = view.findViewById(R.id.mediapicker_enabled);
mMissingPermissionView = view.findViewById(R.id.missing_permission_view);
mEnabledView.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(final View v) {
// Launch an external picker to pick a contact as attachment.
UIIntents.get().launchContactCardPicker(mMediaPicker);
}
});
mEnabledView.setOnClickListener(v -> {
// Launch an external picker to pick a contact as attachment.
UIIntents.get().launchContactCardPicker(mMediaPicker);
});
return view;
}
@@ -128,14 +125,11 @@ class ContactMediaChooser extends MediaChooser {
}
final Uri vCardUri = Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, lookupKey);
if (vCardUri != null) {
SafeAsyncTask.executeOnThreadPool(new Runnable() {
@Override
public void run() {
final PendingAttachmentData pendingItem =
PendingAttachmentData.createPendingAttachmentData(
ContentType.TEXT_X_VCARD.toLowerCase(), vCardUri);
mMediaPicker.dispatchPendingItemAdded(pendingItem);
}
SafeAsyncTask.executeOnThreadPool(() -> {
final PendingAttachmentData pendingItem =
PendingAttachmentData.createPendingAttachmentData(
ContentType.TEXT_X_VCARD.toLowerCase(), vCardUri);
mMediaPicker.dispatchPendingItemAdded(pendingItem);
});
}
}
@@ -92,12 +92,9 @@ public class GalleryGridItemView extends FrameLayout {
mFileName = (TextView) findViewById(R.id.file_name);
mFileType = (TextView) findViewById(R.id.file_type);
setOnClickListener(mOnClickListener);
final OnLongClickListener longClickListener = new OnLongClickListener() {
@Override
public boolean onLongClick(final View v) {
mHostInterface.onItemClicked(v, mData, true /* longClick */);
return true;
}
final OnLongClickListener longClickListener = v -> {
mHostInterface.onItemClicked(v, mData, true /* longClick */);
return true;
};
setOnLongClickListener(longClickListener);
mCheckBox.setOnLongClickListener(longClickListener);
@@ -38,9 +38,7 @@ import com.android.messaging.datamodel.data.GalleryGridItemData;
import com.android.messaging.datamodel.data.MediaPickerData;
import com.android.messaging.datamodel.data.MessagePartData;
import com.android.messaging.datamodel.data.MediaPickerData.MediaPickerDataListener;
import com.android.messaging.datamodel.data.PendingAttachmentData;
import com.android.messaging.ui.UIIntents;
import com.android.messaging.ui.mediapicker.DocumentImagePicker.SelectionListener;
import com.android.messaging.util.Assert;
import com.android.messaging.util.OsUtil;
@@ -59,15 +57,11 @@ class GalleryMediaChooser extends MediaChooser implements
GalleryMediaChooser(final MediaPicker mediaPicker) {
super(mediaPicker);
mAdapter = new GalleryGridAdapter(Factory.get().getApplicationContext(), null);
mDocumentImagePicker = new DocumentImagePicker(mMediaPicker,
new SelectionListener() {
@Override
public void onDocumentSelected(final PendingAttachmentData data) {
if (mBindingRef.isBound()) {
mMediaPicker.dispatchPendingItemAdded(data);
}
}
});
mDocumentImagePicker = new DocumentImagePicker(mMediaPicker, data -> {
if (mBindingRef.isBound()) {
mMediaPicker.dispatchPendingItemAdded(data);
}
});
}
@Override
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -146,13 +147,9 @@ public class LevelTrackingMediaRecorder {
"media recorder. " + ex);
if (mOutputUri != null) {
final Uri outputUri = mOutputUri;
SafeAsyncTask.executeOnThreadPool(new Runnable() {
@Override
public void run() {
SafeAsyncTask.executeOnThreadPool(() ->
Factory.get().getApplicationContext().getContentResolver().delete(
outputUri, null, null);
}
});
outputUri, null, null));
mOutputUri = null;
}
} finally {
@@ -191,26 +188,23 @@ public class LevelTrackingMediaRecorder {
private void startTrackingSoundLevel() {
stopTrackingSoundLevel();
mRefreshLevelThread = new Thread() {
@Override
public void run() {
try {
while (true) {
synchronized (LevelTrackingMediaRecorder.class) {
if (mRecorder != null) {
mLevelSource.setSpeechLevel(getAmplitude());
} else {
// The recording session is over, finish the thread.
return;
}
mRefreshLevelThread = new Thread(() -> {
try {
while (true) {
synchronized (LevelTrackingMediaRecorder.class) {
if (mRecorder != null) {
mLevelSource.setSpeechLevel(getAmplitude());
} else {
// The recording session is over, finish the thread.
return;
}
Thread.sleep(REFRESH_INTERVAL_MILLIS);
}
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
Thread.sleep(REFRESH_INTERVAL_MILLIS);
}
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
}
};
});
mRefreshLevelThread.start();
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,7 +25,6 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
@@ -93,12 +93,7 @@ abstract class MediaChooser extends BasePagerViewHolder
mTabButton.setContentDescription(
inflater.getContext().getResources().getString(getIconDescriptionResource()));
setSelected(mSelected);
mTabButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
mMediaPicker.selectChooser(MediaChooser.this);
}
});
mTabButton.setOnClickListener(view -> mMediaPicker.selectChooser(MediaChooser.this));
}
protected Context getContext() {
@@ -543,12 +543,7 @@ public class MediaPicker extends Fragment implements DraftMessageSubscriptionDat
mOpen = true;
mPagerAdapter.notifyDataSetChanged();
if (mListener != null) {
mListenerHandler.post(new Runnable() {
@Override
public void run() {
mListener.onOpened();
}
});
mListenerHandler.post(() -> mListener.onOpened());
}
if (mSelectedChooser != null) {
mSelectedChooser.onFullScreenChanged(false);
@@ -560,12 +555,7 @@ public class MediaPicker extends Fragment implements DraftMessageSubscriptionDat
setHasOptionsMenu(false);
mOpen = false;
if (mListener != null) {
mListenerHandler.post(new Runnable() {
@Override
public void run() {
mListener.onDismissed();
}
});
mListenerHandler.post(() -> mListener.onDismissed());
}
if (mSelectedChooser != null) {
mSelectedChooser.onOpenedChanged(false);
@@ -575,12 +565,7 @@ public class MediaPicker extends Fragment implements DraftMessageSubscriptionDat
void dispatchFullScreen(final boolean fullScreen) {
setHasOptionsMenu(fullScreen);
if (mListener != null) {
mListenerHandler.post(new Runnable() {
@Override
public void run() {
mListener.onFullScreenChanged(fullScreen);
}
});
mListenerHandler.post(() -> mListener.onFullScreenChanged(fullScreen));
}
if (mSelectedChooser != null) {
mSelectedChooser.onFullScreenChanged(fullScreen);
@@ -596,12 +581,7 @@ public class MediaPicker extends Fragment implements DraftMessageSubscriptionDat
void dispatchItemsSelected(final Collection<MessagePartData> items,
final boolean dismissMediaPicker) {
if (mListener != null) {
mListenerHandler.post(new Runnable() {
@Override
public void run() {
mListener.onItemsSelected(items, dismissMediaPicker);
}
});
mListenerHandler.post(() -> mListener.onItemsSelected(items, dismissMediaPicker));
}
if (isFullScreen() && !dismissMediaPicker) {
@@ -611,12 +591,7 @@ public class MediaPicker extends Fragment implements DraftMessageSubscriptionDat
void dispatchItemUnselected(final MessagePartData item) {
if (mListener != null) {
mListenerHandler.post(new Runnable() {
@Override
public void run() {
mListener.onItemUnselected(item);
}
});
mListenerHandler.post(() -> mListener.onItemUnselected(item));
}
if (isFullScreen()) {
@@ -626,23 +601,13 @@ public class MediaPicker extends Fragment implements DraftMessageSubscriptionDat
void dispatchConfirmItemSelection() {
if (mListener != null) {
mListenerHandler.post(new Runnable() {
@Override
public void run() {
mListener.onConfirmItemSelection();
}
});
mListenerHandler.post(() -> mListener.onConfirmItemSelection());
}
}
void dispatchPendingItemAdded(final PendingAttachmentData pendingItem) {
if (mListener != null) {
mListenerHandler.post(new Runnable() {
@Override
public void run() {
mListener.onPendingItemAdded(pendingItem);
}
});
mListenerHandler.post(() -> mListener.onPendingItemAdded(pendingItem));
}
if (isFullScreen()) {
@@ -652,12 +617,7 @@ public class MediaPicker extends Fragment implements DraftMessageSubscriptionDat
void dispatchChooserSelected(final int chooserIndex) {
if (mListener != null) {
mListenerHandler.post(new Runnable() {
@Override
public void run() {
mListener.onChooserSelected(chooserIndex);
}
});
mListenerHandler.post(() -> mListener.onChooserSelected(chooserIndex));
}
}
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -250,12 +251,7 @@ public class MediaPickerPanel extends ViewGroup {
}
mFullScreen = false;
mExpanded = expanded;
mHandler.post(new Runnable() {
@Override
public void run() {
setDesiredHeight(getDesiredHeight(), animate);
}
});
mHandler.post(() -> setDesiredHeight(getDesiredHeight(), animate));
if (expanded) {
setupViewPager(startingPage);
mMediaPicker.dispatchOpened();
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -110,13 +111,9 @@ class MmsVideoRecorder extends MediaRecorder {
void cleanupTempFile() {
final Uri tempUri = mTempVideoUri;
SafeAsyncTask.executeOnThreadPool(new Runnable() {
@Override
public void run() {
SafeAsyncTask.executeOnThreadPool(() ->
Factory.get().getApplicationContext().getContentResolver().delete(
tempUri, null, null);
}
});
tempUri, null, null));
mTempVideoUri = null;
}
@@ -18,7 +18,6 @@ package com.android.messaging.ui.mediapicker;
import android.animation.ObjectAnimator;
import android.animation.TimeAnimator;
import android.animation.TimeAnimator.TimeListener;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
@@ -107,13 +106,7 @@ public class SoundLevels extends View {
// which might improve things further.
mSpeechLevelsAnimator = new TimeAnimator();
mSpeechLevelsAnimator.setRepeatCount(ObjectAnimator.INFINITE);
mSpeechLevelsAnimator.setTimeListener(new TimeListener() {
@Override
public void onTimeUpdate(final TimeAnimator animation, final long totalTime,
final long deltaTime) {
invalidate();
}
});
mSpeechLevelsAnimator.setTimeListener((animation, totalTime, deltaTime) -> invalidate());
}
@Override