From 6c1e8c1cf754aa59b3106244878d423d919aede8 Mon Sep 17 00:00:00 2001 From: xaxtix Date: Thu, 27 Jul 2023 12:42:23 +0400 Subject: [PATCH] update to 9.7.4 (3712) --- .../exoplayer2/mediacodec/MediaCodecUtil.java | 6 - .../telegram/messenger/AndroidUtilities.java | 16 + .../org/telegram/messenger/BuildVars.java | 4 +- .../telegram/messenger/FileLoadOperation.java | 16 +- .../org/telegram/messenger/FileLoader.java | 9 +- .../telegram/messenger/FilePathDatabase.java | 1 + .../telegram/messenger/MediaController.java | 21 + .../org/telegram/messenger/MessageObject.java | 18 + .../telegram/messenger/MessagesStorage.java | 2 +- .../messenger/NotificationsController.java | 2 +- .../messenger/camera/CameraController.java | 75 ++-- .../telegram/messenger/camera/CameraView.java | 24 +- .../messenger/video/TextureRenderer.java | 1 + .../telegram/ui/ActionBar/AlertDialog.java | 2 +- .../org/telegram/ui/CalendarActivity.java | 6 +- .../telegram/ui/Cells/ChatMessageCell.java | 9 +- .../ui/Cells/SharedPhotoVideoCell2.java | 31 +- .../java/org/telegram/ui/ChatActivity.java | 26 ++ .../ui/Components/AnimatedTextView.java | 1 + .../org/telegram/ui/Components/Bulletin.java | 5 + .../Components/CubicBezierInterpolator.java | 4 +- .../ui/Components/InstantCameraView.java | 21 +- .../ui/Components/JoinGroupAlert.java | 3 + .../Paint/Views/LPhotoPaintView.java | 9 +- .../ui/Components/Paint/Views/PhotoView.java | 3 +- .../Premium/PremiumFeatureBottomSheet.java | 16 +- .../ui/Components/PullForegroundDrawable.java | 116 ++++-- .../ui/Components/RecyclerListView.java | 2 +- .../ui/Components/SharedMediaLayout.java | 63 ++- .../org/telegram/ui/ContactsActivity.java | 2 +- .../java/org/telegram/ui/DialogsActivity.java | 6 +- .../NotificationsCustomSettingsActivity.java | 7 +- .../java/org/telegram/ui/ProfileActivity.java | 4 +- .../ui/Stories/DialogStoriesCell.java | 11 +- .../telegram/ui/Stories/PeerStoriesView.java | 229 +++++++---- .../ui/Stories/StoriesController.java | 42 +- .../ui/Stories/StoriesListPlaceProvider.java | 47 ++- .../telegram/ui/Stories/StoriesUtilities.java | 71 +--- .../telegram/ui/Stories/StoriesViewPager.java | 62 ++- .../ui/Stories/StoryPositionView.java | 4 + .../ui/Stories/StoryPrivacyButton.java | 4 +- .../org/telegram/ui/Stories/StoryViewer.java | 147 ++++--- .../telegram/ui/Stories/UserListPoller.java | 3 + .../ui/Stories/recorder/DownloadButton.java | 52 ++- .../ui/Stories/recorder/DualCameraView.java | 55 ++- .../ui/Stories/recorder/GalleryListView.java | 58 +-- .../ui/Stories/recorder/HintView2.java | 18 +- .../ui/Stories/recorder/PreviewView.java | 136 +++++-- .../ui/Stories/recorder/RecordControl.java | 87 ++++- .../ui/Stories/recorder/StoryEntry.java | 142 +++++-- .../recorder/StoryPrivacyBottomSheet.java | 365 +++++++++++------- .../ui/Stories/recorder/StoryRecorder.java | 133 ++++--- .../src/main/res/raw/camera_frag.glsl | 34 +- TMessagesProj/src/main/res/values/strings.xml | 2 + gradle.properties | 4 +- 55 files changed, 1534 insertions(+), 703 deletions(-) diff --git a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java index d3a03a52c..16583004f 100644 --- a/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java +++ b/TMessagesProj/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java @@ -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 immutableDecoderInfos = ImmutableList.copyOf(decoderInfos); decoderInfosCache.put(key, immutableDecoderInfos); return immutableDecoderInfos; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index f5f4fc775..5c23d442f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -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; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 5ef4036db..5bd738ddf 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -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"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 058f9c73f..5a1313860 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -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(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index a03b4eb20..53ee7e570 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -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) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java b/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java index d78b1766d..c09f367f1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java @@ -470,6 +470,7 @@ public class FilePathDatabase { synchronized (this) { if (dispatchQueue == null) { dispatchQueue = new DispatchQueue("files_database_queue_" + currentAccount); + dispatchQueue.setPriority(Thread.MAX_PRIORITY); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 32f64383f..260962ed3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -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 { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 32f8f18d5..2f9a44f17 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -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; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index dc76ec6f9..10a3cbf26 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -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); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index 99c71bc3f..f9714e3ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -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); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java index 8ef743501..b8f0d2c9a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java @@ -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; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java index b584e60e5..b73af1351 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java @@ -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); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/TextureRenderer.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/TextureRenderer.java index 5ab788362..224baaac4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/TextureRenderer.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/TextureRenderer.java @@ -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(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java index a4781fa06..a393aef40 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -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); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java index 0ed31ca81..67a723b50 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java @@ -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(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java index 40d949bf5..c33877c6f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -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; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java index 1549dd0b6..b9337b333 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java @@ -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)) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index e95577fb7..163b4728f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -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; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java index be24eda58..0046ce03f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java @@ -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; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java index 65f50330c..b67a0533b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -1844,4 +1844,9 @@ public class Bulletin { } } } + + public Bulletin setTag(int tag) { + this.tag = tag; + return this; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CubicBezierInterpolator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CubicBezierInterpolator.java index 2a40a7a2b..e29b0a2c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CubicBezierInterpolator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CubicBezierInterpolator.java @@ -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(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java index 97782f1fc..61377e4dd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -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 { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java index 312982f80..b4c174275 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java @@ -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); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java index e00b7fad3..a4af78ac1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java @@ -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 -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java index 256a1db69..255cee5ab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/PhotoView.java @@ -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(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java index 1e4769c03..be6e31978 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java @@ -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(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PullForegroundDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PullForegroundDrawable.java index 17aaf3211..05346031b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PullForegroundDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PullForegroundDrawable.java @@ -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) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java index dcc316cf8..0a1d27176 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java @@ -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; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java index f852764b9..b6f0d6e23 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -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(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index 1c3cb5f49..c5feee6e8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -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))) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index f202cb469..2215cedcd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -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())) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java index 87ba2f146..d7b32bbf1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java @@ -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); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index d9bfd134d..6b1bfacb4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -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; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java index 9afa2d84f..a02920bbc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java @@ -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 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) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java index 2168f3c24..93e4859ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java @@ -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 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 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 dayGroup = storyViewer.storiesList.getStoryDayGroup(messageObject); - if (dayGroup == null) { - linesPosition = selectedPosition; - linesCount = count; - return; - } - int i = 0; - Iterator 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 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 documents, ArrayList uries); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java index a65624a18..ae830706e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java @@ -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 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 storiesLists; + private final HashMap[] 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> getDays() { + final ArrayList keys = new ArrayList<>(groupedByDay.keySet()); + Collections.sort(keys, (a, b) -> (int) (b - a)); + final ArrayList> days = new ArrayList<>(); + for (Long key : keys) { + TreeSet 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; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java index 59924c88e..9b8be57e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java @@ -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; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java index 7d8535daf..07550cdb9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java @@ -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; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java index fb6dcc79d..8a197f7e6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java @@ -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> days; + int currentAccount = UserConfig.selectedAccount; PagerAdapter pagerAdapter; ArrayList 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 cachedViews = new ArrayList<>(); + private final ArrayList 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> 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 day; + boolean isVisible; + public PageLayout(@NonNull Context context) { super(context); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPositionView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPositionView.java index 39b686d56..8c058ddbc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPositionView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPositionView.java @@ -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); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPrivacyButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPrivacyButton.java index 792f94b24..e401c71fd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPrivacyButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPrivacyButton.java @@ -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; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java index 7ba5538dc..6d39b01d2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java @@ -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 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 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 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 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 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> 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 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 diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/UserListPoller.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/UserListPoller.java index 2b5c1f3e0..8dbac0efa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/UserListPoller.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/UserListPoller.java @@ -58,6 +58,9 @@ public class UserListPoller { ArrayList 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; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java index 3c42a5dfa..93048f72d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DownloadButton.java @@ -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 prepare; private PreparingVideoToast toast; - public DownloadButton(Context context, Runnable prepare, int currentAccount, FrameLayout container, Theme.ResourcesProvider resourcesProvider) { + public DownloadButton(Context context, Utilities.Callback 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); }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DualCameraView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DualCameraView.java index 4283b1486..ed79e7031 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DualCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DualCameraView.java @@ -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])); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java index 728d86589..a9533642a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/GalleryListView.java @@ -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); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java index 9580f0d58..d9b85e336 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintView2.java @@ -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) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PreviewView.java index 26a5227fd..7f9f08ff9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PreviewView.java @@ -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) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/RecordControl.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/RecordControl.java index 330bd5556..2026ff82c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/RecordControl.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/RecordControl.java @@ -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(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java index 8e2544946..7ec1912d0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java @@ -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 { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryPrivacyBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryPrivacyBottomSheet.java index b39b37a7f..18d1a99b2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryPrivacyBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryPrivacyBottomSheet.java @@ -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 groupUsers = new ArrayList<>(); + ArrayList 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 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 animAddingSpans = new ArrayList<>(); + private ArrayList animRemovingSpans = new ArrayList<>(); private ArrayList animators = new ArrayList<>(); private View addingSpan; private final ArrayList 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(); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java index a7b390131..dc85e775b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java @@ -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; diff --git a/TMessagesProj/src/main/res/raw/camera_frag.glsl b/TMessagesProj/src/main/res/raw/camera_frag.glsl index 7cca4725e..08ef4b1ca 100644 --- a/TMessagesProj/src/main/res/raw/camera_frag.glsl +++ b/TMessagesProj/src/main/res/raw/camera_frag.glsl @@ -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); diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index f8fb4486e..1c7d94f12 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -7003,4 +7003,6 @@ Posting stories is currently available only to subscribers of **Telegram Premium**. Hide Stories Unhide Stories + Group Too Large + You can select groups that are up to 200 members. diff --git a/gradle.properties b/gradle.properties index 71be4947c..c9cef59e7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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