update to 9.7.4 (3712)

This commit is contained in:
xaxtix 2023-07-27 12:42:23 +04:00
parent f10844350d
commit 6c1e8c1cf7
55 changed files with 1534 additions and 703 deletions

View file

@ -182,12 +182,6 @@ public final class MediaCodecUtil {
}
}
applyWorkarounds(mimeType, decoderInfos);
for (int i = 0; i < decoderInfos.size(); i++) {
if (decoderInfos.get(i).name.equals("c2.exynos.hevc.decoder")) {
decoderInfos.remove(i);
i--;
}
}
ImmutableList<MediaCodecInfo> immutableDecoderInfos = ImmutableList.copyOf(decoderInfos);
decoderInfosCache.put(key, immutableDecoderInfos);
return immutableDecoderInfos;

View file

@ -177,6 +177,7 @@ import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.IDN;
import java.nio.ByteBuffer;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
@ -5360,4 +5361,19 @@ public class AndroidUtilities {
}
}
public static ByteBuffer cloneByteBuffer(ByteBuffer original) {
ByteBuffer clone;
try {
clone = ByteBuffer.allocate(original.capacity());
} catch (OutOfMemoryError error) {
System.gc();
clone = ByteBuffer.allocate(original.capacity());
}
original.rewind();
clone.put(original);
original.rewind();
clone.flip();
return clone;
}
}

View file

@ -24,8 +24,8 @@ public class BuildVars {
public static boolean USE_CLOUD_STRINGS = true;
public static boolean CHECK_UPDATES = true;
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
public static int BUILD_VERSION = 3705;
public static String BUILD_VERSION_STRING = "9.7.2";
public static int BUILD_VERSION = 3712;
public static String BUILD_VERSION_STRING = "9.7.4";
public static int APP_ID = 4;
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";

View file

@ -747,18 +747,18 @@ public class FileLoadOperation {
return;
}
paused = true;
if (isStory) {
Utilities.stageQueue.postRunnable(() -> {
Utilities.stageQueue.postRunnable(() -> {
if (isStory) {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("debug_loading:" + cacheFileFinal.getName() + " pause operation, clear requests");
}
clearOperaion(null, false);
});
} else {
for (int i = 0; i < requestInfos.size(); i++) {
ConnectionsManager.getInstance(currentAccount).failNotRunningRequest(requestInfos.get(i).requestToken);
} else {
for (int i = 0; i < requestInfos.size(); i++) {
ConnectionsManager.getInstance(currentAccount).failNotRunningRequest(requestInfos.get(i).requestToken);
}
}
}
});
}
public boolean start() {
@ -936,7 +936,7 @@ public class FileLoadOperation {
boolean finalFileExist = cacheFileFinal.exists();
if (finalFileExist && (parentObject instanceof TLRPC.TL_theme || (totalBytesCount != 0 && !ungzip && totalBytesCount != cacheFileFinal.length()))) {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("debug_loading: delete existing file cause file size mismatch " + cacheFileFinal.getName() + " totalSize= " + totalBytesCount + " existingFileSize=" + cacheFileFinal.length());
FileLog.d("debug_loading: delete existing file cause file size mismatch " + cacheFileFinal.getName() + " totalSize=" + totalBytesCount + " existingFileSize=" + cacheFileFinal.length());
}
if (!delegate.hasAnotherRefOnFile(cacheFileFinal.toString())) {
cacheFileFinal.delete();

View file

@ -754,7 +754,7 @@ public class FileLoader extends BaseController {
type = MEDIA_DIR_DOCUMENT;
} else if (location != null) {
documentId = location.volume_id;
dcId = location.dc_id;
dcId = location.dc_id + (location.local_id << 16);
operation = new FileLoadOperation(imageLocation, parentObject, locationExt, locationSize);
type = MEDIA_DIR_IMAGE;
} else if (document != null) {
@ -1230,8 +1230,7 @@ public class FileLoader extends BaseController {
dir = getDirectory(type = MEDIA_DIR_IMAGE);
}
documentId = photoSize.location.volume_id;
dcId = photoSize.location.dc_id;
dcId = photoSize.location.dc_id + (photoSize.location.local_id << 16);
} else if (attach instanceof TLRPC.TL_videoSize) {
TLRPC.TL_videoSize videoSize = (TLRPC.TL_videoSize) attach;
if (videoSize.location == null || videoSize.location.key != null || videoSize.location.volume_id == Integer.MIN_VALUE && videoSize.location.local_id < 0 || videoSize.size < 0) {
@ -1240,14 +1239,14 @@ public class FileLoader extends BaseController {
dir = getDirectory(type = MEDIA_DIR_IMAGE);
}
documentId = videoSize.location.volume_id;
dcId = videoSize.location.dc_id;
dcId = videoSize.location.dc_id + (videoSize.location.local_id << 16);
} else if (attach instanceof TLRPC.FileLocation) {
TLRPC.FileLocation fileLocation = (TLRPC.FileLocation) attach;
if (fileLocation.key != null || fileLocation.volume_id == Integer.MIN_VALUE && fileLocation.local_id < 0) {
dir = getDirectory(MEDIA_DIR_CACHE);
} else {
documentId = fileLocation.volume_id;
dcId = fileLocation.dc_id;
dcId = fileLocation.dc_id + (fileLocation.local_id << 16);
dir = getDirectory(type = MEDIA_DIR_IMAGE);
}
} else if (attach instanceof TLRPC.UserProfilePhoto || attach instanceof TLRPC.ChatPhoto) {

View file

@ -470,6 +470,7 @@ public class FilePathDatabase {
synchronized (this) {
if (dispatchQueue == null) {
dispatchQueue = new DispatchQueue("files_database_queue_" + currentAccount);
dispatchQueue.setPriority(Thread.MAX_PRIORITY);
}
}
}

View file

@ -276,6 +276,27 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
blurExcludeBlurSize = stream.readFloat(exception);
blurAngle = stream.readFloat(exception);
}
public boolean isEmpty() {
return (
Math.abs(enhanceValue) < 0.1f &&
Math.abs(softenSkinValue) < 0.1f &&
Math.abs(exposureValue) < 0.1f &&
Math.abs(contrastValue) < 0.1f &&
Math.abs(warmthValue) < 0.1f &&
Math.abs(saturationValue) < 0.1f &&
Math.abs(fadeValue) < 0.1f &&
tintShadowsColor == 0 &&
tintHighlightsColor == 0 &&
Math.abs(highlightsValue) < 0.1f &&
Math.abs(shadowsValue) < 0.1f &&
Math.abs(vignetteValue) < 0.1f &&
Math.abs(grainValue) < 0.1f &&
blurType == 0 &&
Math.abs(sharpenValue) < 0.1f &&
Math.abs(blurExcludeSize) < 0.1f
);
}
}
public static class CropState {

View file

@ -6949,6 +6949,18 @@ public class MessageObject {
return isVideoMessage(messageOwner);
}
public boolean isVideoStory() {
TLRPC.MessageMedia media = MessageObject.getMedia(messageOwner);
if (media == null) {
return false;
}
TLRPC.StoryItem storyItem = media.storyItem;
if (storyItem == null || storyItem.media == null) {
return false;
}
return MessageObject.isVideoDocument(storyItem.media.document);
}
public boolean isPhoto() {
return isPhoto(messageOwner);
}
@ -7087,6 +7099,12 @@ public class MessageObject {
return attributeDuration;
}
TLRPC.Document document = getDocument();
if (document == null && type == TYPE_STORY) {
TLRPC.StoryItem storyItem = getMedia(messageOwner).storyItem;
if (storyItem != null && storyItem.media != null) {
document = storyItem.media.document;
}
}
if (document == null) {
return 0;
}

View file

@ -6866,7 +6866,7 @@ public class MessagesStorage extends BaseController {
SQLiteCursor cursor = null;
try {
cursor = database.queryFinalized("SELECT uid, info, participants_count FROM chat_settings_v2 WHERE participants_count > 1 AND participants_count <= 20");
cursor = database.queryFinalized("SELECT uid, info, participants_count FROM chat_settings_v2 WHERE participants_count > 1");
while (cursor.next()) {
TLRPC.ChatFull info = null;
long id = cursor.longValue(0);

View file

@ -4658,7 +4658,7 @@ public class NotificationsController extends BaseController {
}
}
boolean needAddPerson = lastMessageObject != null && !(lastMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest);
boolean needAddPerson = lastMessageObject == null || !(lastMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByRequest);
NotificationCompat.MessagingStyle messagingStyle;
if (selfPerson != null && needAddPerson) {
messagingStyle = new NotificationCompat.MessagingStyle(selfPerson);

View file

@ -611,6 +611,10 @@ public class CameraController implements MediaRecorder.OnInfoListener {
}
public void recordVideo(final CameraSession session, final File path, boolean mirror, final VideoTakeCallback callback, final Runnable onVideoStartRecord, ICameraView cameraView) {
recordVideo(session, path, mirror, callback, onVideoStartRecord, cameraView, true);
}
public void recordVideo(final CameraSession session, final File path, boolean mirror, final VideoTakeCallback callback, final Runnable onVideoStartRecord, ICameraView cameraView, boolean createThumbnail) {
if (session == null) {
return;
}
@ -632,7 +636,7 @@ public class CameraController implements MediaRecorder.OnInfoListener {
FileLog.e(e);
}
AndroidUtilities.runOnUIThread(() -> {
cameraView.startRecording(path, this::finishRecordingVideo);
cameraView.startRecording(path, () -> finishRecordingVideo(createThumbnail));
if (onVideoStartRecord != null) {
onVideoStartRecord.run();
@ -703,7 +707,7 @@ public class CameraController implements MediaRecorder.OnInfoListener {
});
}
private void finishRecordingVideo() {
private void finishRecordingVideo(boolean createThumbnail) {
MediaMetadataRetriever mediaMetadataRetriever = null;
long duration = 0;
try {
@ -724,38 +728,47 @@ public class CameraController implements MediaRecorder.OnInfoListener {
FileLog.e(e);
}
}
Bitmap bitmap = SendMessagesHelper.createVideoThumbnail(recordedFile, MediaStore.Video.Thumbnails.MINI_KIND);
if (mirrorRecorderVideo) {
Bitmap b = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
canvas.scale(-1, 1, b.getWidth() / 2, b.getHeight() / 2);
canvas.drawBitmap(bitmap, 0, 0, null);
bitmap.recycle();
bitmap = b;
}
String fileName = Integer.MIN_VALUE + "_" + SharedConfig.getLastLocalId() + ".jpg";
final File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
FileOutputStream stream = null;
try {
stream = new FileOutputStream(cacheFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 87, stream);
} catch (Throwable e) {
FileLog.e(e);
} finally {
if (stream != null) {
try {
stream.close();
} catch (Throwable ignore) {}
final File cacheFile;
Bitmap bitmap = null;
if (createThumbnail) {
bitmap = SendMessagesHelper.createVideoThumbnail(recordedFile, MediaStore.Video.Thumbnails.MINI_KIND);
if (mirrorRecorderVideo) {
Bitmap b = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
canvas.scale(-1, 1, b.getWidth() / 2, b.getHeight() / 2);
canvas.drawBitmap(bitmap, 0, 0, null);
bitmap.recycle();
bitmap = b;
}
String fileName = Integer.MIN_VALUE + "_" + SharedConfig.getLastLocalId() + ".jpg";
cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
FileOutputStream stream = null;
try {
stream = new FileOutputStream(cacheFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 87, stream);
} catch (Throwable e) {
FileLog.e(e);
} finally {
if (stream != null) {
try {
stream.close();
} catch (Throwable ignore) {}
}
}
} else {
cacheFile = null;
}
SharedConfig.saveConfig();
final long durationFinal = duration;
final Bitmap bitmapFinal = bitmap;
AndroidUtilities.runOnUIThread(() -> {
if (onVideoTakeCallback != null) {
String path = cacheFile.getAbsolutePath();
if (bitmapFinal != null) {
ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmapFinal), Utilities.MD5(path), false);
String path = null;
if (cacheFile != null) {
path = cacheFile.getAbsolutePath();
if (bitmapFinal != null) {
ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmapFinal), Utilities.MD5(path), false);
}
}
onVideoTakeCallback.onFinishVideoRecording(path, durationFinal);
onVideoTakeCallback = null;
@ -773,12 +786,16 @@ public class CameraController implements MediaRecorder.OnInfoListener {
tempRecorder.release();
}
if (onVideoTakeCallback != null) {
finishRecordingVideo();
finishRecordingVideo(true);
}
}
}
public void stopVideoRecording(final CameraSession session, final boolean abandon) {
stopVideoRecording(session, abandon, true);
}
public void stopVideoRecording(final CameraSession session, final boolean abandon, final boolean createThumbnail) {
if (recordingCurrentCameraView != null) {
recordingCurrentCameraView.stopRecording();
recordingCurrentCameraView = null;
@ -830,7 +847,7 @@ public class CameraController implements MediaRecorder.OnInfoListener {
}
});
if (!abandon && onVideoTakeCallback != null) {
finishRecordingVideo();
finishRecordingVideo(createThumbnail);
} else {
onVideoTakeCallback = null;
}

View file

@ -556,25 +556,40 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
return false;
}
private Integer shape;
public void dualToggleShape() {
if (flipping || !dual) {
return;
}
Handler handler = cameraThread.getHandler();
MessagesController.getGlobalMainSettings().edit().putInt("dualshape", (int) (cameraThread.shapeTo + 1)).apply();
if (shape == null) {
shape = MessagesController.getGlobalMainSettings().getInt("dualshape", 0);
}
shape++;
MessagesController.getGlobalMainSettings().edit().putInt("dualshape", shape).apply();
if (handler != null) {
handler.sendMessage(handler.obtainMessage(cameraThread.DO_DUAL_TOGGLE_SHAPE));
}
}
public int getDualShape() {
if (shape == null) {
shape = MessagesController.getGlobalMainSettings().getInt("dualshape", 0);
}
return shape;
}
private long lastDualSwitchTime;
public void switchCamera() {
if (flipping || System.currentTimeMillis() < toggleDualUntil && !dualCameraAppeared) {
return;
}
if (dual) {
if (!dualCameraAppeared) {
if (!dualCameraAppeared || System.currentTimeMillis() - lastDualSwitchTime < 420) {
return;
}
lastDualSwitchTime = System.currentTimeMillis();
CameraInfo info0 = info[0];
info[0] = info[1];
info[1] = info0;
@ -2147,6 +2162,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
}
}
fileWriteQueue = new DispatchQueue("VR_FileWriteQueue");
fileWriteQueue.setPriority(Thread.MAX_PRIORITY);
keyframeThumbs.clear();
handler.sendMessage(handler.obtainMessage(MSG_START_RECORDING));
@ -2806,7 +2822,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
bufferInfo.offset = videoBufferInfo.offset;
bufferInfo.flags = videoBufferInfo.flags;
bufferInfo.presentationTimeUs = videoBufferInfo.presentationTimeUs;
ByteBuffer byteBuffer = encodedData.duplicate();
ByteBuffer byteBuffer = AndroidUtilities.cloneByteBuffer(encodedData);
fileWriteQueue.postRunnable(() -> {
try {
mediaMuxer.writeSampleData(videoTrackIndex, byteBuffer, bufferInfo, true);
@ -2891,7 +2907,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
bufferInfo.offset = audioBufferInfo.offset;
bufferInfo.flags = audioBufferInfo.flags;
bufferInfo.presentationTimeUs = audioBufferInfo.presentationTimeUs;
ByteBuffer byteBuffer = encodedData.duplicate();
ByteBuffer byteBuffer = AndroidUtilities.cloneByteBuffer(encodedData);
fileWriteQueue.postRunnable(() -> {
try {
mediaMuxer.writeSampleData(audioTrackIndex, byteBuffer, bufferInfo, false);

View file

@ -1030,6 +1030,7 @@ public class TextureRenderer {
entity.animatedFileDrawable = new AnimatedFileDrawable(new File(entity.text), true, 0, 0, null, null, null, 0, UserConfig.selectedAccount, true, 512, 512, null);
entity.framesPerDraw = entity.animatedFileDrawable.getFps() / videoFps;
entity.currentFrame = 0;
entity.animatedFileDrawable.getNextFrame();
} else {
if (Build.VERSION.SDK_INT >= 19) {
BitmapFactory.Options opts = new BitmapFactory.Options();

View file

@ -1158,7 +1158,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
if (!canCacnel || cancelDialog != null) {
return;
}
Builder builder = new Builder(getContext());
Builder builder = new Builder(getContext(), resourcesProvider);
builder.setTitle(LocaleController.getString("StopLoadingTitle", R.string.StopLoadingTitle));
builder.setMessage(LocaleController.getString("StopLoading", R.string.StopLoading));
builder.setPositiveButton(LocaleController.getString("WaitMore", R.string.WaitMore), null);

View file

@ -68,6 +68,7 @@ import org.telegram.ui.Stories.StoryViewer;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.SortedSet;
public class CalendarActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
@ -214,7 +215,7 @@ public class CalendarActivity extends BaseFragment implements NotificationCenter
holder.drawAbove = storiesPlaceDrawAbove;
holder.view = monthView;
holder.clipParent = fragmentView;
holder.clipTop = Math.max(0, - monthView.getY());
holder.clipTop = AndroidUtilities.dp(36);
holder.clipBottom = fragmentView.getBottom();
holder.avatarImage = null;
return true;
@ -801,8 +802,7 @@ public class CalendarActivity extends BaseFragment implements NotificationCenter
PeriodDay day = getDayAtCoord(e.getX(), e.getY());
if (day != null && day.messageObject != null && callback != null) {
if (storiesList != null) {
int position = storiesList.messageObjects.indexOf(day.messageObject);
getOrCreateStoryViewer().open(getContext(), day.messageObject.storyItem, Math.max(0, position), storiesList, true, storiesPlaceProvider);
getOrCreateStoryViewer().open(getContext(), day.messageObject.storyItem, day.messageObject.getId(), storiesList, true, storiesPlaceProvider);
} else {
callback.onDateSelected(day.messageObject.getId(), day.startOffset);
finishFragment();

View file

@ -11419,6 +11419,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (currentMessageObject == null) {
return;
}
if (currentMessageObject.type == MessageObject.TYPE_STORY && currentMessageObject.isVideoStory()) {
buttonState = 2;
getIconForCurrentState();
return;
}
if (animated && (PhotoViewer.isShowingImage(currentMessageObject) || !attachedToWindow)) {
animated = false;
}
@ -12015,7 +12020,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
}
}
} else if (buttonState == 2) {
if (documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND && currentMessageObject != null && currentMessageObject.isVoiceTranscriptionOpen()) {
if (currentMessageObject != null && currentMessageObject.type == MessageObject.TYPE_STORY) {
delegate.didPressImage(this, 0, 0);
} else if (documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND && currentMessageObject != null && currentMessageObject.isVoiceTranscriptionOpen()) {
if (miniButtonState == 0) {
FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, FileLoader.PRIORITY_NORMAL_UP, 0);
currentMessageObject.loadingCancelled = false;

View file

@ -74,6 +74,7 @@ public class SharedPhotoVideoCell2 extends View {
float crossfadeProgress;
float crossfadeToColumnsCount;
float highlightProgress;
public boolean isFirst, isLast;
private Drawable gradientDrawable;
private boolean gradientDrawableLoading;
@ -303,8 +304,10 @@ public class SharedPhotoVideoCell2 extends View {
super.onDraw(canvas);
final float padding = getPadding();
final float leftpadding = isStory && isFirst ? 0 : padding;
final float rightpadding = isStory && isLast ? 0 : padding;
float imageWidth = (getMeasuredWidth() - padding * 2) * imageScale;
float imageWidth = (getMeasuredWidth() - leftpadding - rightpadding) * imageScale;
float imageHeight = (getMeasuredHeight() - padding * 2) * imageScale;
if (crossfadeProgress > 0.5f && crossfadeToColumnsCount != 9 && currentParentColumnsCount != 9) {
@ -317,23 +320,23 @@ public class SharedPhotoVideoCell2 extends View {
globalGradientView.setParentSize(((View) SharedPhotoVideoCell2.this.getParent()).getMeasuredWidth(), SharedPhotoVideoCell2.this.getMeasuredHeight(), -getX());
globalGradientView.updateColors();
globalGradientView.updateGradient();
float localPadding = padding;
float padPlus = 0;
if (crossfadeProgress > 0.5f && crossfadeToColumnsCount != 9 && currentParentColumnsCount != 9) {
localPadding += 1;
padPlus += 1;
}
canvas.drawRect(localPadding, localPadding, localPadding + imageWidth, localPadding + imageHeight, globalGradientView.getPaint());
canvas.drawRect(leftpadding + padPlus, padding + padPlus, leftpadding + padPlus + imageWidth, padding + padPlus + imageHeight, globalGradientView.getPaint());
}
invalidate();
}
if (imageAlpha != 1f) {
canvas.saveLayerAlpha(0, 0, padding * 2 + imageWidth, padding * 2 + imageHeight, (int) (255 * imageAlpha), Canvas.ALL_SAVE_FLAG);
canvas.saveLayerAlpha(0, 0, leftpadding + rightpadding + imageWidth, padding * 2 + imageHeight, (int) (255 * imageAlpha), Canvas.ALL_SAVE_FLAG);
} else {
canvas.save();
}
if ((checkBoxBase != null && checkBoxBase.isChecked()) || PhotoViewer.isShowingImage(currentMessageObject)) {
canvas.drawRect(padding, padding, imageWidth, imageHeight, sharedResources.backgroundPaint);
canvas.drawRect(leftpadding, padding, leftpadding + imageWidth - rightpadding, imageHeight, sharedResources.backgroundPaint);
}
if (isStory && currentParentColumnsCount == 1) {
@ -357,21 +360,21 @@ public class SharedPhotoVideoCell2 extends View {
imageReceiver.setImageCoords((imageWidth - w) / 2, 0, w, getHeight());
} else if (checkBoxProgress > 0) {
float offset = dp(10) * checkBoxProgress;
imageReceiver.setImageCoords(padding + offset, padding + offset, imageWidth - offset * 2, imageHeight - offset * 2);
blurImageReceiver.setImageCoords(padding + offset, padding + offset, imageWidth - offset * 2, imageHeight - offset * 2);
imageReceiver.setImageCoords(leftpadding + offset, padding + offset, imageWidth - offset * 2, imageHeight - offset * 2);
blurImageReceiver.setImageCoords(leftpadding + offset, padding + offset, imageWidth - offset * 2, imageHeight - offset * 2);
} else {
float localPadding = padding;
float padPlus = 0;
if (crossfadeProgress > 0.5f && crossfadeToColumnsCount != 9 && currentParentColumnsCount != 9) {
localPadding += 1;
padPlus = 1;
}
imageReceiver.setImageCoords(localPadding, localPadding, imageWidth, imageHeight);
blurImageReceiver.setImageCoords(localPadding, localPadding, imageWidth, imageHeight);
imageReceiver.setImageCoords(leftpadding + padPlus, padding + padPlus, imageWidth, imageHeight);
blurImageReceiver.setImageCoords(leftpadding + padPlus, padding + padPlus, imageWidth, imageHeight);
}
if (!PhotoViewer.isShowingImage(currentMessageObject)) {
imageReceiver.draw(canvas);
if (currentMessageObject != null && currentMessageObject.hasMediaSpoilers() && !currentMessageObject.isMediaSpoilersRevealedInSharedMedia) {
canvas.save();
canvas.clipRect(padding, padding, padding + imageWidth, padding + imageHeight);
canvas.clipRect(leftpadding, padding, leftpadding + imageWidth - rightpadding, padding + imageHeight);
if (spoilerRevealProgress != 0f) {
path.rewind();
@ -397,7 +400,7 @@ public class SharedPhotoVideoCell2 extends View {
}
bounds.set(imageReceiver.getImageX(), imageReceiver.getImageY(), imageReceiver.getImageX2(), imageReceiver.getImageY2());
bounds.set(padding, padding, padding + imageWidth, padding + imageHeight);
bounds.set(leftpadding, padding, leftpadding + imageWidth - rightpadding, padding + imageHeight);
drawDuration(canvas, bounds, 1f);
if (checkBoxBase != null && (style == STYLE_CACHE || checkBoxBase.getProgress() != 0)) {

View file

@ -19870,6 +19870,32 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
messageObject.generatePaymentSentMessageText(null);
}
}
if (old.isWebpage() && messageObject.isWebpage()) {
TLRPC.TL_messageMediaWebPage media = (TLRPC.TL_messageMediaWebPage) MessageObject.getMedia(old.messageOwner);
if (media.webpage != null && "telegram_story".equals(media.webpage.type)) {
TLRPC.StoryItem storyItem = null;
for (int i = 0; i < media.webpage.attributes.size(); ++i) {
TLRPC.WebPageAttribute attr = media.webpage.attributes.get(i);
if (attr instanceof TLRPC.TL_webPageAttributeStory) {
storyItem = ((TLRPC.TL_webPageAttributeStory) attr).storyItem;
break;
}
}
if (storyItem != null) {
TLRPC.TL_messageMediaWebPage newMedia = (TLRPC.TL_messageMediaWebPage) MessageObject.getMedia(messageObject.messageOwner);
for (int i = 0; i < newMedia.webpage.attributes.size(); ++i) {
TLRPC.WebPageAttribute attr = newMedia.webpage.attributes.get(i);
if (attr instanceof TLRPC.TL_webPageAttributeStory) {
TLRPC.TL_webPageAttributeStory storyAttr = (TLRPC.TL_webPageAttributeStory) attr;
if (!(storyAttr.storyItem instanceof TLRPC.TL_storyItem)) {
storyAttr.storyItem = storyItem;
}
break;
}
}
}
}
}
if (!old.isEditing()) {
if (old.getFileName().equals(messageObject.getFileName())) {
messageObject.messageOwner.attachPath = old.messageOwner.attachPath;

View file

@ -23,6 +23,7 @@ import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.view.Gravity;
import android.view.View;

View file

@ -1844,4 +1844,9 @@ public class Bulletin {
}
}
}
public Bulletin setTag(int tag) {
this.tag = tag;
return this;
}
}

View file

@ -1,7 +1,9 @@
package org.telegram.ui.Components;
import android.graphics.PointF;
import android.os.Build;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
import androidx.core.graphics.PathParser;
@ -14,7 +16,7 @@ public class CubicBezierInterpolator implements Interpolator {
public static final CubicBezierInterpolator EASE_IN = new CubicBezierInterpolator(.42, 0, 1, 1);
public static final CubicBezierInterpolator EASE_BOTH = new CubicBezierInterpolator(.42, 0, .58, 1);
public static final CubicBezierInterpolator EASE_OUT_BACK = new CubicBezierInterpolator(.34, 1.56, .64, 1);
public static final PathInterpolator Emphasized = new PathInterpolator(PathParser.createPathFromPathData("M 0,0 C 0.05, 0, 0.133333, 0.06, 0.166666, 0.4 C 0.208333, 0.82, 0.25, 1, 1, 1"));
public static final Interpolator Emphasized = Build.VERSION.SDK_INT >= 21 ? new PathInterpolator(PathParser.createPathFromPathData("M 0,0 C 0.05, 0, 0.133333, 0.06, 0.166666, 0.4 C 0.208333, 0.82, 0.25, 1, 1, 1")) : new LinearInterpolator();
protected PointF start;
protected PointF end;
protected PointF a = new PointF();

View file

@ -97,6 +97,7 @@ import org.telegram.messenger.camera.Size;
import org.telegram.messenger.video.MP4Builder;
import org.telegram.messenger.video.Mp4Movie;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.NativeByteBuffer;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ChatActivity;
@ -125,7 +126,7 @@ import javax.microedition.khronos.egl.EGLSurface;
@TargetApi(18)
public class InstantCameraView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
public boolean WRITE_TO_FILE_IN_BACKGROUND = true;
public boolean WRITE_TO_FILE_IN_BACKGROUND;
private int currentAccount = UserConfig.selectedAccount;
private InstantViewCameraContainer cameraContainer;
@ -241,6 +242,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
@SuppressLint("ClickableViewAccessibility")
public InstantCameraView(Context context, Delegate delegate, Theme.ResourcesProvider resourcesProvider) {
super(context);
WRITE_TO_FILE_IN_BACKGROUND = SharedConfig.deviceIsAboveAverage();
this.resourcesProvider = resourcesProvider;
parentView = delegate.getFragmentView();
setWillNotDraw(false);
@ -1827,7 +1829,12 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
}
AudioBufferInfo buffer;
if (buffers.isEmpty()) {
buffer = new AudioBufferInfo();
try {
buffer = new AudioBufferInfo();
} catch (OutOfMemoryError error) {
System.gc();
buffer = new AudioBufferInfo();
}
} else {
buffer = buffers.poll();
}
@ -1925,6 +1932,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
}
fileWriteQueue = new DispatchQueue("IVR_FileWriteQueue");
fileWriteQueue.setPriority(Thread.MAX_PRIORITY);
keyframeThumbs.clear();
frameCount = 0;
@ -2700,7 +2708,6 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
if (encodedData == null) {
throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null");
}
boolean needReleaseBuffers = true;
if (videoBufferInfo.size > 1) {
if ((videoBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
if (prependHeaderSize != 0 && (videoBufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0) {
@ -2732,7 +2739,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
bufferInfo.offset = videoBufferInfo.offset;
bufferInfo.flags = videoBufferInfo.flags;
bufferInfo.presentationTimeUs = videoBufferInfo.presentationTimeUs;
ByteBuffer byteBuffer = encodedData.duplicate();
ByteBuffer byteBuffer = AndroidUtilities.cloneByteBuffer(encodedData);
fileWriteQueue.postRunnable(() -> {
long availableSize = 0;
try {
@ -2779,9 +2786,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
videoTrackIndex = mediaMuxer.addTrack(newFormat, false);
}
}
if (needReleaseBuffers) {
videoEncoder.releaseOutputBuffer(encoderStatus, false);
}
videoEncoder.releaseOutputBuffer(encoderStatus, false);
if ((videoBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
break;
}
@ -2827,7 +2832,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
bufferInfo.offset = audioBufferInfo.offset;
bufferInfo.flags = audioBufferInfo.flags;
bufferInfo.presentationTimeUs = audioBufferInfo.presentationTimeUs;
ByteBuffer byteBuffer = encodedData.duplicate();
ByteBuffer byteBuffer = AndroidUtilities.cloneByteBuffer(encodedData);
fileWriteQueue.postRunnable(() -> {
long availableSize = 0;
try {

View file

@ -338,6 +338,9 @@ public class JoinGroupAlert extends BottomSheet {
private CharSequence ellipsize(TextView textView, TLRPC.ChatInvite chatInvite, int pos) {
String firstName = chatInvite.participants.get(pos).first_name;
if (firstName == null) {
firstName = "";
}
return TextUtils.ellipsize(firstName.trim(), textView.getPaint(), AndroidUtilities.dp(120), TextUtils.TruncateAt.END);
}
}

View file

@ -2408,9 +2408,10 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
deleteView.setBackground(Theme.getSelectorDrawable(false));
deleteView.setGravity(Gravity.CENTER_VERTICAL);
deleteView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(14), 0);
deleteView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
deleteView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
deleteView.setTag(0);
deleteView.setText(LocaleController.getString("PaintDelete", R.string.PaintDelete));
deleteView.setEllipsize(TextUtils.TruncateAt.END);
deleteView.setOnClickListener(v -> {
removeEntity(entityView);
@ -2426,7 +2427,8 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
editView.setBackground(Theme.getSelectorDrawable(false));
editView.setGravity(Gravity.CENTER_VERTICAL);
editView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0);
editView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
editView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
editView.setEllipsize(TextUtils.TruncateAt.END);
editView.setTag(1);
editView.setText(LocaleController.getString("PaintEdit", R.string.PaintEdit));
editView.setOnClickListener(v -> {
@ -2443,8 +2445,9 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
duplicateView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem));
duplicateView.setBackgroundDrawable(Theme.getSelectorDrawable(false));
duplicateView.setGravity(Gravity.CENTER_VERTICAL);
duplicateView.setEllipsize(TextUtils.TruncateAt.END);
duplicateView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0);
duplicateView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
duplicateView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
duplicateView.setTag(2);
duplicateView.setText(LocaleController.getString("PaintDuplicate", R.string.PaintDuplicate));
duplicateView.setOnClickListener(v -> {

View file

@ -66,7 +66,8 @@ public class PhotoView extends EntityView {
centerImage.setParentView(containerView);
centerImage.setRoundRadius(AndroidUtilities.dp(12));
centerImage.setOrientation(orientation, invert, true);
centerImage.setImage(ImageLocation.getForPath(path), null, null, null, null, 1);
final int side = Math.round(Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * .8f / AndroidUtilities.density);
centerImage.setImage(ImageLocation.getForPath(path), side + "_" + side, null, null, null, 1);
updatePosition();
}

View file

@ -616,30 +616,30 @@ public class PremiumFeatureBottomSheet extends BottomSheet implements Notificati
} else if (onlySelectedType) {
if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS) {
title.setText(LocaleController.getString("AdditionalReactions", R.string.AdditionalReactions));
description.setText(LocaleController.getString("AdditionalReactionsDescription", R.string.AdditionalReactionsDescription));
description.setText(AndroidUtilities.replaceTags(LocaleController.getString("AdditionalReactionsDescription", R.string.AdditionalReactionsDescription)));
} else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_ADS) {
title.setText(LocaleController.getString("PremiumPreviewNoAds", R.string.PremiumPreviewNoAds));
description.setText(LocaleController.getString("PremiumPreviewNoAdsDescription2", R.string.PremiumPreviewNoAdsDescription2));
description.setText(AndroidUtilities.replaceTags(LocaleController.getString("PremiumPreviewNoAdsDescription2", R.string.PremiumPreviewNoAdsDescription2)));
} else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_APPLICATION_ICONS) {
title.setText(LocaleController.getString("PremiumPreviewAppIcon", R.string.PremiumPreviewAppIcon));
description.setText(LocaleController.getString("PremiumPreviewAppIconDescription2", R.string.PremiumPreviewAppIconDescription2));
description.setText(AndroidUtilities.replaceTags(LocaleController.getString("PremiumPreviewAppIconDescription2", R.string.PremiumPreviewAppIconDescription2)));
} else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_DOWNLOAD_SPEED) {
title.setText(LocaleController.getString(R.string.PremiumPreviewDownloadSpeed));
description.setText(LocaleController.getString(R.string.PremiumPreviewDownloadSpeedDescription2));
description.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.PremiumPreviewDownloadSpeedDescription2)));
} else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT) {
title.setText(LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagement));
description.setText(LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagementDescription2));
description.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.PremiumPreviewAdvancedChatManagementDescription2)));
} else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_VOICE_TO_TEXT) {
title.setText(LocaleController.getString(R.string.PremiumPreviewVoiceToText));
description.setText(LocaleController.getString(R.string.PremiumPreviewVoiceToTextDescription2));
description.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.PremiumPreviewVoiceToTextDescription2)));
} else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_TRANSLATIONS) {
title.setText(LocaleController.getString(R.string.PremiumPreviewTranslations));
description.setText(LocaleController.getString(R.string.PremiumPreviewTranslationsDescription));
description.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.PremiumPreviewTranslationsDescription)));
}
topViewOnFullHeight = false;
} else {
title.setText(featureData.title);
description.setText(featureData.description);
description.setText(AndroidUtilities.replaceTags(featureData.description));
topViewOnFullHeight = false;
}
requestLayout();

View file

@ -27,6 +27,7 @@ import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.R;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Stories.recorder.HintView2;
import org.telegram.ui.TopicsFragment;
public class PullForegroundDrawable {
@ -88,9 +89,14 @@ public class PullForegroundDrawable {
public float outImageSize;
public float outOverScroll;
private final CharSequence pullTooltipText;
private StaticLayout pullTooltipLayout;
private float pullTooltipLayoutScale = 1;
private float pullTooltipLayoutLeft, pullTooltipLayoutWidth;
private final CharSequence releaseTooltipText;
private StaticLayout releaseTooltipLayout;
private float releaseTooltipLayoutScale = 1;
private float releaseTooltipLayoutLeft, releaseTooltipLayoutWidth;
private boolean willDraw;
@ -120,18 +126,63 @@ public class PullForegroundDrawable {
final ViewConfiguration vc = ViewConfiguration.get(ApplicationLoader.applicationContext);
touchSlop = vc.getScaledTouchSlop();
pullTooltipLayout = new StaticLayout(pullText, 0, pullText.length(), tooltipTextPaint, AndroidUtilities.displaySize.x, Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
pullTooltipLayoutLeft = pullTooltipLayout.getLineCount() > 0 ? pullTooltipLayout.getLineLeft(0) : 0;
pullTooltipLayoutWidth = pullTooltipLayout.getLineCount() > 0 ? pullTooltipLayout.getLineWidth(0) : 0;
releaseTooltipLayout = new StaticLayout(releaseText, 0, releaseText.length(), tooltipTextPaint, AndroidUtilities.displaySize.x, Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
releaseTooltipLayoutLeft = releaseTooltipLayout.getLineCount() > 0 ? releaseTooltipLayout.getLineLeft(0) : 0;
releaseTooltipLayoutWidth = releaseTooltipLayout.getLineCount() > 0 ? releaseTooltipLayout.getLineWidth(0) : 0;
pullTooltipText = pullText;
releaseTooltipText = releaseText;
try {
generalTopicDrawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.msg_filled_general).mutate();
} catch (Exception ignore) {}
}
private int lastWidth;
private void checkTextLayouts(int width) {
if (width != lastWidth) {
float textWidth;
int layoutWidth;
pullTooltipLayout = new StaticLayout(pullTooltipText, tooltipTextPaint, AndroidUtilities.displaySize.x, Layout.Alignment.ALIGN_CENTER, 1, 0, false);
textWidth = 0;
for (int i = 0; i < pullTooltipLayout.getLineCount(); ++i) {
textWidth = Math.max(textWidth, pullTooltipLayout.getLineWidth(i));
}
pullTooltipLayoutScale = Math.min(1, width / textWidth);
layoutWidth = (int) Math.ceil(textWidth);
if (pullTooltipLayoutScale < .8f) {
pullTooltipLayoutScale = .8f;
layoutWidth = HintView2.cutInFancyHalf(pullTooltipText, tooltipTextPaint);
}
pullTooltipLayout = new StaticLayout(pullTooltipText, tooltipTextPaint, layoutWidth, Layout.Alignment.ALIGN_CENTER, 1, 0, false);
pullTooltipLayoutLeft = layoutWidth;
pullTooltipLayoutWidth = 0;
for (int i = 0; i < pullTooltipLayout.getLineCount(); ++i) {
pullTooltipLayoutLeft = Math.min(pullTooltipLayoutLeft, pullTooltipLayout.getLineLeft(i));
pullTooltipLayoutWidth = Math.max(pullTooltipLayoutWidth, pullTooltipLayout.getLineWidth(i));
}
releaseTooltipLayout = new StaticLayout(releaseTooltipText, tooltipTextPaint, AndroidUtilities.displaySize.x, Layout.Alignment.ALIGN_CENTER, 1, 0, false);
textWidth = 0;
for (int i = 0; i < releaseTooltipLayout.getLineCount(); ++i) {
textWidth = Math.max(textWidth, releaseTooltipLayout.getLineWidth(i));
}
releaseTooltipLayoutScale = Math.min(1, width / textWidth);
layoutWidth = (int) Math.ceil(textWidth);
if (releaseTooltipLayoutScale < .8f) {
releaseTooltipLayoutScale = .8f;
layoutWidth = HintView2.cutInFancyHalf(releaseTooltipText, tooltipTextPaint);
}
releaseTooltipLayout = new StaticLayout(releaseTooltipText, tooltipTextPaint, layoutWidth, Layout.Alignment.ALIGN_CENTER, 1, 0, false);
releaseTooltipLayoutLeft = layoutWidth;
releaseTooltipLayoutWidth = 0;
for (int i = 0; i < releaseTooltipLayout.getLineCount(); ++i) {
releaseTooltipLayoutLeft = Math.min(releaseTooltipLayoutLeft, releaseTooltipLayout.getLineLeft(i));
releaseTooltipLayoutWidth = Math.max(releaseTooltipLayoutWidth, releaseTooltipLayout.getLineWidth(i));
}
lastWidth = width;
}
}
public static int getMaxOverscroll() {
return AndroidUtilities.dp(72);
}
@ -191,6 +242,8 @@ public class PullForegroundDrawable {
float bounceP = bounceIn ? (0.07f * bounceProgress) - 0.05f : 0.02f * bounceProgress;
checkTextLayouts(cell.getWidth() - startPadding * 4 - AndroidUtilities.dp(16));
updateTextProgress(pullProgress);
float outProgressHalf = outProgress * 2f;
@ -308,35 +361,40 @@ public class PullForegroundDrawable {
}
float textY = cell.getHeight() - ((diameter + smallMargin * 2) / 2f) + AndroidUtilities.dp(6);
float textCx = cell.getWidth() / 2f - AndroidUtilities.dp(2);
float textCx = (cell.getWidth() + (isTopic ? startPadding * 2 : 0)) / 2f;
if (textSwappingProgress > 0 && textSwappingProgress < 1f) {
canvas.save();
float scale = 0.8f + 0.2f * textSwappingProgress;
canvas.scale(scale, scale, textCx, textY + AndroidUtilities.dp(16) * (1f - textSwappingProgress));
}
canvas.saveLayerAlpha(0, 0, cell.getMeasuredWidth(), cell.getMeasuredHeight(), (int) (255 * textSwappingProgress * startPullProgress * textInProgress), Canvas.ALL_SAVE_FLAG);
canvas.translate(textCx - pullTooltipLayoutLeft - pullTooltipLayoutWidth / 2f, textY + AndroidUtilities.dp(8) * (1f - textSwappingProgress) - tooltipTextPaint.getTextSize());
pullTooltipLayout.draw(canvas);
canvas.restore();
if (textSwappingProgress > 0 && textSwappingProgress < 1f) {
if (pullTooltipLayout != null) {
if (textSwappingProgress > 0 && textSwappingProgress < 1f) {
canvas.save();
float scale = 0.8f + 0.2f * textSwappingProgress;
canvas.scale(scale, scale, textCx, textY + AndroidUtilities.dp(16) * (1f - textSwappingProgress));
}
canvas.saveLayerAlpha(0, 0, cell.getMeasuredWidth(), cell.getMeasuredHeight(), (int) (255 * textSwappingProgress * startPullProgress * textInProgress), Canvas.ALL_SAVE_FLAG);
canvas.translate(textCx - pullTooltipLayoutLeft - pullTooltipLayoutWidth / 2f, textY + AndroidUtilities.dp(8) * (1f - textSwappingProgress) - pullTooltipLayout.getHeight());
canvas.scale(pullTooltipLayoutScale, pullTooltipLayoutScale, pullTooltipLayoutLeft + pullTooltipLayoutWidth / 2f, pullTooltipLayout.getHeight());
pullTooltipLayout.draw(canvas);
canvas.restore();
if (textSwappingProgress > 0 && textSwappingProgress < 1f) {
canvas.restore();
}
}
if (textSwappingProgress > 0 && textSwappingProgress < 1f) {
canvas.save();
float scale = 0.9f + 0.1f * (1f - textSwappingProgress);
canvas.scale(scale, scale, textCx, textY - AndroidUtilities.dp(8) * (textSwappingProgress));
}
canvas.saveLayerAlpha(0, 0, cell.getMeasuredWidth(), cell.getMeasuredHeight(), (int) (255 * (1f - textSwappingProgress) * startPullProgress * textInProgress), Canvas.ALL_SAVE_FLAG);
canvas.translate(textCx - releaseTooltipLayoutLeft - releaseTooltipLayoutWidth / 2f, textY + AndroidUtilities.dp(8) * (textSwappingProgress) - tooltipTextPaint.getTextSize());
releaseTooltipLayout.draw(canvas);
canvas.restore();
if (textSwappingProgress > 0 && textSwappingProgress < 1f) {
if (releaseTooltipLayout != null) {
if (textSwappingProgress > 0 && textSwappingProgress < 1f) {
canvas.save();
float scale = 0.9f + 0.1f * (1f - textSwappingProgress);
canvas.scale(scale, scale, textCx, textY - AndroidUtilities.dp(8) * (textSwappingProgress));
}
canvas.saveLayerAlpha(0, 0, cell.getMeasuredWidth(), cell.getMeasuredHeight(), (int) (255 * (1f - textSwappingProgress) * startPullProgress * textInProgress), Canvas.ALL_SAVE_FLAG);
canvas.translate(textCx - releaseTooltipLayoutLeft - releaseTooltipLayoutWidth / 2f, textY + AndroidUtilities.dp(8) * (textSwappingProgress) - releaseTooltipLayout.getHeight());
canvas.scale(releaseTooltipLayoutScale, releaseTooltipLayoutScale, releaseTooltipLayoutLeft + releaseTooltipLayoutWidth / 2f, releaseTooltipLayout.getHeight());
releaseTooltipLayout.draw(canvas);
canvas.restore();
if (textSwappingProgress > 0 && textSwappingProgress < 1f) {
canvas.restore();
}
}
canvas.restore();
if (!isTopic && changeAvatarColor && outProgress > 0) {

View file

@ -526,7 +526,7 @@ public class RecyclerListView extends RecyclerView {
private boolean floatingDateVisible;
private float floatingDateProgress;
private int[] positionWithOffset = new int[2];
boolean isVisible;
public boolean isVisible;
float touchSlop;
Drawable fastScrollShadowDrawable;
Drawable fastScrollBackgroundDrawable;

View file

@ -377,8 +377,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
public long lastCheckScrollTime;
public boolean fastScrollEnabled;
public ObjectAnimator fastScrollAnimator;
private BlurredRecyclerView listView;
private BlurredRecyclerView animationSupportingListView;
private InternalListView listView;
private InternalListView animationSupportingListView;
private GridLayoutManager animationSupportingLayoutManager;
private FlickerLoadingView progressView;
private StickerEmptyView emptyView;
@ -1880,7 +1880,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
if (archivedHintLayout == null || archivedHintLayout.getWidth() != width) {
archivedHintLayout = new StaticLayout(LocaleController.getString("ProfileStoriesArchiveHint", R.string.ProfileStoriesArchiveHint), archivedHintPaint, width, Layout.Alignment.ALIGN_CENTER, 1f, 0f, false);
archivedHintLayoutWidth = 0;
archivedHintLayoutLeft = 0;
archivedHintLayoutLeft = width;
for (int i = 0; i < archivedHintLayout.getLineCount(); ++i) {
archivedHintLayoutWidth = Math.max(archivedHintLayoutWidth, archivedHintLayout.getLineWidth(i));
archivedHintLayoutLeft = Math.min(archivedHintLayoutLeft, archivedHintLayout.getLineLeft(i));
@ -2225,7 +2225,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
mediaPages[a].listView.setSectionsType(RecyclerListView.SECTIONS_TYPE_DATE);
mediaPages[a].listView.setLayoutManager(layoutManager);
mediaPages[a].addView(mediaPages[a].listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
mediaPages[a].animationSupportingListView = new BlurredRecyclerView(context);
mediaPages[a].animationSupportingListView = new InternalListView(context);
mediaPages[a].animationSupportingListView.setLayoutManager(mediaPages[a].animationSupportingLayoutManager = new GridLayoutManager(context, 3) {
@Override
@ -2243,6 +2243,26 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
});
mediaPages[a].addView(mediaPages[a].animationSupportingListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
mediaPages[a].animationSupportingListView.setVisibility(View.GONE);
mediaPages[a].animationSupportingListView.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
if (view instanceof SharedPhotoVideoCell2) {
SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) view;
final int position = mediaPage.animationSupportingListView.getChildAdapterPosition(cell), spanCount = mediaPage.animationSupportingLayoutManager.getSpanCount();
cell.isFirst = position % spanCount == 0;
cell.isLast = position % spanCount == spanCount - 1;
outRect.left = 0;
outRect.top = 0;
outRect.bottom = 0;
outRect.right = 0;
} else {
outRect.left = 0;
outRect.top = 0;
outRect.bottom = 0;
outRect.right = 0;
}
}
});
mediaPages[a].listView.addItemDecoration(new RecyclerView.ItemDecoration() {
@ -2258,6 +2278,15 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
outRect.top = 0;
}
outRect.right = mediaPage.layoutManager.isLastInRow(position) ? 0 : AndroidUtilities.dp(2);
} else if (view instanceof SharedPhotoVideoCell2) {
SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) view;
final int position = mediaPage.listView.getChildAdapterPosition(cell), spanCount = mediaPage.layoutManager.getSpanCount();
cell.isFirst = position % spanCount == 0;
cell.isLast = position % spanCount == spanCount - 1;
outRect.left = 0;
outRect.top = 0;
outRect.bottom = 0;
outRect.right = 0;
} else {
outRect.left = 0;
outRect.top = 0;
@ -2764,6 +2793,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
);
mediaPage.animationSupportingLayoutManager.setSpanCount(newColumnsCount);
mediaPage.animationSupportingListView.invalidateItemDecorations();
final MediaPage finalMediaPage = mediaPage;
mediaPage.animationSupportingLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
@ -2837,6 +2867,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
}
mediaPages[i].animationSupportingListView.setVisibility(View.GONE);
mediaPages[i].layoutManager.setSpanCount(mediaColumnsCount[ci]);
mediaPages[i].listView.invalidateItemDecorations();
mediaPages[i].listView.invalidate();
if (adapter.getItemCount() == oldItemCount) {
AndroidUtilities.updateVisibleRows(mediaPages[i].listView);
@ -2903,6 +2934,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
}
if (forward) {
mediaPages[i].layoutManager.setSpanCount(mediaColumnsCount[ci]);
mediaPages[i].listView.invalidateItemDecorations();
if (adapter.getItemCount() == oldItemCount) {
AndroidUtilities.updateVisibleRows(mediaPages[i].listView);
} else {
@ -2956,11 +2988,12 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
}
mediaPage.animationSupportingListView.setPadding(
mediaPage.animationSupportingListView.getPaddingLeft(),
changeColumnsTab == TAB_ARCHIVED_STORIES ? AndroidUtilities.dp(2 + 64) : AndroidUtilities.dp(2),
AndroidUtilities.dp(2) + (mediaPage.animationSupportingListView.hintPaddingTop = (changeColumnsTab == TAB_ARCHIVED_STORIES ? AndroidUtilities.dp(64) : 0)),
mediaPage.animationSupportingListView.getPaddingRight(),
mediaPage.animationSupportingListView.getPaddingBottom()
);
mediaPage.animationSupportingLayoutManager.setSpanCount(newColumnsCount);
mediaPage.animationSupportingListView.invalidateItemDecorations();
for (int i = 0; i < mediaPages.length; ++i) {
if (mediaPages[i] != null && isTabZoomable(mediaPages[i].selectedType)) {
AndroidUtilities.updateVisibleRows(mediaPages[i].listView);
@ -3001,6 +3034,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
sharedMediaData[0].setListFrozen(false);
}
mediaPages[i].layoutManager.setSpanCount(mediaColumnsCount[ci]);
mediaPages[i].listView.invalidateItemDecorations();
if (adapter.getItemCount() == oldItemCount) {
AndroidUtilities.updateVisibleRows(mediaPages[i].listView);
} else {
@ -5012,7 +5046,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
mediaPages[a].listView.setPinnedHeaderShadowDrawable(null);
mediaPages[a].listView.setPadding(
mediaPages[a].listView.getPaddingLeft(),
mediaPages[a].selectedType == TAB_ARCHIVED_STORIES ? AndroidUtilities.dp(2 + 64) : AndroidUtilities.dp(2),
AndroidUtilities.dp(2) + (mediaPages[a].listView.hintPaddingTop = mediaPages[a].selectedType == TAB_ARCHIVED_STORIES ? AndroidUtilities.dp(64) : 0),
mediaPages[a].listView.getPaddingRight(),
mediaPages[a].listView.getPaddingBottom()
);
@ -5169,6 +5203,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
mediaPages[a].fastScrollEnabled = fastScrollVisible;
updateFastScrollVisibility(mediaPages[a], false);
mediaPages[a].layoutManager.setSpanCount(spanCount);
mediaPages[a].listView.invalidateItemDecorations();
mediaPages[a].listView.setRecycledViewPool(viewPool);
mediaPages[a].animationSupportingListView.setRecycledViewPool(viewPool);
@ -5350,15 +5385,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
}
} else if (selectedMode == TAB_STORIES || selectedMode == TAB_ARCHIVED_STORIES) {
StoriesController.StoriesList storiesList = (selectedMode == TAB_STORIES ? storiesAdapter : archivedStoriesAdapter).storiesList;
int pos = -1;
for (int i = 0; i < storiesList.messageObjects.size(); ++i) {
MessageObject messageObject = storiesList.messageObjects.get(i);
if (messageObject != null && messageObject.isStory() && messageObject.getId() == message.getId()) {
pos = i;
break;
}
}
profileActivity.getOrCreateStoryViewer().open(getContext(), message.storyItem, Math.max(0, pos), storiesList, StoriesListPlaceProvider.of(mediaPages[a].listView));
profileActivity.getOrCreateStoryViewer().open(getContext(), message.getId(), storiesList, StoriesListPlaceProvider.of(mediaPages[a].listView));
}
}
updateForwardItem();
@ -7540,7 +7567,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
protected void onTabProgress(float progress) {}
protected void onTabScroll(boolean scrolling) {}
private class InternalListView extends BlurredRecyclerView implements StoriesListPlaceProvider.ClippedView {
public static class InternalListView extends BlurredRecyclerView implements StoriesListPlaceProvider.ClippedView {
public int hintPaddingTop;
public InternalListView(Context context) {
super(context);
@ -7548,7 +7577,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
@Override
public void updateClip(int[] clip) {
clip[0] = getPaddingTop() - AndroidUtilities.dp(2);
clip[0] = getPaddingTop() - AndroidUtilities.dp(2) - hintPaddingTop;
clip[1] = getMeasuredHeight() - getPaddingBottom();
}
}

View file

@ -636,7 +636,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
long dialogId = userCell.getDialogId();
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId);
final String key = NotificationsController.getSharedPrefKey(dialogId, 0);
boolean muted = !NotificationsCustomSettingsActivity.isStoriesNotMuted(currentAccount, dialogId);
boolean muted = !NotificationsCustomSettingsActivity.areStoriesNotMuted(currentAccount, dialogId);
ItemOptions filterOptions = ItemOptions.makeOptions(ContactsActivity.this, view)
//.setViewAdditionalOffsets(0, AndroidUtilities.dp(8), 0, 0)
.setScrimViewBackground(Theme.createRoundRectDrawable(0, 0, Theme.getColor(Theme.key_windowBackgroundWhite)))

View file

@ -83,8 +83,6 @@ import androidx.recyclerview.widget.LinearSmoothScrollerCustom;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import com.google.android.exoplayer2.util.Log;
import org.telegram.messenger.AccountInstance;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.AnimationNotificationsLocker;
@ -4816,7 +4814,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}, null);
} else {
final String key = NotificationsController.getSharedPrefKey(dialogId, 0);
boolean muted = !NotificationsCustomSettingsActivity.isStoriesNotMuted(currentAccount, dialogId);
boolean muted = !NotificationsCustomSettingsActivity.areStoriesNotMuted(currentAccount, dialogId);
filterOptions
.add(R.drawable.msg_discussion, LocaleController.getString("SendMessage", R.string.SendMessage), () -> {
presentFragment(ChatActivity.of(dialogId));
@ -11806,7 +11804,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
public void updateStoriesVisibility(boolean animated) {
if (storiesVisibilityAnimator != null || rightSlidingDialogContainer != null && rightSlidingDialogContainer.hasFragment() || searchIsShowed || actionBar.isActionModeShowed() || onlySelect) {
if (dialogStoriesCell == null || storiesVisibilityAnimator != null || rightSlidingDialogContainer != null && rightSlidingDialogContainer.hasFragment() || searchIsShowed || actionBar.isActionModeShowed() || onlySelect) {
return;
}
if (StoryRecorder.isVisible() || (storyViewer != null && storyViewer.isFullyVisible())) {

View file

@ -41,8 +41,6 @@ import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.common.primitives.Chars;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
@ -55,7 +53,6 @@ import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.NotificationsController;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.UserObject;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.TLObject;
@ -86,7 +83,6 @@ import org.telegram.ui.Components.EmptyTextProgressView;
import org.telegram.ui.Components.ItemOptions;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.ListView.AdapterWithDiffUtils;
import org.telegram.ui.Components.MediaActivity;
import org.telegram.ui.Components.RecyclerListView;
import java.util.ArrayList;
@ -95,7 +91,6 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
@ -189,7 +184,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements
return index >= 0 && index >= topPeers.size() - 5;
}
public static boolean isStoriesNotMuted(int currentAccount, long did) {
public static boolean areStoriesNotMuted(int currentAccount, long did) {
SharedPreferences prefs = MessagesController.getNotificationsSettings(currentAccount);
if (prefs.contains("stories_" + did)) {
return prefs.getBoolean("stories_" + did, true);

View file

@ -7264,7 +7264,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
boolean divider = false;
if (showAddToContacts && user != null && !user.contact) {
if (showAddToContacts && user != null && !user.contact && !user.bot && !UserObject.isService(user.id)) {
addToContactsRow = rowCount++;
divider = true;
}
@ -8990,7 +8990,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
totalHeight += listView.getChildAt(i).getMeasuredHeight();
}
}
int paddingHeight = fragmentView.getMeasuredHeight() - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.statusBarHeight - totalHeight;
int paddingHeight = (fragmentView == null ? 0 : fragmentView.getMeasuredHeight()) - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.statusBarHeight - totalHeight;
if (paddingHeight > AndroidUtilities.dp(88)) {
paddingHeight = 0;
}

View file

@ -18,6 +18,7 @@ import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.OvershootInterpolator;
@ -277,7 +278,10 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
}
private void openStoryForCell(StoryCell cell) {
if (cell != null && cell.isSelf && !storiesController.hasSelfStories()) {
if (cell == null) {
return;
}
if (cell.isSelf && !storiesController.hasSelfStories()) {
if (!MessagesController.getInstance(currentAccount).storiesEnabled()) {
showPremiumHint();
} else {
@ -286,8 +290,12 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
return;
}
int position = cell.position;
long startFromDialogId = cell.dialogId;
ArrayList<Long> peerIds = new ArrayList<>();
boolean allStoriesIsRead = true;
if (!storiesController.hasStories(cell.dialogId)) {
return;
}
for (int i = 0; i < items.size(); i++) {
long dialogId = items.get(i).dialogId;
if (dialogId != UserConfig.getInstance(currentAccount).clientUserId && storiesController.hasUnreadStories(dialogId)) {
@ -874,6 +882,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
public void openOverscrollSelectedStory() {
openStoryForCell(overscrollSelectedView);
performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
}
public void setActionBar(ActionBar actionBar) {

View file

@ -51,8 +51,6 @@ import androidx.core.graphics.ColorUtils;
import androidx.core.math.MathUtils;
import androidx.recyclerview.widget.ChatListItemAnimator;
import com.google.android.exoplayer2.util.Log;
import org.telegram.messenger.AccountInstance;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.AnimationNotificationsLocker;
@ -154,9 +152,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.SortedSet;
public class PeerStoriesView extends SizeNotifierFrameLayout implements NotificationCenter.NotificationCenterDelegate {
@ -207,6 +203,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
final SharedResources sharedResources;
RoundRectOutlineProvider outlineProvider;
ArrayList<Integer> day;
int count;
private long dialogId;
boolean isSelf;
@ -216,6 +214,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
private int selectedPosition;
boolean isActive;
private int listPosition;
private int linesPosition, linesCount;
public final StoryItemHolder currentStory = new StoryItemHolder();
@ -263,8 +262,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
private AnimatedFloat progressToHideInterface = new AnimatedFloat(this);
private float prevToHideProgress;
private long videoDuration;
private boolean allowShare;
public boolean allowScreenshots;
private boolean allowShare, allowShareLink;
public boolean forceUpdateOffsets;
private HintView mediaBanTooltip;
@ -588,15 +586,11 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
}
});
}
if (storyViewer.storiesList != null && storyViewer.storiesList.getCount() != linesCount) {
if (storyViewer.storiesList != null) {
if (storyPositionView == null) {
storyPositionView = new StoryPositionView();
}
int position = selectedPosition;
if (storyViewer.reversed) {
position = storyViewer.storiesList.getCount() - 1 - position;
}
storyPositionView.draw(canvas, hideInterfaceAlpha * alpha * (1f - outT), position, storyViewer.storiesList.getCount(), this, headerView);
storyPositionView.draw(canvas, hideInterfaceAlpha * alpha * (1f - outT), listPosition, storyViewer.storiesList.getCount(), this, headerView);
}
canvas.save();
canvas.translate(0, dp(8) - dp(8) * outT);
@ -615,7 +609,21 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
}
public boolean clipWithGradient(int tag) {
return tag == 1;
return tag == 1 || tag == 2;
}
@Override
public void onShow(Bulletin bulletin) {
if (bulletin != null && bulletin.tag == 2 && delegate != null) {
delegate.setBulletinIsVisible(true);
}
}
@Override
public void onHide(Bulletin bulletin) {
if (bulletin != null && bulletin.tag == 2 && delegate != null) {
delegate.setBulletinIsVisible(false);
}
}
@Override
@ -629,6 +637,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Bulletin.removeDelegate(this);
if (delegate != null) {
delegate.setBulletinIsVisible(false);
}
}
@Override
@ -769,8 +780,12 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
storyCaptionView.captionTextview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
checkBlackoutMode = true;
storyCaptionView.expand();
if (storyCaptionView.expanded) {
storyCaptionView.collapse();
} else {
checkBlackoutMode = true;
storyCaptionView.expand();
}
}
});
@ -958,7 +973,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
});
}
if (allowShare || MessagesController.getInstance(currentAccount).storiesExportNopublicLink) {
if (allowShare) {
ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_shareout, LocaleController.getString("BotShare", R.string.BotShare), false, resourcesProvider).setOnClickListener(v -> {
shareStory(false);
if (popupMenu != null) {
@ -985,7 +1000,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
final String key = NotificationsController.getSharedPrefKey(dialogId, 0);
boolean muted = !NotificationsCustomSettingsActivity.isStoriesNotMuted(currentAccount, dialogId);
boolean muted = !NotificationsCustomSettingsActivity.areStoriesNotMuted(currentAccount, dialogId);
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId);
if (!UserObject.isService(dialogId)) {
if (!muted) {
@ -998,7 +1013,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
if (index > 0) {
name = name.substring(0, index);
}
BulletinFactory.global().createUsersBulletin(Arrays.asList(user), AndroidUtilities.replaceTags(LocaleController.formatString("NotificationsStoryMutedHint", R.string.NotificationsStoryMutedHint, name))).show();
BulletinFactory.of(storyContainer, resourcesProvider).createUsersBulletin(Arrays.asList(user), AndroidUtilities.replaceTags(LocaleController.formatString("NotificationsStoryMutedHint", R.string.NotificationsStoryMutedHint, name))).setTag(2).show();
if (popupMenu != null) {
popupMenu.dismiss();
}
@ -1014,7 +1029,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
if (index > 0) {
name = name.substring(0, index);
}
BulletinFactory.global().createUsersBulletin(Arrays.asList(user), AndroidUtilities.replaceTags(LocaleController.formatString("NotificationsStoryUnmutedHint", R.string.NotificationsStoryUnmutedHint, name))).show();
BulletinFactory.of(storyContainer, resourcesProvider).createUsersBulletin(Arrays.asList(user), AndroidUtilities.replaceTags(LocaleController.formatString("NotificationsStoryUnmutedHint", R.string.NotificationsStoryUnmutedHint, name))).setTag(2).show();
if (popupMenu != null) {
popupMenu.dismiss();
}
@ -1024,14 +1039,14 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
if (user.contact) {
if (!user.stories_hidden) {
ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_archive, LocaleController.getString("ArchivePeerStories", R.string.ArchivePeerStories), false, resourcesProvider).setOnClickListener(v -> {
toggleArciveForStory(dialogId);
toggleArchiveForStory(dialogId);
if (popupMenu != null) {
popupMenu.dismiss();
}
});
} else {
ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_unarchive, LocaleController.getString("UnarchiveStories", R.string.UnarchiveStories), false, resourcesProvider).setOnClickListener(v -> {
toggleArciveForStory(dialogId);
toggleArchiveForStory(dialogId);
if (popupMenu != null) {
popupMenu.dismiss();
}
@ -1050,7 +1065,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
});
}
}
if (allowShare || MessagesController.getInstance(currentAccount).storiesExportNopublicLink) {
if (allowShareLink) {
ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_link, LocaleController.getString("CopyLink", R.string.CopyLink), false, resourcesProvider).setOnClickListener(v -> {
AndroidUtilities.addToClipboard(currentStory.createLink());
onLickCopied();
@ -1058,7 +1073,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
popupMenu.dismiss();
}
});
}
if (allowShare) {
ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_shareout, LocaleController.getString("BotShare", R.string.BotShare), false, resourcesProvider).setOnClickListener(v -> {
shareStory(false);
if (popupMenu != null) {
@ -1164,15 +1180,19 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
CharSequence text;
boolean twoLines = true;
if (storyItem.close_friends) {
privacyHint.setInnerPadding(15, 8, 15, 8);
text = AndroidUtilities.replaceTags(LocaleController.formatString("StoryCloseFriendsHint", R.string.StoryCloseFriendsHint, firstName));
} else if (storyItem.contacts) {
privacyHint.setInnerPadding(11, 6, 11, 7);
text = AndroidUtilities.replaceTags(LocaleController.formatString("StoryContactsHint", R.string.StoryContactsHint, firstName));
twoLines = false;
} else if (storyItem.selected_contacts) {
privacyHint.setInnerPadding(15, 8, 15, 8);
text = AndroidUtilities.replaceTags(LocaleController.formatString("StorySelectedContactsHint", R.string.StorySelectedContactsHint, firstName));
} else {
return;
}
text = Emoji.replaceEmoji(text, privacyHint.getTextPaint().getFontMetricsInt(), false);
privacyHint.setMaxWidthPx(twoLines ? HintView2.cutInFancyHalf(text, privacyHint.getTextPaint()) : storyContainer.getMeasuredWidth());
privacyHint.setText(text);
privacyHint.setJoint(1, -(storyContainer.getWidth() - privacyButton.getCenterX()) / AndroidUtilities.density);
@ -1265,7 +1285,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
return null;
}
private void toggleArciveForStory(long dialogId) {
private void toggleArchiveForStory(long dialogId) {
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId);
boolean hide = !user.stories_hidden;
MessagesController messagesController = MessagesController.getInstance(currentAccount);
@ -1285,11 +1305,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
} else {
str = AndroidUtilities.replaceTags(LocaleController.formatString("StoriesMovedToContacts", R.string.StoriesMovedToContacts, ContactsController.formatName(user.first_name, null, 10)));
}
BulletinFactory.global().createUsersBulletin(
Arrays.asList(user),
str,
null,
undoObject).show();
BulletinFactory.of(storyContainer, resourcesProvider).createUsersBulletin(Arrays.asList(user), str, null, undoObject).setTag(2).show();
}, 200);
}
@ -1860,6 +1876,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
} else {
bulletinFactory.createSimpleBulletin(R.raw.forward, AndroidUtilities.replaceTags(LocaleController.formatPluralString("StorySharedToManyChats", dids.size(), dids.size()))).hideAfterBottomSheet(false).show();
}
performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
}
}
};
@ -1898,14 +1915,29 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
});
}
public void setDialogId(long dialogId) {
boolean peerIdChanged = this.dialogId != dialogId;
public void setDay(long dialogId, ArrayList<Integer> day) {
this.dialogId = dialogId;
deletedPeer = false;
forceUpdateOffsets = true;
if (peerIdChanged) {
this.day = day;
bindInternal();
}
public void setDialogId(long dialogId) {
if (this.dialogId != dialogId) {
currentStory.clear();
}
this.dialogId = dialogId;
this.day = null;
bindInternal();
if (storyViewer.overrideUserStories != null) {
storiesController.loadSkippedStories(storyViewer.overrideUserStories, true);
} else {
storiesController.loadSkippedStories(dialogId);
}
}
private void bindInternal() {
deletedPeer = false;
forceUpdateOffsets = true;
if (dialogId >= 0) {
isSelf = dialogId == UserConfig.getInstance(currentAccount).getClientUserId();
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId);
@ -1953,8 +1985,18 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
if (chatActivityEnterView != null) {
chatActivityEnterView.setVisibility(View.GONE);
}
if (storyViewer.storiesList != null) {
selectedPosition = storyViewer.storiesListStartPosition;
if (day != null) {
int index = day.indexOf(storyViewer.dayStoryId);
if (index < 0) {
if (!day.isEmpty()) {
if (storyViewer.dayStoryId > day.get(0)) {
index = 0;
} else if (storyViewer.dayStoryId < day.get(day.size() - 1)) {
index = day.size() - 1;
}
}
}
selectedPosition = Math.max(0, index);
} else if (!uploadingStories.isEmpty()) {
selectedPosition = storyItems.size();
} else {
@ -1995,11 +2037,6 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
storyContainer.invalidate();
invalidate();
}
if (storyViewer.overrideUserStories != null) {
storiesController.loadSkippedStories(storyViewer.overrideUserStories, true);
} else {
storiesController.loadSkippedStories(dialogId);
}
}
private void createUnsupportedContainer() {
@ -2046,13 +2083,13 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
public void preloadMainImage(long dialogId) {
if (this.dialogId == dialogId) {
if (this.dialogId == dialogId && day == null) {
return;
}
this.dialogId = dialogId;
updateStoryItems();
updateSelectedPosition();
updatePosition();
updatePosition(true);
if (storyViewer.overrideUserStories != null) {
storiesController.loadSkippedStories(storyViewer.overrideUserStories, true);
} else {
@ -2061,15 +2098,27 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
}
private void updateSelectedPosition() {
selectedPosition = storyViewer.savedPositions.get(dialogId, -1);
if (selectedPosition == -1) {
if (storyViewer.storiesList != null) {
selectedPosition = storyViewer.storiesListStartPosition;
} else if (!storyViewer.isSingleStory && userStories != null && userStories.max_read_id > 0) {
for (int i = 0; i < storyItems.size(); i++) {
if (storyItems.get(i).id > userStories.max_read_id) {
selectedPosition = i;
break;
if (day != null) {
int index = day.indexOf(storyViewer.dayStoryId);
if (index < 0) {
if (!day.isEmpty()) {
if (storyViewer.dayStoryId > day.get(0)) {
index = 0;
} else if (storyViewer.dayStoryId < day.get(day.size() - 1)) {
index = day.size() - 1;
}
}
}
selectedPosition = index;
} else {
selectedPosition = storyViewer.savedPositions.get(dialogId, -1);
if (selectedPosition == -1) {
if (!storyViewer.isSingleStory && userStories != null && userStories.max_read_id > 0) {
for (int i = 0; i < storyItems.size(); i++) {
if (storyItems.get(i).id > userStories.max_read_id) {
selectedPosition = i;
break;
}
}
}
}
@ -2083,6 +2132,13 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
storyItems.clear();
if (storyViewer.isSingleStory) {
storyItems.add(storyViewer.singleStory);
} else if (day != null && storyViewer.storiesList != null) {
for (int id : day) {
MessageObject messageObject = storyViewer.storiesList.findMessageObject(id);
if (messageObject != null && messageObject.storyItem != null) {
storyItems.add(messageObject.storyItem);
}
}
} else if (storyViewer.storiesList != null) {
// TODO: actually load more stories
for (int i = 0; i < storyViewer.storiesList.messageObjects.size(); ++i) {
@ -2308,7 +2364,11 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
}
}
private void updatePosition() {
public void updatePosition() {
updatePosition(false);
}
private void updatePosition(boolean preload) {
if (storyItems.isEmpty() && uploadingStories.isEmpty()) {
return;
}
@ -2320,8 +2380,6 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
lastNoThumb = false;
unsupported = false;
boolean oldAllowScreenshots = allowScreenshots;
allowScreenshots = true;
int position = selectedPosition;
final boolean wasUploading = isUploading;
@ -2350,12 +2408,13 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
imageReceiver.setImage(null, null, ImageLocation.getForPath(uploadingStory.path), filter, null, null, thumbDrawable, 0, null, null, 0);
}
currentStory.set(uploadingStory);
allowShare = false;
allowShare = allowShareLink = false;
} else {
isUploading = false;
isEditing = false;
if (position < 0 || position > storyItems.size() - 1) {
storyViewer.close(true);
return;
}
TLRPC.StoryItem storyItem = storyItems.get(position);
StoriesController.UploadingStory editingStory = storiesController.findEditingStory(storyItem);
@ -2370,7 +2429,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
}
currentStory.set(editingStory);
currentStory.editingSourceItem = storyItem;
allowShare = false;
allowShare = allowShareLink = false;
} else {
boolean isVideo = storyItem.media != null && MessageObject.isVideoDocument(storyItem.media.document);
Drawable thumbDrawable = null;
@ -2404,7 +2463,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
}
}
} else {
if ((storyViewer.isSingleStory || storyViewer.storiesList != null) && storyViewer.transitionViewHolder.storyImage != null && !storyViewer.reversed) {
if (storyViewer.isSingleStory && storyViewer.transitionViewHolder.storyImage != null) {
thumbDrawable = storyViewer.transitionViewHolder.storyImage.getDrawable();
}
storyItem.dialogId = dialogId;
@ -2435,19 +2494,23 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
}
storyItem.dialogId = dialogId;
currentStory.set(storyItem);
allowShare = !unsupported && currentStory.storyItem != null && !(currentStory.storyItem instanceof TLRPC.TL_storyItemDeleted) && !(currentStory.storyItem instanceof TLRPC.TL_storyItemSkipped);
allowShare = allowShareLink = !unsupported && currentStory.storyItem != null && !(currentStory.storyItem instanceof TLRPC.TL_storyItemDeleted) && !(currentStory.storyItem instanceof TLRPC.TL_storyItemSkipped);
if (allowShare) {
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId);
allowShare = !currentStory.storyItem.noforwards && currentStory.storyItem.isPublic && user != null && UserObject.getPublicUsername(user) != null;
allowShare = currentStory.allowScreenshots() && currentStory.storyItem.isPublic;
}
if (allowShareLink) {
final TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId);
allowShareLink = user != null && UserObject.getPublicUsername(user) != null && currentStory.storyItem.isPublic;
}
NotificationsController.getInstance(currentAccount).processReadStories(dialogId, storyItem.id);
}
}
allowScreenshots = currentStory.allowScreenshots();
if (oldAllowScreenshots != allowScreenshots) {
storyViewer.storiesViewPager.checkAllowScreenshots();
if (currentStory.storyItem != null && !preload) {
storyViewer.dayStoryId = currentStory.storyItem.id;
}
storyViewer.storiesViewPager.checkAllowScreenshots();
imageChanged = true;
if (isSelf) {
updateUserViews();
@ -2534,7 +2597,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
createReplyDisabledView();
unsupportedContainer.setVisibility(View.VISIBLE);
replyDisabledTextView.setVisibility(View.VISIBLE);
allowShare = false;
allowShare = allowShareLink = false;
if (chatActivityEnterView != null) {
chatActivityEnterView.setVisibility(View.GONE);
}
@ -2586,28 +2649,19 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
imageReceiver.bumpPriority();
}
if (storyViewer.storiesList != null && selectedPosition >= 0 && selectedPosition < storyViewer.storiesList.messageObjects.size()) {
MessageObject messageObject = storyViewer.storiesList.messageObjects.get(selectedPosition);
SortedSet<Integer> dayGroup = storyViewer.storiesList.getStoryDayGroup(messageObject);
if (dayGroup == null) {
linesPosition = selectedPosition;
linesCount = count;
return;
}
int i = 0;
Iterator<Integer> it = dayGroup.iterator();
while (it.hasNext()) {
if (it.next() == messageObject.getId()) {
listPosition = 0;
if (storyViewer.storiesList != null && currentStory.storyItem != null) {
int id = currentStory.storyItem.id;
for (int i = 0; i < storyViewer.storiesList.messageObjects.size(); ++i) {
MessageObject obj = storyViewer.storiesList.messageObjects.get(i);
if (obj != null && obj.getId() == id) {
listPosition = i;
break;
}
i++;
}
linesPosition = i;
linesCount = dayGroup.size();
} else {
linesPosition = selectedPosition;
linesCount = count;
}
linesPosition = selectedPosition;
linesCount = count;
if (storyViewer.reversed) {
linesPosition = linesCount - 1 - linesPosition;
}
@ -2972,6 +3026,10 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
return dialogId;
}
public ArrayList<Integer> getCurrentDay() {
return day;
}
public void setPaused(boolean paused) {
if (this.paused != paused) {
this.paused = paused;
@ -3345,7 +3403,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
super.onDraw(canvas);
}
};
backupImageView.setRoundRadius(AndroidUtilities.dp(16));
backupImageView.setRoundRadius(dp(16));
addView(backupImageView, LayoutHelper.createFrame(32, 32, 0, 12, 2, 0, 0));
setClipChildren(false);
@ -3353,6 +3411,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
titleView.setTextSize(14);
titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
titleView.setMaxLines(1);
titleView.setEllipsizeByGradient(dp(4));
// titleView.setSingleLine(true);
// titleView.setEllipsize(TextUtils.TruncateAt.END);
NotificationCenter.listenEmojiLoading(titleView);
@ -3533,6 +3592,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica
void setPopupIsVisible(boolean b);
void setBulletinIsVisible(boolean b);
void setIsInPinchToZoom(boolean b);
void preparePlayer(ArrayList<TLRPC.Document> documents, ArrayList<Uri> uries);

View file

@ -1164,6 +1164,7 @@ public class StoriesController {
}
storiesStorage.deleteAllUserStories(dialogId);
MessagesController.getInstance(currentAccount).checkArchiveFolder();
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated);
}
public StoriesStorage getStoriesStorage() {
@ -1180,6 +1181,7 @@ public class StoriesController {
}
private void checkExpireStories(ArrayList<TLRPC.TL_userStories> dialogListStories) {
boolean notify = false;
for (int k = 0; k < dialogListStories.size(); k++) {
TLRPC.TL_userStories stories = dialogListStories.get(k);
for (int i = 0; i < stories.stories.size(); i++) {
@ -1191,8 +1193,12 @@ public class StoriesController {
if (stories.stories.isEmpty()) {
allStoriesMap.remove(stories.user_id);
dialogListStories.remove(stories);
notify = true;
}
}
if (notify) {
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated);
}
}
public void checkExpiredStories(long dialogId) {
@ -1206,6 +1212,7 @@ public class StoriesController {
if (userStories.stories.isEmpty()) {
dialogListStories.remove(userStories);
hiddenListStories.remove(userStories);
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated);
}
}
@ -1588,7 +1595,7 @@ public class StoriesController {
}
}
private HashMap<Integer, StoriesList> storiesLists;
private final HashMap<Long, StoriesList>[] storiesLists = new HashMap[2];
@NonNull
public StoriesList getStoriesList(long userId, int type) {
@ -1596,13 +1603,12 @@ public class StoriesController {
}
private StoriesList getStoriesList(long userId, int type, boolean createIfNotExist) {
int key = Objects.hash(userId, type);
if (storiesLists == null) {
storiesLists = new HashMap<>();
if (storiesLists[type] == null) {
storiesLists[type] = new HashMap<>();
}
StoriesList list = storiesLists.get(key);
StoriesList list = storiesLists[type].get(userId);
if (list == null && createIfNotExist) {
storiesLists.put(key, list = new StoriesList(currentAccount, userId, type, this::destroyStoryList));
storiesLists[type].put(userId, list = new StoriesList(currentAccount, userId, type, this::destroyStoryList));
}
return list;
}
@ -1630,9 +1636,8 @@ public class StoriesController {
}
public void destroyStoryList(StoriesList list) {
int key = Objects.hash(list.userId, list.type);
if (storiesLists != null) {
storiesLists.remove(key);
if (storiesLists[list.type] != null) {
storiesLists[list.type].remove(list.userId);
}
}
@ -1861,7 +1866,7 @@ public class StoriesController {
return false;
}
private long day(MessageObject messageObject) {
public static long day(MessageObject messageObject) {
if (messageObject == null) {
return 0;
}
@ -1878,6 +1883,19 @@ public class StoriesController {
return groupedByDay.get(day(messageObject));
}
public ArrayList<ArrayList<Integer>> getDays() {
final ArrayList<Long> keys = new ArrayList<>(groupedByDay.keySet());
Collections.sort(keys, (a, b) -> (int) (b - a));
final ArrayList<ArrayList<Integer>> days = new ArrayList<>();
for (Long key : keys) {
TreeSet<Integer> storyIds = groupedByDay.get(key);
if (storyIds != null) {
days.add(new ArrayList<>(storyIds));
}
}
return days;
}
public void invalidateCache() {
if (preloading) {
invalidateAfterPreload = true;
@ -2159,6 +2177,10 @@ public class StoriesController {
}
}
public MessageObject findMessageObject(int storyId) {
return messageObjectsMap.get(storyId);
}
public boolean equal(TLRPC.StoryItem a, TLRPC.StoryItem b) {
if (a == null && b == null) {
return true;

View file

@ -3,11 +3,13 @@ package org.telegram.ui.Stories;
import android.graphics.Canvas;
import android.view.View;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.ChatActionCell;
import org.telegram.ui.Cells.ChatMessageCell;
import org.telegram.ui.Cells.DialogCell;
@ -16,6 +18,7 @@ import org.telegram.ui.Cells.SharedPhotoVideoCell2;
import org.telegram.ui.Cells.UserCell;
import org.telegram.ui.Components.BlurredRecyclerView;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.SharedMediaLayout;
public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider {
@ -30,6 +33,7 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider {
public static StoriesListPlaceProvider of(RecyclerListView recyclerListView, boolean hiddenArchive) {
return new StoriesListPlaceProvider(recyclerListView, hiddenArchive);
}
public StoriesListPlaceProvider(RecyclerListView recyclerListView, boolean hiddenArchive) {
this.recyclerListView = recyclerListView;
this.isHiddenArchive = hiddenArchive;
@ -127,27 +131,32 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider {
updateClip(holder);
return true;
}
}else if (child instanceof SharedPhotoVideoCell2) {
} else if (child instanceof SharedPhotoVideoCell2) {
SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) child;
if (cell.getStyle() == SharedPhotoVideoCell2.STYLE_CACHE) {
if (cell.storyId == storyId) {
holder.view = child;
holder.storyImage = cell.imageReceiver;
holder.clipParent = (View) cell.getParent();
holder.drawAbove = cell::drawDuration;
updateClip(holder);
return true;
}
} else {
MessageObject msg = cell.getMessageObject();
if (msg != null && msg.isStory() && msg.getId() == messageId && msg.storyItem.dialogId == dialogId) {
holder.view = child;
holder.storyImage = cell.imageReceiver;
holder.clipParent = (View) cell.getParent();
holder.drawAbove = cell::drawDuration;
updateClip(holder);
return true;
MessageObject msg = cell.getMessageObject();
if (
cell.getStyle() == SharedPhotoVideoCell2.STYLE_CACHE && cell.storyId == storyId ||
msg != null && msg.isStory() && msg.getId() == storyId && msg.storyItem.dialogId == dialogId
) {
final RecyclerListView.FastScroll fastScroll = listView.getFastScroll();
final int[] loc = new int[2];
if (fastScroll != null) {
fastScroll.getLocationInWindow(loc);
}
holder.view = child;
holder.storyImage = cell.imageReceiver;
holder.drawAbove = (canvas, bounds, alpha) -> {
cell.drawDuration(canvas, bounds, alpha);
if (fastScroll != null && fastScroll.isVisible && fastScroll.getVisibility() == View.VISIBLE) {
canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), (int) (0xFF * alpha), Canvas.ALL_SAVE_FLAG);
canvas.translate(loc[0], loc[1]);
fastScroll.draw(canvas);
canvas.restore();
}
};
holder.clipParent = (View) cell.getParent();
updateClip(holder);
return true;
}
} else if (child instanceof UserCell) {
UserCell cell = (UserCell) child;

View file

@ -46,7 +46,7 @@ import java.util.Collections;
public class StoriesUtilities {
private final static int ANIMATION_SEGMENT_COUNT = 20;
private final static int ANIMATION_SEGMENT_COUNT = 16;
public static final int STATE_EMPTY = 0;
public static final int STATE_HAS_UNREAD = 1;
public static final int STATE_READ = 2;
@ -155,11 +155,8 @@ public class StoriesUtilities {
float scale = params.buttonBounce != null ? params.buttonBounce.getScale(0.08f) : 1f;
if (params.showProgress != showProgress && showProgress) {
params.alphas = new float[ANIMATION_SEGMENT_COUNT];
for (int i = 0; i < ANIMATION_SEGMENT_COUNT; i++) {
params.alphas[i] = 1f;
}
params.sweepAngle = 180;
params.sweepAngle = 1f;
params.inc = false;
}
params.showProgress = showProgress;
if (params.currentState == STATE_EMPTY && params.progressToSate == 1f) {
@ -387,36 +384,19 @@ public class StoriesUtilities {
float len = 360 / (float) ANIMATION_SEGMENT_COUNT;
params.updateProgressParams();
view.invalidate();
float originalStrokeWidth = paint.getStrokeWidth();
for (int i = 0; i < ANIMATION_SEGMENT_COUNT; i++) {
float startAngle = i * len;
float endAngle = startAngle + len;
float segmentLen = endAngle - startAngle;
float centerA = (startAngle + segmentLen / 2f);
if (params.alphas == null) {
params.alphas = new float[ANIMATION_SEGMENT_COUNT];
}
if ((centerA > params.globalAngle && centerA < params.globalAngle + params.sweepAngle) || (centerA + 360 > params.globalAngle) && (centerA + 360 < params.globalAngle + params.sweepAngle)) {
params.alphas[i] += AndroidUtilities.screenRefreshTime / 150f;
if (params.alphas[i] > 1) {
params.alphas[i] = 1f;
}
} else {
params.alphas[i] -= AndroidUtilities.screenRefreshTime / 500f;
if (params.alphas[i] < 0) {
params.alphas[i] = 0;
}
}
if (params.alphas[i] == 0) {
continue;
}
startAngle += segmentLen / 2f * (1f - params.alphas[i]);
endAngle -= segmentLen / 2f * (1f - params.alphas[i]);
paint.setStrokeWidth(originalStrokeWidth * params.alphas[i]);
canvas.drawArc(rectTmp, startAngle, endAngle - startAngle, false, paint);
if (params.inc) {
canvas.drawArc(rectTmp, params.globalAngle, 360 * params.sweepAngle, false, paint);
} else {
canvas.drawArc(rectTmp, params.globalAngle + 360, -360 * (params.sweepAngle), false, paint);
}
for (int i = 0; i < ANIMATION_SEGMENT_COUNT; i++) {
float startAngle = i * len + 10;
float endAngle = startAngle + len - 10;
float segmentLen = endAngle - startAngle;
canvas.drawArc(rectTmp, params.globalAngle + startAngle, segmentLen, false, paint);
}
paint.setStrokeWidth(originalStrokeWidth);
}
private static void checkStoryCellGrayPaint(boolean isArchive) {
@ -787,8 +767,6 @@ public class StoriesUtilities {
public AvatarStoryParams(boolean isStoryCell) {
this.isStoryCell = isStoryCell;
}
public float[] alphas;
float sweepAngle;
boolean inc;
float globalAngle;
@ -796,27 +774,20 @@ public class StoriesUtilities {
UserStoriesLoadOperation operation;
private void updateProgressParams() {
float sweepStep = 360 * AndroidUtilities.screenRefreshTime / 1500f;
int len = 360 / ANIMATION_SEGMENT_COUNT;
if (inc) {
sweepAngle += sweepStep;
if (sweepAngle >= 300) {
sweepAngle += 16 / 1000f;
if (sweepAngle >= 1f) {
sweepAngle = 1f;
inc = false;
}
} else {
sweepAngle -= sweepStep;
if (sweepAngle < 10) {
sweepAngle -= 16 / 1000f;
if (sweepAngle < 0) {
sweepAngle = 0;
inc = true;
}
}
float angleStep = 360 * AndroidUtilities.screenRefreshTime / 900.0f;
globalAngle += angleStep;
if (!inc) {
globalAngle += sweepStep;
}
if (globalAngle > 360) {
globalAngle %= 360;
}
globalAngle += 16 / 5000f * 360;
}
float startX, startY;

View file

@ -18,9 +18,13 @@ import org.telegram.messenger.UserConfig;
import org.telegram.ui.ActionBar.Theme;
import java.util.ArrayList;
import java.util.TreeSet;
public class StoriesViewPager extends ViewPager {
long daysDialogId;
ArrayList<ArrayList<Integer>> days;
int currentAccount = UserConfig.selectedAccount;
PagerAdapter pagerAdapter;
ArrayList<Long> dialogs = new ArrayList<>();
@ -55,10 +59,13 @@ public class StoriesViewPager extends ViewPager {
setAdapter(pagerAdapter = new PagerAdapter() {
@Override
public int getCount() {
if (days != null) {
return days.size();
}
return dialogs.size();
}
ArrayList<PeerStoriesView> cachedViews = new ArrayList<>();
private final ArrayList<PeerStoriesView> cachedViews = new ArrayList<>();
@NonNull
@Override
@ -84,7 +91,13 @@ public class StoriesViewPager extends ViewPager {
view.setDelegate(delegate);
view.setLongpressed(storyViewer.isLongpressed);
pageLayout.setTag(position);
pageLayout.dialogId = dialogs.get(position);
if (days != null) {
pageLayout.day = days.get(storyViewer.reversed ? days.size() - 1 - position : position);
pageLayout.dialogId = daysDialogId;
} else {
pageLayout.day = null;
pageLayout.dialogId = dialogs.get(position);
}
pageLayout.addView(view);
view.requestLayout();
container.addView(pageLayout);
@ -110,13 +123,20 @@ public class StoriesViewPager extends ViewPager {
if (Math.abs(position) >= 1f) {
pageLayout.setVisible(false);
AndroidUtilities.runOnUIThread(() -> {
if (pageLayout.day != null) {
pageLayout.peerStoryView.day = pageLayout.day;
}
pageLayout.peerStoryView.preloadMainImage(pageLayout.dialogId);
}, 16);
return;
}
if (!pageLayout.isVisible) {
pageLayout.setVisible(true);
pageLayout.peerStoryView.setDialogId(pageLayout.dialogId);
if (days != null) {
pageLayout.peerStoryView.setDay(pageLayout.dialogId, pageLayout.day);
} else {
pageLayout.peerStoryView.setDialogId(pageLayout.dialogId);
}
}
pageLayout.peerStoryView.setOffset(position);
page.setCameraDistance(page.getWidth() * 15);
@ -135,9 +155,11 @@ public class StoriesViewPager extends ViewPager {
toPosition = positionOffsetPixels > 0 ? selectedPosition + 1 : selectedPosition - 1;
progress = positionOffset;
if (selectedPosition >= 0 && selectedPosition < dialogs.size() && dialogs.get(selectedPosition) == UserConfig.getInstance(currentAccount).clientUserId) {
final long me = UserConfig.getInstance(currentAccount).clientUserId;
if (selectedPosition >= 0 && (days == null ? selectedPosition < dialogs.size() && dialogs.get(selectedPosition) == me : daysDialogId == me)) {
delegate.setHideEnterViewProgress(1f - progress);
} else if (toPosition >= 0 && toPosition < dialogs.size() && dialogs.get(toPosition) == UserConfig.getInstance(currentAccount).clientUserId) {
} else if (toPosition >= 0 && (days == null ? toPosition < dialogs.size() && dialogs.get(toPosition) == me : daysDialogId == me)) {
delegate.setHideEnterViewProgress(progress);
} else {
delegate.setHideEnterViewProgress(0);
@ -178,7 +200,7 @@ public class StoriesViewPager extends ViewPager {
boolean allowScreenshots = true;
for (int i = 0; i < getChildCount(); i++) {
PageLayout layout = (PageLayout) getChildAt(i);
if (layout.isVisible && !layout.peerStoryView.allowScreenshots) {
if (layout.isVisible && !layout.peerStoryView.currentStory.allowScreenshots()) {
allowScreenshots = false;
break;
}
@ -218,6 +240,25 @@ public class StoriesViewPager extends ViewPager {
updateDelegate = true;
}
public void setDays(long dialogId, ArrayList<ArrayList<Integer>> days, int currentAccount) {
this.daysDialogId = dialogId;
this.days = days;
this.currentAccount = currentAccount;
setAdapter(null);
setAdapter(pagerAdapter);
int position;
for (position = 0; position < days.size(); ++position) {
if (days.get(position).contains(storyViewer.dayStoryId)) {
break;
}
}
if (storyViewer.reversed) {
position = days.size() - 1 - position;
}
setCurrentItem(position);
updateDelegate = true;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
@ -240,7 +281,7 @@ public class StoriesViewPager extends ViewPager {
}
public boolean switchToNext(boolean forward) {
if (forward && getCurrentItem() < dialogs.size() - 1) {
if (forward && getCurrentItem() < (days != null ? days : dialogs).size() - 1) {
setCurrentItem(getCurrentItem() + 1, !useSurfaceInViewPagerWorkAround());
return true;
}
@ -286,6 +327,9 @@ public class StoriesViewPager extends ViewPager {
}
public long getCurrentDialogId() {
if (days != null) {
return daysDialogId;
}
if (getCurrentItem() < dialogs.size()) {
return dialogs.get(getCurrentItem());
}
@ -337,8 +381,12 @@ public class StoriesViewPager extends ViewPager {
private class PageLayout extends FrameLayout {
public PeerStoriesView peerStoryView;
long dialogId;
ArrayList<Integer> day;
boolean isVisible;
public PageLayout(@NonNull Context context) {
super(context);
}

View file

@ -11,6 +11,7 @@ import android.widget.FrameLayout;
import androidx.core.graphics.ColorUtils;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.Utilities;
import org.telegram.ui.Cells.DialogCell;
import org.telegram.ui.Components.AnimatedTextView;
@ -46,7 +47,10 @@ public class StoryPositionView {
}
canvas.save();
float top = headerView.getY() + headerView.titleView.getTop() + textDrawable.getHeight() / 2f - 1;// + //(headerView.titleView.getMeasuredHeight() - textDrawable.getHeight()) / 2f + AndroidUtilities.dp(1);
int rightPadding = (int) textDrawable.getCurrentWidth();
headerView.titleView.setRightPadding(rightPadding);
float left = AndroidUtilities.dp(4) + headerView.getLeft() + headerView.titleView.getLeft() + headerView.titleView.getTextWidth();
left -= Utilities.clamp(headerView.titleView.getTextWidth() + rightPadding - headerView.titleView.getWidth(), rightPadding, 0);
canvas.translate(left, top);
float horizontalPadding = AndroidUtilities.dp(8);

View file

@ -32,7 +32,7 @@ public class StoryPrivacyButton extends View {
private final Paint[] backgroundPaint = new Paint[2];
private final AnimatedFloat crossfadeT = new AnimatedFloat(this, 0, 260, CubicBezierInterpolator.EASE_OUT_QUINT);
private boolean draw;
public boolean draw;
private int iconResId;
private final Drawable[] icon = new Drawable[2];
private final float[] iconSize = new float[2];
@ -77,6 +77,7 @@ public class StoryPrivacyButton extends View {
} else {
draw = false;
}
setVisibility(draw ? View.VISIBLE : View.GONE);
invalidate();
return draw;
}
@ -105,6 +106,7 @@ public class StoryPrivacyButton extends View {
} else {
draw = false;
}
setVisibility(draw ? View.VISIBLE : View.GONE);
invalidate();
return draw;
}

View file

@ -22,6 +22,7 @@ import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import android.util.SparseArray;
import android.view.GestureDetector;
import android.view.Gravity;
@ -73,6 +74,7 @@ import org.telegram.ui.LaunchActivity;
import java.util.ArrayList;
import java.util.Objects;
import java.util.TreeSet;
public class StoryViewer {
@ -83,7 +85,7 @@ public class StoryViewer {
public boolean foundViewToClose = false;
public int allowScreenshotsCounter;
public boolean allowScreenshots;
public boolean allowScreenshots = true;
public static ArrayList<StoryViewer> globalInstances = new ArrayList<>();
BaseFragment fragment;
@ -175,8 +177,8 @@ public class StoryViewer {
boolean isSingleStory;
StoriesController.StoriesList storiesList;
public int dayStoryId;
TLRPC.TL_userStories overrideUserStories;
int storiesListStartPosition;
boolean reversed;
TLRPC.StoryItem singleStory;
@ -185,6 +187,7 @@ public class StoryViewer {
private int fromRadius;
private static boolean runOpenAnimationAfterLayout;
private boolean isPopupVisible;
private boolean isBulletinVisible;
public boolean isLongpressed;
@ -261,12 +264,12 @@ public class StoryViewer {
open(context, null, peerIds, position, null, null, placeProvider, false);
}
public void open(Context context, TLRPC.StoryItem storyItem, int startPosition, StoriesController.StoriesList storiesList, PlaceProvider placeProvider) {
public void open(Context context, int startStoryId, StoriesController.StoriesList storiesList, PlaceProvider placeProvider) {
currentAccount = UserConfig.selectedAccount;
ArrayList<Long> peerIds = new ArrayList<>();
peerIds.add(storiesList.userId);
storiesListStartPosition = startPosition;
open(context, storyItem, peerIds, 0, storiesList, null, placeProvider, false);
dayStoryId = startStoryId;
open(context, null, peerIds, 0, storiesList, null, placeProvider, false);
}
public void open(Context context, TLRPC.TL_userStories userStories, PlaceProvider placeProvider) {
@ -276,14 +279,14 @@ public class StoryViewer {
currentAccount = UserConfig.selectedAccount;
ArrayList<Long> peerIds = new ArrayList<>();
peerIds.add(userStories.user_id);
open(context, userStories.stories.get(0), peerIds, 0, null, userStories, placeProvider, reversed);
open(context, userStories.stories.get(0), peerIds, 0, null, userStories, placeProvider, false);
}
public void open(Context context, TLRPC.StoryItem storyItem, int startPosition, StoriesController.StoriesList storiesList, boolean reversed, PlaceProvider placeProvider) {
public void open(Context context, TLRPC.StoryItem storyItem, int startStoryId, StoriesController.StoriesList storiesList, boolean reversed, PlaceProvider placeProvider) {
currentAccount = UserConfig.selectedAccount;
ArrayList<Long> peerIds = new ArrayList<>();
peerIds.add(storiesList.userId);
storiesListStartPosition = startPosition;
dayStoryId = startStoryId;
open(context, storyItem, peerIds, 0, storiesList, null, placeProvider, reversed);
}
@ -314,6 +317,9 @@ public class StoryViewer {
currentAccount = UserConfig.selectedAccount;
swipeToDismissOffset = 0;
swipeToDismissHorizontalOffset = 0;
if (storiesViewPager != null) {
storiesViewPager.setHorizontalProgressToDismiss(0);
}
swipeToReplyProgress = 0;
swipeToReplyOffset = 0;
allowSwipeToReply = false;
@ -393,7 +399,7 @@ public class StoryViewer {
int maxOffset = AndroidUtilities.dp(200);
if (swipeToReplyOffset > maxOffset && !swipeToReplyWaitingKeyboard) {
swipeToReplyWaitingKeyboard = true;
storiesViewPager.getCurrentPeerView().showKeyboard();
showKeyboard();
windowView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
}
swipeToReplyProgress = Utilities.clamp(swipeToReplyOffset / maxOffset, 1f, 0);
@ -411,11 +417,6 @@ public class StoryViewer {
} else {
selfStoriesViewsOffset += distanceY;
}
// int maxOffset = AndroidUtilities.dp(200);
// if (selfStoriesViewsOffset > maxOffset) {
// storiesViewPager.getCurrentPeerView().showKeyboard();
// }
// swipeToReplyProgress = Utilities.clamp(swipeToReplyOffset / maxOffset, 1f, 0);
storiesViewPager.getCurrentPeerView().invalidate();
containerView.invalidate();
if (selfStoriesViewsOffset < 0) {
@ -447,10 +448,7 @@ public class StoryViewer {
if (velocityY < -1000 && !swipeToReplyWaitingKeyboard) {
swipeToReplyWaitingKeyboard = true;
windowView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
storiesViewPager.getCurrentPeerView().showKeyboard();
AndroidUtilities.runOnUIThread(() -> {
cancelSwipeToReply();
}, 200);
showKeyboard();
}
}
if (selfStoriesViewsOffset != 0) {
@ -1097,20 +1095,41 @@ public class StoryViewer {
@Override
public void switchToNextAndRemoveCurrentPeer() {
ArrayList<Long> newPeers = new ArrayList<>(peerIds);
int index = newPeers.indexOf(storiesViewPager.getCurrentPeerView().getCurrentPeer());
if (index >= 0) {
newPeers.remove(index);
if (storiesList != null) {
if (storiesViewPager.days == null) {
return;
}
ArrayList<ArrayList<Integer>> newDays = new ArrayList<>(storiesViewPager.days);
int index = newDays.indexOf(storiesViewPager.getCurrentPeerView().getCurrentDay());
if (index >= 0) {
newDays.remove(index);
} else {
close(false);
return;
}
if (!storiesViewPager.switchToNext(true)) {
close(false);
} else {
storiesViewPager.onNextIdle(() -> {
storiesViewPager.setDays(storiesList.userId, newDays, currentAccount);
});
}
} else {
close(false);
return;
}
if (!storiesViewPager.switchToNext(true)) {
close(false);
} else {
storiesViewPager.onNextIdle(() -> {
storiesViewPager.setPeerIds(newPeers, currentAccount, index);
});
ArrayList<Long> newPeers = new ArrayList<>(peerIds);
int index = newPeers.indexOf(storiesViewPager.getCurrentPeerView().getCurrentPeer());
if (index >= 0) {
newPeers.remove(index);
} else {
close(false);
return;
}
if (!storiesViewPager.switchToNext(true)) {
close(false);
} else {
storiesViewPager.onNextIdle(() -> {
storiesViewPager.setPeerIds(newPeers, currentAccount, index);
});
}
}
}
@ -1164,10 +1183,14 @@ public class StoryViewer {
@Override
public void requestPlayer(TLRPC.Document document, Uri uri, long t, PeerStoriesView.VideoPlayerSharedScope scope) {
if (isClosed) {
if (isClosed || progressToOpen != 1f) {
scope.firstFrameRendered = false;
scope.player = null;
return;
}
boolean sameUri = Objects.equals(lastUri, uri);
String lastAutority = lastUri == null ? null : lastUri.getAuthority();
String autority = uri == null ? null : uri.getAuthority();
boolean sameUri = Objects.equals(lastAutority, autority);
if (!sameUri || playerHolder == null) {
lastUri = uri;
if (playerHolder != null) {
@ -1218,6 +1241,13 @@ public class StoryViewer {
currentPlayerScope.textureView = textureView;
currentPlayerScope.surfaceView = surfaceView;
}
if (USE_SURFACE_VIEW) {
if (uri == null) {
surfaceView.setVisibility(View.INVISIBLE);
} else {
surfaceView.setVisibility(View.VISIBLE);
}
}
}
@Override
@ -1259,6 +1289,12 @@ public class StoryViewer {
updatePlayingMode();
}
@Override
public void setBulletinIsVisible(boolean b) {
StoryViewer.this.isBulletinVisible = b;
updatePlayingMode();
}
@Override
public void setIsInPinchToZoom(boolean b) {
StoryViewer.this.isInPinchToZoom = b;
@ -1335,15 +1371,14 @@ public class StoryViewer {
aspectRatioFrameLayout.addView(textureView);
}
volumeControl = new StoriesVolumeContorl(context);
containerView.addView(volumeControl, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 4, 0, 4, 0));
}
AndroidUtilities.removeFromParent(containerView);
windowView.addView(containerView);
AndroidUtilities.removeFromParent(aspectRatioFrameLayout);
windowView.addView(aspectRatioFrameLayout);
AndroidUtilities.removeFromParent(containerView);
windowView.addView(containerView);
windowView.setClipChildren(false);
if (ATTACH_TO_FRAGMENT) {
@ -1355,7 +1390,11 @@ public class StoryViewer {
if (isSingleStory) {
updateTransitionParams();
}
storiesViewPager.setPeerIds(peerIds, currentAccount, position);
if (storiesList != null) {
storiesViewPager.setDays(storiesList.userId, storiesList.getDays(), currentAccount);
} else {
storiesViewPager.setPeerIds(peerIds, currentAccount, position);
}
windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (ATTACH_TO_FRAGMENT) {
@ -1412,6 +1451,13 @@ public class StoryViewer {
AndroidUtilities.hideKeyboard(fragment.getFragmentView());
}
private void showKeyboard() {
storiesViewPager.getCurrentPeerView().showKeyboard();
AndroidUtilities.runOnUIThread(() -> {
cancelSwipeToReply();
}, 200);
}
ValueAnimator swipeToViewsAnimator;
public void cancelSwipeToViews(boolean open) {
@ -1474,17 +1520,21 @@ public class StoryViewer {
}
public void cancelSwipeToReply() {
if (swipeToReplyOffset != 0 && allowSwipeToReply) {
if (swipeToReplyBackAnimator == null) {
inSwipeToDissmissMode = false;
allowSwipeToReply = false;
swipeToReplyBackAnimator = ValueAnimator.ofFloat(swipeToReplyProgress, 0);
swipeToReplyBackAnimator = ValueAnimator.ofFloat(swipeToReplyOffset, 0);
swipeToReplyBackAnimator.addUpdateListener(animation -> {
swipeToReplyProgress = (float) animation.getAnimatedValue();
swipeToReplyOffset = (float) animation.getAnimatedValue();
int maxOffset = AndroidUtilities.dp(200);
swipeToReplyProgress = Utilities.clamp(swipeToReplyOffset / maxOffset, 1f, 0);
storiesViewPager.getCurrentPeerView().invalidate();
});
swipeToReplyBackAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
swipeToReplyBackAnimator = null;
swipeToReplyOffset = 0;
swipeToReplyProgress = 0;
storiesViewPager.getCurrentPeerView().invalidate();
}
@ -1610,9 +1660,11 @@ public class StoryViewer {
int position = peerView == null ? 0 : peerView.getSelectedPosition();
int storyId = peerView == null || position < 0 || position >= peerView.storyItems.size() ? 0 : peerView.storyItems.get(position).id;
TLRPC.StoryItem storyItem = peerView == null || position < 0 || position >= peerView.storyItems.size() ? null : peerView.storyItems.get(position);
if (storyItem == null && isSingleStory) {
storyItem = singleStory;
}
transitionViewHolder.clear();
if (placeProvider.findView(storiesViewPager.getCurrentDialogId(), messageId, storyId, storyItem == null ? -1 : storyItem.messageType, transitionViewHolder)) {
if (placeProvider.findView(storiesViewPager.getCurrentDialogId(), messageId, storiesList != null ? dayStoryId : storyId, storyItem == null ? -1 : storyItem.messageType, transitionViewHolder)) {
if (transitionViewHolder.view != null) {
int[] loc = new int[2];
transitionViewHolder.view.getLocationOnScreen(loc);
@ -1707,7 +1759,7 @@ public class StoryViewer {
}
public boolean isPaused() {
return isPopupVisible || isCaption || isWaiting || isInTouchMode || keyboardVisible || currentDialog != null || allowTouchesByViewpager || isClosed || isRecording || progressToOpen != 1f || selfStoriesViewsOffset != 0 || isHintVisible || (isSwiping && USE_SURFACE_VIEW) || isOverlayVisible;
return isPopupVisible || isBulletinVisible || isCaption || isWaiting || isInTouchMode || keyboardVisible || currentDialog != null || allowTouchesByViewpager || isClosed || isRecording || progressToOpen != 1f || selfStoriesViewsOffset != 0 || isHintVisible || (isSwiping && USE_SURFACE_VIEW) || isOverlayVisible;
}
public void updatePlayingMode() {
@ -1836,6 +1888,10 @@ public class StoryViewer {
transitionViewHolder.storyImage.setAlpha(1f);
transitionViewHolder.storyImage.setVisible(true, true);
}
PeerStoriesView peerStoriesView = getCurrentPeerView();
if (peerStoriesView != null) {
peerStoriesView.updatePosition();
}
updatePlayingMode();
locker.unlock();
}
@ -2183,7 +2239,6 @@ public class StoryViewer {
} catch (Exception e) {
FileLog.e(e);
}
}
}
}
@ -2411,7 +2466,7 @@ public class StoryViewer {
onReadyListener.run();
onReadyListener = null;
}
});
}, 16);
}
@Override

View file

@ -58,6 +58,9 @@ public class UserListPoller {
ArrayList<TLRPC.User> usersToUpdate = new ArrayList<>();
for (int i = 0; i < vector.objects.size(); i++) {
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogsFinal.get(i));
if (user == null) {
continue;
}
user.stories_max_id = (int) vector.objects.get(i);
if (user.stories_max_id != 0) {
user.flags2 |= 32;

View file

@ -58,12 +58,13 @@ public class DownloadButton extends ImageView {
private boolean downloading;
private boolean downloadingVideo;
private boolean preparing;
private CircularProgressDrawable progressDrawable;
private Runnable prepare;
private Utilities.Callback<Runnable> prepare;
private PreparingVideoToast toast;
public DownloadButton(Context context, Runnable prepare, int currentAccount, FrameLayout container, Theme.ResourcesProvider resourcesProvider) {
public DownloadButton(Context context, Utilities.Callback<Runnable> prepare, int currentAccount, FrameLayout container, Theme.ResourcesProvider resourcesProvider) {
super(context);
this.prepare = prepare;
@ -117,15 +118,6 @@ public class DownloadButton extends ImageView {
if (downloading || currentEntry == null) {
return;
}
downloading = true;
if (toast != null) {
toast.hide();
toast = null;
}
if (prepare != null) {
prepare.run();
}
if (savedToGalleryUri != null) {
if (Build.VERSION.SDK_INT >= 30) {
getContext().getContentResolver().delete(savedToGalleryUri, null);
@ -139,16 +131,28 @@ public class DownloadButton extends ImageView {
savedToGalleryUri = null;
}
}
downloading = true;
if (toast != null) {
toast.hide();
toast = null;
}
if (prepare != null) {
preparing = true;
prepare.run(this::onClickInternal);
}
if (currentEntry.wouldBeVideo()) {
downloadingVideo = true;
final File file = AndroidUtilities.generateVideoPath();
if (buildingVideo != null) {
buildingVideo.stop(true);
buildingVideo = null;
}
toast = new PreparingVideoToast(getContext());
toast.setOnCancelListener(() -> {
preparing = false;
if (buildingVideo != null) {
buildingVideo.stop(true);
buildingVideo = null;
}
if (toast != null) {
toast.hide();
@ -157,6 +161,22 @@ public class DownloadButton extends ImageView {
updateImage();
});
container.addView(toast);
} else {
downloadingVideo = false;
}
updateImage();
if (prepare == null) {
onClickInternal();
}
}
private void onClickInternal() {
if (!preparing) {
return;
}
preparing = false;
if (currentEntry.wouldBeVideo()) {
final File file = AndroidUtilities.generateVideoPath();
buildingVideo = new BuildingVideo(currentAccount, currentEntry, file, () -> {
if (!downloading || currentEntry == null) {
return;
@ -172,7 +192,9 @@ public class DownloadButton extends ImageView {
savedToGalleryUri = uri;
}, false);
}, progress -> {
toast.setProgress(progress);
if (toast != null) {
toast.setProgress(progress);
}
}, () -> {
if (!downloading || currentEntry == null) {
return;
@ -182,7 +204,6 @@ public class DownloadButton extends ImageView {
updateImage();
});
} else {
downloadingVideo = false;
final File file = AndroidUtilities.generatePicturePath(false, "png");
if (file == null) {
toast.setDone(R.raw.error, LocaleController.getString("UnknownError"), 3500);
@ -282,6 +303,9 @@ public class DownloadButton extends ImageView {
message.attachPath = file.getAbsolutePath();
messageObject = new MessageObject(currentAccount, message, (MessageObject) null, false, false);
entry.getVideoEditedInfo(info -> {
if (messageObject == null) {
return;
}
messageObject.videoEditedInfo = info;
MediaController.getInstance().scheduleVideoConvert(messageObject);
});

View file

@ -171,8 +171,8 @@ public class DualCameraView extends CameraView implements CameraController.Error
if (setDefault) {
matrix.postConcat(toScreen);
float w = getMeasuredWidth() * .4f;
float h = getMeasuredHeight() * .4f;
float w = getMeasuredWidth() * .43f;
float h = getMeasuredHeight() * .43f;
float px = Math.min(getMeasuredWidth(), getMeasuredWidth()) * .025f;
float py = px * 2;
@ -192,30 +192,56 @@ public class DualCameraView extends CameraView implements CameraController.Error
toGL.mapPoints(vertex);
getDualPosition().invert(invMatrix);
invMatrix.mapPoints(vertex);
return vertex[0] >= -1 && vertex[0] <= 1 && vertex[1] >= -1 && vertex[1] <= 1;
int shape = getDualShape() % 3;
boolean square = shape == 0 || shape == 1 || shape == 3;
float H = square ? 9 / 16f : 1f;
return vertex[0] >= -1 && vertex[0] <= 1 && vertex[1] >= -H && vertex[1] <= H;
}
private float tapX, tapY;
private long tapTime;
private Matrix invMatrix = new Matrix();
private Runnable longpressRunnable;
private boolean checkTap(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
tapTime = System.currentTimeMillis();
tapX = ev.getX();
tapY = ev.getY();
lastFocusToPoint = null;
if (longpressRunnable != null) {
AndroidUtilities.cancelRunOnUIThread(longpressRunnable);
longpressRunnable = null;
}
if (isAtDual(tapX, tapY)) {
AndroidUtilities.runOnUIThread(longpressRunnable = () -> {
if (tapTime > 0) {
this.dualToggleShape();
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
}, ViewConfiguration.getLongPressTimeout());
}
return true;
} else if (ev.getAction() == MotionEvent.ACTION_UP) {
if (System.currentTimeMillis() - tapTime <= ViewConfiguration.getTapTimeout() && MathUtils.distance(tapX, tapY, ev.getX(), ev.getY()) < AndroidUtilities.dp(10)) {
if (isAtDual(tapX, tapY)) {
lastFocusToPoint = this::dualToggleShape;
switchCamera();
lastFocusToPoint = null;
} else {
lastFocusToPoint = () -> focusToPoint((int) tapX, (int) tapY);
}
}
tapTime = -1;
if (longpressRunnable != null) {
AndroidUtilities.cancelRunOnUIThread(longpressRunnable);
longpressRunnable = null;
}
} else if (ev.getAction() == MotionEvent.ACTION_CANCEL) {
tapTime = -1;
lastFocusToPoint = null;
if (longpressRunnable != null) {
AndroidUtilities.cancelRunOnUIThread(longpressRunnable);
longpressRunnable = null;
}
}
return false;
}
@ -270,6 +296,12 @@ public class DualCameraView extends CameraView implements CameraController.Error
down = isPointInsideDual(touchMatrix, touch.x, touch.y);
}
if (ev.getAction() == MotionEvent.ACTION_MOVE && down) {
if (MathUtils.distance(tx, ty, ltx, lty) > AndroidUtilities.dp(2)) {
if (longpressRunnable != null) {
AndroidUtilities.cancelRunOnUIThread(longpressRunnable);
longpressRunnable = null;
}
}
if (ev.getPointerCount() > 1) {
if (lastTouchDistance != 0) {
extractPointsData(touchMatrix);
@ -326,8 +358,8 @@ public class DualCameraView extends CameraView implements CameraController.Error
}
if (cy < 0) {
finalMatrix.postTranslate(0, -cy);
} else if (cy > getHeight()) {
finalMatrix.postTranslate(0, getHeight() - cy);
} else if (cy > getHeight() - AndroidUtilities.dp(150)) {
finalMatrix.postTranslate(0, getHeight() - AndroidUtilities.dp(150) - cy);
}
finalMatrix.postConcat(toGL);
matrix.set(finalMatrix);
@ -420,14 +452,17 @@ public class DualCameraView extends CameraView implements CameraController.Error
if (verticesDst == null) {
verticesDst = new float[8];
}
int shape = getDualShape() % 3;
boolean square = shape == 0 || shape == 1 || shape == 3;
float H = square ? 9 / 16f : 1f;
verticesSrc[0] = -1;
verticesSrc[1] = -1;
verticesSrc[1] = -H;
verticesSrc[2] = 1;
verticesSrc[3] = -1;
verticesSrc[3] = -H;
verticesSrc[4] = 1;
verticesSrc[5] = 1;
verticesSrc[5] = H;
verticesSrc[6] = -1;
verticesSrc[7] = 1;
verticesSrc[7] = H;
matrix.mapPoints(verticesDst, verticesSrc);
double a1 = Math.sqrt((verticesDst[0] - verticesDst[2]) * (verticesDst[0] - verticesDst[2]) + (verticesDst[1] - verticesDst[3]) * (verticesDst[1] - verticesDst[3]));

View file

@ -55,6 +55,7 @@ import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.DispatchQueue;
import org.telegram.messenger.DispatchQueuePool;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.LocaleController;
@ -77,6 +78,7 @@ import org.telegram.ui.Components.RecyclerListView;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -607,28 +609,16 @@ public class GalleryListView extends FrameLayout implements NotificationCenter.N
Bitmap bitmap = null;
if (entry instanceof MediaController.PhotoEntry) {
MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) entry;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
Uri uri;
if (photoEntry.isVideo) {
uri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, photoEntry.imageId);
} else {
uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, photoEntry.imageId);
}
try {
bitmap = getContext().getContentResolver().loadThumbnail(uri, new Size(rw, rh), null);
} catch (Exception ignore) {}
} else {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
readBitmap(photoEntry, opts);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
readBitmap(photoEntry, opts);
opts.inSampleSize = StoryEntry.calculateInSampleSize(opts, rw, rh);
opts.inPreferredConfig = Bitmap.Config.RGB_565;
opts.inDither = true;
opts.inJustDecodeBounds = false;
bitmap = readBitmap(photoEntry, opts);
}
StoryEntry.setupScale(opts, rw, rh);
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
opts.inDither = true;
opts.inJustDecodeBounds = false;
bitmap = readBitmap(photoEntry, opts);
final boolean needGradient = bitmap != null && ((float) bitmap.getHeight() / bitmap.getWidth()) < ASPECT_RATIO;
if (needGradient) {
@ -648,8 +638,8 @@ public class GalleryListView extends FrameLayout implements NotificationCenter.N
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getPath(), opts);
opts.inSampleSize = StoryEntry.calculateInSampleSize(opts, rw, rh);
opts.inPreferredConfig = Bitmap.Config.RGB_565;
StoryEntry.setupScale(opts, rw, rh);
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
opts.inDither = true;
opts.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(file.getPath(), opts);
@ -761,8 +751,28 @@ public class GalleryListView extends FrameLayout implements NotificationCenter.N
} else if (photoEntry.isVideo) {
return MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), photoEntry.imageId, MediaStore.Video.Thumbnails.MINI_KIND, options);
} else {
return BitmapFactory.decodeFile(photoEntry.path, options);
// return MediaStore.Images.Thumbnails.getThumbnail(getContext().getContentResolver(), photoEntry.imageId, MediaStore.Video.Thumbnails.MINI_KIND, options);
// Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, photoEntry.imageId);
//
// Bitmap bitmap = null;
// InputStream is = null;
// try {
// is = getContext().getContentResolver().openInputStream(uri);
// bitmap = BitmapFactory.decodeStream(is, null, options);
// } catch (Exception e) {
// FileLog.e(e, false);
// } finally {
// if (is != null) {
// try {
// is.close();
// } catch (Exception e2) {}
// }
// }
// if (bitmap == null && options != null && !options.inJustDecodeBounds) {
// return BitmapFactory.decodeFile(photoEntry.path, options);
// } else {
// return bitmap;
// }
return MediaStore.Images.Thumbnails.getThumbnail(getContext().getContentResolver(), photoEntry.imageId, MediaStore.Video.Thumbnails.MINI_KIND, options);
}
}

View file

@ -198,17 +198,27 @@ public class HintView2 extends View {
return false;
}
private static int getTextWidth(CharSequence text, TextPaint paint) {
if (text instanceof Spannable) {
StaticLayout layout = new StaticLayout(text, paint, 99999, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false);
if (layout.getLineCount() > 0)
return (int) Math.ceil(layout.getLineWidth(0));
return 0;
}
return (int) paint.measureText(text.toString());
}
// returns max width
public static int cutInFancyHalf(CharSequence text, TextPaint paint) {
if (text == null) {
return 0;
}
float fullLineWidth = paint.measureText(text.toString());
float fullLineWidth = getTextWidth(text, paint);
final int L = text.toString().length(), m = L / 2;
if (L <= 0) {
if (L <= 0 || contains(text, '\n')) {
return (int) Math.ceil(fullLineWidth);
}
int l = m - 2, r = m + 2;
int l = m - 1, r = m + 1;
int c = m;
while (l >= 0 && r < L) {
if (text.charAt(l) == ' ') {
@ -222,7 +232,7 @@ public class HintView2 extends View {
l--;
r++;
}
return (int) Math.ceil(Math.max(fullLineWidth * .3f, Math.max(c, L - c) / (float) L * fullLineWidth));
return (int) Math.ceil(Math.max(fullLineWidth * .3f, Math.max(c + .5f, L - c + .5f) / (float) L * fullLineWidth));
}
public HintView2 useScale(boolean enable) {

View file

@ -52,6 +52,8 @@ import java.util.Map;
public class PreviewView extends FrameLayout {
private Bitmap bitmap;
private Bitmap thumbBitmap;
private StoryEntry entry;
private VideoPlayer videoPlayer;
private int videoWidth, videoHeight;
@ -254,6 +256,10 @@ public class PreviewView extends FrameLayout {
bitmap.recycle();
bitmap = null;
}
if (thumbBitmap != null) {
thumbBitmap.recycle();
thumbBitmap = null;
}
if (entry != null) {
final int rw = getMeasuredWidth() <= 0 ? AndroidUtilities.displaySize.x : getMeasuredWidth();
final int rh = (int) (rw * 16 / 9f);
@ -284,41 +290,77 @@ public class PreviewView extends FrameLayout {
}
if (bitmap == null) {
String path = entry.getOriginalFile().getPath();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
if (entry.isVideo) {
if (entry.thumbPath != null) {
BitmapFactory.decodeFile(entry.thumbPath, options);
} else {
try {
MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageId, MediaStore.Video.Thumbnails.MINI_KIND, options);
} catch (Throwable e) {
bitmap = null;
invalidate();
return;
}
}
} else {
BitmapFactory.decodeFile(path, options);
}
options.inJustDecodeBounds = false;
StoryEntry.setupScale(options, rw, rh);
if (entry.isVideo) {
if (entry.thumbPath != null) {
BitmapFactory.decodeFile(entry.thumbPath, options);
} else {
try {
bitmap = MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageId, MediaStore.Video.Thumbnails.MINI_KIND, options);
} catch (Throwable e) {
bitmap = null;
invalidate();
return;
final long imageIdFinal = imageId;
bitmap = StoryEntry.getScaledBitmap(opts -> {
if (entry.isVideo) {
if (entry.thumbPath != null) {
return BitmapFactory.decodeFile(entry.thumbPath, opts);
} else {
try {
return MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageIdFinal, MediaStore.Video.Thumbnails.MINI_KIND, opts);
} catch (Throwable e) {
invalidate();
return null;
}
}
} else {
return BitmapFactory.decodeFile(path, opts);
}
} else {
bitmap = BitmapFactory.decodeFile(path, options);
}
}, rw, rh, false);
// this.thumbAlpha.set(0, true);
// thumbBitmap = StoryEntry.getScaledBitmap(opts -> {
// if (entry.isVideo) {
// if (entry.thumbPath != null) {
// return BitmapFactory.decodeFile(entry.thumbPath, opts);
// } else {
// try {
// return MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageIdFinal, MediaStore.Video.Thumbnails.MINI_KIND, opts);
// } catch (Throwable e) {
// invalidate();
// return null;
// }
// }
// } else {
// return BitmapFactory.decodeFile(path, opts);
// }
// }, rw / 4, rh / 4, false);
//
// Utilities.themeQueue.postRunnable(() -> {
// final Bitmap bitmapFinal = StoryEntry.getScaledBitmap(opts -> {
// if (entry.isVideo) {
// if (entry.thumbPath != null) {
// return BitmapFactory.decodeFile(entry.thumbPath, opts);
// } else {
// try {
// return MediaStore.Video.Thumbnails.getThumbnail(getContext().getContentResolver(), imageIdFinal, MediaStore.Video.Thumbnails.MINI_KIND, opts);
// } catch (Throwable e) {
// invalidate();
// return null;
// }
// }
// } else {
// return BitmapFactory.decodeFile(path, opts);
// }
// }, rw, rh, true);
// AndroidUtilities.runOnUIThread(() -> {
// if (PreviewView.this.entry != entry) {
// if (bitmapFinal != null) {
// bitmapFinal.recycle();
// }
// return;
// }
// bitmap = bitmapFinal;
// if (!entry.isDraft && entry.isVideo && bitmap != null && entry.width <= 0) {
// entry.width = bitmap.getWidth();
// entry.height = bitmap.getHeight();
// entry.setupMatrix();
// }
// invalidate();
// });
// });
return;
}
if (!entry.isDraft && entry.isVideo && bitmap != null) {
entry.width = bitmap.getWidth();
@ -339,6 +381,13 @@ public class PreviewView extends FrameLayout {
gradientPaint.setShader(new LinearGradient(0, 0, 0, height, colors, new float[]{0, 1}, Shader.TileMode.CLAMP));
invalidate();
});
} else if (thumbBitmap != null) {
DominantColors.getColors(true, thumbBitmap, true, colors -> {
entry.gradientTopColor = colors[0];
entry.gradientBottomColor = colors[1];
gradientPaint.setShader(new LinearGradient(0, 0, 0, height, colors, new float[]{0, 1}, Shader.TileMode.CLAMP));
invalidate();
});
} else {
gradientPaint.setShader(null);
}
@ -628,14 +677,27 @@ public class PreviewView extends FrameLayout {
invalidate();
}
private final AnimatedFloat thumbAlpha = new AnimatedFloat(this, 0, 320, CubicBezierInterpolator.EASE_OUT);
@Override
protected void dispatchDraw(Canvas canvas) {
canvas.drawRect(0, 0, getWidth(), getHeight(), gradientPaint);
if (draw && entry != null && bitmap != null) {
matrix.set(entry.matrix);
matrix.preScale((float) entry.width / bitmap.getWidth(), (float) entry.height / bitmap.getHeight());
matrix.postScale((float) getWidth() / entry.resultWidth, (float) getHeight() / entry.resultHeight);
canvas.drawBitmap(bitmap, matrix, bitmapPaint);
if (draw && entry != null) {
float alpha = this.thumbAlpha.set(bitmap != null);
if (thumbBitmap != null && (1f - alpha) > 0) {
matrix.set(entry.matrix);
matrix.preScale((float) entry.width / thumbBitmap.getWidth(), (float) entry.height / thumbBitmap.getHeight());
matrix.postScale((float) getWidth() / entry.resultWidth, (float) getHeight() / entry.resultHeight);
bitmapPaint.setAlpha(0xFF);
canvas.drawBitmap(thumbBitmap, matrix, bitmapPaint);
}
if (bitmap != null) {
matrix.set(entry.matrix);
matrix.preScale((float) entry.width / bitmap.getWidth(), (float) entry.height / bitmap.getHeight());
matrix.postScale((float) getWidth() / entry.resultWidth, (float) getHeight() / entry.resultHeight);
bitmapPaint.setAlpha((int) (0xFF * alpha));
canvas.drawBitmap(bitmap, matrix, bitmapPaint);
}
}
super.dispatchDraw(canvas);
if (draw && entry != null) {

View file

@ -16,6 +16,7 @@ import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.SurfaceTexture;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
import android.view.TextureView;
@ -38,6 +39,7 @@ import org.telegram.messenger.Utilities;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AnimatedFloat;
import org.telegram.ui.Components.ButtonBounce;
import org.telegram.ui.Components.CircularProgressDrawable;
import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.Point;
@ -101,7 +103,6 @@ public class RecordControl extends View {
private final ButtonBounce recordButton = new ButtonBounce(this);
private final ButtonBounce flipButton = new ButtonBounce(this);
private final ButtonBounce galleryButton = new ButtonBounce(this);
private final ButtonBounce lockButton = new ButtonBounce(this);
private float flipDrawableRotate;
@ -245,6 +246,11 @@ public class RecordControl extends View {
private final AnimatedFloat recordingLongT = new AnimatedFloat(this, 0, 850, CubicBezierInterpolator.EASE_OUT_QUINT);
private boolean recording;
private float loadingSegments[] = new float[2];
private final AnimatedFloat recordingLoadingT = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
private boolean recordingLoading;
private long recordingLoadingStart;
private boolean touch;
private boolean discardParentTouch;
private long touchStart;
@ -266,7 +272,6 @@ public class RecordControl extends View {
touch = false;
recordButton.setPressed(false);
flipButton.setPressed(false);
galleryButton.setPressed(false);
lockButton.setPressed(false);
return;
}
@ -287,7 +292,6 @@ public class RecordControl extends View {
touch = false;
recordButton.setPressed(false);
flipButton.setPressed(false);
galleryButton.setPressed(false);
lockButton.setPressed(false);
}
};
@ -326,11 +330,11 @@ public class RecordControl extends View {
}
canvas.save();
scale = lerp(recordButton.getScale(.2f), 1, recordingT);
scale = lerp(recordButton.getScale(startModeIsVideo ? 0 : .2f), 1, recordingT);
canvas.scale(scale, scale, cx, cy);
mainPaint.setColor(ColorUtils.blendARGB(WHITE, RED, isVideo));
float acx = lerp(cx, recordCx.set(cx + dp(4) * touchCenterT16), touchIsCenterT);
float r = lerp(lerp(dp(29), dp(12), recordingT), dp(32), touchIsCenterT);
float r = lerp(lerp(dp(29), dp(12), recordingT), dp(32) - dp(4) * Math.abs(touchCenterT96), touchIsCenterT);
float rad = lerp(lerp(dp(32), dp(7), recordingT), dp(32), touchIsCenterT);
AndroidUtilities.rectTmp.set(acx - r, cy - r, acx + r, cy + r);
canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, mainPaint);
@ -346,10 +350,32 @@ public class RecordControl extends View {
long duration = System.currentTimeMillis() - recordingStart;
AndroidUtilities.rectTmp.set(cx - or, cy - or, cx + or, cy + or);
float recordEndT = recording ? 0 : 1f - recordingLongT;
float sweepAngle = /*lerp(*/duration / (float) MAX_DURATION * 360/*, 0, recordEndT)*/;
float sweepAngle = duration / (float) MAX_DURATION * 360;
float recordingLoading = this.recordingLoadingT.set(this.recordingLoading);
outlineFilledPaint.setStrokeWidth(dp(3));
outlineFilledPaint.setAlpha((int) (0xFF * (1f - recordEndT)));
canvas.drawArc(AndroidUtilities.rectTmp, -90/* + 360 * recordEndT*/, sweepAngle, false, outlineFilledPaint);
outlineFilledPaint.setAlpha((int) (0xFF * Math.max(.7f * recordingLoading, 1f - recordEndT)));
if (recordingLoading <= 0) {
canvas.drawArc(AndroidUtilities.rectTmp, -90, sweepAngle, false, outlineFilledPaint);
} else {
final long now = SystemClock.elapsedRealtime();
CircularProgressDrawable.getSegments((now - recordingLoadingStart) % 5400, loadingSegments);
invalidate();
float fromAngle = loadingSegments[0], toAngle = loadingSegments[1];
float center = (fromAngle + toAngle) / 2f;
float amplitude = Math.abs(toAngle - fromAngle) / 2f;
if (this.recordingLoading) {
center = lerp(-90 + sweepAngle / 2f, center, recordingLoading);
amplitude = lerp(sweepAngle / 2f, amplitude, recordingLoading);
}
canvas.drawArc(AndroidUtilities.rectTmp, center - amplitude, amplitude * 2, false, outlineFilledPaint);
}
if (recording) {
invalidate();
@ -360,10 +386,11 @@ public class RecordControl extends View {
post(() -> {
recording = false;
longpressRecording = false;
this.recordingLoadingStart = SystemClock.elapsedRealtime();
this.recordingLoading = true;
touch = false;
recordButton.setPressed(false);
flipButton.setPressed(false);
galleryButton.setPressed(false);
lockButton.setPressed(false);
delegate.onVideoRecordEnd(true);
});
@ -412,7 +439,25 @@ public class RecordControl extends View {
canvas.restore();
}
final float tr = longpressRecording ? touchT * isVideo * recordingT * lerp(dp(16), lerp(dp(8) + dp(8) * Math.abs(touchCenterT96), dp(22), touchIsButtonT), Math.max(touchIsButtonT, touchIsCenterT)) : 0;
final float tr;
if (longpressRecording) {
tr = (
touchT *
isVideo *
recordingT *
lerp(
dp(16),
lerp(
dp(8) + dp(8) * Math.abs(touchCenterT96),
dp(22),
touchIsButtonT
),
Math.max(touchIsButtonT, touchIsCenterT)
)
);
} else {
tr = 0;
}
float locked = lockedT.set(!longpressRecording && recording ? 1 : 0);
if (tr > 0) {
redPaint.setAlpha(0xFF);
@ -556,7 +601,11 @@ public class RecordControl extends View {
final float x = Utilities.clamp(event.getX() + ox, rightCx, leftCx), y = event.getY() + oy;
final boolean innerFlipButton = isPressed(x, y, rightCx, cy, dp(7), true);
if (action == MotionEvent.ACTION_DOWN || touch) {
if (recordingLoading) {
recordButton.setPressed(false);
flipButton.setPressed(false);
lockButton.setPressed(false);
} else if (action == MotionEvent.ACTION_DOWN || touch) {
recordButton.setPressed(isPressed(x, y, cx, cy, dp(60), false));
flipButton.setPressed(isPressed(x, y, rightCx, cy, dp(30), true));
lockButton.setPressed(isPressed(x, y, leftCx, cy, dp(30), false));
@ -619,6 +668,8 @@ public class RecordControl extends View {
delegate.onVideoRecordLocked();
} else {
recording = false;
this.recordingLoadingStart = SystemClock.elapsedRealtime();
this.recordingLoading = true;
delegate.onVideoRecordEnd(false);
}
} else if (recordButton.isPressed()) {
@ -638,6 +689,8 @@ public class RecordControl extends View {
}
} else {
recording = false;
this.recordingLoadingStart = SystemClock.elapsedRealtime();
this.recordingLoading = true;
delegate.onVideoRecordEnd(false);
}
}
@ -651,7 +704,6 @@ public class RecordControl extends View {
recordButton.setPressed(false);
flipButton.setPressed(false);
galleryButton.setPressed(false);
lockButton.setPressed(false);
invalidate();
@ -667,11 +719,20 @@ public class RecordControl extends View {
return;
}
recording = false;
this.recordingLoadingStart = SystemClock.elapsedRealtime();
this.recordingLoading = true;
delegate.onVideoRecordEnd(false);
recordButton.setPressed(false);
flipButton.setPressed(false);
galleryButton.setPressed(false);
lockButton.setPressed(false);
invalidate();
}
public void stopRecordingLoading(boolean animated) {
this.recordingLoading = false;
if (!animated) {
this.recordingLoadingT.set(false, true);
}
invalidate();
}
}

View file

@ -2,6 +2,8 @@ package org.telegram.ui.Stories.recorder;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
@ -197,12 +199,7 @@ public class StoryEntry extends IStoryPart {
File file = filterFile != null ? filterFile : this.file;
if (file != null) {
try {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(file.getPath(), opts);
opts.inJustDecodeBounds = false;
setupScale(opts, resultWidth, resultHeight);
Bitmap fileBitmap = BitmapFactory.decodeFile(file.getPath(), opts);
Bitmap fileBitmap = getScaledBitmap(opts -> BitmapFactory.decodeFile(file.getPath(), opts), resultWidth, resultHeight, true);
final float scale = (float) width / fileBitmap.getWidth();
tempMatrix.preScale(scale, scale);
canvas.drawBitmap(fileBitmap, tempMatrix, bitmapPaint);
@ -214,13 +211,8 @@ public class StoryEntry extends IStoryPart {
for (int i = 0; i < parts.size(); ++i) {
try {
Part part = parts.get(i);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(part.file.getPath(), opts);
opts.inJustDecodeBounds = false;
setupScale(opts, resultWidth, resultHeight);
Bitmap fileBitmap = BitmapFactory.decodeFile(part.file.getPath(), opts);
final Part part = parts.get(i);
Bitmap fileBitmap = getScaledBitmap(opts -> BitmapFactory.decodeFile(part.file.getPath(), opts), resultWidth, resultHeight, false);
final float scale = (float) part.width / fileBitmap.getWidth();
tempMatrix.set(part.matrix);
tempMatrix.preScale(scale, scale);
@ -233,12 +225,7 @@ public class StoryEntry extends IStoryPart {
if (paintFile != null) {
try {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(paintFile.getPath(), opts);
opts.inJustDecodeBounds = false;
setupScale(opts, resultWidth, resultHeight);
Bitmap paintBitmap = BitmapFactory.decodeFile(paintFile.getPath(), opts);
Bitmap paintBitmap = getScaledBitmap(opts -> BitmapFactory.decodeFile(paintFile.getPath(), opts), resultWidth, resultHeight, false);
canvas.save();
float scale = resultWidth / (float) paintBitmap.getWidth();
canvas.scale(scale, scale);
@ -254,7 +241,7 @@ public class StoryEntry extends IStoryPart {
try {
FileOutputStream stream = new FileOutputStream(dest);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 75, stream);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 95, stream);
stream.close();
} catch (Exception e) {
FileLog.e(e);
@ -263,6 +250,64 @@ public class StoryEntry extends IStoryPart {
finalBitmap.recycle();
}
public static interface DecodeBitmap {
public Bitmap decode(BitmapFactory.Options options);
}
public static Bitmap getScaledBitmap(DecodeBitmap decode, int maxWidth, int maxHeight, boolean allowBlur) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
decode.decode(opts);
opts.inJustDecodeBounds = false;
opts.inScaled = false;
final Runtime runtime = Runtime.getRuntime();
final long availableMemory = runtime.maxMemory() - (runtime.totalMemory() - runtime.freeMemory());
final boolean enoughMemory = (opts.outWidth * opts.outHeight * 4L + maxWidth * maxHeight * 4L) * 1.1 <= availableMemory;
if (opts.outWidth <= maxWidth && opts.outHeight <= maxHeight) {
return decode.decode(opts);
}
if (enoughMemory && SharedConfig.getDevicePerformanceClass() >= SharedConfig.PERFORMANCE_CLASS_AVERAGE) {
Bitmap bitmap = decode.decode(opts);
final float scaleX = maxWidth / (float) bitmap.getWidth(), scaleY = maxHeight / (float) bitmap.getHeight();
float scale = Math.max(scaleX, scaleY);
// if (SharedConfig.getDevicePerformanceClass() >= SharedConfig.PERFORMANCE_CLASS_HIGH) {
// scale = Math.min(scale * 2, 1);
// }
final int w = (int) (bitmap.getWidth() * scale), h = (int) (bitmap.getHeight() * scale);
Bitmap scaledBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(scaledBitmap);
final Matrix matrix = new Matrix();
final BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
paint.setShader(shader);
int blurRadius = Utilities.clamp(Math.round(1f / scale), 8, 0);
matrix.reset();
matrix.postScale(scale, scale);
shader.setLocalMatrix(matrix);
canvas.drawRect(0, 0, w, h, paint);
if (allowBlur && blurRadius > 0) {
Utilities.stackBlurBitmap(scaledBitmap, blurRadius);
}
return scaledBitmap;
} else {
opts.inScaled = true;
opts.inDensity = opts.outWidth;
opts.inTargetDensity = maxWidth;
return decode.decode(opts);
}
}
public File getOriginalFile() {
if (filterFile != null) {
return filterFile;
@ -270,11 +315,18 @@ public class StoryEntry extends IStoryPart {
return file;
}
public void updateFilter(PhotoFilterView filterView) {
public void updateFilter(PhotoFilterView filterView, Runnable whenDone) {
clearFilter();
filterState = filterView.getSavedFilterState();
if (!isVideo) {
if (filterState.isEmpty()) {
if (whenDone != null) {
whenDone.run();
}
return;
}
Bitmap bitmap = filterView.getBitmap();
if (bitmap == null) {
return;
@ -290,14 +342,40 @@ public class StoryEntry extends IStoryPart {
bitmap.recycle();
filterFile = makeCacheFile(currentAccount, false);
try {
FileOutputStream stream = new FileOutputStream(filterFile);
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
} catch (Exception e) {
FileLog.e(e);
if (filterFile != null && filterFile.exists()) {
filterFile.delete();
}
filterFile = makeCacheFile(currentAccount, "webp");
if (whenDone == null) {
try {
FileOutputStream stream = new FileOutputStream(filterFile);
rotatedBitmap.compress(Bitmap.CompressFormat.WEBP, 90, stream);
} catch (Exception e) {
FileLog.e(e);
}
rotatedBitmap.recycle();
} else {
Utilities.themeQueue.postRunnable(() -> {
try {
FileOutputStream stream = new FileOutputStream(filterFile);
rotatedBitmap.compress(Bitmap.CompressFormat.WEBP, 90, stream);
} catch (Exception e) {
FileLog.e(e, false);
try {
FileOutputStream stream = new FileOutputStream(filterFile);
rotatedBitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
} catch (Exception e2) {
FileLog.e(e2, false);
}
}
rotatedBitmap.recycle();
AndroidUtilities.runOnUIThread(whenDone);
});
}
} else {
if (whenDone != null) {
whenDone.run();
}
rotatedBitmap.recycle();
}
}
@ -669,6 +747,10 @@ public class StoryEntry extends IStoryPart {
}
public static File makeCacheFile(final int account, boolean video) {
return makeCacheFile(account, video ? "mp4" : "jpg");
}
public static File makeCacheFile(final int account, String ext) {
TLRPC.TL_fileLocationToBeDeprecated location = new TLRPC.TL_fileLocationToBeDeprecated();
location.volume_id = Integer.MIN_VALUE;
location.dc_id = Integer.MIN_VALUE;
@ -676,7 +758,7 @@ public class StoryEntry extends IStoryPart {
location.file_reference = new byte[0];
TLObject object;
if (video) {
if ("mp4".equals(ext)) {
TLRPC.VideoSize videoSize = new TLRPC.TL_videoSize_layer127();
videoSize.location = location;
object = videoSize;
@ -686,7 +768,7 @@ public class StoryEntry extends IStoryPart {
object = photoSize;
}
return FileLoader.getInstance(account).getPathToAttach(object, video ? "mp4" : "jpg", true);
return FileLoader.getInstance(account).getPathToAttach(object, ext, true);
}
public static class HDRInfo {

View file

@ -13,9 +13,11 @@ import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
@ -35,6 +37,7 @@ import android.util.Log;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@ -64,6 +67,7 @@ import com.google.zxing.common.detector.MathUtils;
import org.checkerframework.checker.units.qual.A;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.BotWebViewVibrationEffect;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.DialogObject;
@ -212,7 +216,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
@Override
public void setContainerHeight(float value) {
super.setContainerHeight(value);
sectionCell.setTranslationY(getY() - (contentView == null ? 0 : contentView.getPaddingTop()) + containerHeight - 1);
sectionCell.setTranslationY(getY() - (contentView == null ? 0 : contentView.getPaddingTop()) + Math.min(dp(150), containerHeight) - 1);
if (contentView != null) {
contentView.invalidate();
}
@ -221,7 +225,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
@Override
public void setTranslationY(float translationY) {
super.setTranslationY(translationY);
sectionCell.setTranslationY(getY() - (contentView == null ? 0 : contentView.getPaddingTop()) + containerHeight - 1);
sectionCell.setTranslationY(getY() - (contentView == null ? 0 : contentView.getPaddingTop()) + Math.min(dp(150), containerHeight) - 1);
if (contentView != null) {
contentView.invalidate();
}
@ -239,87 +243,63 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
});
contentView = new FrameLayout(context) {
private final AnimatedFloat topGradientAlpha = new AnimatedFloat(this, 0, 200, CubicBezierInterpolator.DEFAULT);
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
{
paint.setShader(new LinearGradient(0, 0, 0, dp(12), new int[] { getThemedColor(Theme.key_dialogBackground), ColorUtils.setAlphaComponent(getThemedColor(Theme.key_dialogBackground), 0)}, new float[] { 0, 1 }, Shader.TileMode.CLAMP));
backgroundPaint.setColor(getThemedColor(Theme.key_dialogBackground));
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (child == searchField && listView != null && searchPosition >= 0) {
float gradientAlpha = topGradientAlpha.set(searchField.getTranslationY() < 0);
if (gradientAlpha > 0) {
boolean r = super.drawChild(canvas, child, drawingTime);
canvas.save();
canvas.translate(0, getPaddingTop());
paint.setAlpha((int) (0xFF * gradientAlpha));
canvas.drawRect(0, 0, getWidth(), dp(12), paint);
canvas.restore();
float t = child.getY() + child.getHeight() - 3, b = sectionCell.getY();
if (t < b) {
canvas.drawRect(0, t, getWidth(), b, backgroundPaint);
}
return r;
}
}
return super.drawChild(canvas, child, drawingTime);
}
};
contentView = new FrameLayout(context);
contentView.setPadding(0, AndroidUtilities.statusBarHeight + AndroidUtilities.dp(56), 0, 0);
contentView.setClipToPadding(true);
addView(contentView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL));
listView = new RecyclerListView(context, resourcesProvider) {
private long tapTime;
private float tapX, tapY;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
tapTime = System.currentTimeMillis();
tapX = ev.getX();
tapY = ev.getY();
} else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
if (MathUtils.distance(tapX, tapY, ev.getX(), ev.getY()) >= AndroidUtilities.touchSlop) {
tapTime = -1;
if (searchField.currentDeletingSpan != null) {
searchField.currentDeletingSpan.cancelDeleteAnimation();
searchField.currentDeletingSpan = null;
}
}
} else if (ev.getAction() == MotionEvent.ACTION_UP) {
if (MathUtils.distance(tapX, tapY, ev.getX(), ev.getY()) <= AndroidUtilities.touchSlop && System.currentTimeMillis() - tapTime <= ViewConfiguration.getTapTimeout() && searchField != null && searchField.spansContainer != null) {
float x = ev.getX(), y = contentView.getPaddingTop() + ev.getY();
x -= searchField.getX();
y -= searchField.getY();
if (x < 0 || y < 0 || x > searchField.getWidth() || y > searchField.getHeight()) {
return super.dispatchTouchEvent(ev);
}
for (int i = 0; i < searchField.spansContainer.getChildCount(); ++i) {
View child = searchField.spansContainer.getChildAt(i);
if (x < child.getX() || y < child.getY() || x >= child.getX() + child.getWidth() || y >= child.getY() + child.getHeight() || !(child instanceof GroupCreateSpan)) {
continue;
}
GroupCreateSpan span = (GroupCreateSpan) child;
onClick(span);
break;
}
tapTime = -1;
return true;
}
tapTime = -1;
} else if (ev.getAction() == MotionEvent.ACTION_CANCEL) {
tapTime = -1;
if (searchField.currentDeletingSpan != null) {
searchField.currentDeletingSpan.cancelDeleteAnimation();
searchField.currentDeletingSpan = null;
}
}
return super.dispatchTouchEvent(ev);
}
// private long tapTime;
// private float tapX, tapY;
// @Override
// public boolean dispatchTouchEvent(MotionEvent ev) {
// if (ev.getAction() == MotionEvent.ACTION_DOWN) {
// tapTime = System.currentTimeMillis();
// tapX = ev.getX();
// tapY = ev.getY();
// } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
// if (MathUtils.distance(tapX, tapY, ev.getX(), ev.getY()) >= AndroidUtilities.touchSlop) {
// tapTime = -1;
// if (searchField.currentDeletingSpan != null) {
// searchField.currentDeletingSpan.cancelDeleteAnimation();
// searchField.currentDeletingSpan = null;
// }
// }
// } else if (ev.getAction() == MotionEvent.ACTION_UP) {
// if (MathUtils.distance(tapX, tapY, ev.getX(), ev.getY()) <= AndroidUtilities.touchSlop && System.currentTimeMillis() - tapTime <= ViewConfiguration.getTapTimeout() && searchField != null && searchField.spansContainer != null) {
// float x = ev.getX(), y = contentView.getPaddingTop() + ev.getY();
// x -= searchField.getX();
// y -= searchField.getY();
// if (x < 0 || y < 0 || x > searchField.getWidth() || y > searchField.getHeight()) {
// return super.dispatchTouchEvent(ev);
// }
// for (int i = 0; i < searchField.spansContainer.getChildCount(); ++i) {
// View child = searchField.spansContainer.getChildAt(i);
// if (x < child.getX() || y < child.getY() || x >= child.getX() + child.getWidth() || y >= child.getY() + child.getHeight() || !(child instanceof GroupCreateSpan)) {
// continue;
// }
// GroupCreateSpan span = (GroupCreateSpan) child;
// onClick(span);
// break;
// }
// tapTime = -1;
// return true;
// }
// tapTime = -1;
// } else if (ev.getAction() == MotionEvent.ACTION_CANCEL) {
// tapTime = -1;
// if (searchField.currentDeletingSpan != null) {
// searchField.currentDeletingSpan.cancelDeleteAnimation();
// searchField.currentDeletingSpan = null;
// }
// }
// return super.dispatchTouchEvent(ev);
// }
//
// @Override
// public boolean onTouchEvent(MotionEvent e) {
// return super.onTouchEvent(e);
// }
};
listView.setClipToPadding(false);
listView.setTranslateSelector(true);
@ -386,7 +366,18 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
searchField.spansContainer.removeAllSpans(true);
} else if (item.chat != null) {
final long id = item.chat.id;
if (selectedUsersByGroup.containsKey(id)) {
if (getParticipantsCount(item.chat) > 200) {
// AndroidUtilities.shakeViewSpring(view, shiftDp = -shiftDp);
// BotWebViewVibrationEffect.APP_ERROR.vibrate();
try {
performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
} catch (Throwable ignore) {}
new AlertDialog.Builder(getContext(), resourcesProvider)
.setTitle(LocaleController.getString("GroupTooLarge", R.string.GroupTooLarge))
.setMessage(LocaleController.getString("GroupTooLargeMessage", R.string.GroupTooLargeMessage))
.setPositiveButton(LocaleController.getString("OK", R.string.OK), null)
.show();
} else if (selectedUsersByGroup.containsKey(id)) {
selectedUsersByGroup.remove(id);
updateSpans(true);
} else {
@ -394,7 +385,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(id);
if (chatFull != null && chatFull.participants != null && !chatFull.participants.participants.isEmpty()) {
selectChat(id, chatFull.participants);
} else if (chatFull == null) {
} else {
if (progressDialog != null) {
progressDialog.dismiss();
progressDialog = null;
@ -489,6 +480,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
updateButton(true);
updateCheckboxes(true);
searchField.scrollToBottom();
} else if (item.viewType == VIEW_TYPE_CHECK) {
if (!(view instanceof TextCell)) {
return;
@ -501,12 +493,12 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
boolean allowShare = selectedType == TYPE_EVERYONE;
if (allowScreenshots) {
BulletinFactory.of(container, resourcesProvider)
.createSimpleBulletin(R.raw.ic_save_to_gallery, LocaleController.getString(allowShare ? R.string.StoryEnabledScreenshotsShare : R.string.StoryEnabledScreenshots))
.createSimpleBulletin(R.raw.ic_save_to_gallery, LocaleController.getString(allowShare ? R.string.StoryEnabledScreenshotsShare : R.string.StoryEnabledScreenshots), 4)
.setDuration(5000)
.show(true);
} else {
BulletinFactory.of(container, resourcesProvider)
.createSimpleBulletin(R.raw.passcode_lock_close, LocaleController.getString(allowShare ? R.string.StoryDisabledScreenshotsShare : R.string.StoryDisabledScreenshots))
.createSimpleBulletin(R.raw.passcode_lock_close, LocaleController.getString(allowShare ? R.string.StoryDisabledScreenshotsShare : R.string.StoryDisabledScreenshots), 4)
.setDuration(5000)
.show(true);
}
@ -514,12 +506,12 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
keepOnMyPage = cell.isChecked();
if (keepOnMyPage) {
BulletinFactory.of(container, resourcesProvider)
.createSimpleBulletin(R.raw.msg_story_keep, LocaleController.getString(R.string.StoryEnableKeep))
.createSimpleBulletin(R.raw.msg_story_keep, LocaleController.getString(R.string.StoryEnableKeep), 4)
.setDuration(5000)
.show(true);
} else {
BulletinFactory.of(container, resourcesProvider)
.createSimpleBulletin(R.raw.fire_on, LocaleController.getString(R.string.StoryDisableKeep))
.createSimpleBulletin(R.raw.fire_on, LocaleController.getString(R.string.StoryDisableKeep), 4)
.setDuration(5000)
.show(true);
}
@ -671,20 +663,49 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
private void selectChat(long id, TLRPC.ChatParticipants participants) {
ArrayList<Long> groupUsers = new ArrayList<>();
ArrayList<Long> nonContactsUsers = new ArrayList<>();
final boolean mustBeContacts = pageType == PAGE_TYPE_CLOSE_FRIENDS || pageType == PAGE_TYPE_EXCLUDE_CONTACTS;
if (participants != null && participants.participants != null) {
for (int i = 0; i < participants.participants.size(); ++i) {
long userId = participants.participants.get(i).user_id;
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(userId);
if (user != null && !UserObject.isUserSelf(user) && !user.bot && user.id != 777000 && userId != 0) {
groupUsers.add(userId);
if (mustBeContacts && !user.contact) {
nonContactsUsers.add(userId);
} else {
groupUsers.add(userId);
}
selectedUsers.remove(userId);
}
}
}
selectedUsersByGroup.put(id, groupUsers);
updateSpans(true);
updateButton(true);
updateCheckboxes(true);
if (!nonContactsUsers.isEmpty()) {
if (groupUsers.isEmpty()) {
new AlertDialog.Builder(getContext(), resourcesProvider)
.setMessage("All group members are not in your contact list.")
.setNegativeButton("Cancel", null)
.show();
} else {
new AlertDialog.Builder(getContext(), resourcesProvider)
.setMessage(nonContactsUsers.size() + " members are not in your contact list")
.setPositiveButton("Add " + groupUsers.size() + " contacts", (di, a) -> {
selectedUsersByGroup.put(id, groupUsers);
updateSpans(true);
updateButton(true);
updateCheckboxes(true);
di.dismiss();
searchField.scrollToBottom();
})
.setNegativeButton("Cancel", null)
.show();
}
} else {
selectedUsersByGroup.put(id, groupUsers);
updateSpans(true);
updateButton(true);
updateCheckboxes(true);
searchField.scrollToBottom();
}
}
private void updateSpans(boolean animated) {
@ -726,7 +747,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
continue;
}
GroupCreateSpan span = new GroupCreateSpan(getContext(), obj, null, true, resourcesProvider);
// span.setOnClickListener(this);
span.setOnClickListener(this);
toAdd.add(span);
}
}
@ -883,6 +904,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
updateSpans(false);
searchField.setText("");
searchField.setVisibility(pageType == PAGE_TYPE_SHARE ? View.GONE : View.VISIBLE);
searchField.scrollToBottom();
query = null;
updateItems(false);
updateButton(false);
@ -1169,7 +1191,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
private float getSearchFieldTop() {
float top = -Math.max(0, searchField.resultContainerHeight - dp(150));
float top = -Math.max(0, Math.min(dp(150), searchField.resultContainerHeight) - dp(150));
for (int i = 0; i < listView.getChildCount(); ++i) {
View child = listView.getChildAt(i);
if (child.getTag() instanceof Integer && (int) child.getTag() == 34) {
@ -1453,7 +1475,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
contentView.setPadding(0, AndroidUtilities.statusBarHeight + AndroidUtilities.dp(56), 0, 0);
if (wasKeyboardVisible != keyboardVisible) {
float searchFieldTop = getSearchFieldTop();
if (keyboardVisible && searchFieldTop + searchField.resultContainerHeight > listView.getPaddingTop()) {
if (keyboardVisible && searchFieldTop + Math.min(dp(150), searchField.resultContainerHeight) > listView.getPaddingTop()) {
scrollToTopSmoothly();
}
if (pageType == PAGE_TYPE_SHARE) {
@ -1623,7 +1645,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height));
} else if (viewType == VIEW_TYPE_SEARCH) {
holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, searchField.resultContainerHeight));
holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, Math.min(dp(150), searchField.resultContainerHeight)));
} else if (viewType == VIEW_TYPE_HEADER2) {
((HeaderCell2) holder.itemView).setText(item.text, item.text2);
} else if (viewType == VIEW_TYPE_NO_USERS) {
@ -1640,7 +1662,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
cell.setText(item.text);
}
} else if (viewType == VIEW_TYPE_CHECK) {
((TextCell) holder.itemView).setTextAndCheck(item.text, item.resId == 0 ? allowScreenshots : keepOnMyPage, !divider);
((TextCell) holder.itemView).setTextAndCheck(item.text, item.resId == 0 ? allowScreenshots : keepOnMyPage, divider);
}
}
@ -2258,7 +2280,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
continue;
}
int participants_count = getParticipantsCount(chat);
if (participants_count > 1 && participants_count <= 20) {
if (participants_count > 1) {
contains.put(-chat.id, true);
users.add(chat);
}
@ -2398,6 +2420,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
subtitleTextView.setTextColor(Theme.getColor(isOnline[0] ? Theme.key_dialogTextBlue2 : Theme.key_dialogTextGray3, resourcesProvider));
checkBox.setVisibility(View.VISIBLE);
checkBox.setAlpha(1f);
radioButton.setVisibility(View.GONE);
}
@ -2405,7 +2428,10 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
avatarDrawable.setInfo(chat);
imageView.setForUserOrChat(chat, avatarDrawable);
titleTextView.setText(chat.title);
CharSequence text = chat.title;
text = Emoji.replaceEmoji(text, titleTextView.getPaint().getFontMetricsInt(), false);
titleTextView.setText(text);
isOnline[0] = false;
String subtitle;
if (ChatObject.isChannel(chat) && !chat.megagroup) {
@ -2435,6 +2461,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
subtitleTextView.setTextColor(Theme.getColor(isOnline[0] ? Theme.key_dialogTextBlue2 : Theme.key_dialogTextGray3, resourcesProvider));
checkBox.setVisibility(View.VISIBLE);
checkBox.setAlpha(participants_count > 200 ? .3f : 1f);
radioButton.setVisibility(View.GONE);
}
@ -2655,7 +2682,6 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
private Runnable updateHeight;
private boolean ignoreTextChange;
private Utilities.Callback<String> onSearchTextChange;
public SearchUsersCell(Context context, Theme.ResourcesProvider resourcesProvider, Runnable updateHeight) {
@ -2683,6 +2709,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (!AndroidUtilities.showKeyboard(this)) {
fullScroll(View.FOCUS_DOWN);
clearFocus();
requestFocus();
}
@ -2758,11 +2785,60 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
});
}
private final AnimatedFloat topGradientAlpha = new AnimatedFloat(this, 0, 300, CubicBezierInterpolator.EASE_OUT_QUINT);
private final LinearGradient topGradient = new LinearGradient(0, 0, 0, dp(8), new int[] { 0xff000000, 0x00000000 }, new float[] { 0, 1 }, Shader.TileMode.CLAMP);
private final Paint topGradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Matrix topGradientMatrix = new Matrix();
private final AnimatedFloat bottomGradientAlpha = new AnimatedFloat(this, 0, 300, CubicBezierInterpolator.EASE_OUT_QUINT);
private final LinearGradient bottomGradient = new LinearGradient(0, 0, 0, dp(8), new int[] { 0x00000000, 0xff000000 }, new float[] { 0, 1 }, Shader.TileMode.CLAMP);
private final Paint bottomGradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Matrix bottomGradientMatrix = new Matrix();
{
topGradientPaint.setShader(topGradient);
topGradientPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
bottomGradientPaint.setShader(bottomGradient);
bottomGradientPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
@Override
protected void dispatchDraw(Canvas canvas) {
final int y = getScrollY();
canvas.saveLayerAlpha(0, y, getWidth(), y + getHeight(), 0xFF, Canvas.ALL_SAVE_FLAG);
super.dispatchDraw(canvas);
canvas.save();
float alpha = topGradientAlpha.set(canScrollVertically(-1));
topGradientMatrix.reset();
topGradientMatrix.postTranslate(0, y);
topGradient.setLocalMatrix(topGradientMatrix);
topGradientPaint.setAlpha((int) (0xFF * alpha));
canvas.drawRect(0, y, getWidth(), y + dp(8), topGradientPaint);
alpha = bottomGradientAlpha.set(canScrollVertically(1));
bottomGradientMatrix.reset();
bottomGradientMatrix.postTranslate(0, y + getHeight() - dp(8));
bottomGradient.setLocalMatrix(bottomGradientMatrix);
bottomGradientPaint.setAlpha((int) (0xFF * alpha));
canvas.drawRect(0, y + getHeight() - dp(8), getWidth(), y + getHeight(), bottomGradientPaint);
canvas.restore();
canvas.restore();
}
@Override
public void requestChildFocus(View child, View focused) {
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!AndroidUtilities.findClickableView(this, ev.getX(), ev.getY())) {
return false;
}
// if (!AndroidUtilities.findClickableView(this, ev.getX(), ev.getY())) {
// return false;
// }
return super.dispatchTouchEvent(ev);
}
@ -2797,8 +2873,8 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY),
heightMeasureSpec
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(dp(150), MeasureSpec.AT_MOST)
);
}
@ -2815,10 +2891,17 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
return animator;
}
private boolean scroll;
public void scrollToBottom() {
scroll = true;
}
public class SpansContainer extends ViewGroup {
private AnimatorSet currentAnimation;
private boolean animationStarted;
private ArrayList<View> animAddingSpans = new ArrayList<>();
private ArrayList<View> animRemovingSpans = new ArrayList<>();
private ArrayList<Animator> animators = new ArrayList<>();
private View addingSpan;
private final ArrayList<View> removingSpans = new ArrayList<>();
@ -2933,6 +3016,10 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
editText.bringPointIntoView(editText.getSelectionStart());
}
}
if (scroll) {
fullScroll(View.FOCUS_DOWN);
scroll = false;
}
setMeasuredDimension(width, (int) containerHeight);
}
@ -2945,46 +3032,12 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
}
public void addSpan(final GroupCreateSpan span, boolean animated) {
allSpans.add(span);
if (currentAnimation != null && currentAnimation.isRunning()) {
currentAnimation.setupEndValues();
currentAnimation.cancel();
}
animationStarted = false;
if (animated) {
currentAnimation = new AnimatorSet();
currentAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animator) {
addingSpan = null;
currentAnimation = null;
animationStarted = false;
editText.setAllowDrawCursor(true);
if (updateHeight != null) {
updateHeight.run();
}
}
});
addingSpan = span;
animators.clear();
animators.add(ObjectAnimator.ofFloat(addingSpan, View.SCALE_X, 0.01f, 1.0f));
animators.add(ObjectAnimator.ofFloat(addingSpan, View.SCALE_Y, 0.01f, 1.0f));
animators.add(ObjectAnimator.ofFloat(addingSpan, View.ALPHA, 0.0f, 1.0f));
}
addView(span);
}
public void removeSpan(final GroupCreateSpan span) {
ignoreScrollEvent = true;
allSpans.remove(span);
span.setOnClickListener(null);
if (currentAnimation != null) {
currentAnimation.setupEndValues();
currentAnimation.cancel();
}
setupEndValues();
animationStarted = false;
currentAnimation = new AnimatorSet();
currentAnimation.addListener(new AnimatorListenerAdapter() {
@ -3002,6 +3055,9 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
});
removingSpans.clear();
removingSpans.add(span);
animAddingSpans.clear();
animRemovingSpans.clear();
animAddingSpans.add(span);
animators.clear();
animators.add(ObjectAnimator.ofFloat(span, View.SCALE_X, 1.0f, 0.01f));
animators.add(ObjectAnimator.ofFloat(span, View.SCALE_Y, 1.0f, 0.01f));
@ -3022,10 +3078,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
toDelete.get(i).setOnClickListener(null);
}
if (currentAnimation != null) {
currentAnimation.setupEndValues();
currentAnimation.cancel();
}
setupEndValues();
if (animated) {
animationStarted = false;
currentAnimation = new AnimatorSet();
@ -3046,14 +3099,18 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
});
animators.clear();
animAddingSpans.clear();
animRemovingSpans.clear();
for (int i = 0; i < toDelete.size(); ++i) {
GroupCreateSpan span = toDelete.get(i);
animRemovingSpans.add(span);
animators.add(ObjectAnimator.ofFloat(span, View.SCALE_X, 1.0f, 0.01f));
animators.add(ObjectAnimator.ofFloat(span, View.SCALE_Y, 1.0f, 0.01f));
animators.add(ObjectAnimator.ofFloat(span, View.ALPHA, 1.0f, 0.0f));
}
for (int i = 0; i < toAdd.size(); ++i) {
GroupCreateSpan addingSpan = toAdd.get(i);
animAddingSpans.add(addingSpan);
animators.add(ObjectAnimator.ofFloat(addingSpan, View.SCALE_X, 0.01f, 1.0f));
animators.add(ObjectAnimator.ofFloat(addingSpan, View.SCALE_Y, 0.01f, 1.0f));
animators.add(ObjectAnimator.ofFloat(addingSpan, View.ALPHA, 0.0f, 1.0f));
@ -3086,10 +3143,7 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
spans.get(i).setOnClickListener(null);
}
if (currentAnimation != null) {
currentAnimation.setupEndValues();
currentAnimation.cancel();
}
setupEndValues();
if (animated) {
animationStarted = false;
currentAnimation = new AnimatorSet();
@ -3109,8 +3163,11 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
});
animators.clear();
animAddingSpans.clear();
animRemovingSpans.clear();
for (int i = 0; i < spans.size(); ++i) {
GroupCreateSpan span = spans.get(i);
animAddingSpans.add(span);
animators.add(ObjectAnimator.ofFloat(span, View.SCALE_X, 1.0f, 0.01f));
animators.add(ObjectAnimator.ofFloat(span, View.SCALE_Y, 1.0f, 0.01f));
animators.add(ObjectAnimator.ofFloat(span, View.ALPHA, 1.0f, 0.0f));
@ -3126,6 +3183,24 @@ public class StoryPrivacyBottomSheet extends BottomSheet implements Notification
}
requestLayout();
}
private void setupEndValues() {
if (currentAnimation != null) {
currentAnimation.cancel();
}
for (int i = 0; i < animAddingSpans.size(); ++i) {
animAddingSpans.get(i).setScaleX(1f);
animAddingSpans.get(i).setScaleY(1f);
animAddingSpans.get(i).setAlpha(1f);
}
for (int i = 0; i < animRemovingSpans.size(); ++i) {
animRemovingSpans.get(i).setScaleX(0f);
animRemovingSpans.get(i).setScaleY(0f);
animRemovingSpans.get(i).setAlpha(0f);
}
animAddingSpans.clear();
animRemovingSpans.clear();
}
}
}

View file

@ -1627,9 +1627,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
titleTextView.setRightPadding(AndroidUtilities.dp(96));
actionBarContainer.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 56, Gravity.TOP | Gravity.FILL_HORIZONTAL, 71, 0, 0, 0));
downloadButton = new DownloadButton(context, () -> {
applyFilter();
downloadButton = new DownloadButton(context, done -> {
applyPaint(true);
applyFilter(done);
}, currentAccount, windowView, resourcesProvider);
actionBarContainer.addView(downloadButton, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.RIGHT));
@ -1766,7 +1766,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
navbarContainer.addView(modeSwitcherView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL));
hintTextView = new HintTextView(context);
navbarContainer.addView(hintTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 8, 0, 8, 8));
navbarContainer.addView(hintTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.CENTER, 8, 0, 8, 8));
previewButtons = new PreviewButtons(context);
previewButtons.setVisibility(View.GONE);
@ -1788,6 +1788,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
}
if (outputEntry.isEdit) {
outputEntry.editedPrivacy = false;
applyFilter(null);
upload(true);
} else {
previewView.updatePauseReason(3, true);
@ -1805,9 +1806,6 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
return;
}
previewView.updatePauseReason(5, true);
if (whenDone != null) {
whenDone.run();
}
outputEntry.privacy = privacy;
StoryPrivacySelector.save(currentAccount, outputEntry.privacy);
outputEntry.pinned = keepInProfile;
@ -1815,7 +1813,10 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
outputEntry.privacyRules.clear();
outputEntry.privacyRules.addAll(privacy.rules);
outputEntry.editedPrivacy = true;
upload(true);
applyFilter(() -> {
whenDone.run();
upload(true);
});
}, false);
privacySheet.setOnDismissListener(di -> {
previewView.updatePauseReason(3, false);
@ -1910,7 +1911,6 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
}
private void upload(boolean asStory) {
applyFilter();
applyPaint(true);
if (outputEntry == null) {
close(true);
@ -2188,26 +2188,35 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
}
outputFile = StoryEntry.makeCacheFile(currentAccount, true);
CameraController.getInstance().recordVideo(cameraView.getCameraSession(), outputFile, false, (thumbPath, duration) -> {
if (recordControl != null) {
recordControl.stopRecordingLoading(true);
}
if (outputFile == null || cameraView == null) {
return;
}
takingVideo = false;
stoppingTakingVideo = false;
animateRecording(false, true);
if (duration <= 800) {
animateRecording(false, true);
setAwakeLock(false);
videoTimerView.setRecording(false, true);
if (recordControl != null) {
recordControl.stopRecordingLoading(true);
}
try {
outputFile.delete();
outputFile = null;
} catch (Exception e) {
FileLog.e(e);
}
try {
new File(thumbPath).delete();
} catch (Exception e) {
FileLog.e(e);
if (thumbPath != null) {
try {
new File(thumbPath).delete();
} catch (Exception e) {
FileLog.e(e);
}
}
return;
}
@ -2223,17 +2232,19 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
outputEntry.height = height;
outputEntry.setupMatrix();
}
navigateToPreviewWithPlayerAwait(() -> navigateTo(PAGE_PREVIEW, true), 0);
navigateToPreviewWithPlayerAwait(() -> {
navigateTo(PAGE_PREVIEW, true);
}, 0);
}, () /* onVideoStart */ -> {
whenStarted.run();
hintTextView.setText(byLongPress ? LocaleController.getString("StoryHintSwipeToZoom", R.string.StoryHintSwipeToZoom) : LocaleController.getString("StoryHintPinchToZoom", R.string.StoryHintPinchToZoom), false);
animateRecording(true, true);
setAwakeLock(true);
videoTimerView.setRecording(true, true);
showVideoTimer(true, true);
}, cameraView);
}, cameraView, false);
if (!isVideo) {
isVideo = true;
@ -2267,8 +2278,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
AndroidUtilities.runOnUIThread(() -> {
if (takingVideo && stoppingTakingVideo && cameraView != null) {
showZoomControls(false, true);
animateRecording(false, true);
CameraController.getInstance().stopVideoRecording(cameraView.getCameraSessionRecording(), false);
// animateRecording(false, true);
// setAwakeLock(false);
CameraController.getInstance().stopVideoRecording(cameraView.getCameraSessionRecording(), false, false);
}
}, byDuration ? 0 : 400);
}
@ -2311,6 +2323,19 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
}
};
private void setAwakeLock(boolean lock) {
if (lock) {
windowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
} else {
windowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
}
try {
windowManager.updateViewLayout(windowView, windowLayoutParams);
} catch (Exception e) {
FileLog.e(e);
}
}
private AnimatorSet recordingAnimator;
private boolean animatedRecording;
private void animateRecording(boolean recording, boolean animated) {
@ -2343,18 +2368,20 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
recordingAnimator = new AnimatorSet();
recordingAnimator.playTogether(
ObjectAnimator.ofFloat(backButton, View.ALPHA, recording ? 0 : 1),
ObjectAnimator.ofFloat(flashButton, View.ALPHA, recording ? 0 : 1),
ObjectAnimator.ofFloat(dualButton, View.ALPHA, recording || cameraView == null || !cameraView.dualAvailable() ? 0 : 1),
ObjectAnimator.ofFloat(hintTextView, View.ALPHA, recording ? 1 : 0),
ObjectAnimator.ofFloat(hintTextView, View.TRANSLATION_Y, recording ? 0 : dp(16)),
ObjectAnimator.ofFloat(modeSwitcherView, View.ALPHA, recording ? 0 : 1),
ObjectAnimator.ofFloat(modeSwitcherView, View.TRANSLATION_Y, recording ? dp(16) : 0)
ObjectAnimator.ofFloat(flashButton, View.ALPHA, recording || currentPage != PAGE_CAMERA ? 0 : 1),
ObjectAnimator.ofFloat(dualButton, View.ALPHA, recording || currentPage != PAGE_CAMERA || cameraView == null || !cameraView.dualAvailable() ? 0 : 1),
ObjectAnimator.ofFloat(hintTextView, View.ALPHA, recording && currentPage == PAGE_CAMERA ? 1 : 0),
ObjectAnimator.ofFloat(hintTextView, View.TRANSLATION_Y, recording || currentPage != PAGE_CAMERA ? 0 : dp(16)),
ObjectAnimator.ofFloat(modeSwitcherView, View.ALPHA, recording || currentPage != PAGE_CAMERA ? 0 : 1),
ObjectAnimator.ofFloat(modeSwitcherView, View.TRANSLATION_Y, recording || currentPage != PAGE_CAMERA ? dp(16) : 0)
);
recordingAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (recording) {
backButton.setVisibility(View.GONE);
}
if (recording || currentPage != PAGE_CAMERA) {
flashButton.setVisibility(View.GONE);
}
}
@ -2365,14 +2392,14 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
} else {
backButton.setAlpha(recording ? 0 : 1f);
backButton.setVisibility(recording ? View.GONE : View.VISIBLE);
flashButton.setAlpha(recording ? 0 : 1f);
flashButton.setVisibility(recording ? View.GONE : View.VISIBLE);
dualButton.setAlpha(recording ? 0 : 1f);
dualButton.setVisibility(recording || cameraView == null || !cameraView.dualAvailable() ? View.GONE : View.VISIBLE);
hintTextView.setAlpha(recording ? 1f : 0);
hintTextView.setTranslationY(recording ? 0 : dp(16));
modeSwitcherView.setAlpha(recording ? 0 : 1f);
modeSwitcherView.setTranslationY(recording ? dp(16) : 0);
flashButton.setAlpha(recording || currentPage != PAGE_CAMERA ? 0 : 1f);
flashButton.setVisibility(recording || currentPage != PAGE_CAMERA ? View.GONE : View.VISIBLE);
dualButton.setAlpha(recording || currentPage != PAGE_CAMERA ? 0 : 1f);
dualButton.setVisibility(recording || currentPage != PAGE_CAMERA || cameraView == null || !cameraView.dualAvailable() ? View.GONE : View.VISIBLE);
hintTextView.setAlpha(recording && currentPage == PAGE_CAMERA ? 1f : 0);
hintTextView.setTranslationY(recording || currentPage != PAGE_CAMERA ? 0 : dp(16));
modeSwitcherView.setAlpha(recording || currentPage != PAGE_CAMERA ? 0 : 1f);
modeSwitcherView.setTranslationY(recording || currentPage != PAGE_CAMERA ? dp(16) : 0);
}
}
@ -2537,6 +2564,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
animators.add(ObjectAnimator.ofFloat(recordControl, View.TRANSLATION_Y, page == PAGE_CAMERA ? 0 : dp(24)));
animators.add(ObjectAnimator.ofFloat(modeSwitcherView, View.ALPHA, page == PAGE_CAMERA ? 1 : 0));
animators.add(ObjectAnimator.ofFloat(modeSwitcherView, View.TRANSLATION_Y, page == PAGE_CAMERA ? 0 : dp(24)));
backButton.setVisibility(View.VISIBLE);
animators.add(ObjectAnimator.ofFloat(backButton, View.ALPHA, 1));
animators.add(ObjectAnimator.ofFloat(hintTextView, View.ALPHA, page == PAGE_CAMERA && animatedRecording ? 1 : 0));
animators.add(ObjectAnimator.ofFloat(captionContainer, View.ALPHA, page == PAGE_PREVIEW ? 1f : 0));
animators.add(ObjectAnimator.ofFloat(captionContainer, View.TRANSLATION_Y, page == PAGE_PREVIEW ? 0 : dp(12)));
animators.add(ObjectAnimator.ofFloat(titleTextView, View.ALPHA, page == PAGE_PREVIEW ? 1f : 0));
@ -2572,6 +2602,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
recordControl.setTranslationY(page == PAGE_CAMERA ? 0 : dp(16));
modeSwitcherView.setAlpha(page == PAGE_CAMERA ? 1f : 0);
modeSwitcherView.setTranslationY(page == PAGE_CAMERA ? 0 : dp(16));
backButton.setVisibility(View.VISIBLE);
backButton.setAlpha(1f);
hintTextView.setAlpha(page == PAGE_CAMERA && animatedRecording ? 1f : 0);
captionContainer.setAlpha(page == PAGE_PREVIEW ? 1f : 0);
captionContainer.setTranslationY(page == PAGE_PREVIEW ? 0 : dp(12));
muteButton.setAlpha(page == PAGE_PREVIEW && isVideo ? 1f : 0);
@ -2886,6 +2919,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
if (toPage == PAGE_CAMERA) {
requestCameraPermission(false);
recordControl.setVisibility(View.VISIBLE);
if (recordControl != null) {
recordControl.stopRecordingLoading(false);
}
modeSwitcherView.setVisibility(View.VISIBLE);
zoomControlView.setVisibility(View.VISIBLE);
zoomControlView.setAlpha(0);
@ -2994,6 +3030,8 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
zoomControlView.setVisibility(View.GONE);
modeSwitcherView.setVisibility(View.GONE);
dualButton.setVisibility(View.GONE);
animateRecording(false, false);
setAwakeLock(false);
}
cameraViewThumb.setClickable(toPage == PAGE_CAMERA);
if (fromPage == PAGE_PREVIEW) {
@ -3397,7 +3435,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
// privacySelectorHint.hide();
Bulletin.hideVisible();
if (photoFilterView != null && toMode == EDIT_MODE_FILTER) {
applyFilter();
applyFilter(null);
}
if (photoFilterEnhanceView != null) {
photoFilterEnhanceView.setAllowTouch(false);
@ -3459,14 +3497,16 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
outputEntry.paintFile = FileLoader.getInstance(currentAccount).getPathToAttach(size, true);
}
private void applyFilter() {
private void applyFilter(Runnable whenDone) {
if (photoFilterView == null || outputEntry == null) {
if (whenDone != null) {
whenDone.run();
}
return;
}
outputEntry.editedMedia |= photoFilterView.hasChanges();
outputEntry.updateFilter(photoFilterView);
outputEntry.filterState = photoFilterView.getSavedFilterState();
if (!outputEntry.isVideo) {
outputEntry.updateFilter(photoFilterView, whenDone);
if (whenDone == null && !outputEntry.isVideo && previewView != null) {
previewView.set(outputEntry);
}
}
@ -3474,16 +3514,14 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
// private Matrix photoFilterStartMatrix, photoFilterEndMatrix;
private void createFilterPhotoView() {
if (photoFilterView != null) {
if (photoFilterView != null || outputEntry == null) {
return;
}
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(outputEntry.file.getPath(), opts);
StoryEntry.setupScale(opts, outputEntry.resultWidth, outputEntry.resultHeight);
opts.inJustDecodeBounds = false;
Bitmap photoBitmap = photoFilterBitmap = BitmapFactory.decodeFile(outputEntry.file.getPath(), opts);
Bitmap photoBitmap = previewView.getPhotoBitmap();
if (photoBitmap == null) {
return;
}
photoFilterView = new PhotoFilterView(activity, previewView.getTextureView(), photoBitmap, previewView.getOrientation(), outputEntry == null ? null : outputEntry.filterState, null, 0, false, false, resourcesProvider);
containerView.addView(photoFilterView);
@ -3491,6 +3529,9 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
photoFilterEnhanceView.setFilterView(photoFilterView);
}
photoFilterViewTextureView = photoFilterView.getMyTextureView();
if (photoFilterViewTextureView != null) {
photoFilterViewTextureView.setOpaque(false);
}
previewView.setFilterTextureView(photoFilterViewTextureView);
if (photoFilterViewTextureView != null) {
photoFilterViewTextureView.setAlpha(0f);
@ -3508,7 +3549,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
orderPreviewViews();
photoFilterView.getDoneTextView().setOnClickListener(v -> {
applyFilter();
applyFilter(null);
switchToEditMode(EDIT_MODE_NONE, true);
});
photoFilterView.getCancelTextView().setOnClickListener(v -> {
@ -3782,7 +3823,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg
return;
}
showSavedDraftHint = !outputEntry.isDraft;
applyFilter();
applyFilter(null);
applyPaint(false);
destroyPhotoFilterView();
StoryEntry storyEntry = outputEntry;

View file

@ -15,20 +15,46 @@ uniform float blur;
float modI(float a,float b) {
return floor(a-floor((a+0.5)/b)*b+0.5);
}
bool eq(float a, float b) {
return abs(a - b) < .1;
}
bool eq(float a, float b, float b2) {
return abs(a - b) < .1 || abs(a - b2) < .1;
}
float box(vec2 position, vec2 halfSize, float cornerRadius) {
position = abs(position) - halfSize + cornerRadius;
return length(max(position, 0.0)) + min(max(position.x, position.y), 0.0) - cornerRadius;
}
float star(in vec2 p, in float r) {
const vec2 acs = vec2(.9659258, .258819);
const vec2 ecs = vec2(.8090169, .5877852);
float bn = mod(atan(p.x,p.y),.52359876)-.26179938;
p = length(p)*vec2(cos(bn),abs(sin(bn))) - r*acs;
p += ecs*clamp( -dot(p,ecs), 0.0, r*acs.y/ecs.y);
return length(p)*sign(p.x);
}
float opSmoothUnion(float d1, float d2, float k) {
float h = max(k-abs(d1-d2),0.0);
return min(d1, d2) - h*h*0.25/k;
}
float scene() {
vec2 p = (uv - vec2(.5)) * vec2(1., pixelWH.x / pixelWH.y);
vec2 r = .5 * vec2(1., pixelWH.x / pixelWH.y) * scale;
float R = min(r.x, r.y), rr = roundRadius / pixelWH.y;
float a = modI(shapeFrom, 3.), b = modI(shapeTo, 3.);
return box(
p,
mix(abs(a-2.)<.1 ? r : vec2(R), abs(b-2.)<.1 ? r : vec2(R), shapeT),
mix(abs(a)<.1 ? R : rr, abs(b)<.1 ? R : rr, shapeT)
float boxSDF = box(
p,
mix(eq(a, 2.) ? r : vec2(R), eq(b, 2.) ? r : vec2(R), shapeT),
mix(eq(a, 0., 3.) ? R : rr, eq(b, 0., 3.) ? R : rr, shapeT)
) * pixelWH.x;
if (eq(3., a, b)) {
float starSDF = opSmoothUnion(box(p, vec2(R * .78), R), star(p, R * .78), .25) * pixelWH.x;
float starA = eq(a, 3.) ? 1. - shapeT : 0.;
float starB = eq(b, 3.) ? shapeT : 0.;
return mix(boxSDF, starSDF, starA + starB);
} else {
return boxSDF;
}
}
vec4 makeblur() {
vec2 S = 4. * vec2(1., pixelWH.x / pixelWH.y);

View file

@ -7003,4 +7003,6 @@
<string name="StoriesPremiumHint">Posting stories is currently available only to subscribers of **Telegram Premium**.</string>
<string name="ArchivePeerStories">Hide Stories</string>
<string name="UnarchiveStories">Unhide Stories</string>
<string name="GroupTooLarge">Group Too Large</string>
<string name="GroupTooLargeMessage">You can select groups that are up to 200 members.</string>
</resources>

View file

@ -13,8 +13,8 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Sat Mar 12 05:53:50 MSK 2016
APP_VERSION_CODE=3705
APP_VERSION_NAME=9.7.2
APP_VERSION_CODE=3712
APP_VERSION_NAME=9.7.4
APP_PACKAGE=org.telegram.messenger
RELEASE_KEY_PASSWORD=android
RELEASE_KEY_ALIAS=androidkey