diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 6a0a860ea0..0acf076748 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -3,12 +3,12 @@ import cn.hutool.core.util.RuntimeUtil apply plugin: "com.android.application" apply plugin: "kotlin-android" -def verName = "10.0.1" -def verCode = 1134 +def verName = "10.0.3" +def verCode = 1135 -def officialVer = "10.0.1" -def officialCode = 3793 +def officialVer = "10.0.3" +def officialCode = 3801 def serviceAccountCredentialsFile = rootProject.file("service_account_credentials.json") diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp index e11deac875..42edf148ea 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -1307,11 +1307,11 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag request->startTime = 0; request->startTimeMillis = 0; request->minStartTime = (int32_t) (getCurrentTimeMonotonicMillis() / 1000 + 2); - } else if (error->error_code == 420) { + } else if (error->error_code == 420 && (request->requestFlags & RequestFlagIgnoreFloodWait) == 0 && error->error_message.find("STORY_SEND_FLOOD") == std::string::npos) { int32_t waitTime = 2; static std::string floodWait = "FLOOD_WAIT_"; static std::string slowmodeWait = "SLOWMODE_WAIT_"; - discardResponse = (request->requestFlags & RequestFlagIgnoreFloodWait) == 0; + discardResponse = true; if (error->error_message.find(floodWait) != std::string::npos) { std::string num = error->error_message.substr(floodWait.size(), error->error_message.size() - floodWait.size()); waitTime = atoi(num.c_str()); @@ -3058,7 +3058,9 @@ void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround, bool if (!workaround && updatingDcSettingsAgain && updatingDcSettingsAgainDcNum == dcNum) { updatingDcSettingsAgain = false; for (auto & datacenter : datacenters) { - datacenter.second->resetInitVersion(); + if (datacenter.first == dcNum) { + datacenter.second->resetInitVersion(); + } } updateDcSettings(updatingDcSettingsAgainDcNum, false, false); return; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index 97b04c646b..bf07b63023 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -724,6 +724,9 @@ public static void normalizeTimePart(StringBuilder stringBuilder, long time) { public static void getViewPositionInParent(View view, ViewGroup parent, float[] pointPosition) { pointPosition[0] = 0; pointPosition[1] = 0; + if (view == null || parent == null) { + return; + } View currentView = view; while (currentView != parent) { //fix strange offset inside view pager @@ -759,6 +762,22 @@ public static void getBitmapFromSurface(SurfaceView surfaceView, Bitmap surfaceB } } + @RequiresApi(api = Build.VERSION_CODES.N) + public static void getBitmapFromSurface(Surface surface, Bitmap surfaceBitmap) { + if (surface == null || !surface.isValid()) { + return; + } + CountDownLatch countDownLatch = new CountDownLatch(1); + PixelCopy.request(surface, surfaceBitmap, copyResult -> { + countDownLatch.countDown(); + }, Utilities.searchQueue.getHandler()); + try { + countDownLatch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + public static float[] getCoordinateInParent(ViewGroup parentView, View view) { float x = 0, y = 0; View child = view; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java index 885a008a50..9011aff2f0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java @@ -1333,6 +1333,13 @@ public static int migrate(MessagesStorage messagesStorage, int version) throws E version = 128; } + if (version == 128) { + database.executeFast("ALTER TABLE story_drafts ADD COLUMN type INTEGER default 0").stepThis().dispose(); + + database.executeFast("PRAGMA user_version = 129").stepThis().dispose(); + version = 129; + } + return version; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java index c261e9c581..3d5322a417 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java @@ -95,7 +95,7 @@ public static class Preset { public int maxVideoBitrate; public Preset(int[] m, long p, long v, long f, boolean pv, boolean pm, boolean e, boolean l, int bitrate, boolean preloadStories) { - System.arraycopy(m, 0, mask, 0, mask.length); + System.arraycopy(m, 0, mask, 0, Math.max(m.length, mask.length)); sizes[PRESET_SIZE_NUM_PHOTO] = p; sizes[PRESET_SIZE_NUM_VIDEO] = v; sizes[PRESET_SIZE_NUM_DOCUMENT] = f; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index d44e0b7e59..dd3391301c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -76,9 +76,18 @@ public int getPositionInQueue() { public boolean checkPrefixPreloadFinished() { if (preloadPrefixSize > 0 && downloadedBytes > preloadPrefixSize) { long minStart = Long.MAX_VALUE; - for (int b = 0; b < notLoadedBytesRanges.size(); b++) { - Range range = notLoadedBytesRanges.get(b); - minStart = Math.min(minStart, range.start); + ArrayList array = notLoadedBytesRanges; + if (array == null) { + return true; + } + try { + for (int b = 0; b < array.size(); b++) { + Range range = array.get(b); + minStart = Math.min(minStart, range.start); + } + } catch (Throwable e) { + FileLog.e(e); + return true; } if (minStart > preloadPrefixSize) { return true; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 3939d9b461..fd7eb7883b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -320,6 +320,9 @@ public boolean isLoadingVideoAny(TLRPC.Document document) { } public void cancelFileUpload(final String location, final boolean enc) { + if (location == null) { + return; + } fileLoaderQueue.postRunnable(() -> { FileUploadOperation operation; if (!enc) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java index f62f59fd2d..b99a1a45af 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java @@ -24,6 +24,8 @@ import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; @@ -226,4 +228,29 @@ public static void setPriorityForDocument(TLRPC.Document document, int priority) priorityMap.put(document.id, priority); } } + + @Nullable + public static Uri prepareUri(int currentAccount, TLRPC.Document document, Object parent) { + String attachFileName = FileLoader.getAttachFileName(document); + File file = FileLoader.getInstance(currentAccount).getPathToAttach(document); + + if (file != null && file.exists()) { + return Uri.fromFile(file); + } + try { + String params = "?account=" + currentAccount + + "&id=" + document.id + + "&hash=" + document.access_hash + + "&dc=" + document.dc_id + + "&size=" + document.size + + "&mime=" + URLEncoder.encode(document.mime_type, "UTF-8") + + "&rid=" + FileLoader.getInstance(currentAccount).getFileReference(parent) + + "&name=" + URLEncoder.encode(FileLoader.getDocumentFileName(document), "UTF-8") + + "&reference=" + Utilities.bytesToHex(document.file_reference != null ? document.file_reference : new byte[0]); + return Uri.parse("tg://" + attachFileName + params); + } catch (UnsupportedEncodingException e) { + FileLog.e(e); + } + return null; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 661fdc1284..7cc97d90b4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -2255,7 +2255,7 @@ public boolean hasImageLoaded() { } public boolean hasNotThumb() { - return currentImageDrawable != null || currentMediaDrawable != null || staticThumbDrawable instanceof VectorAvatarThumbDrawable; + return currentImageDrawable != null || currentMediaDrawable != null || staticThumbDrawable instanceof VectorAvatarThumbDrawable || (staticThumbDrawable != null && currentImageKey == null && currentMediaKey == null); } public boolean hasStaticThumb() { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index da8849977c..dcaa89215a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -155,7 +155,7 @@ public class MessagesController extends BaseController implements NotificationCe public StoriesController storiesController; private boolean hasArchivedChats; private boolean hasStories; - public long storiesChangelogUserId; + public long storiesChangelogUserId = 777000; public static TLRPC.Peer getPeerFromInputPeer(TLRPC.InputPeer peer) { if (peer.chat_id != 0) { @@ -412,10 +412,9 @@ protected void setLocal(int currentAccount, Integer arguments, TLRPC.TL_help_app try { SQLiteDatabase database = MessagesStorage.getInstance(currentAccount).getDatabase(); if (database != null) { - if (data == null) { - database.executeFast("DELETE FROM app_config").stepThis().dispose(); - } else { - SQLitePreparedStatement state = database.executeFast("REPLACE INTO app_config VALUES(?)"); + database.executeFast("DELETE FROM app_config").stepThis().dispose(); + if (data != null) { + SQLitePreparedStatement state = database.executeFast("INSERT INTO app_config VALUES(?)"); state.requery(); NativeByteBuffer buffer = new NativeByteBuffer(data.getObjectSize()); data.serializeToStream(buffer); @@ -16509,7 +16508,7 @@ public boolean processUpdateArray(ArrayList updates, ArrayList Instance = new SparseArray(); private static final Object lockObject = new Object(); - public final static int LAST_DB_VERSION = 128; + public final static int LAST_DB_VERSION = 129; private boolean databaseMigrationInProgress; public boolean showClearDatabaseAlert; private LongSparseIntArray dialogIsForum = new LongSparseIntArray(); @@ -679,7 +679,7 @@ public static void createTables(SQLiteDatabase database) throws SQLiteException database.executeFast("CREATE TABLE profile_stories (dialog_id INTEGER, story_id INTEGER, data BLOB, PRIMARY KEY(dialog_id, story_id));").stepThis().dispose(); database.executeFast("CREATE TABLE archived_stories (story_id INTEGER PRIMARY KEY, data BLOB);").stepThis().dispose(); - database.executeFast("CREATE TABLE story_drafts (id INTEGER PRIMARY KEY, date INTEGER, data BLOB);").stepThis().dispose(); + database.executeFast("CREATE TABLE story_drafts (id INTEGER PRIMARY KEY, date INTEGER, data BLOB, type INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE story_pushes (uid INTEGER, sid INTEGER, date INTEGER, localName TEXT, flags INTEGER, expire_date INTEGER, PRIMARY KEY(uid, sid));").stepThis().dispose(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java index e6d82ac1b1..3fcd8fdf71 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java @@ -73,12 +73,9 @@ public static void sendRegistrationToServer(@PushType int pushType, String token req.events.add(event); sendStat = false; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (error != null) { - SharedConfig.pushStatSent = true; - SharedConfig.saveConfig(); - } - })); + SharedConfig.pushStatSent = true; + SharedConfig.saveConfig(); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, null); } AndroidUtilities.runOnUIThread(() -> MessagesController.getInstance(currentAccount).registerForPush(pushType, token)); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index d499608d91..57bfbf0ddf 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -4738,11 +4738,15 @@ public void sendMessage(SendMessageParams sendMessageParams) { reqSend.reply_to = SendMessagesHelper.creteReplyInput(replyToTopMsg.getId()); reqSend.flags |= 512; } + if (newMsg.from_id != null) { reqSend.send_as = getMessagesController().getInputPeer(newMsg.from_id); } reqSend.hide_via = !params.containsKey("bot"); - if (newMsg.reply_to != null && newMsg.reply_to.reply_to_msg_id != 0) { + if (replyToStoryItem != null) { + reqSend.reply_to = creteReplyInput(replyToStoryItem); + reqSend.flags |= 1; + } else if (newMsg.reply_to != null && newMsg.reply_to.reply_to_msg_id != 0) { reqSend.flags |= 1; reqSend.reply_to = SendMessagesHelper.creteReplyInput(newMsg.reply_to.reply_to_msg_id); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index 68d8157815..7920657908 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -1614,7 +1614,22 @@ public static boolean isAppUpdateAvailable() { } public static boolean setNewAppVersionAvailable(TLRPC.TL_help_appUpdate update) { - if (update == null) { + String updateVersionString = null; + int versionCode = 0; + try { + PackageInfo packageInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); + versionCode = packageInfo.versionCode; + updateVersionString = packageInfo.versionName; + } catch (Exception e) { + FileLog.e(e); + } + if (versionCode == 0) { + versionCode = BuildVars.BUILD_VERSION; + } + if (updateVersionString == null) { + updateVersionString = BuildVars.BUILD_VERSION_STRING; + } + if (update == null || update.version == null || versionBiggerOrEqual(updateVersionString, update.version)) { pendingAppUpdate = null; pendingAppUpdateBuildVersion = 0; saveConfig(); @@ -1626,6 +1641,22 @@ public static boolean setNewAppVersionAvailable(TLRPC.TL_help_appUpdate update) return true; } + // returns a >= b + private static boolean versionBiggerOrEqual(String a, String b) { + String[] partsA = a.split("\\."); + String[] partsB = b.split("\\."); + for (int i = 0; i < Math.min(partsA.length, partsB.length); ++i) { + int numA = Integer.parseInt(partsA[i]); + int numB = Integer.parseInt(partsB[i]); + if (numA < numB) { + return false; + } else if (numA > numB) { + return true; + } + } + return true; + } + public static boolean checkPasscode(String passcode) { if (passcodeSalt.length == 0) { boolean result = Utilities.MD5(passcode).equals(passcodeHash); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index ae8d07116e..8aea32280d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -281,6 +281,7 @@ private void checkPremiumSelf(TLRPC.User oldUser, TLRPC.User newUser) { getMediaDataController().loadPremiumPromo(false); getMediaDataController().loadReactions(false, true); + getMessagesController().getStoriesController().invalidateStoryLimit(); }); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java index 2bff56b50a..cec8e3a6c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java @@ -349,7 +349,6 @@ private boolean convertVideoInternal(String videoPath, File cacheFile, long lastFramePts = -1; if (videoIndex >= 0) { - try { long videoTime = -1; boolean outputDone = false; @@ -444,27 +443,22 @@ private boolean convertVideoInternal(String videoPath, File cacheFile, outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate); outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); -// boolean hasHDR = false; -// int hdrType = 0; -// int colorTransfer = 0, colorStandard = 0, colorRange = 0; -// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { -// if (videoFormat.containsKey(MediaFormat.KEY_COLOR_TRANSFER)) { -// colorTransfer = videoFormat.getInteger(MediaFormat.KEY_COLOR_TRANSFER); -// } -// if (videoFormat.containsKey(MediaFormat.KEY_COLOR_STANDARD)) { -// colorStandard = videoFormat.getInteger(MediaFormat.KEY_COLOR_STANDARD); -// } -// if (videoFormat.containsKey(MediaFormat.KEY_COLOR_RANGE)) { -// colorRange = videoFormat.getInteger(MediaFormat.KEY_COLOR_RANGE); -// } -// if (videoFormat.containsKey(MediaFormat.KEY_HDR_STATIC_INFO)) { -// ByteBuffer bytes = videoFormat.getByteBuffer(MediaFormat.KEY_HDR_STATIC_INFO); -// } -// if ((colorTransfer == MediaFormat.COLOR_TRANSFER_ST2084 || colorTransfer == MediaFormat.COLOR_TRANSFER_HLG) && colorStandard == MediaFormat.COLOR_STANDARD_BT2020) { -// hasHDR = true; -// hdrType = colorTransfer == MediaFormat.COLOR_TRANSFER_HLG ? 1 : 2; -// } -// } + boolean hasHDR = false; + int colorTransfer = 0, colorStandard = 0, colorRange = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (videoFormat.containsKey(MediaFormat.KEY_COLOR_TRANSFER)) { + colorTransfer = videoFormat.getInteger(MediaFormat.KEY_COLOR_TRANSFER); + } + if (videoFormat.containsKey(MediaFormat.KEY_COLOR_STANDARD)) { + colorStandard = videoFormat.getInteger(MediaFormat.KEY_COLOR_STANDARD); + } + if (videoFormat.containsKey(MediaFormat.KEY_COLOR_RANGE)) { + colorRange = videoFormat.getInteger(MediaFormat.KEY_COLOR_RANGE); + } + if ((colorTransfer == MediaFormat.COLOR_TRANSFER_ST2084 || colorTransfer == MediaFormat.COLOR_TRANSFER_HLG) && colorStandard == MediaFormat.COLOR_STANDARD_BT2020) { + hasHDR = true; + } + } if (Build.VERSION.SDK_INT < 23 && Math.min(h, w) <= 480 && !isAvatar) { if (bitrate > 921600) { @@ -482,6 +476,15 @@ private boolean convertVideoInternal(String videoPath, File cacheFile, encoder.start(); outputSurface = new OutputSurface(savedFilterState, null, paintPath, mediaEntities, cropState, resultWidth, resultHeight, originalWidth, originalHeight, rotationValue, framerate, false, gradientTopColor, gradientBottomColor, hdrInfo, parts); + if (hdrInfo == null && outputSurface.supportsEXTYUV() && hasHDR) { + hdrInfo = new StoryEntry.HDRInfo(); + hdrInfo.colorTransfer = colorTransfer; + hdrInfo.colorStandard = colorStandard; + hdrInfo.colorRange = colorRange; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + outputFormat.setInteger(MediaFormat.KEY_COLOR_TRANSFER, MediaFormat.COLOR_TRANSFER_SDR_VIDEO); + } + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && hdrInfo != null && hdrInfo.getHDRType() != 0 && outputSurface.supportsEXTYUV()) { outputSurface.changeFragmentShader( hdrFragmentShader(originalWidth, originalHeight, resultWidth, resultHeight, true, hdrInfo), @@ -1164,6 +1167,7 @@ private static String hdrFragmentShader( } shaderCode = shaderCode.replace("$dstWidth", dstWidth + ".0"); shaderCode = shaderCode.replace("$dstHeight", dstHeight + ".0"); + // TODO(@dkaraush): use minlum/maxlum return shaderCode + "\n" + "in vec2 vTextureCoord;\n" + "out vec4 fragColor;\n" + diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java new file mode 100644 index 0000000000..5e30a3317a --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java @@ -0,0 +1,426 @@ +package org.telegram.messenger.video; + +import android.graphics.Bitmap; +import android.graphics.Paint; +import android.graphics.SurfaceTexture; +import android.net.Uri; +import android.os.Build; +import android.view.SurfaceView; +import android.view.TextureView; + +import com.google.android.exoplayer2.ExoPlayer; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DispatchQueue; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.FileStreamLoadOperation; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.Components.VideoPlayer; + +//used for player in background thread +public class VideoPlayerHolderBase { + + public boolean paused; + public TLRPC.Document document; + VideoPlayer videoPlayer; + Runnable initRunnable; + volatile boolean released; + public boolean firstFrameRendered; + + public float progress; + int lastState; + public long currentPosition; + private int currentAccount; + long playerDuration; + boolean audioDisabled; + public boolean stubAvailable; + + private TextureView textureView; + private SurfaceView surfaceView; + public Bitmap playerStubBitmap; + public Paint playerStubPaint; + public long pendingSeekTo; + Uri contentUri; + + public VideoPlayerHolderBase() { + + } + + public VideoPlayerHolderBase with(SurfaceView surfaceView) { + this.surfaceView = surfaceView; + this.textureView = null; + return this; + } + + public VideoPlayerHolderBase with(TextureView textureView) { + this.surfaceView = null; + this.textureView = textureView; + return this; + } + + + final DispatchQueue dispatchQueue = Utilities.getOrCreatePlayerQueue(); + public Uri uri; + + Runnable progressRunnable = new Runnable() { + @Override + public void run() { + if (videoPlayer != null) { + if (lastState == ExoPlayer.STATE_ENDED) { + progress = 1f; + } else { + currentPosition = videoPlayer.getCurrentPosition(); + playerDuration = videoPlayer.getDuration(); + } + if (lastState == ExoPlayer.STATE_READY) { + dispatchQueue.cancelRunnable(progressRunnable); + dispatchQueue.postRunnable(progressRunnable, 16); + } + } + } + }; + + long startTime; + + public void preparePlayer(Uri uri, boolean audioDisabled) { + this.audioDisabled = audioDisabled; + this.currentAccount = currentAccount; + this.contentUri = uri; + paused = true; + if (initRunnable != null) { + dispatchQueue.cancelRunnable(initRunnable); + } + dispatchQueue.postRunnable(initRunnable = () -> { + if (released) { + return; + } + ensurePlayerCreated(audioDisabled); + videoPlayer.preparePlayer(uri, "other", FileLoader.PRIORITY_LOW); + videoPlayer.setPlayWhenReady(false); + videoPlayer.setWorkerQueue(dispatchQueue); + }); + } + + public void start(boolean paused, Uri uri, long t, boolean audioDisabled) { + startTime = System.currentTimeMillis(); + this.audioDisabled = audioDisabled; + this.paused = paused; + dispatchQueue.postRunnable(initRunnable = () -> { + if (released) { + return; + } + if (videoPlayer == null) { + ensurePlayerCreated(audioDisabled); + videoPlayer.preparePlayer(uri, "other"); + videoPlayer.setWorkerQueue(dispatchQueue); + if (!paused) { + if (surfaceView != null) { + videoPlayer.setSurfaceView(surfaceView); + } else { + videoPlayer.setTextureView(textureView); + } + videoPlayer.setPlayWhenReady(true); + } + } else { + if (!paused) { + if (surfaceView != null) { + videoPlayer.setSurfaceView(surfaceView); + } else { + videoPlayer.setTextureView(textureView); + } + videoPlayer.play(); + } + } + if (t > 0) { + videoPlayer.seekTo(t); + } + + // videoPlayer.setVolume(isInSilentMode ? 0 : 1f); + AndroidUtilities.runOnUIThread(() -> initRunnable = null); + }); + } + + private void ensurePlayerCreated(boolean audioDisabled) { + if (videoPlayer != null) { + videoPlayer.releasePlayer(true); + } + videoPlayer = new VideoPlayer(false, audioDisabled); + videoPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() { + @Override + public void onStateChanged(boolean playWhenReady, int playbackState) { + lastState = playbackState; + if (playbackState == ExoPlayer.STATE_READY || playbackState == ExoPlayer.STATE_BUFFERING) { + dispatchQueue.cancelRunnable(progressRunnable); + dispatchQueue.postRunnable(progressRunnable); + } else if (playbackState == ExoPlayer.STATE_ENDED) { + if (needRepeat()) { + progress = 0; + videoPlayer.seekTo(0); + videoPlayer.play(); + } else { + progress = 1f; + } + } + VideoPlayerHolderBase.this.onStateChanged(playWhenReady, playbackState); + } + + @Override + public void onError(VideoPlayer player, Exception e) { + FileLog.e(e); + } + + @Override + public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { + + } + + @Override + public void onRenderedFirstFrame() { + AndroidUtilities.runOnUIThread(() -> { + if (released ) { + return; + } + VideoPlayerHolderBase.this.onRenderedFirstFrame(); + + if (onReadyListener != null) { + onReadyListener.run(); + onReadyListener = null; + } + }, 16); + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { + + } + + @Override + public boolean onSurfaceDestroyed(SurfaceTexture surfaceTexture) { + return false; + } + }); + videoPlayer.setIsStory(); + } + + + private Runnable onReadyListener; + public void setOnReadyListener(Runnable listener) { + onReadyListener = listener; + } + + public boolean release(Runnable whenReleased) { + TLRPC.Document document = this.document; + if (document != null) { + int priority = FileStreamLoadOperation.getStreamPrioriy(document); + if (priority != FileLoader.PRIORITY_LOW) { + FileStreamLoadOperation.setPriorityForDocument(document, FileLoader.PRIORITY_LOW); + FileLoader.getInstance(currentAccount).changePriority(FileLoader.PRIORITY_LOW, document, null, null, null, null, null); + } + } + released = true; + dispatchQueue.cancelRunnable(initRunnable); + initRunnable = null; + dispatchQueue.postRunnable(() -> { + if (videoPlayer != null) { + videoPlayer.setTextureView(null); + videoPlayer.setSurfaceView(null); + videoPlayer.releasePlayer(false); + } + if (document != null) { + FileLoader.getInstance(currentAccount).cancelLoadFile(document); + } + if (whenReleased != null) { + AndroidUtilities.runOnUIThread(whenReleased); + } + videoPlayer = null; + }); + if (playerStubBitmap != null) { + AndroidUtilities.recycleBitmap(playerStubBitmap); + playerStubBitmap = null; + } + return true; + } + + public void pause() { + if (released) { + return; + } + if (paused) { + return; + } + paused = true; + if (surfaceView != null && firstFrameRendered && surfaceView.getHolder().getSurface().isValid()) { + stubAvailable = true; + if (playerStubBitmap == null) { + playerStubBitmap = Bitmap.createBitmap(720, 1280, Bitmap.Config.ARGB_8888); + playerStubPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + AndroidUtilities.getBitmapFromSurface(surfaceView, playerStubBitmap); + } + } + dispatchQueue.postRunnable(() -> { + if (videoPlayer != null) { + videoPlayer.pause(); + } + }); + } + + public void play() { + if (released) { + return; + } + if (!paused) { + return; + } + paused = false; + dispatchQueue.postRunnable(() -> { + if (videoPlayer != null) { + if (surfaceView != null) { + videoPlayer.setSurfaceView(surfaceView); + } else { + videoPlayer.setTextureView(textureView); + } + if (pendingSeekTo > 0) { + videoPlayer.seekTo(pendingSeekTo); + pendingSeekTo = 0; + } + videoPlayer.setPlayWhenReady(true); + } + }); + } + + public void setAudioEnabled(boolean enabled, boolean prepared) { + boolean disabled = !enabled; + if (audioDisabled == disabled) { + return; + } + audioDisabled = disabled; + dispatchQueue.postRunnable(() -> { + if (videoPlayer == null) { + return; + } + boolean playing = videoPlayer.isPlaying(); + if (enabled && !videoPlayer.createdWithAudioTrack()) { + //release and create new with audio track + videoPlayer.pause(); + long position = videoPlayer.getCurrentPosition(); + videoPlayer.releasePlayer(false); + videoPlayer = null; + ensurePlayerCreated(audioDisabled); + videoPlayer.preparePlayer(uri, "other"); + videoPlayer.setWorkerQueue(dispatchQueue); + if (!prepared) { + if (surfaceView != null) { + videoPlayer.setSurfaceView(surfaceView); + } else { + videoPlayer.setTextureView(textureView); + } + } + // videoPlayer.setTextureView(textureView); + videoPlayer.seekTo(position + 50); + if (playing && !prepared) { + videoPlayer.setPlayWhenReady(true); + videoPlayer.play(); + } else { + videoPlayer.setPlayWhenReady(false); + videoPlayer.pause(); + } + } else { + videoPlayer.setVolume(enabled ? 1f : 0); + } + }); + } + + public float getPlaybackProgress(long totalDuration) { + if (lastState == ExoPlayer.STATE_ENDED) { + progress = 1f; + } else { + float localProgress; + if (totalDuration != 0) { + localProgress = currentPosition / (float) totalDuration; + } else { + localProgress = currentPosition / (float) playerDuration; + } + if (localProgress < progress) { + return progress; + } + progress = localProgress; + } + return progress; + } + + public void loopBack() { + progress = 0; + lastState = ExoPlayer.STATE_IDLE; + dispatchQueue.postRunnable(() -> { + if (videoPlayer != null) { + videoPlayer.seekTo(0); + } + progress = 0; + currentPosition = 0; + }); + } + + public void setVolume(float v) { + dispatchQueue.postRunnable(() -> { + if (videoPlayer != null) { + videoPlayer.setVolume(v); + } + }); + } + + public boolean isBuffering() { + return !released && lastState == ExoPlayer.STATE_BUFFERING; + } + + public long getCurrentPosition() { + return currentPosition; + } + + public long getDuration() { + return playerDuration; + } + + public boolean isPlaying() { + return !paused; + } + + public void onRenderedFirstFrame() { + + } + + public void onStateChanged(boolean playWhenReady, int playbackState) { + + } + + public boolean needRepeat() { + return false; + } + + public void seekTo(long position) { + dispatchQueue.postRunnable(() -> { + if (videoPlayer == null) { + pendingSeekTo = position; + return; + } + videoPlayer.seekTo(position); + }); + } + + public Uri getCurrentUri() { + return contentUri; + } + + public void setPlaybackSpeed(float currentVideoSpeed) { + dispatchQueue.postRunnable(() -> { + if (videoPlayer == null) { + return; + } + videoPlayer.setPlaybackSpeed(currentVideoSpeed); + }); + + } +} 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 ed299f7a02..f95a6c0d4a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -56,6 +56,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLog; +import org.telegram.messenger.LiteMode; import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; @@ -271,10 +272,10 @@ public AlertDialog(Context context, int progressStyle, Theme.ResourcesProvider r super(context, R.style.TransparentDialog); this.resourcesProvider = resourcesProvider; - blurredNativeBackground = supportsNativeBlur() && progressViewStyle == ALERT_TYPE_MESSAGE; backgroundColor = getThemedColor(Theme.key_dialogBackground); final boolean isDark = AndroidUtilities.computePerceivedBrightness(backgroundColor) < 0.721f; - blurredBackground = blurredNativeBackground || !supportsNativeBlur() && SharedConfig.getDevicePerformanceClass() >= SharedConfig.PERFORMANCE_CLASS_HIGH && isDark; + blurredNativeBackground = supportsNativeBlur() && progressViewStyle == ALERT_TYPE_MESSAGE; + blurredBackground = (blurredNativeBackground || !supportsNativeBlur() && SharedConfig.getDevicePerformanceClass() >= SharedConfig.PERFORMANCE_CLASS_HIGH && LiteMode.isEnabled(LiteMode.FLAG_CHAT_BLUR)) && isDark; backgroundPaddings = new Rect(); if (progressStyle != ALERT_TYPE_SPINNER || blurredBackground) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java index aa2f89f452..19fdccd9c2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java @@ -65,6 +65,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; @@ -989,8 +990,12 @@ private void layoutOverflowPanelItems(List menuItems) { }); } final int size = menuItems.size(); + final boolean premiumLocked = MessagesController.getInstance(UserConfig.selectedAccount).premiumLocked; for (int i = 0; i < size; i++) { - overflowPanelAdapter.add(menuItems.get(i)); + final MenuItem menuItem = menuItems.get(i); + if (!premiumOptions.contains(menuItem.getItemId()) || !premiumLocked) { + overflowPanelAdapter.add(menuItem); + } } mOverflowPanel.setAdapter(overflowPanelAdapter); if (mOpenOverflowUpwards) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java index 09a213995c..bff0779416 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -1074,7 +1074,7 @@ private PatternsLoader(ArrayList accents) { for (int a = 0, N = accents.size(); a < N; a++) { ThemeAccent accent = accents.get(a); File wallpaper = accent.getPathToWallpaper(); - if (wallpaper != null && wallpaper.exists()) { + if (wallpaper != null && wallpaper.length() > 0) { accents.remove(a); a--; N--; @@ -9712,7 +9712,9 @@ public static BackgroundDrawableSettings createBackgroundDrawable( int gradientToColor2 = currentColors.get(key_chat_wallpaper_gradient_to2); int gradientToColor1 = currentColors.get(key_chat_wallpaper_gradient_to1); + boolean bitmapCreated = false; if (wallpaperFile != null && wallpaperFile.exists()) { + bitmapCreated = true; try { if (backgroundColor != 0 && gradientToColor1 != 0 && gradientToColor2 != 0) { MotionBackgroundDrawable motionBackgroundDrawable = new MotionBackgroundDrawable(backgroundColor, gradientToColor1, gradientToColor2, gradientToColor3, false); @@ -9724,6 +9726,9 @@ public static BackgroundDrawableSettings createBackgroundDrawable( patternBitmap = patternBitmap.copy(Bitmap.Config.ALPHA_8, false); toRecycle.recycle(); } + if (patternBitmap == null) { + bitmapCreated = false; + } motionBackgroundDrawable.setPatternBitmap(intensity, patternBitmap); motionBackgroundDrawable.setPatternColorFilter(motionBackgroundDrawable.getPatternColor()); settings.wallpaper = motionBackgroundDrawable; @@ -9736,6 +9741,9 @@ public static BackgroundDrawableSettings createBackgroundDrawable( } catch (Throwable e) { FileLog.e(e); } + } + if (bitmapCreated) { + } else if (backgroundColor != 0) { int rotation = currentColors.get(key_chat_wallpaper_gradient_rotation, -1); if (rotation == -1) { @@ -9752,7 +9760,9 @@ public static BackgroundDrawableSettings createBackgroundDrawable( FileOutputStream stream = null; try { stream = new FileOutputStream(wallpaperFile); - patternBitmap.compress(Bitmap.CompressFormat.PNG, 90, stream); + Bitmap bitmap = patternBitmap.copy(Bitmap.Config.ARGB_8888, true); + bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream); + bitmap.recycle(); stream.close(); } catch (Exception e) { FileLog.e(e); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java index d718af337d..c45120211f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java @@ -492,15 +492,13 @@ public void updateList(RecyclerListView recyclerListView, boolean hasHiddenArchi } else { tabsTranslation = 0; } - if (hasHiddenArchive && position == 0 && recyclerListView.getPaddingTop() - view.getTop() - view.getMeasuredHeight() + tabsTranslation < 0) { - position = 1; - offset = tabsTranslation; + if (recyclerListView.getScrollState() != RecyclerView.SCROLL_STATE_DRAGGING) { + if (hasHiddenArchive && position == 0 && recyclerListView.getPaddingTop() - view.getTop() - view.getMeasuredHeight() + tabsTranslation < 0) { + position = 1; + offset = tabsTranslation; + } + layoutManager.scrollToPositionWithOffset(position, (int) offset); } -// if (firstUpdate && hasStories) { -// offset -= AndroidUtilities.dp(DialogStoriesCell.HEIGHT_IN_DP); -// } -// firstUpdate = false; - layoutManager.scrollToPositionWithOffset(position, (int) offset); } } DiffUtil.calculateDiff(new DiffUtil.Callback() { @@ -1110,7 +1108,7 @@ public void openHiddenStories() { } } - parentFragment.getOrCreateStoryViewer().open(mContext, null, peerIds, 0, null, null, StoriesListPlaceProvider.of(recyclerListView), false); + parentFragment.getOrCreateStoryViewer().open(mContext, null, peerIds, 0, null, null, StoriesListPlaceProvider.of(recyclerListView, true), false); } public void setIsTransitionSupport() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index 3972d2a274..b63e2bd849 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -27,6 +27,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.database.DataSetObserver; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -65,6 +66,7 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.SoundEffectConstants; +import android.view.Surface; import android.view.TextureView; import android.view.VelocityTracker; import android.view.View; @@ -112,6 +114,7 @@ import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; +import org.telegram.messenger.FileStreamLoadOperation; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; @@ -127,6 +130,7 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.WebFile; import org.telegram.messenger.browser.Browser; +import org.telegram.messenger.video.VideoPlayerHolderBase; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; @@ -172,6 +176,7 @@ import org.telegram.ui.Components.TextPaintWebpageUrlSpan; import org.telegram.ui.Components.TranslateAlert2; import org.telegram.ui.Components.TypefaceSpan; +import org.telegram.ui.Components.VideoPlayer; import org.telegram.ui.Components.WebPlayerView; import java.io.File; @@ -843,6 +848,11 @@ protected void onAttachedToWindow() { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); attachedToWindow = false; + if (videoPlayer != null) { + videoPlayer.release(null); + videoPlayer = null; + } + currentPlayer = null; } @Override @@ -3083,6 +3093,7 @@ public void setParentActivity(Activity activity, BaseFragment fragment) { windowView.setClipChildren(true); windowView.setFocusable(false); containerView = new FrameLayout(activity) { + @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (windowView.movingPage) { @@ -3148,7 +3159,8 @@ public void invalidate() { windowView.addView(fullscreenVideoContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); fullscreenAspectRatioView = new AspectRatioFrameLayout(activity); - fullscreenAspectRatioView.setVisibility(View.GONE); + fullscreenAspectRatioView.setVisibility(View.VISIBLE); + fullscreenAspectRatioView.setBackgroundColor(Color.BLACK); fullscreenVideoContainer.addView(fullscreenAspectRatioView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); fullscreenTextureView = new TextureView(activity); @@ -3210,6 +3222,12 @@ public void setTranslationX(float translationX) { setCurrentHeaderHeight((int) (windowView.startMovingHeaderHeight + (AndroidUtilities.dp(56) - windowView.startMovingHeaderHeight) * progress)); } } + + @Override + protected void dispatchDraw(Canvas canvas) { + checkVideoPlayer(); + super.dispatchDraw(canvas); + } }; ((DefaultItemAnimator) listView[i].getItemAnimator()).setDelayAnimations(false); listView[i].setLayoutManager(layoutManager[i] = new LinearLayoutManager(parentActivity, LinearLayoutManager.VERTICAL, false)); @@ -3327,6 +3345,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) { if (recyclerView.getChildCount() == 0) { return; } + recyclerView.invalidate(); textSelectionHelper.onParentScrolled(); headerView.invalidate(); checkScroll(dy); @@ -3792,13 +3811,10 @@ public void onTextCopied() { }); containerView.addView(textSelectionHelper.getOverlayView(activity)); - pinchToZoomHelper = new PinchToZoomHelper(containerView, windowView); - pinchToZoomHelper.setClipBoundsListener(new PinchToZoomHelper.ClipBoundsListener() { - @Override - public void getClipTopBottom(float[] topBottom) { - topBottom[0] = currentHeaderHeight; - topBottom[1] = listView[0].getMeasuredHeight(); - } + pinchToZoomHelper = new PinchToZoomHelper(containerView, containerView); + pinchToZoomHelper.setClipBoundsListener(topBottom -> { + topBottom[0] = currentHeaderHeight; + topBottom[1] = listView[0].getMeasuredHeight(); }); pinchToZoomHelper.setCallback(new PinchToZoomHelper.Callback() { @Override @@ -3811,6 +3827,43 @@ public void onZoomStarted(MessageObject messageObject) { updatePaintColors(); } + VideoPlayerHolderBase videoPlayer; + BlockVideoCell currentPlayer; + + private void checkVideoPlayer() { + RecyclerView recyclerView = listView[0]; + if (recyclerView == null && attachedToWindow) { + return; + } + BlockVideoCell bestView = null; + float bestViewCenterX = 0; + float parentCenterX = recyclerView.getMeasuredHeight() / 2f; + for (int i = 0; i < recyclerView.getChildCount(); i++) { + View child = recyclerView.getChildAt(i); + if (child instanceof BlockVideoCell) { + float centerX = child.getTop() + child.getMeasuredHeight() / 2f; + if (bestView == null || (Math.abs(parentCenterX - centerX) < (Math.abs(parentCenterX - bestViewCenterX)))) { + bestView = (BlockVideoCell) child; + bestViewCenterX = centerX; + } + } + } + boolean allowPlayer = !PhotoViewer.getInstance().isVisibleOrAnimating(); + if (!allowPlayer || (currentPlayer != null && currentPlayer != bestView && videoPlayer != null)) { + if (videoPlayer != null) { + currentPlayer.playFrom = videoPlayer.getCurrentPosition(); + videoPlayer.release(null); + } + videoPlayer = null; + currentPlayer = null; + } + if (allowPlayer && bestView != null) { + bestView.startVideoPlayer(); + currentPlayer = bestView; + } + + } + private void showSearch(boolean show) { if (searchContainer == null || (searchContainer.getTag() != null) == show) { return; @@ -4105,7 +4158,7 @@ private void setCurrentHeaderHeight(int newHeight) { return; } int maxHeight = AndroidUtilities.dp(56); - int minHeight = Math.max(AndroidUtilities.statusBarHeight, AndroidUtilities.dp(24)); + int minHeight = AndroidUtilities.dp(24); if (newHeight < minHeight) { newHeight = minHeight; @@ -6031,9 +6084,12 @@ public void notifyItemRangeRemoved(int positionStart, int itemCount) { private class BlockVideoCell extends FrameLayout implements DownloadController.FileDownloadProgressListener, TextSelectionHelper.ArticleSelectableView { + public long playFrom; private DrawingText captionLayout; private DrawingText creditLayout; private ImageReceiver imageView; + private AspectRatioFrameLayout aspectRatioFrameLayout; + private TextureView textureView; private RadialProgress2 radialProgress; private BlockChannelCell channelCell; private int currentType; @@ -6062,6 +6118,7 @@ private class BlockVideoCell extends FrameLayout implements DownloadController.F private MessageObject.GroupedMessagePosition groupPosition; private WebpageAdapter parentAdapter; + private boolean firstFrameRendered; public BlockVideoCell(Context context, WebpageAdapter adapter, int type) { super(context); @@ -6077,9 +6134,25 @@ public BlockVideoCell(Context context, WebpageAdapter adapter, int type) { radialProgress.setColors(0x66000000, 0x7f000000, 0xffffffff, 0xffd9d9d9); TAG = DownloadController.getInstance(currentAccount).generateObserverTag(); channelCell = new BlockChannelCell(context, parentAdapter, 1); + + aspectRatioFrameLayout = new AspectRatioFrameLayout(context); + aspectRatioFrameLayout.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT); + textureView = new TextureView(context); + textureView.setOpaque(false); + aspectRatioFrameLayout.addView(textureView); + + addView(aspectRatioFrameLayout); addView(channelCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == aspectRatioFrameLayout && pinchToZoomHelper.isInOverlayModeFor(this)) { + return true; + } + return super.drawChild(canvas, child, drawingTime); + } + public void setBlock(TLRPC.TL_pageBlockVideo block, boolean first, boolean last) { currentBlock = block; parentBlock = null; @@ -6105,7 +6178,7 @@ public View getChannelCell() { @Override public boolean onTouchEvent(MotionEvent event) { - if (pinchToZoomHelper.checkPinchToZoom(event, this, imageView, null)) { + if (pinchToZoomHelper.checkPinchToZoom(event, this, imageView, textureView, null)) { return true; } float x = event.getX(); @@ -6213,23 +6286,29 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } } imageView.setQualityThumbDocument(currentDocument); - imageView.setImageCoords(photoX, (isFirst || currentType == 1 || currentType == 2 || currentBlock.level > 0) ? 0 : AndroidUtilities.dp(8), photoWidth, photoHeight); - + int photoY = (isFirst || currentType == 1 || currentType == 2 || currentBlock.level > 0) ? 0 : AndroidUtilities.dp(8); + imageView.setImageCoords(photoX, photoY, photoWidth, photoHeight); if (isGif) { autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(DownloadController.AUTODOWNLOAD_TYPE_VIDEO, currentDocument.size); File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument, true); if (autoDownload || path.exists()) { imageView.setStrippedLocation(null); - imageView.setImage(ImageLocation.getForDocument(currentDocument), ImageLoader.AUTOPLAY_FILTER, null, null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, parentAdapter.currentPage, 1); + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(currentDocument.thumbs, 1000); + imageView.setImage(null, null, ImageLocation.getForObject(photoSize, currentDocument), "200_200", ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, parentAdapter.currentPage, 1); } else { imageView.setStrippedLocation(ImageLocation.getForDocument(currentDocument)); imageView.setImage(null, null, null, null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, parentAdapter.currentPage, 1); } + FrameLayout.LayoutParams params = (LayoutParams) aspectRatioFrameLayout.getLayoutParams(); + params.leftMargin = photoX; + params.topMargin = photoY; + params.width = photoWidth; + params.height = photoHeight; } else { imageView.setStrippedLocation(null); imageView.setImage(null, null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", 0, null, parentAdapter.currentPage, 1); } - imageView.setAspectFit(true); + // imageView.setAspectFit(true); buttonX = (int) (imageView.getImageX() + (imageView.getImageWidth() - size) / 2.0f); buttonY = (int) (imageView.getImageY() + (imageView.getImageHeight() - size) / 2.0f); radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size); @@ -6263,7 +6342,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { channelCell.measure(widthMeasureSpec, heightMeasureSpec); channelCell.setTranslationY(imageView.getImageHeight() - AndroidUtilities.dp(39)); - setMeasuredDimension(width, height); + super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); } @Override @@ -6276,9 +6355,6 @@ protected void onDraw(Canvas canvas) { } if (!pinchToZoomHelper.isInOverlayModeFor(this)) { imageView.draw(canvas); - if (imageView.getVisible()) { - radialProgress.draw(canvas); - } } int count = 0; if (captionLayout != null) { @@ -6298,6 +6374,13 @@ protected void onDraw(Canvas canvas) { if (currentBlock.level > 0) { canvas.drawRect(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(20), getMeasuredHeight() - (currentBlock.bottom ? AndroidUtilities.dp(6) : 0), quoteLinePaint); } + super.onDraw(canvas); + + if (!pinchToZoomHelper.isInOverlayModeFor(this)) { + if (imageView.getVisible()) { + radialProgress.draw(canvas); + } + } } private int getIconForCurrentState() { @@ -6385,11 +6468,14 @@ private void didPressedButton(boolean animated) { } } + @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); imageView.onDetachedFromWindow(); DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); + playFrom = 0; + firstFrameRendered = false; } @Override @@ -6399,6 +6485,41 @@ protected void onAttachedToWindow() { updateButtonState(false); } + private void startVideoPlayer() { + if (currentDocument == null || videoPlayer != null) { + return; + } +// if (!firstFrameRendered) { +// textureView.setAlpha(0f); +// } + videoPlayer = new VideoPlayerHolderBase() { + @Override + public boolean needRepeat() { + return true; + } + + @Override + public void onRenderedFirstFrame() { + super.onRenderedFirstFrame(); + if (!firstFrameRendered) { + firstFrameRendered = true; + textureView.setAlpha(1f); + } + } + }.with(textureView); + + TLRPC.Document document = currentDocument; + Uri uri = FileStreamLoadOperation.prepareUri(currentAccount, document, parentAdapter.currentPage); + if (uri == null) { + return; + } + + videoPlayer.seekTo(playFrom); + videoPlayer.preparePlayer(uri, true); + videoPlayer.play(); + + } + @Override public void onFailedDownload(String fileName, boolean canceled) { updateButtonState(false); @@ -9989,7 +10110,7 @@ public View getChannelCell() { @Override public boolean onTouchEvent(MotionEvent event) { - if (pinchToZoomHelper.checkPinchToZoom(event, this, imageView, null)) { + if (pinchToZoomHelper.checkPinchToZoom(event, this, imageView, null, null)) { return true; } float x = event.getX(); @@ -11329,7 +11450,11 @@ public boolean openPhoto(TLRPC.PageBlock block, WebpageAdapter adapter) { } final PhotoViewer photoViewer = PhotoViewer.getInstance(); photoViewer.setParentActivity(parentFragment); - return photoViewer.openPhoto(index, new RealPageBlocksAdapter(adapter.currentPage, pageBlocks), new PageBlocksPhotoViewerProvider(pageBlocks)); + if (photoViewer.openPhoto(index, new RealPageBlocksAdapter(adapter.currentPage, pageBlocks), new PageBlocksPhotoViewerProvider(pageBlocks))) { + checkVideoPlayer(); + return true; + } + return false; } @@ -11363,6 +11488,11 @@ public boolean isVideo(int index) { return !(index >= pageBlocks.size() || index < 0) && WebPageUtils.isVideo(page, get(index)); } + @Override + public boolean isHardwarePlayer(int index) { + return !(index >= pageBlocks.size() || index < 0) && !WebPageUtils.isVideo(page, get(index)) && adapter[0].getTypeForBlock(get(index)) == 5; + } + @Override public TLObject getMedia(int index) { if (index >= pageBlocks.size() || index < 0) { @@ -11530,6 +11660,19 @@ private ImageReceiver getImageReceiverView(View view, TLRPC.PageBlock pageBlock, BlockVideoCell cell = (BlockVideoCell) view; if (cell.currentBlock == pageBlock) { view.getLocationInWindow(coords); + if (cell == currentPlayer && videoPlayer != null && videoPlayer.firstFrameRendered) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Surface surface = new Surface(cell.textureView.getSurfaceTexture()); + Bitmap bitmap = Bitmap.createBitmap(cell.textureView.getMeasuredWidth(), cell.textureView.getMeasuredHeight(), Bitmap.Config.ARGB_8888); + AndroidUtilities.getBitmapFromSurface(surface, bitmap); + surface.release(); + cell.imageView.setImageBitmap(bitmap); + } else { + cell.imageView.setImageBitmap(cell.textureView.getBitmap()); + } + cell.firstFrameRendered = false; + cell.textureView.setAlpha(0); + } return cell.imageView; } } else if (view instanceof BlockCollageCell) { @@ -11562,5 +11705,47 @@ private ImageReceiver getImageReceiverView(View view, TLRPC.PageBlock pageBlock, return null; } + + @Override + public void onClose() { + super.onClose(); + checkVideoPlayer(); + } + + @Override + public void onReleasePlayerBeforeClose(int photoIndex) { + VideoPlayer player = PhotoViewer.getInstance().getVideoPlayer(); + TextureView textureView = PhotoViewer.getInstance().getVideoTextureView(); + BlockVideoCell videoCell = getViewFromListView(listView[0], pageBlocks.get(photoIndex)); + if (videoCell != null && player != null && textureView != null) { + videoCell.playFrom = player.getCurrentPosition(); + videoCell.firstFrameRendered = false; + videoCell.textureView.setAlpha(0); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Surface surface = new Surface(textureView.getSurfaceTexture()); + Bitmap bitmap = Bitmap.createBitmap(textureView.getMeasuredWidth(), textureView.getMeasuredHeight(), Bitmap.Config.ARGB_8888); + AndroidUtilities.getBitmapFromSurface(surface, bitmap); + surface.release(); + videoCell.imageView.setImageBitmap(bitmap); + } else { + videoCell.imageView.setImageBitmap(textureView.getBitmap()); + } + } + checkVideoPlayer(); + } + + private BlockVideoCell getViewFromListView(ViewGroup listView, TLRPC.PageBlock pageBlock) { + int count = listView.getChildCount(); + for (int a = 0; a < count; a++) { + View view = listView.getChildAt(a); + if (view instanceof BlockVideoCell) { + BlockVideoCell cell = (BlockVideoCell) view; + if (cell.currentBlock == pageBlock) { + return cell; + } + } + } + return null; + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java index 13910a0f9f..162091e1ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java @@ -196,7 +196,7 @@ public boolean findView(long dialogId, int messageId, int storyId, int type, Sto holder.storyImage = imageReceiver; if (storiesPlaceDrawAbove == null) { - storiesPlaceDrawAbove = (canvas, bounds, alpha) -> { + storiesPlaceDrawAbove = (canvas, bounds, alpha, opening) -> { blackoutPaint.setAlpha((int) (80 * alpha)); float r = AndroidUtilities.lerp(0, Math.min(bounds.width(), bounds.height()) / 2f, alpha); canvas.drawRoundRect(bounds, r, r, blackoutPaint); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java index 3211929960..7f8720cc82 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -1410,7 +1410,7 @@ protected void onDraw(Canvas canvas) { } else { giftPremiumSubtitleLayout.draw(canvas); } - } else { + } else if (giftPremiumSubtitleLayout != null) { giftPremiumSubtitleLayout.draw(canvas); } canvas.restore(); 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 e041cc9027..4fc947e0e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -3292,7 +3292,7 @@ private boolean checkPinchToZoom(MotionEvent ev) { isRoundVideo || currentMessageObject.isAnimatedSticker() || (currentMessageObject.isDocument() && !currentMessageObject.isGif()) || currentMessageObject.needDrawBluredPreview()) { return false; } - return pinchToZoomHelper.checkPinchToZoom(ev, this, photoImage, currentMessageObject); + return pinchToZoomHelper.checkPinchToZoom(ev, this, photoImage, null, currentMessageObject); } private boolean checkTextSelection(MotionEvent event) { @@ -6851,7 +6851,7 @@ private void setMessageContent(MessageObject messageObject, MessageObject.Groupe photoImage.setImageBitmap(getResources().getDrawable(R.drawable.sticker)); } if (!reactionsLayoutInBubble.isSmall) { - reactionsLayoutInBubble.measure(maxWidth, currentMessageObject.isOutOwner() && (currentMessageObject.isAnimatedEmoji() || currentMessageObject.isAnyKindOfSticker()) ? Gravity.RIGHT : Gravity.LEFT); + reactionsLayoutInBubble.measure(maxWidth + AndroidUtilities.dp(36), currentMessageObject.isOutOwner() && (currentMessageObject.isAnimatedEmoji() || currentMessageObject.isAnyKindOfSticker()) ? Gravity.RIGHT : Gravity.LEFT); reactionsLayoutInBubble.drawServiceShaderBackground = 1f; reactionsLayoutInBubble.totalHeight = reactionsLayoutInBubble.height + AndroidUtilities.dp(8); additionHeight += reactionsLayoutInBubble.totalHeight; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java index 03c090adeb..927b7b04ff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java @@ -327,6 +327,7 @@ public void buildLayout() { drawPremium = !savedMessages && MessagesController.getInstance(currentAccount).isPremiumUser(user); updateStatus(drawCheck, user, false); } else if (contact != null) { + dialog_id = 0; if (!LocaleController.isRTL) { nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); } else { @@ -753,7 +754,12 @@ protected void onDraw(Canvas canvas) { actionLayout.draw(canvas); canvas.restore(); } - StoriesUtilities.drawAvatarWithStory(dialog_id, canvas, avatarImage, avatarStoryParams); + if (user != null) { + StoriesUtilities.drawAvatarWithStory(user.id, canvas, avatarImage, avatarStoryParams); + } else { + avatarImage.setImageCoords(avatarStoryParams.originalAvatarRect); + avatarImage.draw(canvas); + } } @Override @@ -799,7 +805,7 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { @Override public boolean onTouchEvent(MotionEvent event) { - if (avatarStoryParams.checkOnTouchEvent(event, this)) { + if (user != null && avatarStoryParams.checkOnTouchEvent(event, this)) { return true; } if (actionButton != null && actionButton.checkTouchEvent(event)) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java index 50c933c07c..d64114e935 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ReactedUserHolderView.java @@ -194,6 +194,7 @@ public void setUserReaction(TLRPC.User user, TLRPC.Chat chat, TLRPC.Reaction rea String contentDescription; boolean hasReactImage = false; if (like) { + reactView.setAnimatedEmojiDrawable(null); hasReactImage = true; Drawable likeDrawableFilled = ContextCompat.getDrawable(getContext(), R.drawable.media_like_active).mutate(); reactView.setColorFilter(new PorterDuffColorFilter(0xFFFF2E38, PorterDuff.Mode.MULTIPLY)); @@ -202,6 +203,7 @@ public void setUserReaction(TLRPC.User user, TLRPC.Chat chat, TLRPC.Reaction rea } else if (reaction != null) { ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction); if (visibleReaction.emojicon != null) { + reactView.setAnimatedEmojiDrawable(null); TLRPC.TL_availableReaction r = MediaDataController.getInstance(currentAccount).getReactionsMap().get(visibleReaction.emojicon); if (r != null) { SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(r.static_icon.thumbs, Theme.key_windowBackgroundGray, 1.0f); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java index 812ae12f04..600c5f4d7d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java @@ -284,7 +284,7 @@ public boolean isDisabled() { } public boolean showingBitmap() { - return imageView.getBitmap() != null; + return imageView.hasNotThumb(); } public ImageReceiver getImageView() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index a72e50bc50..da8a555d83 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -9195,7 +9195,9 @@ public void onAnimationEnd(Animator animation) { blurredView.animate().setListener(new HideViewAfterAnimation(blurredView)).alpha(0).start(); blurredView.setTag(null); chatListView.invalidate(); - fragmentView.invalidate(); + if (fragmentView != null) { + fragmentView.invalidate(); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java index e167ef977a..a0bfd17a64 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java @@ -1695,10 +1695,15 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) { } } - canvas.save(); - canvas.clipRect(backgroundPaddingLeft, actionBar.getY() + actionBar.getMeasuredHeight() - currentPanTranslationY, getMeasuredWidth() - backgroundPaddingLeft, getMeasuredHeight()); - boolean result = super.drawChild(canvas, child, drawingTime); - canvas.restore(); + boolean result; + if (child != contactsLayout && child != audioLayout) { + canvas.save(); + canvas.clipRect(backgroundPaddingLeft, actionBar.getY() + actionBar.getMeasuredHeight() - currentPanTranslationY, getMeasuredWidth() - backgroundPaddingLeft, getMeasuredHeight()); + result = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + } else { + result = super.drawChild(canvas, child, drawingTime); + } if (drawBackground) { if (rad != 1.0f && actionBarType != 2) { @@ -2100,11 +2105,15 @@ public void setTranslationY(float translationY) { buttonsRecyclerView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); containerView.addView(buttonsRecyclerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 84, Gravity.BOTTOM | Gravity.LEFT)); buttonsRecyclerView.setOnItemClickListener((view, position) -> { - if (baseFragment != null && baseFragment.getParentActivity() == null) { + BaseFragment lastFragment = baseFragment; + if (lastFragment == null) { + lastFragment = LaunchActivity.getLastFragment(); + } + if (lastFragment == null || lastFragment.getParentActivity() == null) { return; } if (view instanceof AttachButton) { - final Activity activity = baseFragment.getParentActivity(); + final Activity activity = lastFragment.getParentActivity(); int num = (Integer) view.getTag(); if (num == 1) { if (!photosEnabled && !videosEnabled) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java index 3b86a05f5c..533aacd8ab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java @@ -55,7 +55,6 @@ import android.widget.TextView; import androidx.annotation.Keep; -import androidx.exifinterface.media.ExifInterface; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearSmoothScroller; @@ -113,7 +112,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java index ff67ee6f6e..6b8e359d63 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java @@ -621,7 +621,7 @@ public void setHintText(CharSequence text) { public void setHintText(CharSequence text, boolean animated) { if (hintAnimatedDrawable != null) { - hintAnimatedDrawable.setText(text, true); + hintAnimatedDrawable.setText(text, !LocaleController.isRTL); } else { if (text == null) { text = ""; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FilterShaders.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FilterShaders.java index 78c561d3b9..0ec78a9812 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FilterShaders.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FilterShaders.java @@ -3,6 +3,7 @@ import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.PointF; +import android.media.MediaFormat; import android.opengl.GLES11Ext; import android.opengl.GLES20; import android.opengl.GLUtils; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java index 2a080128fa..bd8a780c9d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java @@ -666,7 +666,7 @@ public HeaderView(Context context) { description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); description.setGravity(Gravity.CENTER_HORIZONTAL); description.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); - addView(description, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 24, 0, 24, 24)); + addView(description, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 24, 0, 24, 24)); updatePremiumButtonText(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java index 685469bbfd..90f593b081 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java @@ -110,43 +110,45 @@ protected void onDraw(Canvas canvas) { invalidate(); } } - if (type == TYPE_REACTIONS) { - if (currentColor != 0) { - canvas.drawPath(path, paint); - } else { - PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -AndroidUtilities.dp(24), 0); - canvas.drawPath(path, PremiumGradient.getInstance().getMainGradientPaint()); - } - if (cellFlickerDrawable == null) { - cellFlickerDrawable = new CellFlickerDrawable(); - } - cellFlickerDrawable.setParentWidth(getMeasuredWidth() / 2); - cellFlickerDrawable.drawFrame = false; - cellFlickerDrawable.draw(canvas, path, this); - canvas.save(); - canvas.clipPath(path); - starParticles.onDraw(canvas); - canvas.restore(); - invalidate(); - } else { - float cx = getMeasuredWidth() / 2f; - float cy = getMeasuredHeight() / 2f; - if (oldShaderPaint == null) { - shaderCrossfadeProgress = 1f; - } - if (shaderCrossfadeProgress != 1f) { - paint.setAlpha((int) (255 * shaderCrossfadeProgress)); - canvas.drawCircle(cx, cy, cx, oldShaderPaint); - canvas.drawCircle(cx, cy, cx, paint); - shaderCrossfadeProgress += 16 / 150f; - if (shaderCrossfadeProgress > 1f) { - shaderCrossfadeProgress = 1f; - oldShaderPaint = null; + if (paint != null) { + if (type == TYPE_REACTIONS) { + if (currentColor != 0) { + canvas.drawPath(path, paint); + } else { + PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -AndroidUtilities.dp(24), 0); + canvas.drawPath(path, PremiumGradient.getInstance().getMainGradientPaint()); + } + if (cellFlickerDrawable == null) { + cellFlickerDrawable = new CellFlickerDrawable(); } + cellFlickerDrawable.setParentWidth(getMeasuredWidth() / 2); + cellFlickerDrawable.drawFrame = false; + cellFlickerDrawable.draw(canvas, path, this); + canvas.save(); + canvas.clipPath(path); + starParticles.onDraw(canvas); + canvas.restore(); invalidate(); - paint.setAlpha(255); } else { - canvas.drawCircle(cx, cy, cx, paint); + float cx = getMeasuredWidth() / 2f; + float cy = getMeasuredHeight() / 2f; + if (oldShaderPaint == null) { + shaderCrossfadeProgress = 1f; + } + if (shaderCrossfadeProgress != 1f) { + paint.setAlpha((int) (255 * shaderCrossfadeProgress)); + canvas.drawCircle(cx, cy, cx, oldShaderPaint); + canvas.drawCircle(cx, cy, cx, paint); + shaderCrossfadeProgress += 16 / 150f; + if (shaderCrossfadeProgress > 1f) { + shaderCrossfadeProgress = 1f; + oldShaderPaint = null; + } + invalidate(); + paint.setAlpha(255); + } else { + canvas.drawCircle(cx, cy, cx, paint); + } } } super.onDraw(canvas); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java index c61469b0e9..6efd479281 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java @@ -404,8 +404,8 @@ public boolean onTouchEvent(MotionEvent ev) { if (pinchToZoomHelper != null && getCurrentItemView() != null) { if (action != MotionEvent.ACTION_DOWN && isDownReleased && !pinchToZoomHelper.isInOverlayMode()) { - pinchToZoomHelper.checkPinchToZoom(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0), this, getCurrentItemView().getImageReceiver(), null); - } else if (pinchToZoomHelper.checkPinchToZoom(ev, this, getCurrentItemView().getImageReceiver(), null)) { + pinchToZoomHelper.checkPinchToZoom(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0), this, getCurrentItemView().getImageReceiver(), null,null); + } else if (pinchToZoomHelper.checkPinchToZoom(ev, this, getCurrentItemView().getImageReceiver(), null,null)) { if (!isDownReleased) { isDownReleased = true; callback.onRelease(); 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 ee000ea704..80d56f6fb2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -53,6 +53,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.recyclerview.widget.GridLayoutManager; @@ -79,6 +80,7 @@ import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.browser.Browser; @@ -1017,7 +1019,7 @@ public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObj mediaPages[0].listView.getLocationInWindow(coords); object.animatingImageViewYOffset = -coords[1]; object.imageReceiver = imageReceiver; - object.allowTakeAnimation = false; + object.allowTakeAnimation = true; object.radius = object.imageReceiver.getRoundRadius(); object.thumb = object.imageReceiver.getBitmapSafe(); object.parentView.getLocationInWindow(coords); @@ -1513,8 +1515,10 @@ public void onClick(View view) { if (isStories) { StoriesAdapter adapter = tab == TAB_STORIES ? storiesAdapter : archivedStoriesAdapter; - showPhotosItem.setChecked(adapter.storiesList.showPhotos()); - showVideosItem.setChecked(adapter.storiesList.showVideos()); + if (adapter.storiesList != null) { + showPhotosItem.setChecked(adapter.storiesList.showPhotos()); + showVideosItem.setChecked(adapter.storiesList.showVideos()); + } showPhotosItem.setOnClickListener(v -> { if (changeTypeAnimation) { return; @@ -1524,6 +1528,9 @@ public void onClick(View view) { return; } showPhotosItem.getCheckView().setChecked(!showPhotosItem.getCheckView().isChecked(), true); + if (adapter.storiesList == null) { + return; + } adapter.storiesList.updateFilters(showPhotosItem.getCheckView().isChecked(), showVideosItem.getCheckView().isChecked()); }); showVideosItem.setOnClickListener(v -> { @@ -1535,6 +1542,9 @@ public void onClick(View view) { return; } showVideosItem.getCheckView().setChecked(!showVideosItem.getCheckView().isChecked(), true); + if (adapter.storiesList == null) { + return; + } adapter.storiesList.updateFilters(showPhotosItem.getCheckView().isChecked(), showVideosItem.getCheckView().isChecked()); }); } else { @@ -2572,10 +2582,10 @@ protected int getInitialTab() { } public void setStoriesFilter(boolean photos, boolean videos) { - if (storiesAdapter != null) { + if (storiesAdapter != null && storiesAdapter.storiesList != null) { storiesAdapter.storiesList.updateFilters(photos, videos); } - if (archivedStoriesAdapter != null) { + if (archivedStoriesAdapter != null && archivedStoriesAdapter.storiesList != null) { archivedStoriesAdapter.storiesList.updateFilters(photos, videos); } } @@ -5447,6 +5457,9 @@ private void onItemClick(int index, View view, MessageObject message, int a, int } } else if (selectedMode == TAB_STORIES || selectedMode == TAB_ARCHIVED_STORIES) { StoriesController.StoriesList storiesList = (selectedMode == TAB_STORIES ? storiesAdapter : archivedStoriesAdapter).storiesList; + if (storiesList == null) { + return; + } profileActivity.getOrCreateStoryViewer().open(getContext(), message.getId(), storiesList, StoriesListPlaceProvider.of(mediaPages[a].listView).with(forward -> { if (forward) { storiesList.load(false, 30); @@ -6827,10 +6840,16 @@ public int getItemViewType(int i) { } public int getStoriesCount(int tab) { + StoriesController.StoriesList list; if (tab == TAB_STORIES) { - return storiesAdapter.storiesList.getCount(); + list = storiesAdapter.storiesList; } else if (tab == TAB_ARCHIVED_STORIES) { - return archivedStoriesAdapter.storiesList.getCount(); + list = archivedStoriesAdapter.storiesList; + } else { + return 0; + } + if (list != null) { + return list.getCount(); } return 0; } @@ -6838,7 +6857,8 @@ public int getStoriesCount(int tab) { private class StoriesAdapter extends SharedPhotoVideoAdapter { private final boolean isArchive; - public StoriesController.StoriesList storiesList; + @Nullable + public final StoriesController.StoriesList storiesList; private StoriesAdapter supportingAdapter; private int id; @@ -6846,7 +6866,9 @@ public StoriesAdapter(Context context, boolean isArchive) { super(context); this.isArchive = isArchive; storiesList = profileActivity.getMessagesController().getStoriesController().getStoriesList(dialog_id, isArchive ? StoriesController.StoriesList.TYPE_ARCHIVE : StoriesController.StoriesList.TYPE_PINNED); - id = storiesList.link(); + if (storiesList != null) { + id = storiesList.link(); + } checkColumns(); } @@ -6869,6 +6891,9 @@ private StoriesAdapter(Context context, boolean isArchive, StoriesController.Sto } private void checkColumns() { + if (storiesList == null) { + return; + } if (!isArchive && (!storiesColumnsCountSet || allowStoriesSingleColumn && storiesList.getCount() > 1) && storiesList.getCount() > 0 && !isStoriesView()) { if (storiesList.getCount() < 5) { mediaColumnsCount[1] = storiesList.getCount(); @@ -6913,6 +6938,9 @@ public int getTopOffset() { @Override public int getItemCount() { + if (storiesList == null) { + return 0; + } return storiesList.isOnlyCache() && hasInternet() ? 0 : storiesList.getCount(); } @@ -6945,6 +6973,9 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + if (storiesList == null) { + return; + } int viewType = holder.getItemViewType(); if (viewType == 0) { SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) holder.itemView; @@ -6952,6 +6983,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { position -= getTopOffset(); if (position < 0 || position >= storiesList.messageObjects.size()) { cell.setMessageObject(null, columnsCount()); + cell.isStory = true; return; } MessageObject messageObject = storiesList.messageObjects.get(position); @@ -6965,6 +6997,10 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } public void load(boolean force) { + if (storiesList == null) { + return; + } + final int columnCount = columnsCount(); final int count = Math.min(100, Math.max(1, columnCount / 2) * columnCount * columnCount); storiesList.load(force, count); @@ -6977,6 +7013,9 @@ public int getItemViewType(int i) { @Override public String getLetter(int position) { + if (storiesList == null) { + return null; + } position -= getTopOffset(); if (position < 0 || position >= storiesList.messageObjects.size()) { return null; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java index e6bd70033f..eacaaf0c1e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java @@ -652,19 +652,16 @@ private void updateLightStatusBar(boolean open) { protected void onDraw(Canvas canvas) { int y = scrollOffsetY - backgroundPaddingTop + AndroidUtilities.dp(6); int top = scrollOffsetY - backgroundPaddingTop - AndroidUtilities.dp(13); - int height = getMeasuredHeight() + AndroidUtilities.dp(15) + backgroundPaddingTop; int statusBarHeight = 0; float radProgress = 1.0f; if (Build.VERSION.SDK_INT >= 21) { top += AndroidUtilities.statusBarHeight; y += AndroidUtilities.statusBarHeight; - height -= AndroidUtilities.statusBarHeight; if (fullHeight) { if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight * 2) { int diff = Math.min(AndroidUtilities.statusBarHeight, AndroidUtilities.statusBarHeight * 2 - top - backgroundPaddingTop); top -= diff; - height += diff; radProgress = 1.0f - Math.min(1.0f, (diff * 2) / (float) AndroidUtilities.statusBarHeight); } if (top + backgroundPaddingTop < AndroidUtilities.statusBarHeight) { @@ -673,7 +670,7 @@ protected void onDraw(Canvas canvas) { } } - shadowDrawable.setBounds(0, top, getMeasuredWidth(), height); + shadowDrawable.setBounds(0, top, getMeasuredWidth(), getMeasuredHeight()); shadowDrawable.draw(canvas); if (radProgress != 1.0f) { @@ -946,6 +943,7 @@ public void requestLayout() { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploaded); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadFailed); } + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.stickersDidLoad); updateFields(); updateSendButton(); @@ -1178,9 +1176,10 @@ public void onClick(View widget) { premiumButtonView.setVisibility(View.INVISIBLE); } + final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); boolean notInstalled; if (stickerSet != null && stickerSet.set != null && stickerSet.set.emojis) { - ArrayList sets = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_EMOJIPACKS); + ArrayList sets = mediaDataController.getStickerSets(MediaDataController.TYPE_EMOJIPACKS); boolean has = false; for (int i = 0; sets != null && i < sets.size(); ++i) { if (sets.get(i) != null && sets.get(i).set != null && sets.get(i).set.id == stickerSet.set.id) { @@ -1190,7 +1189,7 @@ public void onClick(View widget) { } notInstalled = !has; } else { - notInstalled = stickerSet == null || stickerSet.set == null || !MediaDataController.getInstance(currentAccount).isStickerPackInstalled(stickerSet.set.id); + notInstalled = stickerSet == null || stickerSet.set == null || !mediaDataController.isStickerPackInstalled(stickerSet.set.id); } if (customButtonDelegate != null) { @@ -1199,7 +1198,22 @@ public void onClick(View widget) { dismiss(); } }, customButtonDelegate.getCustomButtonText(), customButtonDelegate.getCustomButtonTextColorKey(), customButtonDelegate.getCustomButtonColorKey(), customButtonDelegate.getCustomButtonRippleColorKey()); - } else if (notInstalled) { + return; + } + if (notInstalled) { + int type = MediaDataController.TYPE_IMAGE; + if (stickerSet != null && stickerSet.set != null && stickerSet.set.emojis) { + type = MediaDataController.TYPE_EMOJIPACKS; + } else if (stickerSet != null && stickerSet.set != null && stickerSet.set.masks) { + type = MediaDataController.TYPE_MASK; + } + if (!mediaDataController.areStickersLoaded(type)) { + mediaDataController.checkStickers(type); + setButton(null, "", -1, -1, -1); + return; + } + } + if (notInstalled) { optionsButton.hideSubItem(menu_archive); String text; if (stickerSet != null && stickerSet.set != null && stickerSet.set.masks) { @@ -1640,6 +1654,7 @@ public void dismiss() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploaded); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadFailed); } + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.stickersDidLoad); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 4); } @@ -1712,6 +1727,8 @@ public void didReceivedNotification(int id, int account, Object... args) { if (uploadImportStickers.isEmpty()) { updateFields(); } + } else if (id == NotificationCenter.stickersDidLoad) { + updateFields(); } } @@ -1730,16 +1747,24 @@ private void setButton(View.OnClickListener onClickListener, String title, int c ViewGroup.MarginLayoutParams shadowParams = (ViewGroup.MarginLayoutParams) shadow[1].getLayoutParams(); ViewGroup.MarginLayoutParams gridParams = (ViewGroup.MarginLayoutParams) gridView.getLayoutParams(); ViewGroup.MarginLayoutParams emptyParams = (ViewGroup.MarginLayoutParams) emptyView.getLayoutParams(); - if (backgroundColorKey >= 0 && backgroundSelectorColorKey >= 0) { + if (onClickListener == null) { + pickerBottomLayout.setAlpha(0f); + } else if (backgroundColorKey >= 0 && backgroundSelectorColorKey >= 0) { pickerBottomLayout.setBackground(Theme.createSimpleSelectorRoundRectDrawable(dp(6), getThemedColor(backgroundColorKey), getThemedColor(backgroundSelectorColorKey))); pickerBottomFrameLayout.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); params.leftMargin = params.topMargin = params.rightMargin = params.bottomMargin = dp(8); emptyParams.bottomMargin = gridParams.bottomMargin = shadowParams.bottomMargin = dp(64); + if (pickerBottomLayout.getAlpha() < 1f) { + pickerBottomLayout.animate().alpha(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(240).start(); + } } else { pickerBottomLayout.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_dialogBackground), Theme.multAlpha(getThemedColor(Theme.key_text_RedBold), .1f))); pickerBottomFrameLayout.setBackgroundColor(Color.TRANSPARENT); params.leftMargin = params.topMargin = params.rightMargin = params.bottomMargin = 0; emptyParams.bottomMargin = gridParams.bottomMargin = shadowParams.bottomMargin = dp(48); + if (pickerBottomLayout.getAlpha() < 1f) { + pickerBottomLayout.animate().alpha(1f).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).setDuration(240).start(); + } } containerView.requestLayout(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java index 24cdb5ced0..2653730a5a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java @@ -235,10 +235,12 @@ public void onPageSelected(int page, boolean forward) { onTabPageSelected(page); int trasnlationX = viewPages[0] != null ? viewPages[0].getMeasuredWidth() : 0; - if (forward) { - viewPages[1].setTranslationX(trasnlationX); - } else { - viewPages[1].setTranslationX(-trasnlationX); + if (viewPages[1] != null) { + if (forward) { + viewPages[1].setTranslationX(trasnlationX); + } else { + viewPages[1].setTranslationX(-trasnlationX); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 580cc618cf..7f244b0185 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -1946,7 +1946,7 @@ protected void onMeasure(int widthSpec, int heightSpec) { } int pos = parentPage.layoutManager.findFirstVisibleItemPosition(); - if (pos != RecyclerView.NO_POSITION && parentPage.itemTouchhelper.isIdle() && !parentPage.layoutManager.hasPendingScrollPosition()) { + if (pos != RecyclerView.NO_POSITION && parentPage.itemTouchhelper.isIdle() && !parentPage.layoutManager.hasPendingScrollPosition() && parentPage.listView.getScrollState() != RecyclerView.SCROLL_STATE_DRAGGING) { RecyclerView.ViewHolder holder = parentPage.listView.findViewHolderForAdapterPosition(pos); if (holder != null) { int top = holder.itemView.getTop(); @@ -6420,6 +6420,9 @@ public void onResume() { boolean hasNotStoragePermission = (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED; boolean hasNotNotificationsPermission = Build.VERSION.SDK_INT >= 33 && activity.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED; AndroidUtilities.runOnUIThread(() -> { + if (getParentActivity() == null) { + return; + } afterSignup = false; if (hasNotNotificationsPermission || hasNotContactsPermission || hasNotStoragePermission) { askingForPermissions = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java index 9d0f65b615..878e68d76c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java @@ -121,6 +121,8 @@ import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.BlobDrawable; +import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.CheckBoxSquare; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.EditTextBoldCursor; @@ -152,6 +154,7 @@ import org.telegram.ui.Components.voip.PrivateVideoPreviewDialog; import org.telegram.ui.Components.voip.RTMPStreamPipOverlay; import org.telegram.ui.Components.voip.VoIPToggleButton; +import org.webrtc.voiceengine.WebRtcAudioTrack; import java.io.File; import java.util.ArrayList; @@ -8719,4 +8722,26 @@ public boolean isRtmpLandscapeMode() { public boolean isRtmpStream() { return call != null && call.call.rtmp_stream; } + + @Override + public boolean dispatchKeyEvent(@NonNull KeyEvent event) { + if (parentActivity == null) { + return super.dispatchKeyEvent(event); + } + if (event.getAction() == KeyEvent.ACTION_DOWN && (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN)) { + if (VoIPService.getSharedInstance() != null) { + if (Build.VERSION.SDK_INT >= 32) { + boolean oldValue = WebRtcAudioTrack.isSpeakerMuted(); + AudioManager am = (AudioManager) parentActivity.getSystemService(AUDIO_SERVICE); + int minVolume = am.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL); + boolean mute = am.getStreamVolume(AudioManager.STREAM_VOICE_CALL) == minVolume && event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN; + WebRtcAudioTrack.setSpeakerMute(mute); + if (oldValue != WebRtcAudioTrack.isSpeakerMuted()) { + getUndoView().showWithAction(0, mute ? UndoView.ACTION_VOIP_SOUND_MUTED : UndoView.ACTION_VOIP_SOUND_UNMUTED, null); + } + } + } + } + return super.dispatchKeyEvent(event); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 1ee3c6e40f..6492cbdeff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -7230,6 +7230,10 @@ public boolean dispatchKeyEvent(KeyEvent event) { int keyCode = event.getKeyCode(); if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN) { BaseFragment baseFragment = getLastFragment(); + if (baseFragment != null && baseFragment.overlayStoryViewer != null && baseFragment.overlayStoryViewer.isShown()) { + baseFragment.overlayStoryViewer.dispatchKeyEvent(event); + return true; + } if (baseFragment != null && baseFragment.storyViewer != null && baseFragment.storyViewer.isShown()) { baseFragment.storyViewer.dispatchKeyEvent(event); return true; @@ -7562,14 +7566,14 @@ public static BaseFragment getLastFragment() { public void requestCustomNavigationBar() { if (customNavigationBar == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { customNavigationBar = drawerLayoutContainer.createNavigationBar(); - if (customNavigationBar != null) { - FrameLayout decorView = (FrameLayout) getWindow().getDecorView(); - decorView.addView(customNavigationBar); - if (customNavigationBar.getLayoutParams().height != AndroidUtilities.navigationBarHeight || ((FrameLayout.LayoutParams)customNavigationBar.getLayoutParams()).topMargin != customNavigationBar.getHeight()) { - customNavigationBar.getLayoutParams().height = AndroidUtilities.navigationBarHeight; - ((FrameLayout.LayoutParams)customNavigationBar.getLayoutParams()).topMargin = drawerLayoutContainer.getMeasuredHeight(); - customNavigationBar.requestLayout(); - } + FrameLayout decorView = (FrameLayout) getWindow().getDecorView(); + decorView.addView(customNavigationBar); + } + if (customNavigationBar != null) { + if (customNavigationBar.getLayoutParams().height != AndroidUtilities.navigationBarHeight || ((FrameLayout.LayoutParams)customNavigationBar.getLayoutParams()).topMargin != customNavigationBar.getHeight()) { + customNavigationBar.getLayoutParams().height = AndroidUtilities.navigationBarHeight; + ((FrameLayout.LayoutParams)customNavigationBar.getLayoutParams()).topMargin = drawerLayoutContainer.getMeasuredHeight(); + customNavigationBar.requestLayout(); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index cb6517a6ec..c0806339f2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -1695,6 +1695,7 @@ private void onAuthSuccess(TLRPC.TL_auth_authorization res, boolean afterSignup) ContactsController.getInstance(currentAccount).checkAppAccount(); MessagesController.getInstance(currentAccount).checkPromoInfo(true); ConnectionsManager.getInstance(currentAccount).updateDcSettings(); + MessagesController.getInstance(currentAccount).loadAppConfig(); if (res.future_auth_token != null) { AuthTokensHelper.saveLogInToken(res); @@ -4238,7 +4239,7 @@ public void afterTextChanged(Editable s) {} } else if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { createTimer(); } - } else if (currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL)) { + } else if (currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL)) { timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 2, 0)); setProblemTextVisible(time < 1000); timeText.setVisibility(time < 1000 ? GONE : VISIBLE); @@ -4314,6 +4315,9 @@ private void createCodeTimer() { return; } codeTime = 15000; + if (time > codeTime) { + codeTime = time; + } codeTimer = new Timer(); lastCodeTime = System.currentTimeMillis(); codeTimer.schedule(new TimerTask() { @@ -4376,6 +4380,8 @@ public void run() { int seconds = time / 1000 - minutes * 60; if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_MISSED_CALL) { timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, minutes, seconds)); + } else if (currentType == AUTH_TYPE_SMS && nextType == AUTH_TYPE_SMS) { + timeText.setText(LocaleController.formatString("ResendSmsAvailableIn", R.string.ResendSmsAvailableIn, minutes, seconds)); } else if (nextType == AUTH_TYPE_SMS) { timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, minutes, seconds)); } @@ -4562,7 +4568,11 @@ public void onNextPressed(String code) { tryHideProgress(false); nextPressed = false; if (error == null) { - animateSuccess(() -> new AlertDialog.Builder(getParentActivity()) + Activity activity = getParentActivity(); + if (activity == null) { + return; + } + animateSuccess(() -> new AlertDialog.Builder(activity) .setTitle(LocaleController.getString(R.string.CancelLinkSuccessTitle)) .setMessage(LocaleController.formatString("CancelLinkSuccess", R.string.CancelLinkSuccess, PhoneFormat.getInstance().format("+" + phone))) .setPositiveButton(LocaleController.getString(R.string.Close), null) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index bea4d0e936..e5de9b1596 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -30,7 +30,6 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.ColorFilter; import android.graphics.Matrix; import android.graphics.Outline; import android.graphics.Paint; @@ -70,7 +69,6 @@ import android.transition.TransitionSet; import android.transition.TransitionValues; import android.util.FloatProperty; -import android.util.Log; import android.util.Pair; import android.util.Property; import android.util.Range; @@ -147,6 +145,7 @@ import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; +import org.telegram.messenger.FileStreamLoadOperation; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; @@ -154,7 +153,6 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MediaDataController; -import org.telegram.messenger.MessageCustomParamsHelper; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; @@ -256,7 +254,6 @@ import org.telegram.ui.Components.ViewHelper; import org.telegram.ui.Components.spoilers.SpoilersTextView; import org.telegram.ui.Stories.DarkThemeResourceProvider; -import org.telegram.ui.Stories.StoryCaptionView; import java.io.ByteArrayInputStream; import java.io.File; @@ -296,6 +293,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private int classGuid; private PhotoViewerProvider placeProvider; private boolean isVisible; + private boolean isVisibleOrAnimating; private int maxSelectedPhotos = -1; private boolean allowOrder = true; @@ -322,6 +320,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat public boolean closePhotoAfterSelect = true; private TextSelectionHelper.SimpleTextSelectionHelper textSelectionHelper; + public TextureView getVideoTextureView() { + return videoTextureView; + } + + public boolean isVisibleOrAnimating() { + return isVisibleOrAnimating; + } + private static class PhotoViewerActionBarContainer extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { private FrameLayout container; @@ -1773,6 +1779,7 @@ public interface PageBlocksAdapter { void updateSlideshowCell(TLRPC.PageBlock currentPageBlock); Object getParentObject(); + boolean isHardwarePlayer(int index); } private Rect hitRect = new Rect(); @@ -2601,6 +2608,7 @@ default boolean onDeletePhoto(int index) { default boolean canLoadMoreAvatars() { return true; } + default void onReleasePlayerBeforeClose(int currentIndex) {}; } private class FrameLayoutDrawer extends SizeNotifierFrameLayoutPhoto { @@ -3805,7 +3813,7 @@ public void didReceivedNotification(int id, int account, Object... args) { boolean animated = a == 0 || a == 1 && sideImage == rightImage || a == 2 && sideImage == leftImage; photoProgressViews[a].setProgress(1.0f, animated); checkProgress(a, false, animated); - if (videoPlayer == null && a == 0 && (currentMessageObject != null && currentMessageObject.isVideo() || currentBotInlineResult != null && (currentBotInlineResult.type.equals("video") || MessageObject.isVideoDocument(currentBotInlineResult.document)) || pageBlocksAdapter != null && pageBlocksAdapter.isVideo(currentIndex))) { + if (videoPlayer == null && a == 0 && (currentMessageObject != null && currentMessageObject.isVideo() || currentBotInlineResult != null && (currentBotInlineResult.type.equals("video") || MessageObject.isVideoDocument(currentBotInlineResult.document)) || pageBlocksAdapter != null && (pageBlocksAdapter.isVideo(currentIndex) || pageBlocksAdapter.isHardwarePlayer(currentIndex)))) { onActionClick(false); } if (a == 0 && videoPlayer != null) { @@ -5283,6 +5291,7 @@ public void dismiss() { PipInstance = Instance; Instance = null; isVisible = false; + isVisibleOrAnimating = false; if (currentPlaceObject != null && !currentPlaceObject.imageReceiver.getVisible()) { currentPlaceObject.imageReceiver.setVisible(true, true); } @@ -8096,6 +8105,7 @@ private void switchToPip(boolean fromGesture) { Instance = null; switchingInlineMode = true; isVisible = false; + isVisibleOrAnimating = false; AndroidUtilities.cancelRunOnUIThread(hideActionBarRunnable); if (currentPlaceObject != null && !currentPlaceObject.imageReceiver.getVisible()) { currentPlaceObject.imageReceiver.setVisible(true, true); @@ -8456,6 +8466,7 @@ public void getOutline(View view, Outline outline) { try { isVisible = true; + isVisibleOrAnimating = true; WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); wm.addView(windowView, windowLayoutParams); onShowView(); @@ -9604,9 +9615,11 @@ public void onAnimationEnd(Animator animation) { waitingForFirstTextureUpload = 0; } - if (firstFrameView != null) { - firstFrameView.checkFromPlayer(videoPlayer); - } + AndroidUtilities.runOnUIThread(() -> { + if (firstFrameView != null) { + firstFrameView.checkFromPlayer(videoPlayer); + } + }); } }); } @@ -9667,7 +9680,7 @@ public void onAnimationEnd(Animator animation) { videoPlayer.setPlayWhenReady(playWhenReady); } - playerLooping = currentMessageObject != null && currentMessageObject.getDuration() <= 30; + playerLooping = (currentMessageObject != null && currentMessageObject.getDuration() <= 30) || (pageBlocksAdapter != null && pageBlocksAdapter.isHardwarePlayer(currentIndex)); videoPlayerControlFrameLayout.setSeekBarTransitionEnabled(playerLooping); videoPlayer.setLooping(playerLooping); @@ -9687,8 +9700,11 @@ public void onAnimationEnd(Animator animation) { if (pageBlocksAdapter != null) { bottomLayout.setVisibility(View.VISIBLE); } - - setVideoPlayerControlVisible(!isCurrentVideo, true); + if (pageBlocksAdapter != null && pageBlocksAdapter.isHardwarePlayer(currentIndex) && !pageBlocksAdapter.isVideo(currentIndex)) { + setVideoPlayerControlVisible(false, true); + } else { + setVideoPlayerControlVisible(!isCurrentVideo, true); + } if (!isCurrentVideo) { scheduleActionBarHide(playerAutoStarted ? 3000 : 1000); } @@ -12475,7 +12491,7 @@ private void onPhotoShow(final MessageObject messageObject, final TLRPC.FileLoca MessagesController.getInstance(currentAccount).loadDialogPhotos(avatarsDialogId, 80, 0, true, classGuid); } } - if (currentMessageObject != null && (currentMessageObject.isVideo() || currentMessageObject.isGif()) || currentBotInlineResult != null && (currentBotInlineResult.type.equals("video") || MessageObject.isVideoDocument(currentBotInlineResult.document)) || (pageBlocksAdapter != null && pageBlocksAdapter.isVideo(index)) || (sendPhotoType == SELECT_TYPE_NO_SELECT && ((MediaController.PhotoEntry)imagesArrLocals.get(index)).isVideo)) { + if (currentMessageObject != null && (currentMessageObject.isVideo() || currentMessageObject.isGif()) || currentBotInlineResult != null && (currentBotInlineResult.type.equals("video") || MessageObject.isVideoDocument(currentBotInlineResult.document)) || (pageBlocksAdapter != null && (pageBlocksAdapter.isVideo(index) || pageBlocksAdapter.isHardwarePlayer(index))) || (sendPhotoType == SELECT_TYPE_NO_SELECT && ((MediaController.PhotoEntry)imagesArrLocals.get(index)).isVideo)) { playerAutoStarted = true; onActionClick(false); } else if (!imagesArrLocals.isEmpty()) { @@ -13147,7 +13163,7 @@ private void setIsAboutToSwitchToIndex(int index, boolean init, boolean animated countView.updateShow(size > 1, true); countView.set(switchingToIndex + 1, size); } - if (currentAnimation != null) { + if (currentAnimation != null || (!pageBlocksAdapter.isVideo(index) && pageBlocksAdapter.isHardwarePlayer(index))) { menuItem.hideSubItem(gallery_menu_save); if (allowShare) { menuItem.showSubItem(gallery_menu_savegif); @@ -13481,7 +13497,7 @@ private void setImageIndex(int index, boolean init, boolean animateCaption) { final TLRPC.PageBlock pageBlock = pageBlocksAdapter.get(currentIndex); sameImage = currentPageBlock != null && currentPageBlock == pageBlock; currentPageBlock = pageBlock; - isVideo = pageBlocksAdapter.isVideo(currentIndex); + isVideo = pageBlocksAdapter.isVideo(currentIndex) || pageBlocksAdapter.isHardwarePlayer(currentIndex); } setMenuItemIcon(false, true); @@ -13968,7 +13984,7 @@ private void checkProgress(int a, boolean scroll, boolean animated) { f2 = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), currentFileNames[a]); } else if (pageBlocksAdapter != null) { f1 = pageBlocksAdapter.getFile(index); - isVideo = pageBlocksAdapter.isVideo(index); + isVideo = pageBlocksAdapter.isVideo(index) || pageBlocksAdapter.isHardwarePlayer(index); canAutoPlay = shouldIndexAutoPlayed(index); } File f1Final = f1; @@ -14284,7 +14300,7 @@ private void setIndexToImage(ImageReceiver imageReceiver, int index, CropTransfo ImageLocation imageLocation = needFullImage ? ImageLocation.getForPhoto(fileLocation, photo) : null; imageReceiver.setImage(imageLocation, null, imageThumbLocation, "b", thumbPlaceHolder, size[0], null, pageBlocksAdapter.getParentObject(), 1); imageReceiver.setMark(needFullImage ? null : MARK_DEFERRED_IMAGE_LOADING); - } else if (pageBlocksAdapter.isVideo(index)) { + } else if (pageBlocksAdapter.isVideo(index) || pageBlocksAdapter.isHardwarePlayer(index)) { if (!(fileLocation.location instanceof TLRPC.TL_fileLocationUnavailable)) { ImageReceiver.BitmapHolder placeHolder = null; if (currentThumb != null && imageReceiver == centerImage) { @@ -14605,6 +14621,7 @@ public boolean openPhotoForSelect(final TLRPC.FileLocation fileLocation, final I } isVisible = true; + isVisibleOrAnimating = true; togglePhotosListView(false, false); @@ -14917,6 +14934,7 @@ public boolean openPhoto(final MessageObject messageObject, } isVisible = true; + isVisibleOrAnimating = true; togglePhotosListView(false, false); @@ -15459,6 +15477,7 @@ public void closePhoto(boolean animated, boolean fromEditMode) { qualityPicker.cancelButton.callOnClick(); return; } + isVisibleOrAnimating = false; openedFullScreenVideo = false; try { if (visibleDialog != null) { @@ -15529,6 +15548,9 @@ public void closePhoto(boolean animated, boolean fromEditMode) { view.setScaleY(1f); } } + if (placeProvider != null) { + placeProvider.onReleasePlayerBeforeClose(currentIndex); + } final PlaceProviderObject object = placeProvider.getPlaceForPhoto(currentMessageObject, getFileLocation(currentFileLocation), currentIndex, true); if (videoPlayer != null && object != null) { AnimatedFileDrawable animation = object.imageReceiver.getAnimation(); @@ -15917,6 +15939,7 @@ private void onPhotoClosed(PlaceProviderObject object) { FileLoader.getInstance(currentAccount).cancelLoadFile(currentMessageObject.getDocument()); } isVisible = false; + isVisibleOrAnimating = false; cropInitied = false; disableShowCheck = true; currentMessageObject = null; @@ -16608,7 +16631,7 @@ private boolean shouldMessageObjectAutoPlayed(MessageObject messageObject) { private boolean shouldIndexAutoPlayed(int index) { if (pageBlocksAdapter != null) { - if (pageBlocksAdapter.isVideo(index) && SharedConfig.isAutoplayVideo()) { + if ((pageBlocksAdapter.isVideo(index) || pageBlocksAdapter.isHardwarePlayer(index)) && SharedConfig.isAutoplayVideo()) { final File mediaFile = pageBlocksAdapter.getFile(index); if (mediaFile != null && mediaFile.exists()) { return true; @@ -17533,7 +17556,8 @@ private void onActionClick(boolean download) { } file = pageBlocksAdapter.getFile(currentIndex); if (file != null && !file.exists()) { - file = null; + uri = FileStreamLoadOperation.prepareUri(currentAccount, (TLRPC.Document) media, pageBlocksAdapter.getParentObject()); + isStreaming = true; } } else if (sendPhotoType == SELECT_TYPE_NO_SELECT) { if (!imagesArrLocals.isEmpty() && currentIndex >= 0 && currentIndex < imagesArrLocals.size()) { @@ -17586,6 +17610,7 @@ private void onActionClick(boolean download) { return; } preparePlayer(uri, true, false); + videoSizeSet = true; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java index f995c14dba..aab9968f2d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java @@ -53,6 +53,7 @@ public class PinchToZoomHelper { private ZoomOverlayView overlayView; private View child; private ImageReceiver childImage; + private TextureView childTextureView; private ImageReceiver fullImage = new ImageReceiver(); private ImageReceiver blurImage = new ImageReceiver(); @@ -116,7 +117,7 @@ public PinchToZoomHelper() { this.isSimple = true; } - public void startZoom(View child, ImageReceiver image, MessageObject messageObject) { + public void startZoom(View child, ImageReceiver image, TextureView textureView, MessageObject messageObject) { this.child = child; this.messageObject = messageObject; @@ -202,6 +203,7 @@ public void startZoom(View child, ImageReceiver image, MessageObject messageObje } else { isHardwareVideo = false; this.childImage = new ImageReceiver(); + this.childTextureView = textureView; this.childImage.onAttachedToWindow(); Drawable drawable = image.getDrawable(); this.childImage.setImageBitmap(drawable); @@ -584,6 +586,12 @@ private void drawImage(Canvas canvas) { fullImage.draw(canvas); } } + if (childTextureView != null) { + canvas.save(); + canvas.translate(childImage.getImageX(), childImage.getImageY()); + childTextureView.draw(canvas); + canvas.restore(); + } } else { videoPlayerContainer.setPivotX(pinchCenterX - imageX); videoPlayerContainer.setPivotY(pinchCenterY - imageY); @@ -708,7 +716,7 @@ public interface ClipBoundsListener { void getClipTopBottom(float[] topBottom); } - public boolean checkPinchToZoom(MotionEvent ev, View child, ImageReceiver image, MessageObject messageObject) { + public boolean checkPinchToZoom(MotionEvent ev, View child, ImageReceiver image, TextureView textureView, MessageObject messageObject) { if (!zoomEnabled(child, image)) { return false; } @@ -749,7 +757,7 @@ public boolean checkPinchToZoom(MotionEvent ev, View child, ImageReceiver image, pinchTranslationX = 0f; pinchTranslationY = 0f; child.getParent().requestDisallowInterceptTouchEvent(true); - startZoom(child, image, messageObject); + startZoom(child, image, textureView, messageObject); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 0a1979522f..62e328a5aa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -8307,7 +8307,9 @@ private void updateProfileData(boolean reload) { } onlineTextView[2].setVisibility(View.VISIBLE); - onlineTextView[3].setVisibility(View.VISIBLE); + if (!searchMode) { + onlineTextView[3].setVisibility(View.VISIBLE); + } if (previousTransitionFragment != null) { previousTransitionFragment.checkAndUpdateAvatar(); @@ -9065,6 +9067,7 @@ private Animator searchExpandTransition(boolean enter) { avatarContainer.setVisibility(View.VISIBLE); nameTextView[1].setVisibility(View.VISIBLE); onlineTextView[1].setVisibility(View.VISIBLE); + onlineTextView[3].setVisibility(View.VISIBLE); if (Math.min(1f, extraHeight / AndroidUtilities.dp(88f)) > 0.85 && !searchMode && NekoConfig.showIdAndDc.Bool()) idTextView.setVisibility(View.VISIBLE); @@ -9116,6 +9119,7 @@ private Animator searchExpandTransition(boolean enter) { } nameTextView[1].setAlpha(progressHalf); onlineTextView[1].setAlpha(progressHalf); + onlineTextView[3].setAlpha(progressHalf); idTextView.setAlpha(progressHalf); searchItem.getSearchField().setAlpha(progressHalfEnd); @@ -9195,6 +9199,7 @@ private void updateSearchViewState(boolean enter) { } nameTextView[1].setVisibility(hide); onlineTextView[1].setVisibility(hide); + onlineTextView[3].setVisibility(hide); idTextView.setVisibility(hide); if (otherItem != null) { 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 e272d3c673..69cb3b9f5e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java @@ -52,6 +52,7 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.ButtonBounce; @@ -333,7 +334,7 @@ private void openStoryForCell(StoryCell cell, boolean overscroll) { } return; } - if (!storiesController.hasStories(cell.dialogId)) { + if (!storiesController.hasStories(cell.dialogId) && (!cell.isSelf || !storiesController.hasUploadingStories())) { return; } TLRPC.TL_userStories userStories = storiesController.getStories(cell.dialogId); @@ -1075,6 +1076,7 @@ public class StoryCell extends FrameLayout { SimpleTextView textView; long dialogId; boolean isSelf; + boolean isFail; boolean crossfadeToDialog; long crossfadeToDialogId; @@ -1093,6 +1095,8 @@ public class StoryCell extends FrameLayout { private float overscrollProgress; private boolean selectedForOverscroll; + private final AnimatedFloat failT = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + public StoryCell(Context context) { super(context); params.isArchive = type == TYPE_ARCHIVE; @@ -1138,6 +1142,7 @@ public void setDialogId(long dialogId) { this.dialogId = dialogId; isSelf = dialogId == UserConfig.getInstance(currentAccount).getClientUserId(); + isFail = isSelf && storiesController.isLastUploadingFailed(); TLObject object; if (dialogId > 0) { object = user = MessagesController.getInstance(currentAccount).getUser(dialogId); @@ -1159,7 +1164,10 @@ public void setDialogId(long dialogId) { } if (dialogId == UserConfig.getInstance(currentAccount).getClientUserId()) { textView.setRightDrawable(null); - if (!storiesController.getUploadingStories().isEmpty()) { + if (storiesController.isLastUploadingFailed()) { + textView.setText(LocaleController.getString("FailedStory", R.string.FailedStory)); + isUploadingState = false; + } else if (!storiesController.getUploadingStories().isEmpty()) { StoriesUtilities.applyUploadingStr(textView, true, false); isUploadingState = true; } else if (storiesController.getEditingStory() != null) { @@ -1340,6 +1348,7 @@ protected void dispatchDraw(Canvas canvas) { drawCircleForce = true; invalidate(); } else { + float failT = this.failT.set(isFail); if (drawAvatar) { if (progressWasDrawn) { animateBounce(); @@ -1360,14 +1369,23 @@ public void onAnimationEnd(Animator animation) { valueAnimator.setDuration(100); valueAnimator.start(); } + failT *= params.progressToSegments; params.animate = !progressWasDrawn; params.progressToArc = getArcProgress(cx, radius); params.isLast = isLast; params.isFirst = isFirst; params.crossfadeToDialog = 0; + params.alpha = 1f - failT; + StoriesUtilities.drawAvatarWithStory(dialogId, canvas, avatarImage, storiesController.hasSelfStories(), params); - // avatarImage.draw(canvas); + + if (failT > 0) { + final Paint paint = StoriesUtilities.getErrorPaint(avatarImage); + paint.setStrokeWidth(AndroidUtilities.dp(2)); + paint.setAlpha((int) (0xFF * failT)); + canvas.drawCircle(x + finalSize / 2, y + finalSize / 2, (finalSize / 2 + AndroidUtilities.dp(4)) * params.getScale(), paint); + } } progressWasDrawn = false; if (drawAvatar) { @@ -1375,6 +1393,7 @@ public void onAnimationEnd(Animator animation) { float s = 1f - progressHalf; canvas.scale(s, s, cx + AndroidUtilities.dp(16), cy + AndroidUtilities.dp(16)); drawPlus(canvas, cx, cy, 1f); + drawFail(canvas, cx, cy, failT); canvas.restore(); } } @@ -1542,6 +1561,31 @@ public void drawPlus(Canvas canvas, float cx, float cy, float alpha) { addNewStoryDrawable.draw(canvas); } + public void drawFail(Canvas canvas, float cx, float cy, float alpha) { + if (!isSelf || alpha <= 0) { + return; + } + float cx2 = cx + AndroidUtilities.dp(17); + float cy2 = cy + AndroidUtilities.dp(17); + addCirclePaint.setColor(Theme.multAlpha(Theme.getColor(Theme.key_text_RedBold), alpha)); + if (type == TYPE_DIALOGS) { + backgroundPaint.setColor(Theme.multAlpha(Theme.getColor(Theme.key_actionBarDefault), alpha)); + } else { + backgroundPaint.setColor(Theme.multAlpha(Theme.getColor(Theme.key_actionBarDefaultArchived), alpha)); + } + float r = AndroidUtilities.dp(9) * CubicBezierInterpolator.EASE_OUT_BACK.getInterpolation(alpha); + canvas.drawCircle(cx2, cy2, r + AndroidUtilities.dp(2), backgroundPaint); + canvas.drawCircle(cx2, cy2, r, addCirclePaint); + + addCirclePaint.setColor(Theme.multAlpha(getTextColor(), alpha)); + + AndroidUtilities.rectTmp.set(cx2 - AndroidUtilities.dp(1), cy2 - AndroidUtilities.dpf2(4.6f), cx2 + AndroidUtilities.dp(1), cy2 + AndroidUtilities.dpf2(1.6f)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(3), AndroidUtilities.dp(3), addCirclePaint); + + AndroidUtilities.rectTmp.set(cx2 - AndroidUtilities.dp(1), cy2 + AndroidUtilities.dpf2(2.6f), cx2 + AndroidUtilities.dp(1), cy2 + AndroidUtilities.dpf2(2.6f + 2)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(3), AndroidUtilities.dp(3), addCirclePaint); + } + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); 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 edefe50176..3219c1a100 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java @@ -42,6 +42,7 @@ import android.view.TextureView; import android.view.View; import android.view.ViewGroup; +import android.view.ViewPropertyAnimator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -125,6 +126,7 @@ import org.telegram.ui.Components.LoadingDrawable; import org.telegram.ui.Components.MediaActivity; import org.telegram.ui.Components.MentionsContainerView; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; @@ -240,12 +242,15 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica Delegate delegate; private boolean paused; StoriesController storiesController; - private boolean isUploading, isEditing; + private boolean isUploading, isEditing, isFailed; private FrameLayout selfView; ChatActivityEnterView chatActivityEnterView; private ValueAnimator changeBoundAnimator; ReactionsContainerLayout reactionsContainerLayout; + private StoryFailView failView; + private ViewPropertyAnimator failViewAnimator; + Paint inputBackgroundPaint; int lastKeyboardHeight; @@ -431,12 +436,12 @@ protected void dispatchDraw(Canvas canvas) { imageReceiver.setImageCoords(0, 0, getMeasuredWidth(), getMeasuredHeight() + 1); imageReceiver.draw(canvas); if (isActive) { - if (storyViewer.USE_SURFACE_VIEW && playerSharedScope.player != null && playerSharedScope.player.paused && storyViewer.playerStubBitmap != null && playerSharedScope.player.stubAvailable) { - float sx = getMeasuredWidth() / (float) storyViewer.playerStubBitmap.getWidth(); - float sy = getMeasuredHeight() / (float) storyViewer.playerStubBitmap.getHeight(); + if (storyViewer.USE_SURFACE_VIEW && playerSharedScope.player != null && playerSharedScope.player.paused && playerSharedScope.player.playerStubBitmap != null && playerSharedScope.player.stubAvailable) { + float sx = getMeasuredWidth() / (float) playerSharedScope.player.playerStubBitmap.getWidth(); + float sy = getMeasuredHeight() / (float) playerSharedScope.player.playerStubBitmap.getHeight(); canvas.save(); canvas.scale(sx, sy); - canvas.drawBitmap(storyViewer.playerStubBitmap, 0, 0, storyViewer.playerStubPaint); + canvas.drawBitmap(playerSharedScope.player.playerStubBitmap, 0, 0, playerSharedScope.player.playerStubPaint); canvas.restore(); } else { if (!storyViewer.USE_SURFACE_VIEW || allowDrawSurface) { @@ -467,11 +472,11 @@ protected void dispatchDraw(Canvas canvas) { } boolean storyDrawing; if (currentStory.isVideo) { - storyDrawing = playerSharedScope.renderView != null && playerSharedScope.firstFrameRendered && !(playerSharedScope.player.progress == 0 && playerSharedScope.isBuffering()); + storyDrawing = playerSharedScope.renderView != null && playerSharedScope.player != null && playerSharedScope.firstFrameRendered && !(playerSharedScope.player.progress == 0 && playerSharedScope.isBuffering() && !playerSharedScope.player.paused); } else { storyDrawing = imageReceiver.hasNotThumb(); } - loadingDrawableAlpha2.set(!storyDrawing && currentStory.uploadingStory == null ? 1f : 0f); + loadingDrawableAlpha2.set(isActive && !storyDrawing && currentStory.uploadingStory == null ? 1f : 0f); loadingDrawableAlpha.set(loadingDrawableAlpha2.get() == 1f ? 1f : 0); if (loadingDrawableAlpha.get() > 0) { @@ -617,7 +622,7 @@ private void drawLines(Canvas canvas) { } } invalidate(); - } else if (!paused && isActive && !isUploading && !isEditing && imageReceiver.hasNotThumb()) { + } else if (!paused && isActive && !isUploading && !isEditing && !isFailed && imageReceiver.hasNotThumb()) { long currentTime = System.currentTimeMillis(); if (lastDrawTime != 0) { if (!isCaptionPartVisible) { @@ -638,7 +643,7 @@ private void drawLines(Canvas canvas) { switchEventSent = true; post(() -> { if (delegate != null) { - if (isUploading || isEditing) { + if (isUploading || isEditing || isFailed) { if (currentStory.isVideo()) { playerSharedScope.player.loopBack(); } else { @@ -951,6 +956,17 @@ protected void onCreate(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLay if (isSelf) { TLRPC.StoryItem storyItem = currentStory.storyItem; if (currentStory.uploadingStory != null) { +// if (currentStory.uploadingStory.failed) { +// ActionBarMenuSubItem item = ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_edit, LocaleController.getString("Edit", R.string.Edit), false, resourcesProvider); +// item.setOnClickListener(v -> { +// Activity activity = AndroidUtilities.findActivity(context); +// if (activity == null) { +// return; +// } +// StoryRecorder.getInstance(activity, currentAccount) +// .openEdit(StoryRecorder.SourceView.fromStoryViewer(storyViewer), currentStory.uploadingStory.entry, 0, true); +// }); +// } ActionBarMenuSubItem item = ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_cancel, LocaleController.getString("Cancel", R.string.Cancel), false, resourcesProvider); item.setOnClickListener(v -> { if (currentStory.uploadingStory != null) { @@ -1079,7 +1095,9 @@ protected void onCreate(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLay }); } - createStealthModeItem(popupLayout); + if (!MessagesController.getInstance(currentAccount).premiumLocked) { + createStealthModeItem(popupLayout); + } if (allowShareLink) { ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_shareout, LocaleController.getString("BotShare", R.string.BotShare), false, resourcesProvider).setOnClickListener(v -> { @@ -1171,7 +1189,7 @@ protected void onCreate(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLay popupMenu.dismiss(); } }); - } else { + } else if (!MessagesController.getInstance(currentAccount).premiumLocked) { Drawable lockIcon = ContextCompat.getDrawable(context, R.drawable.msg_gallery_locked2); lockIcon.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(Color.WHITE, Color.BLACK, 0.5f), PorterDuff.Mode.MULTIPLY)); CombinedDrawable combinedDrawable = new CombinedDrawable( @@ -1200,7 +1218,9 @@ public void setColorFilter(ColorFilter colorFilter) { } } - createStealthModeItem(popupLayout); + if (!MessagesController.getInstance(currentAccount).premiumLocked) { + createStealthModeItem(popupLayout); + } if (allowShareLink) { ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_link, LocaleController.getString("CopyLink", R.string.CopyLink), false, resourcesProvider).setOnClickListener(v -> { AndroidUtilities.addToClipboard(currentStory.createLink()); @@ -1628,6 +1648,22 @@ private boolean drawLinesAsCounter() { return false;//linesCount > 20; } + private void createFailView() { + if (failView != null) { + return; + } + failView = new StoryFailView(getContext(), resourcesProvider); + failView.setOnClickListener(v -> { + if (currentStory != null && currentStory.uploadingStory != null) { + currentStory.uploadingStory.tryAgain(); + updatePosition(); + } + }); + failView.setAlpha(0f); + failView.setVisibility(View.GONE); + addView(failView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 0)); + } + private void createEnterView() { Theme.ResourcesProvider emojiResourceProvider = new WrappedResourceProvider(resourcesProvider) { @Override @@ -1960,7 +1996,7 @@ public void sendBotInlineResult(TLRPC.BotInlineResult result, boolean notify, in params.put("query_id", "" + result.query_id); params.put("bot", "" + uid); params.put("bot_name", mentionContainer.getAdapter().getContextBotName()); - SendMessagesHelper.prepareSendingBotContextResult(storyViewer.fragment, getAccountInstance(), result, params, dialogId, null, null, null, notify, scheduleDate); + SendMessagesHelper.prepareSendingBotContextResult(storyViewer.fragment, getAccountInstance(), result, params, dialogId, null, null, currentStory.storyItem, notify, scheduleDate); chatActivityEnterView.setFieldText(""); afterMessageSend(); MediaDataController.getInstance(currentAccount).increaseInlineRaiting(uid); @@ -2372,14 +2408,15 @@ private void bindInternal(int startFromPosition) { if (chatActivityEnterView == null) { createEnterView(); } + if (failView != null) { + failView.setVisibility(View.GONE); + } if (startFromPosition == -1) { updateSelectedPosition(); } if (chatActivityEnterView != null) { chatActivityEnterView.setVisibility(View.VISIBLE); - if (!TextUtils.isEmpty(chatActivityEnterView.getEditField().getText())) { - chatActivityEnterView.getEditField().setText(""); - } + chatActivityEnterView.getEditField().setText(storyViewer.getDraft(dialogId, currentStory.storyItem)); chatActivityEnterView.setDialogId(dialogId, currentAccount); TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(dialogId); if (userFull != null) { @@ -2717,6 +2754,7 @@ protected void onAttachedToWindow() { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storiesUpdated); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storiesListUpdated); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.stealthModeChanged); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storiesLimitUpdate); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); } @@ -2744,6 +2782,7 @@ protected void onDetachedFromWindow() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storiesUpdated); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storiesListUpdated); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.stealthModeChanged); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storiesLimitUpdate); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); } @@ -2782,6 +2821,44 @@ public void didReceivedNotification(int id, int account, Object... args) { storyCaptionView.captionTextview.invalidate(); } else if (id == NotificationCenter.stealthModeChanged) { checkStealthMode(true); + } else if (id == NotificationCenter.storiesLimitUpdate) { + StoriesController.StoryLimit storyLimit = MessagesController.getInstance(currentAccount).getStoriesController().checkStoryLimit(); + if (storyLimit == null || delegate == null) { + return; + } + final Activity activity = storyViewer != null && storyViewer.parentActivity != null ? storyViewer.parentActivity : AndroidUtilities.findActivity(getContext()); + if (activity == null) { + return; + } + final LimitReachedBottomSheet sheet = new LimitReachedBottomSheet(new BaseFragment() { + @Override + public boolean isLightStatusBar() { + return false; + } + + @Override + public Activity getParentActivity() { + return activity; + } + + @Override + public Theme.ResourcesProvider getResourceProvider() { + return new WrappedResourceProvider(resourcesProvider) { + @Override + public void appendColors() { + sparseIntArray.append(Theme.key_dialogBackground, 0xFF1F1F1F); + sparseIntArray.append(Theme.key_windowBackgroundGray, 0xFF333333); + } + }; + } + + @Override + public boolean presentFragment(BaseFragment fragment) { + storyViewer.presentFragment(fragment); + return true; + } + }, activity, storyLimit.getLimitReachedType(), currentAccount); + delegate.showDialog(sheet); } } @@ -2830,6 +2907,7 @@ private void updatePosition(boolean preload) { final boolean wasUploading = isUploading; final boolean wasEditing = isEditing; + final boolean wasFailed = isFailed; currentStory.editingSourceItem = null; if (!uploadingStories.isEmpty() && position >= storyItems.size()) { @@ -2840,6 +2918,8 @@ private void updatePosition(boolean preload) { return; } StoriesController.UploadingStory uploadingStory = uploadingStories.get(position); + isFailed = uploadingStory.failed; + isUploading = !isFailed; Drawable thumbDrawable = null; imageReceiver.setCrossfadeWithOldImage(false); imageReceiver.setCrossfadeDuration(ImageReceiver.DEFAULT_CROSSFADE_DURATION); @@ -2848,7 +2928,7 @@ private void updatePosition(boolean preload) { Utilities.blurBitmap(blurredBitmap, 3, 1, blurredBitmap.getWidth(), blurredBitmap.getHeight(), blurredBitmap.getRowBytes()); thumbDrawable = new BitmapDrawable(blurredBitmap); } - if (uploadingStory.isVideo) { + if (uploadingStory.isVideo || uploadingStory.hadFailed) { imageReceiver.setImage(null, null, ImageLocation.getForPath(uploadingStory.firstFramePath), filter, null, null, thumbDrawable, 0, null, null, 0); } else { imageReceiver.setImage(null, null, ImageLocation.getForPath(uploadingStory.path), filter, null, null, thumbDrawable, 0, null, null, 0); @@ -2859,6 +2939,7 @@ private void updatePosition(boolean preload) { } else { isUploading = false; isEditing = false; + isFailed = false; if (position < 0 || position > storyItems.size() - 1) { storyViewer.close(true); return; @@ -2968,7 +3049,7 @@ private void updatePosition(boolean preload) { final boolean sameId = getStoryId(currentStory.storyItem, currentStory.uploadingStory) == getStoryId(oldStoryItem, oldUploadingStory) || oldUploadingStory != null && currentStory.storyItem != null && TextUtils.equals(oldUploadingStory.path, currentStory.storyItem.attachPath); - final boolean animateSubtitle = sameId && (isEditing != wasEditing || isUploading != wasUploading); + final boolean animateSubtitle = sameId && (isEditing != wasEditing || isUploading != wasUploading || isFailed != wasFailed); boolean storyChanged = false; if (!( @@ -2977,7 +3058,10 @@ private void updatePosition(boolean preload) { )) { storyChanged = true; if (chatActivityEnterView != null) { - chatActivityEnterView.getEditField().setText(""); + if (oldStoryItem != null) { + storyViewer.saveDraft(oldStoryItem.dialogId, oldStoryItem, chatActivityEnterView.getEditField().getText()); + } + chatActivityEnterView.getEditField().setText(storyViewer.getDraft(dialogId, currentStory.storyItem)); } currentImageTime = 0; switchEventSent = false; @@ -2997,7 +3081,11 @@ private void updatePosition(boolean preload) { if (storyChanged || oldUploadingStory != null && currentStory.uploadingStory == null) { if (currentStory.uploadingStory != null) { - headerView.setSubtitle(StoriesUtilities.getUploadingStr(headerView.subtitleView[0], false, isEditing), animateSubtitle); + if (currentStory.uploadingStory.failed) { + headerView.setSubtitle(LocaleController.getString("FailedToUploadStory", R.string.FailedToUploadStory), animateSubtitle); + } else { + headerView.setSubtitle(StoriesUtilities.getUploadingStr(headerView.subtitleView[0], false, isEditing), animateSubtitle); + } } else if (currentStory.storyItem != null) { if (currentStory.storyItem.date == -1) { headerView.setSubtitle(LocaleController.getString("CachedStory", R.string.CachedStory)); @@ -3144,26 +3232,36 @@ private void updatePosition(boolean preload) { } } -// final boolean closeFriends = currentStory.forCloseFriends(); -// if (oldStoryItem != null && currentStory.storyItem != null && oldStoryItem.id == currentStory.storyItem.id) { -// if (closeFriends) { -// closeFriendsBadge.setVisibility(View.VISIBLE); -// } -// closeFriendsBadge.clearAnimation(); -// closeFriendsBadge.animate().scaleX(closeFriends ? 1 : 0).scaleY(closeFriends ? 1 : 0).withEndAction(() -> { -// if (!closeFriends) { -// closeFriendsBadge.setVisibility(View.GONE); -// } -// }).setInterpolator(closeFriends ? new OvershootInterpolator(3) : CubicBezierInterpolator.DEFAULT).setDuration(closeFriends ? 240 : 120).start(); -// } else { -// closeFriendsBadge.setScaleX(closeFriends ? 1 : 0); -// closeFriendsBadge.setScaleY(closeFriends ? 1 : 0); -// closeFriendsBadge.setVisibility(currentStory.forCloseFriends() ? View.VISIBLE : View.GONE); -// } -// closeFriendsBadge.setTranslationX(muteIconContainer.getVisibility() == View.VISIBLE ? -AndroidUtilities.dp(44) : 0); - //sharedResources.muteDrawable.setIcon(storyViewer.soundEnabled() ? R.drawable.media_mute : R.drawable.media_unmute, false); - sharedResources.setIconMuted(!storyViewer.soundEnabled(), false); + if (currentStory.uploadingStory != null && currentStory.uploadingStory.failed) { + createFailView(); + failView.set(currentStory.uploadingStory.entry.error); + failView.setVisibility(View.VISIBLE); + if (failViewAnimator != null) { + failViewAnimator.cancel(); + failViewAnimator = null; + } + if (sameId) { + failViewAnimator = failView.animate().alpha(1f).setDuration(180).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + failViewAnimator.start(); + } else { + failView.setAlpha(1f); + } + } else if (failView != null) { + if (failViewAnimator != null) { + failViewAnimator.cancel(); + failViewAnimator = null; + } + if (sameId) { + failView.setVisibility(View.VISIBLE); + failViewAnimator = failView.animate().alpha(0f).setDuration(180).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).withEndAction(() -> failView.setVisibility(View.GONE)); + failViewAnimator.start(); + } else { + failView.setAlpha(0f); + failView.setVisibility(View.GONE); + } + } + sharedResources.setIconMuted(!storyViewer.soundEnabled(), false); if (isActive && currentStory.storyItem != null) { FileLog.d("StoryViewer displayed story dialogId=" + dialogId + " storyId=" + currentStory.storyItem.id); } @@ -3244,6 +3342,9 @@ private void updatePreloadImages() { StoriesController.UploadingStory uploadingStory = uploadingStories.get(position); setStoryImage(uploadingStory, imageReceiver, filter); } else { + if (storyItems.isEmpty()) { + continue; + } if (position < 0) { position = 0; } @@ -3654,6 +3755,9 @@ public void setActive(long t, boolean active) { updatePreloadImages(); muteIconView.setAnimation(sharedResources.muteDrawable); isActive = true; + if (currentStory.storyItem != null) { + FileLog.d("StoryViewer displayed story dialogId=" + dialogId + " storyId=" + currentStory.storyItem.id); + } //storyViewer.allowScreenshots(allowScreenshots); } else { @@ -3809,7 +3913,7 @@ public boolean showKeyboard() { } public void checkPinchToZoom(MotionEvent ev) { - pinchToZoomHelper.checkPinchToZoom(ev, storyContainer, null, null); + pinchToZoomHelper.checkPinchToZoom(ev, storyContainer, null, null,null); } @@ -4056,7 +4160,7 @@ public void drawUploadingProgress(Canvas canvas, RectF rect, boolean allowDraw, if ((storyItemHolder != null && storyItemHolder.uploadingStory != null) || progressToUploading != 0) { float progress = 1f; final boolean disappearing; - if (storyItemHolder != null && storyItemHolder.uploadingStory != null) { + if (storyItemHolder != null && storyItemHolder.uploadingStory != null && !storyItemHolder.uploadingStory.failed) { progressToUploading = 1f; progress = storyItemHolder.uploadingStory.progress; disappearing = false; @@ -4451,6 +4555,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { lastOpenedKeyboardHeight = keyboardHeight; checkReactionsLayout(); ReactionsEffectOverlay.dismissAll(); + } else { + storyViewer.saveDraft(dialogId, currentStory.storyItem, chatActivityEnterView.getEditText()); } if (keyboardVisible && mentionContainer != null) { mentionContainer.setVisibility(View.VISIBLE); @@ -4882,6 +4988,7 @@ private void afterMessageSend() { instantCameraView.resetCameraFile(); instantCameraView.cancel(false); } + storyViewer.clearDraft(dialogId, currentStory.storyItem); messageSent = true; storyViewer.closeKeyboardOrEmoji(); BulletinFactory bulletinFactory = BulletinFactory.of(storyContainer, resourcesProvider); @@ -5152,7 +5259,7 @@ public void onAnimationEnd(Animator animation) { @Override public boolean needEnterText() { - delegate.requestAdjust(true); + delegate.requestAdjust(false); return false; } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java index d9a266178d..43b959a42e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java @@ -840,7 +840,7 @@ public boolean findView(long dialogId, int messageId, int storyId, int type, Sto if (a != null && b != null) { final RectF aRect = new RectF(a.cachedRect), bRect = new RectF(b.cachedRect); final StoryCircle circle = a, nextCircle = b; - holder.drawClip = (canvas, bounds, alpha) -> { + holder.drawClip = (canvas, bounds, alpha, opening) -> { aRect.set(circle.cachedRect); bRect.set(nextCircle.cachedRect); circle.cachedRect.set(bounds); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java index f060affe93..567625ec58 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java @@ -642,7 +642,7 @@ public void onDataRecieved(ViewsModel model) { updateViewsVisibility(); } listAdapter.updateRows(); - recyclerItemsEnterAnimator.showItemsAnimated(oldCount); + recyclerItemsEnterAnimator.showItemsAnimated(oldCount - 1); checkLoadMore(); // }); } @@ -742,8 +742,15 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { view = new ReactedUserHolderView(ReactedUserHolderView.STYLE_STORY, currentAccount, getContext(), resourcesProvider) { @Override public void openStory(long dialogId, Runnable onDone) { - LaunchActivity.getLastFragment().getOrCreateOverlayStoryViewer().doOnAnimationReady(onDone); - LaunchActivity.getLastFragment().getOrCreateOverlayStoryViewer().open(getContext(), dialogId, StoriesListPlaceProvider.of(recyclerListView)); + BaseFragment lastFragment = LaunchActivity.getLastFragment(); + if (lastFragment == null) { + return; + } + if (lastFragment.getOrCreateOverlayStoryViewer().isShowing) { + return; + } + lastFragment.getOrCreateOverlayStoryViewer().doOnAnimationReady(onDone); + lastFragment.getOrCreateOverlayStoryViewer().open(getContext(), dialogId, StoriesListPlaceProvider.of(recyclerListView)); } }; break; @@ -830,14 +837,12 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { emptyView.title.setVisibility(View.GONE); SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); spannableStringBuilder.append(AndroidUtilities.replaceTags(LocaleController.getString("ExpiredViewsStub", R.string.ExpiredViewsStub))); - spannableStringBuilder.append("\n\n"); - spannableStringBuilder.append(AndroidUtilities.replaceSingleTag(LocaleController.getString("ExpiredViewsStubPremiumDescription", R.string.ExpiredViewsStubPremiumDescription), () -> { - showPremiumAlert(); - })); + if (!MessagesController.getInstance(currentAccount).premiumLocked) { + spannableStringBuilder.append("\n\n"); + spannableStringBuilder.append(AndroidUtilities.replaceSingleTag(LocaleController.getString("ExpiredViewsStubPremiumDescription", R.string.ExpiredViewsStubPremiumDescription), SelfStoryViewsPage.this::showPremiumAlert)); + emptyView.createButtonLayout(LocaleController.getString("LearnMore", R.string.LearnMore), SelfStoryViewsPage.this::showPremiumAlert); + } emptyView.subtitle.setText(spannableStringBuilder); - emptyView.createButtonLayout(LocaleController.getString("LearnMore", R.string.LearnMore), () -> { - showPremiumAlert(); - }); } else { emptyView.title.setVisibility(View.VISIBLE); emptyView.title.setText(LocaleController.getString("NoViews", R.string.NoViews)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java index 2f5f5e1f4a..ff177e741f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java @@ -312,7 +312,8 @@ public void setOffset(float selfStoriesViewsOffset) { final PeerStoriesView currentView = storyViewer.getCurrentPeerView(); if (oldProgressToOpen == 1f && progressToOpen != 1f) { if (storyViewer.storiesList != null) { - MessageObject object = storyViewer.storiesList.messageObjects.get(selfStoriesPreviewView.getClosestPosition()); + int p = Utilities.clamp(selfStoriesPreviewView.getClosestPosition(), storyViewer.storiesList.messageObjects.size() - 1, 0); + MessageObject object = storyViewer.storiesList.messageObjects.get(p); long date = StoriesController.StoriesList.day(object); if (storyViewer.transitionViewHolder.storyImage != null) { storyViewer.transitionViewHolder.storyImage.setVisible(true, true); 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 66328c894f..7a366c532a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java @@ -8,6 +8,7 @@ import android.webkit.MimeTypeMap; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.collection.LongSparseArray; import com.google.android.exoplayer2.util.Consumer; @@ -201,9 +202,11 @@ private void fixDeletedAndNonContactsStories(ArrayList lis for (int k = 0; k < list.size(); k++) { TLRPC.TL_userStories userStories = list.get(k); TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(userStories.user_id); + boolean removed = false; if (user != null && !isContactOrService(user)) { list.remove(k); k--; + removed = true; } for (int i = 0; i < userStories.stories.size(); i++) { if (userStories.stories.get(i) instanceof TLRPC.TL_storyItemDeleted) { @@ -211,7 +214,7 @@ private void fixDeletedAndNonContactsStories(ArrayList lis i--; } } - if (userStories.stories.isEmpty()) { + if (!removed && userStories.stories.isEmpty()) { list.remove(k); k--; } @@ -225,6 +228,9 @@ public DraftsController getDraftsController() { public boolean hasStories(long dialogId) { if (NaConfig.INSTANCE.getDisableStories().Bool()) return false; + if (getSelfUserId() == dialogId && hasUploadingStories()) { + return true; + } TLRPC.TL_userStories stories = allStoriesMap.get(dialogId); return stories != null && !stories.stories.isEmpty(); } @@ -393,8 +399,16 @@ private void processAllStoriesResponse(TLRPC.TL_stories_allStories storiesRespon hiddenListStories.clear(); } } - FileLog.d("StoriesController processAllStoriesResponse " + storiesResponse.user_stories.size() + " " + fromCache + " " + hidden); - + if (BuildVars.LOGS_ENABLED) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < storiesResponse.user_stories.size(); i++) { + if (builder.length() != 0) { + builder.append(", "); + } + builder.append(storiesResponse.user_stories.get(i).user_id); + } + FileLog.d("StoriesController cache=" + fromCache + " hidden=" + hidden + " processAllStoriesResponse {" + builder + "}"); + } MessagesController.getInstance(currentAccount).putUsers(storiesResponse.users, fromCache); for (int i = 0; i < storiesResponse.user_stories.size(); i++) { @@ -410,14 +424,12 @@ private void processAllStoriesResponse(TLRPC.TL_stories_allStories storiesRespon allStoriesMap.put(userStories.user_id, userStories); for (int k = 0; k < 2; k++) { ArrayList storiesList = k == 0 ? hiddenListStories : dialogListStories; - // if (isNext) { - for (int j = 0; j < storiesList.size(); j++) { - if (storiesList.get(j).user_id == userStories.user_id) { - storiesList.remove(j); - break; - } + for (int j = 0; j < storiesList.size(); j++) { + if (storiesList.get(j).user_id == userStories.user_id) { + storiesList.remove(j); + break; } - // } + } } TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(userStories.user_id); if (user == null) { @@ -527,6 +539,13 @@ public void uploadStory(StoryEntry entry, boolean count) { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated); } + public void putUploadingDrafts(ArrayList entries) { + for (StoryEntry entry : entries) { + uploadingStories.add(new UploadingStory(entry)); + } + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated); + } + public ArrayList getDialogListStories() { return dialogListStories; } @@ -539,6 +558,13 @@ public ArrayList getUploadingStories() { return uploadingStories; } + public boolean isLastUploadingFailed() { + if (uploadingStories.isEmpty()) { + return false; + } + return uploadingStories.get(uploadingStories.size() - 1).failed; + } + public ArrayList getUploadingAndEditingStories() { return uploadingAndEditingStories; } @@ -914,7 +940,9 @@ public boolean markStoryAsRead(long dialogId, TLRPC.StoryItem storyItem) { TLRPC.TL_userStories userStories = getStories(dialogId); if (userStories == null) { TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(dialogId); - userStories = userFull.stories; + if (userFull != null) { + userStories = userFull.stories; + } } return markStoryAsRead(userStories, storyItem, false); } @@ -1366,13 +1394,17 @@ public class UploadingStory implements NotificationCenter.NotificationCenterDele private boolean putMessages; private boolean isCloseFriends; + public boolean hadFailed; + public boolean failed; + public UploadingStory(StoryEntry entry) { + this.entry = entry; random_id = Utilities.random.nextLong(); edit = entry.isEdit; - this.entry = entry; if (entry.uploadThumbFile != null) { this.firstFramePath = entry.uploadThumbFile.getAbsolutePath(); } + failed = hadFailed = entry.isError; } private void startForeground() { @@ -1430,6 +1462,21 @@ public void start() { startForeground(); } + public void tryAgain() { + failed = false; + entryDestroyed = false; + progress = 0; + uploadProgress = 0; + convertingProgress = 0; + if (path != null) { + try { + new File(path).delete(); + path = null; + } catch (Exception ignore) {} + } + start(); + } + private void upload() { if (entry.shareUserIds != null) { putMessages(); @@ -1445,7 +1492,9 @@ public void cleanup() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.filePreparingStarted); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileNewChunkAvailable); - uploadingStories.remove(UploadingStory.this); + if (!failed) { + uploadingStories.remove(UploadingStory.this); + } uploadingAndEditingStories.remove(UploadingStory.this); if (edit) { editingStories.remove(entry.editStoryId); @@ -1489,7 +1538,15 @@ public void didReceivedNotification(int id, int account, Object... args) { } } else if (id == NotificationCenter.filePreparingFailed) { if (args[0] == messageObject) { - // TODO + if (!edit) { + entry.isError = true; + entry.error = new TLRPC.TL_error(); + entry.error.code = 400; + entry.error.text = "FILE_PREPARE_FAILED"; + entryDestroyed = true; + hadFailed = failed = true; + getDraftsController().edit(entry); + } cleanup(); } } else if (id == NotificationCenter.fileUploaded) { @@ -1664,8 +1721,9 @@ private void sendUploadedRequest(TLRPC.InputFile uploadedFile) { req = sendStory; } - currentRequest = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + final RequestDelegate requestDelegate = (response, error) -> { if (response != null) { + failed = false; TLRPC.Updates updates = (TLRPC.Updates) response; int storyId = 0; TLRPC.StoryItem storyItem = null; @@ -1718,6 +1776,11 @@ private void sendUploadedRequest(TLRPC.InputFile uploadedFile) { final TLRPC.StoryItem storyItemFinal = storyItem; AndroidUtilities.runOnUIThread(() -> { entryDestroyed = true; + if (entry.isError) { + getDraftsController().delete(entry); + } + entry.isError = false; + entry.error = null; getDraftsController().saveForEdit(entry, did, storyItemFinal); if (!edit) { invalidateStoryLimit(); @@ -1725,10 +1788,31 @@ private void sendUploadedRequest(TLRPC.InputFile uploadedFile) { }); MessagesController.getInstance(currentAccount).processUpdateArray(updates.updates, updates.users, updates.chats, false, updates.date); } + } else if (error != null && !edit) { + AndroidUtilities.runOnUIThread(() -> { + entry.isError = true; + if (checkStoryError(error)) { + entry.error = null; + } else { + entry.error = error; + } + entryDestroyed = true; + hadFailed = failed = true; + getDraftsController().edit(entry); + }); } AndroidUtilities.runOnUIThread(this::cleanup); - }); + }; + + if (BuildVars.DEBUG_PRIVATE_VERSION && !edit && entry.caption != null && entry.caption.toString().contains("#failtest") && !hadFailed) { + TLRPC.TL_error error = new TLRPC.TL_error(); + error.code = 400; + error.text = "FORCED_TO_FAIL"; + requestDelegate.run(null, error); + } else { + currentRequest = ConnectionsManager.getInstance(currentAccount).sendRequest(req, requestDelegate); + } } private void putMessages() { @@ -1750,6 +1834,10 @@ private void putMessages() { } public void cancel() { + if (failed) { + getDraftsController().delete(entry); + uploadingStories.remove(UploadingStory.this); + } canceled = true; if (entry.wouldBeVideo()) { MediaController.getInstance().cancelVideoConvert(messageObject); @@ -1768,12 +1856,16 @@ public boolean isCloseFriends() { private final HashMap[] storiesLists = new HashMap[2]; - @NonNull + @Nullable public StoriesList getStoriesList(long userId, int type) { return getStoriesList(userId, type, true); } + @Nullable private StoriesList getStoriesList(long userId, int type, boolean createIfNotExist) { + if (type == StoriesList.TYPE_ARCHIVE && userId != getSelfUserId()) { + return null; + } if (storiesLists[type] == null) { storiesLists[type] = new HashMap<>(); } @@ -2716,26 +2808,49 @@ public StoryLimit checkStoryLimit() { storyLimitFetched = true; if (res instanceof TLRPC.TL_boolTrue) { storyLimitCached = null; - } else if (err != null && err.text != null) { - if (err.text.startsWith("STORY_SEND_FLOOD_WEEKLY_")) { - long until = 0; - try { - until = Long.parseLong(err.text.substring("STORY_SEND_FLOOD_WEEKLY_".length())); - } catch (Exception ignore) {} - storyLimitCached = new StoryLimit(StoryLimit.LIMIT_WEEK, until); - } else if (err.text.startsWith("STORY_SEND_FLOOD_MONTHLY_")) { - long until = 0; - try { - until = Long.parseLong(err.text.substring("STORY_SEND_FLOOD_MONTHLY_".length())); - } catch (Exception ignore) {} - storyLimitCached = new StoryLimit(StoryLimit.LIMIT_MONTH, until); - } + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesLimitUpdate); + } else { + checkStoryError(err); } - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesLimitUpdate); - })); + }), ConnectionsManager.RequestFlagDoNotWaitFloodWait); return null; } + public boolean checkStoryError(TLRPC.TL_error err) { + boolean limitUpdate = false; + if (err != null && err.text != null) { + if (err.text.startsWith("STORY_SEND_FLOOD_WEEKLY_")) { + long until = 0; + try { + until = Long.parseLong(err.text.substring("STORY_SEND_FLOOD_WEEKLY_".length())); + } catch (Exception ignore) {} + storyLimitCached = new StoryLimit(StoryLimit.LIMIT_WEEK, until); + limitUpdate = true; + } else if (err.text.startsWith("STORY_SEND_FLOOD_MONTHLY_")) { + long until = 0; + try { + until = Long.parseLong(err.text.substring("STORY_SEND_FLOOD_MONTHLY_".length())); + } catch (Exception ignore) {} + storyLimitCached = new StoryLimit(StoryLimit.LIMIT_MONTH, until); + limitUpdate = true; + } else if (err.text.equals("STORIES_TOO_MUCH")) { + storyLimitCached = new StoryLimit(StoryLimit.LIMIT_COUNT, 0); + limitUpdate = true; + } else if (err.text.equals("PREMIUM_ACCOUNT_REQUIRED")) { + MessagesController mc = MessagesController.getInstance(currentAccount); + if ("enabled".equals(mc.storiesPosting)) { + mc.getMainSettings().edit().putString("storiesPosting", mc.storiesPosting = "premium").apply(); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesEnabledUpdate); + } + limitUpdate = true; + } + } + if (limitUpdate) { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesLimitUpdate); + } + return limitUpdate; + } + public boolean hasStoryLimit() { StoryLimit storyLimit = checkStoryLimit(); return storyLimit != null && storyLimit.active(currentAccount); 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 b3e0e61cb5..e5ddb45c86 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java @@ -1,7 +1,11 @@ package org.telegram.ui.Stories; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Region; import android.view.View; import org.telegram.messenger.AndroidUtilities; @@ -9,6 +13,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ChatActionCell; @@ -102,12 +107,23 @@ public boolean findView(long dialogId, int messageId, int storyId, int type, Sto holder.clipParent = storiesCell; holder.clipTop = holder.clipBottom = 0; holder.alpha = 1; + if (cell.isFail) { + final Path path = new Path(); + holder.drawClip = (canvas, bounds, alpha, opening) -> { + path.rewind(); + final float t = opening ? 1f - (float) Math.pow(1f - alpha, 2) : (float) Math.pow(alpha, 2); + path.addCircle(bounds.right + dp(7) - dp(14) * t, bounds.bottom + dp(7) - dp(14) * t, dp(11), Path.Direction.CW); + canvas.clipPath(path, Region.Op.DIFFERENCE); + }; + } else { + holder.drawClip = null; + } // updateClip(holder); return true; } } else if (child instanceof DialogCell) { DialogCell cell = (DialogCell) child; - if (cell.getDialogId() == dialogId || (isHiddenArchive && cell.isDialogFolder())) { + if ((cell.getDialogId() == dialogId && !isHiddenArchive) || (isHiddenArchive && cell.isDialogFolder())) { holder.view = child; holder.params = cell.storyParams; holder.avatarImage = cell.avatarImage; @@ -162,7 +178,7 @@ public boolean findView(long dialogId, int messageId, int storyId, int type, Sto } holder.view = child; holder.storyImage = cell.imageReceiver; - holder.drawAbove = (canvas, bounds, alpha) -> { + holder.drawAbove = (canvas, bounds, alpha, opening) -> { 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); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesStorage.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesStorage.java index 8f5016e4de..ff3012f0a5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesStorage.java @@ -281,11 +281,11 @@ public void saveAllStories(ArrayList user_stories, boolean } if (!isNext) { try { - SQLiteCursor cursor = database.queryFinalized("SELECT dialog_id FROM stories"); + SQLiteCursor cursor = database.queryFinalized("SELECT DISTINCT dialog_id FROM stories"); ArrayList dialogsToDelete = new ArrayList<>(); while (cursor.next()) { - long dialogId = cursor.longValue(1); + long dialogId = cursor.longValue(0); TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); if (user == null) { user = MessagesStorage.getInstance(currentAccount).getUser(dialogId); 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 d6e194a176..ffc587f1ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java @@ -61,6 +61,7 @@ public class StoriesUtilities { public static final int STATE_PROGRESS = 3; public static GradientTools[] storiesGradientTools = new GradientTools[2]; public static GradientTools closeFriendsGradientTools; + public static GradientTools errorGradientTools; public static Paint grayPaint; public static Paint closeFriendsLastColor; @@ -209,9 +210,9 @@ public static void drawAvatarWithStory(long dialogId, Canvas canvas, ImageReceiv float inset = params.isStoryCell ? -AndroidUtilities.dp(4) : 0;//AndroidUtilities.lerp(AndroidUtilities.dp(2), 0, imageScale); if (animateOut) { inset += AndroidUtilities.dp(5) * progressToSate; - gradientTools.paint.setAlpha((int) (255 * (1f - progressToSate))); + gradientTools.paint.setAlpha((int) (0xFF * params.alpha * (1f - progressToSate))); } else { - gradientTools.paint.setAlpha((int) (255 * progressToSate)); + gradientTools.paint.setAlpha((int) (0xFF * params.alpha * progressToSate)); inset += AndroidUtilities.dp(5) * (1f - progressToSate); } rectTmp.set(params.originalAvatarRect); @@ -233,9 +234,9 @@ public static void drawAvatarWithStory(long dialogId, Canvas canvas, ImageReceiv Paint closeFriendsPaint = null; if (params.drawSegments) { unreadPaint = getActiveCirclePaint(avatarImage, params.isStoryCell); - unreadPaint.setAlpha(255); + unreadPaint.setAlpha((int) (0xFF * params.alpha)); closeFriendsPaint = getCloseFriendsPaint(avatarImage); - closeFriendsPaint.setAlpha(255); + closeFriendsPaint.setAlpha((int) (0xFF * params.alpha)); checkGrayPaint(params.resourcesProvider); } float inset; @@ -246,9 +247,9 @@ public static void drawAvatarWithStory(long dialogId, Canvas canvas, ImageReceiv } if (animateOut) { inset += AndroidUtilities.dp(5) * progressToSate; - paint.setAlpha((int) (255 * (1f - progressToSate))); + paint.setAlpha((int) (0xFF * params.alpha * (1f - progressToSate))); } else { - paint.setAlpha((int) (255 * progressToSate)); + paint.setAlpha((int) (0xFF * params.alpha * progressToSate)); inset += AndroidUtilities.dp(5) * (1f - progressToSate); } rectTmp.set(params.originalAvatarRect); @@ -279,9 +280,9 @@ public static void drawAvatarWithStory(long dialogId, Canvas canvas, ImageReceiv Paint closeFriendsPaint = null; if (params.drawSegments) { unreadPaint = getActiveCirclePaint(avatarImage, params.isStoryCell); - unreadPaint.setAlpha(255); + unreadPaint.setAlpha((int) (0xFF * params.alpha)); closeFriendsPaint = getCloseFriendsPaint(avatarImage); - closeFriendsPaint.setAlpha(255); + closeFriendsPaint.setAlpha((int) (0xFF * params.alpha)); checkGrayPaint(params.resourcesProvider); } float inset; @@ -293,9 +294,9 @@ public static void drawAvatarWithStory(long dialogId, Canvas canvas, ImageReceiv boolean animateOut = params.prevState == STATE_PROGRESS && params.progressToSate != 1f; if (animateOut) { inset += AndroidUtilities.dp(7) * progressToSate; - paint.setAlpha((int) (255 * (1f - progressToSate))); + paint.setAlpha((int) (0xFF * params.alpha * (1f - progressToSate))); } else { - paint.setAlpha((int) (255 * progressToSate)); + paint.setAlpha((int) (0xFF * params.alpha * progressToSate)); inset += AndroidUtilities.dp(5) * (1f - progressToSate); } rectTmp.set(params.originalAvatarRect); @@ -589,6 +590,12 @@ public static void updateColors() { if (storiesGradientTools[1] != null) { storiesGradientTools[1].setColors(Theme.getColor(Theme.key_stories_circle1), Theme.getColor(Theme.key_stories_circle2)); } + if (errorGradientTools != null) { + int orange = Theme.getColor(Theme.key_color_orange); + final int red = Theme.getColor(Theme.key_text_RedBold); + orange = ColorUtils.blendARGB(orange, red, .25f); + errorGradientTools.setColors(orange, red); + } } public static Paint getCloseFriendsPaint(ImageReceiver avatarImage) { @@ -597,7 +604,7 @@ public static Paint getCloseFriendsPaint(ImageReceiver avatarImage) { closeFriendsGradientTools.isDiagonal = true; closeFriendsGradientTools.isRotate = true; closeFriendsGradientTools.setColors(Theme.getColor(Theme.key_stories_circle_closeFriends1), Theme.getColor(Theme.key_stories_circle_closeFriends2)); - closeFriendsGradientTools.paint.setStrokeWidth(AndroidUtilities.dp(2.3f)); + closeFriendsGradientTools.paint.setStrokeWidth(AndroidUtilities.dpf2(2.3f)); closeFriendsGradientTools.paint.setStyle(Paint.Style.STROKE); closeFriendsGradientTools.paint.setStrokeCap(Paint.Cap.ROUND); } @@ -605,6 +612,23 @@ public static Paint getCloseFriendsPaint(ImageReceiver avatarImage) { return closeFriendsGradientTools.paint; } + public static Paint getErrorPaint(ImageReceiver avatarImage) { + if (errorGradientTools == null) { + errorGradientTools = new GradientTools(); + errorGradientTools.isDiagonal = true; + errorGradientTools.isRotate = true; + int orange = Theme.getColor(Theme.key_color_orange); + final int red = Theme.getColor(Theme.key_text_RedBold); + orange = ColorUtils.blendARGB(orange, red, .25f); + errorGradientTools.setColors(orange, red); + errorGradientTools.paint.setStrokeWidth(AndroidUtilities.dpf2(2.3f)); + errorGradientTools.paint.setStyle(Paint.Style.STROKE); + errorGradientTools.paint.setStrokeCap(Paint.Cap.ROUND); + } + errorGradientTools.setBounds(avatarImage.getImageX(), avatarImage.getImageY(), avatarImage.getImageX2(), avatarImage.getImageY2()); + return errorGradientTools.paint; + } + public static void setStoryMiniImage(ImageReceiver imageReceiver, TLRPC.StoryItem storyItem) { if (storyItem == null) { return; @@ -962,6 +986,7 @@ public static class AvatarStoryParams { public long crossfadeToDialog; public float crossfadeToDialogProgress; public float progressToProgressSegments; + public float alpha = 1f; private long dialogId; public int currentState; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java index 2db9e5586c..282a611599 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java @@ -488,7 +488,7 @@ public void expand(boolean force) { ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f); valueAnimator.addUpdateListener(animation -> { float value = (float) animation.getAnimatedValue(); - final float toScrollY = (captionContainer.getBottom() - getMeasuredHeight()); + final float toScrollY = Math.min(getMeasuredHeight() - blackoutBottomOffset - AndroidUtilities.dp(64), captionContainer.getBottom() - getMeasuredHeight()); setScrollY((int) AndroidUtilities.lerp(fromScrollY, toScrollY, value)); captionTextview.progressToExpand = AndroidUtilities.lerp(fromP, toP, value); captionTextview.invalidate(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryFailView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryFailView.java new file mode 100644 index 0000000000..ad89eafe62 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryFailView.java @@ -0,0 +1,95 @@ +package org.telegram.ui.Stories; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.dpf2; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; +import org.webrtc.voiceengine.WebRtcAudioEffects; + +public class StoryFailView extends FrameLayout { + + private final Paint redPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint whitePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private final TextView titleTextView; + private final TextView subtitleTextView; + private final TextView button; + + public StoryFailView(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + + redPaint.setColor(Theme.getColor(Theme.key_text_RedBold, resourcesProvider)); + whitePaint.setColor(Color.WHITE); + setWillNotDraw(false); + + titleTextView = new TextView(context); + titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + titleTextView.setText(LocaleController.getString(R.string.StoryError)); + titleTextView.setTextColor(Color.WHITE); + addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.LEFT, 44, 0, 0, 0)); + + subtitleTextView = new TextView(context); + subtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 8); + subtitleTextView.setTextColor(Theme.multAlpha(Color.WHITE, .5f)); + subtitleTextView.setVisibility(View.GONE); + subtitleTextView.setTranslationY(dp(9)); + addView(subtitleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.LEFT, 44, 0, 0, 0)); + + button = new TextView(context); + button.setPadding(dp(13), 0, dp(13), 0); + button.setBackground(Theme.createSimpleSelectorRoundRectDrawable(dp(16), 0x1fffffff, 0x38ffffff)); + button.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + button.setText(LocaleController.getString(R.string.TryAgain)); + button.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + button.setTextColor(Color.WHITE); + button.setGravity(Gravity.CENTER); + addView(button, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 32, Gravity.CENTER_VERTICAL | Gravity.RIGHT, 0, 0, 12, 0)); + } + + public void set(TLRPC.TL_error error) { + if (error == null || TextUtils.isEmpty(error.text)) { + titleTextView.setTranslationY(0); + subtitleTextView.setVisibility(View.GONE); + } else { + titleTextView.setTranslationY(-dpf2(5.33f)); + subtitleTextView.setText(error.text); + subtitleTextView.setVisibility(View.VISIBLE); + } + } + + @Override + public void setOnClickListener(@Nullable OnClickListener l) { + button.setOnClickListener(l); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + final float cx = dp(13 + 10), cy = getHeight() / 2f; + + canvas.drawCircle(cx, cy, dp(10), redPaint); + AndroidUtilities.rectTmp.set(cx - AndroidUtilities.dp(1), cy - AndroidUtilities.dpf2(4.6f), cx + AndroidUtilities.dp(1), cy + AndroidUtilities.dpf2(1.6f)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(3), AndroidUtilities.dp(3), whitePaint); + AndroidUtilities.rectTmp.set(cx - AndroidUtilities.dp(1), cy + AndroidUtilities.dpf2(2.6f), cx + AndroidUtilities.dp(1), cy + AndroidUtilities.dpf2(2.6f + 2)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(3), AndroidUtilities.dp(3), whitePaint); + } +} 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 39a35e3eaf..1fe1732b8c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java @@ -18,11 +18,11 @@ import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.RectF; -import android.graphics.SurfaceTexture; import android.media.AudioManager; import android.net.Uri; import android.os.Build; -import android.util.Log; +import android.text.Editable; +import android.util.LongSparseArray; import android.util.SparseArray; import android.view.GestureDetector; import android.view.Gravity; @@ -45,12 +45,11 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; +import com.google.android.exoplayer2.util.Log; -import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationNotificationsLocker; import org.telegram.messenger.BuildVars; -import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.FileStreamLoadOperation; @@ -62,6 +61,8 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.messenger.support.LongSparseIntArray; +import org.telegram.messenger.support.SparseLongArray; +import org.telegram.messenger.video.VideoPlayerHolderBase; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.BaseFragment; @@ -73,9 +74,7 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RadialProgress; import org.telegram.ui.Components.RecyclerListView; -import org.telegram.ui.Components.SharedMediaLayout; import org.telegram.ui.Components.SizeNotifierFrameLayout; -import org.telegram.ui.Components.VideoPlayer; import org.telegram.ui.LaunchActivity; import java.util.ArrayList; @@ -106,6 +105,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat private static TLRPC.StoryItem lastStoryItem; Theme.ResourcesProvider resourcesProvider = new DarkThemeResourceProvider(); + private boolean opening; ValueAnimator openCloseAnimator; ValueAnimator swipeToDissmissBackAnimator; ValueAnimator swipeToReplyBackAnimator; @@ -221,6 +221,8 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat private boolean isLikesReactions; private float lastStoryContainerHeight; + LongSparseArray replyDrafts = new LongSparseArray<>(); + public static boolean isShowingImage(MessageObject messageObject) { if (lastStoryItem == null || messageObject.type != MessageObject.TYPE_STORY && !messageObject.isWebpage() || runOpenAnimationAfterLayout) { return false; @@ -654,11 +656,11 @@ protected void dispatchDraw(Canvas canvas) { transitionViewHolder.storyImage.setVisible(true, false); int r = canvas.getSaveCount(); if (transitionViewHolder.drawClip != null) { - transitionViewHolder.drawClip.clip(canvas, rect3, 1f - progress2); + transitionViewHolder.drawClip.clip(canvas, rect3, 1f - progress2, opening); } transitionViewHolder.storyImage.draw(canvas); if (transitionViewHolder.drawAbove != null) { - transitionViewHolder.drawAbove.draw(canvas, rect3, 1f - progress2); + transitionViewHolder.drawAbove.draw(canvas, rect3, 1f - progress2, opening); } transitionViewHolder.storyImage.setVisible(wasVisible, false); transitionViewHolder.storyImage.setImageCoords(x, y, w, h); @@ -686,23 +688,27 @@ protected void dispatchDraw(Canvas canvas) { rect2.set(toX, toY, toX + headerView.backupImageView.getMeasuredWidth(), toY + headerView.backupImageView.getMeasuredHeight()); } - AndroidUtilities.lerp(rect1, rect2, progressToOpen, AndroidUtilities.rectTmp); + AndroidUtilities.lerp(rect1, rect2, progressToOpen, rect3); + int r = canvas.getSaveCount(); + if (transitionViewHolder != null && transitionViewHolder.drawClip != null) { + transitionViewHolder.drawClip.clip(canvas, rect3, 1f - progress2, opening); + } if (animateAvatar) { boolean crossfade = transitionViewHolder != null && transitionViewHolder.crossfadeToAvatarImage != null; if (!crossfade || progressToOpen != 0) { - headerView.backupImageView.getImageReceiver().setImageCoords(AndroidUtilities.rectTmp); - headerView.backupImageView.getImageReceiver().setRoundRadius((int) (AndroidUtilities.rectTmp.width() / 2f)); + headerView.backupImageView.getImageReceiver().setImageCoords(rect3); + headerView.backupImageView.getImageReceiver().setRoundRadius((int) (rect3.width() / 2f)); headerView.backupImageView.getImageReceiver().setVisible(true, false); final float alpha = crossfade ? progressToOpen : 1f; float thisAlpha = alpha; if (transitionViewHolder != null && transitionViewHolder.alpha < 1 && transitionViewHolder.bgPaint != null) { transitionViewHolder.bgPaint.setAlpha((int) (0xFF * (1f - progress2))); - canvas.drawCircle(AndroidUtilities.rectTmp.centerX(), AndroidUtilities.rectTmp.centerY(), AndroidUtilities.rectTmp.width() / 2f, transitionViewHolder.bgPaint); + canvas.drawCircle(rect3.centerX(), rect3.centerY(), rect3.width() / 2f, transitionViewHolder.bgPaint); thisAlpha = AndroidUtilities.lerp(transitionViewHolder.alpha, thisAlpha, progress2); } headerView.backupImageView.getImageReceiver().setAlpha(thisAlpha); - headerView.drawUploadingProgress(canvas, AndroidUtilities.rectTmp, !runOpenAnimationAfterLayout, progressToOpen); + headerView.drawUploadingProgress(canvas, rect3, !runOpenAnimationAfterLayout, progressToOpen); headerView.backupImageView.getImageReceiver().draw(canvas); headerView.backupImageView.getImageReceiver().setAlpha(alpha); headerView.backupImageView.getImageReceiver().setVisible(false, false); @@ -716,10 +722,10 @@ protected void dispatchDraw(Canvas canvas) { ); int oldRadius = transitionViewHolder.crossfadeToAvatarImage.getRoundRadius()[0]; boolean isVisible = transitionViewHolder.crossfadeToAvatarImage.getVisible(); - transitionViewHolder.crossfadeToAvatarImage.setImageCoords(AndroidUtilities.rectTmp); - transitionViewHolder.crossfadeToAvatarImage.setRoundRadius((int) (AndroidUtilities.rectTmp.width() / 2f)); + transitionViewHolder.crossfadeToAvatarImage.setImageCoords(rect3); + transitionViewHolder.crossfadeToAvatarImage.setRoundRadius((int) (rect3.width() / 2f)); transitionViewHolder.crossfadeToAvatarImage.setVisible(true, false); - canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (255 * (1f - progressToOpen)), Canvas.ALL_SAVE_FLAG); + canvas.saveLayerAlpha(rect3, (int) (255 * (1f - progressToOpen)), Canvas.ALL_SAVE_FLAG); transitionViewHolder.crossfadeToAvatarImage.draw(canvas); canvas.restore(); transitionViewHolder.crossfadeToAvatarImage.setVisible(isVisible, false); @@ -728,6 +734,10 @@ protected void dispatchDraw(Canvas canvas) { // transitionViewHolder.crossfadeToAvatarImage.setVisible(false, false); } } + if (transitionViewHolder != null && transitionViewHolder.drawAbove != null) { + transitionViewHolder.drawAbove.draw(canvas, rect3, 1f - progress2, opening); + } + canvas.restoreToCount(r); } @@ -1272,7 +1282,7 @@ public void requestPlayer(TLRPC.Document document, Uri uri, long t, PeerStoriesV } } if (playerHolder == null) { - playerHolder = new VideoPlayerHolder(); + playerHolder = new VideoPlayerHolder(surfaceView, textureView); playerHolder.document = document; } // if (surfaceView != null) { @@ -1412,7 +1422,7 @@ public void preparePlayer(ArrayList documents, ArrayList ur } for (int i = 0; i < uries.size(); i++) { Uri uri = uries.get(i); - VideoPlayerHolder playerHolder = new VideoPlayerHolder(); + VideoPlayerHolder playerHolder = new VideoPlayerHolder(surfaceView, textureView); playerHolder.uri = uri; playerHolder.document = documents.get(i); FileStreamLoadOperation.setPriorityForDocument(playerHolder.document, FileLoader.PRIORITY_LOW); @@ -1476,6 +1486,7 @@ public void invalidate() { windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); if (ATTACH_TO_FRAGMENT) { + AndroidUtilities.removeFromParent(windowView); windowView.setFitsSystemWindows(true); fragment.getLayoutContainer().addView(windowView); AndroidUtilities.requestAdjustResize(fragment.getParentActivity(), fragment.getClassGuid()); @@ -1707,7 +1718,9 @@ public PeerStoriesView getCurrentPeerView() { private void lockOrientation(boolean lock) { Activity activity = AndroidUtilities.findActivity(fragment.getContext()); if (activity != null) { - activity.setRequestedOrientation(lock ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); + try { + activity.setRequestedOrientation(lock ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); + } catch (Exception ignore) {} if (lock) { activity.getWindow().addFlags(FLAG_KEEP_SCREEN_ON); } else { @@ -2001,6 +2014,7 @@ private void startOpenAnimation() { peerStoriesView.headerView.radialProgress.copyParams(transitionViewHolder.radialProgressUpload); } } + opening = true; openCloseAnimator = ValueAnimator.ofFloat(0, 1f); openCloseAnimator.addUpdateListener(animation -> { progressToOpen = (float) animation.getAnimatedValue(); @@ -2095,6 +2109,7 @@ private void startCloseAnimation(boolean backAnimation) { updateTransitionParams(); locker.lock(); fromDismissOffset = swipeToDismissOffset; + opening = false; openCloseAnimator = ValueAnimator.ofFloat(progressToOpen, 0); openCloseAnimator.addUpdateListener(animation -> { progressToOpen = (float) animation.getAnimatedValue(); @@ -2117,6 +2132,9 @@ private void startCloseAnimation(boolean backAnimation) { layoutAndFindView(); } AndroidUtilities.runOnUIThread(() -> { + if (openCloseAnimator == null) { + return; + } containerView.enableHwAcceleration(); openCloseAnimator.addListener(new AnimatorListenerAdapter() { @Override @@ -2473,6 +2491,33 @@ public void didReceivedNotification(int id, int account, Object... args) { } } + public void saveDraft(long dialogId, TLRPC.StoryItem storyItem, CharSequence text) { + if (dialogId == 0 || storyItem == null) { + return; + } + Log.d("kek", "saveDraft" + dialogId + "_" + storyItem.id + " " + text); + replyDrafts.put(draftHash(dialogId, storyItem), text); + } + + public CharSequence getDraft(long dialogId, TLRPC.StoryItem storyItem) { + if (dialogId == 0 || storyItem == null) { + return ""; + } + Log.d("kek", "getDraft " + dialogId + "_" + storyItem.id + " " + replyDrafts.get(draftHash(dialogId, storyItem), "")); + return replyDrafts.get(draftHash(dialogId, storyItem), ""); + } + + public void clearDraft(long dialogId, TLRPC.StoryItem storyItem) { + if (dialogId == 0 || storyItem == null) { + return; + } + replyDrafts.remove(draftHash(dialogId, storyItem)); + } + + private long draftHash(long dialogId, TLRPC.StoryItem oldStoryItem) { + return dialogId + (dialogId >> 16) + ((long) oldStoryItem.id << 16); + } + public interface PlaceProvider { boolean findView(long dialogId, int messageId, int storyId, int type, TransitionViewHolder holder); @@ -2483,11 +2528,11 @@ default void loadNext(boolean forward) { } public interface HolderDrawAbove { - void draw(Canvas canvas, RectF bounds, float alpha); + void draw(Canvas canvas, RectF bounds, float alpha, boolean opening); } public interface HolderClip { - void clip(Canvas canvas, RectF bounds, float alpha); + void clip(Canvas canvas, RectF bounds, float alpha, boolean opening); } public static class TransitionViewHolder { @@ -2527,356 +2572,55 @@ public void clear() { static int queuePointer = 0; - public class VideoPlayerHolder { - - public boolean paused; - public TLRPC.Document document; - VideoPlayer videoPlayer; - Runnable initRunnable; - volatile boolean released; - boolean firstFrameRendered; - - float progress; - int lastState; - public long currentPosition; - long playerDuration; - boolean audioDisabled; - boolean stubAvailable; - boolean logBuffering; - - final DispatchQueue dispatchQueue = Utilities.getOrCreatePlayerQueue(); - Uri uri; - - Runnable progressRunnable = new Runnable() { - @Override - public void run() { - if (videoPlayer != null) { - if (lastState == ExoPlayer.STATE_ENDED) { - progress = 1f; - } else { - currentPosition = videoPlayer.getCurrentPosition(); - playerDuration = videoPlayer.getDuration(); - } - if (lastState == ExoPlayer.STATE_READY) { - dispatchQueue.cancelRunnable(progressRunnable); - dispatchQueue.postRunnable(progressRunnable, 16); - } - } - } - }; + public class VideoPlayerHolder extends VideoPlayerHolderBase { - long startTime; + boolean logBuffering; - void preparePlayer(Uri uri, boolean audioDisabled) { - this.audioDisabled = audioDisabled; - paused = true; - if (initRunnable != null) { - dispatchQueue.cancelRunnable(initRunnable); + public VideoPlayerHolder(SurfaceView surfaceView, TextureView textureView) { + if (USE_SURFACE_VIEW) { + with(surfaceView); + } else { + with(textureView); } - dispatchQueue.postRunnable(initRunnable = () -> { - if (released) { - return; - } - ensurePlayerCreated(audioDisabled); - videoPlayer.preparePlayer(uri, "other", FileLoader.PRIORITY_LOW); - videoPlayer.setPlayWhenReady(false); - videoPlayer.setWorkerQueue(dispatchQueue); - }); } - void start(boolean paused, Uri uri, long t, boolean audioDisabled) { - startTime = System.currentTimeMillis(); - this.audioDisabled = audioDisabled; - this.paused = paused; - dispatchQueue.postRunnable(initRunnable = () -> { - if (released) { - return; - } - if (videoPlayer == null) { - ensurePlayerCreated(audioDisabled); - videoPlayer.preparePlayer(uri, "other"); - videoPlayer.setWorkerQueue(dispatchQueue); - if (!paused) { - if (USE_SURFACE_VIEW) { - videoPlayer.setSurfaceView(surfaceView); - } else { - videoPlayer.setTextureView(textureView); - } - videoPlayer.setPlayWhenReady(true); - } - } else { - if (!paused) { - if (USE_SURFACE_VIEW) { - videoPlayer.setSurfaceView(surfaceView); - } else { - videoPlayer.setTextureView(textureView); - } - videoPlayer.play(); - } - } - if (t > 0) { - videoPlayer.seekTo(t); - } - videoPlayer.setVolume(isInSilentMode ? 0 : 1f); - AndroidUtilities.runOnUIThread(() -> initRunnable = null); - }); + @Override + public boolean needRepeat() { + return isCaptionPartVisible; } - private void ensurePlayerCreated(boolean audioDisabled) { - if (videoPlayer != null) { - videoPlayer.releasePlayer(true); - } - videoPlayer = new VideoPlayer(false, audioDisabled); - videoPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() { - @Override - public void onStateChanged(boolean playWhenReady, int playbackState) { - lastState = playbackState; - if (playbackState == ExoPlayer.STATE_READY || playbackState == ExoPlayer.STATE_BUFFERING) { - dispatchQueue.cancelRunnable(progressRunnable); - dispatchQueue.postRunnable(progressRunnable); - if (firstFrameRendered && playbackState == ExoPlayer.STATE_BUFFERING) { - logBuffering = true; - AndroidUtilities.runOnUIThread(() -> { - final PeerStoriesView storiesView = getCurrentPeerView(); - if (storiesView != null && storiesView.currentStory.storyItem != null) { - FileLog.d("StoryViewer displayed story buffering dialogId=" + storiesView.getCurrentPeer() + " storyId=" + storiesView.currentStory.storyItem.id); - } - }); - } - if (logBuffering && playbackState == ExoPlayer.STATE_READY) { - logBuffering = false; - AndroidUtilities.runOnUIThread(() -> { - final PeerStoriesView storiesView = getCurrentPeerView(); - if (storiesView != null && storiesView.currentStory.storyItem != null) { - FileLog.d("StoryViewer displayed story playing dialogId=" + storiesView.getCurrentPeer() + " storyId=" + storiesView.currentStory.storyItem.id); - } - }); - } - - - } else if (playbackState == ExoPlayer.STATE_ENDED) { - if (isCaptionPartVisible) { - progress = 0; - videoPlayer.seekTo(0); - videoPlayer.play(); - } else { - progress = 1f; - } - } - } - - @Override - public void onError(VideoPlayer player, Exception e) { - FileLog.e(e); - } - - @Override - public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { - - } - - @Override - public void onRenderedFirstFrame() { - AndroidUtilities.runOnUIThread(() -> { - if (released || currentPlayerScope == null) { - return; - } - firstFrameRendered = currentPlayerScope.firstFrameRendered = true; - currentPlayerScope.invalidate(); - - if (onReadyListener != null) { - onReadyListener.run(); - onReadyListener = null; - } - }, 16); - } - - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { - - } - - @Override - public boolean onSurfaceDestroyed(SurfaceTexture surfaceTexture) { - return false; - } - }); - videoPlayer.setIsStory(); - } - - private Runnable onReadyListener; - public void setOnReadyListener(Runnable listener) { - onReadyListener = listener; - } - - boolean release(Runnable whenReleased) { - TLRPC.Document document = this.document; - if (document != null) { - int priority = FileStreamLoadOperation.getStreamPrioriy(document); - if (priority != FileLoader.PRIORITY_LOW) { - FileStreamLoadOperation.setPriorityForDocument(document, FileLoader.PRIORITY_LOW); - FileLoader.getInstance(currentAccount).changePriority(FileLoader.PRIORITY_LOW, document, null, null, null, null, null); - // FileLoader.getInstance(currentAccount).cancelLoadFile(document); - } - // FileLoader.getInstance(currentAccount).changePriority(FileLoader.PRIORITY_LOW, document, null, null, null, null, null); - } - released = true; - dispatchQueue.cancelRunnable(initRunnable); - initRunnable = null; - dispatchQueue.postRunnable(() -> { - if (videoPlayer != null) { - try { - videoPlayer.setTextureView(null); - videoPlayer.setSurfaceView(null); - } catch (Exception e) { - - } - videoPlayer.releasePlayer(false); - } - if (document != null) { - FileLoader.getInstance(currentAccount).cancelLoadFile(document); - // FileLoader.getInstance(currentAccount).changePriority(FileLoader.PRIORITY_LOW, document, null, null, null, null, null); - } - if (whenReleased != null) { - AndroidUtilities.runOnUIThread(whenReleased); - } - videoPlayer = null; - }); - if (playerStubBitmap != null) { - AndroidUtilities.recycleBitmap(playerStubBitmap); - playerStubBitmap = null; - } - return true; - } - - public void pause() { - if (released) { - return; - } - if (paused) { - return; - } - paused = true; - if (USE_SURFACE_VIEW && surfaceView != null && firstFrameRendered && surfaceView.getHolder().getSurface().isValid()) { - stubAvailable = true; - if (playerStubBitmap == null) { - playerStubBitmap = Bitmap.createBitmap(720, 1280, Bitmap.Config.ARGB_8888); - playerStubPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - AndroidUtilities.getBitmapFromSurface(surfaceView, playerStubBitmap); - } - } - dispatchQueue.postRunnable(() -> { - if (videoPlayer != null) { - videoPlayer.pause(); - } - }); - } - - public void play() { - if (released) { - return; - } - if (!paused) { + @Override + public void onRenderedFirstFrame() { + if (currentPlayerScope == null) { return; } - paused = false; - dispatchQueue.postRunnable(() -> { - if (videoPlayer != null) { - if (USE_SURFACE_VIEW) { - videoPlayer.setSurfaceView(surfaceView); - } else { - videoPlayer.setTextureView(textureView); - } - videoPlayer.setPlayWhenReady(true); - } - }); + firstFrameRendered = currentPlayerScope.firstFrameRendered = true; + currentPlayerScope.invalidate(); } - public void setAudioEnabled(boolean enabled, boolean prepared) { - boolean disabled = !enabled; - if (audioDisabled == disabled) { - return; - } - audioDisabled = disabled; - dispatchQueue.postRunnable(() -> { - if (videoPlayer == null) { - return; - } - boolean playing = videoPlayer.isPlaying(); - if (enabled && !videoPlayer.createdWithAudioTrack()) { - //release and create new with audio track - videoPlayer.pause(); - long position = videoPlayer.getCurrentPosition(); - videoPlayer.releasePlayer(false); - videoPlayer = null; - ensurePlayerCreated(audioDisabled); - videoPlayer.preparePlayer(uri, "other"); - videoPlayer.setWorkerQueue(dispatchQueue); - if (!prepared) { - if (USE_SURFACE_VIEW) { - videoPlayer.setSurfaceView(surfaceView); - } else { - videoPlayer.setTextureView(textureView); + @Override + public void onStateChanged(boolean playWhenReady, int playbackState) { + if (playbackState == ExoPlayer.STATE_READY || playbackState == ExoPlayer.STATE_BUFFERING) { + if (firstFrameRendered && playbackState == ExoPlayer.STATE_BUFFERING) { + logBuffering = true; + AndroidUtilities.runOnUIThread(() -> { + final PeerStoriesView storiesView = getCurrentPeerView(); + if (storiesView != null && storiesView.currentStory.storyItem != null) { + FileLog.d("StoryViewer displayed story buffering dialogId=" + storiesView.getCurrentPeer() + " storyId=" + storiesView.currentStory.storyItem.id); } - } - // videoPlayer.setTextureView(textureView); - videoPlayer.seekTo(position + 50); - if (playing && !prepared) { - videoPlayer.setPlayWhenReady(true); - videoPlayer.play(); - } else { - videoPlayer.setPlayWhenReady(false); - videoPlayer.pause(); - } - } else { - videoPlayer.setVolume(enabled ? 1f : 0); - } - }); - } - - public float getPlaybackProgress(long totalDuration) { - if (lastState == ExoPlayer.STATE_ENDED) { - progress = 1f; - } else { - float localProgress; - if (totalDuration != 0) { - localProgress = currentPosition / (float) totalDuration; - } else { - localProgress = currentPosition / (float) playerDuration; + }); } - if (localProgress < progress) { - return progress; + if (logBuffering && playbackState == ExoPlayer.STATE_READY) { + logBuffering = false; + AndroidUtilities.runOnUIThread(() -> { + final PeerStoriesView storiesView = getCurrentPeerView(); + if (storiesView != null && storiesView.currentStory.storyItem != null) { + FileLog.d("StoryViewer displayed story playing dialogId=" + storiesView.getCurrentPeer() + " storyId=" + storiesView.currentStory.storyItem.id); + } + }); } - progress = localProgress; } - return progress; - } - - public void loopBack() { - progress = 0; - lastState = ExoPlayer.STATE_IDLE; - dispatchQueue.postRunnable(() -> { - if (videoPlayer != null) { - videoPlayer.seekTo(0); - } - progress = 0; - currentPosition = 0; - }); - } - - public void setVolume(float v) { - dispatchQueue.postRunnable(() -> { - if (videoPlayer != null) { - videoPlayer.setVolume(v); - } - }); - } - - public boolean isBuffering() { - return !released && lastState == ExoPlayer.STATE_BUFFERING; } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/CaptionContainerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/CaptionContainerView.java index 2018b64481..15049911bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/CaptionContainerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/CaptionContainerView.java @@ -205,7 +205,7 @@ public void afterTextChanged(Editable s) { limitTextView.cancelAnimation(); limitTextView.setText(limitText); limitTextView.setTextColor(length >= limit ? 0xffEC7777 : 0xffffffff); - if (length > limit && !premium && length < MessagesController.getInstance(currentAccount).storyCaptionLengthLimitPremium && length > lastLength && captionLimitToast()) { + if (length > limit && !premium && length < MessagesController.getInstance(currentAccount).storyCaptionLengthLimitPremium && length > lastLength && (captionLimitToast() || MessagesController.getInstance(currentAccount).premiumLocked)) { AndroidUtilities.shakeViewSpring(limitTextView, shiftDp = -shiftDp); BotWebViewVibrationEffect.APP_ERROR.vibrate(); } 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 761aa45095..765a54615a 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 @@ -174,7 +174,7 @@ private void onClick() { } private void onClickInternal() { - if (!preparing) { + if (!preparing || currentEntry == null) { return; } preparing = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftsController.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftsController.java index a93706e5f1..9a58c1a72e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftsController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftsController.java @@ -1,13 +1,10 @@ package org.telegram.ui.Stories.recorder; -import android.net.wifi.WifiManager; import android.text.SpannableString; import android.text.TextUtils; -import android.util.Log; import androidx.annotation.NonNull; -import org.checkerframework.checker.units.qual.A; import org.telegram.SQLite.SQLiteCursor; import org.telegram.SQLite.SQLiteDatabase; import org.telegram.SQLite.SQLitePreparedStatement; @@ -15,27 +12,22 @@ import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; -import org.telegram.messenger.ImageLoader; import org.telegram.messenger.MediaController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.AbstractSerializedData; import org.telegram.tgnet.NativeByteBuffer; -import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import java.io.File; import java.io.IOException; -import java.nio.file.CopyOption; -import java.nio.file.Files; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.List; public class DraftsController { @@ -46,27 +38,22 @@ public class DraftsController { public DraftsController(int currentAccount) { this.currentAccount = currentAccount; + loadFailed(); } - private boolean loaded, loading; public final ArrayList drafts = new ArrayList<>(); - public void load() { - if (loaded || loading) { - return; - } - - loading = true; + private void loadInternal(final boolean failed, Utilities.Callback> callback) { final MessagesStorage storage = MessagesStorage.getInstance(currentAccount); storage.getStorageQueue().postRunnable(() -> { SQLiteCursor cursor = null; - final ArrayList savedDrafts = new ArrayList<>(); + final ArrayList loadedDrafts = new ArrayList<>(); try { SQLiteDatabase database = storage.getDatabase(); if (database == null) { return; } - cursor = database.queryFinalized("SELECT id, data FROM story_drafts ORDER BY date DESC"); + cursor = database.queryFinalized("SELECT id, data, type FROM story_drafts WHERE type = " + (failed ? "2" : "0 OR type = 1") + " ORDER BY date DESC"); while (cursor.next()) { long id = cursor.longValue(0); NativeByteBuffer buffer = cursor.byteBufferValue(1); @@ -74,7 +61,7 @@ public void load() { try { StoryDraft draft = new StoryDraft(buffer, true); draft.id = id; - savedDrafts.add(draft); + loadedDrafts.add(draft); } catch (Exception e) { FileLog.e(e); } @@ -89,36 +76,83 @@ public void load() { } } - AndroidUtilities.runOnUIThread(() -> { - final long now = System.currentTimeMillis(); - ArrayList ids = new ArrayList<>(); - ArrayList deleteEntries = new ArrayList<>(); - for (int i = 0; i < savedDrafts.size(); ++i) { - StoryEntry entry = savedDrafts.get(i).toEntry(); - if (entry == null) { - continue; - } - if ( - entry.file == null || - !entry.file.exists() || - (entry.isEdit ? - (now > entry.editExpireDate) : - (now - entry.draftDate > EXPIRATION_PERIOD) - ) - ) { - deleteEntries.add(entry); - } else { - drafts.add(entry); - ids.add(entry.draftId); - } + AndroidUtilities.runOnUIThread(() -> callback.run(loadedDrafts)); + }); + } + + private boolean loaded, loading; + public void load() { + if (loaded || loading) { + return; + } + + loading = true; + loadInternal(false, loadedDrafts -> { + final long now = System.currentTimeMillis(); + ArrayList ids = new ArrayList<>(); + ArrayList deleteEntries = new ArrayList<>(); + for (int i = 0; i < loadedDrafts.size(); ++i) { + StoryEntry entry = loadedDrafts.get(i).toEntry(); + if (entry == null) { + continue; } - delete(deleteEntries); + if ( + entry.file == null || + !entry.file.exists() || + (entry.isEdit ? + (now > entry.editExpireDate) : + (now - entry.draftDate > EXPIRATION_PERIOD) + ) + ) { + deleteEntries.add(entry); + } else { + drafts.add(entry); + ids.add(entry.draftId); + } + } + delete(deleteEntries); - loading = false; - loaded = true; + loading = false; + loaded = true; - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesDraftsUpdated); - }); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesDraftsUpdated); + }); + } + + private boolean loadedFailed, loadingFailed; + private void loadFailed() { + if (loadedFailed || loadingFailed) { + return; + } + + loadingFailed = true; + loadInternal(true, loadedDrafts -> { + final long now = System.currentTimeMillis(); + ArrayList ids = new ArrayList<>(); + ArrayList deleteEntries = new ArrayList<>(); + ArrayList appendEntries = new ArrayList<>(); + for (int i = 0; i < loadedDrafts.size(); ++i) { + StoryEntry entry = loadedDrafts.get(i).toEntry(); + if (entry == null) { + continue; + } + if ( + entry.file == null || + !entry.file.exists() || + now - entry.draftDate > EXPIRATION_PERIOD + ) { + deleteEntries.add(entry); + } else { + appendEntries.add(entry); + ids.add(entry.draftId); + } + } + delete(deleteEntries); + + loadingFailed = false; + loadedFailed = true; + + MessagesController.getInstance(currentAccount).getStoriesController().putUploadingDrafts(appendEntries); }); } @@ -128,7 +162,9 @@ public void edit(StoryEntry entry) { } prepare(entry); drafts.remove(entry); - drafts.add(0, entry); + if (!entry.isError) { + drafts.add(0, entry); + } final StoryDraft draft = new StoryDraft(entry); final MessagesStorage storage = MessagesStorage.getInstance(currentAccount); storage.getStorageQueue().postRunnable(() -> { @@ -139,13 +175,20 @@ public void edit(StoryEntry entry) { return; } - state = database.executeFast("REPLACE INTO story_drafts VALUES (?, ?, ?)"); + state = database.executeFast("REPLACE INTO story_drafts VALUES (?, ?, ?, ?)"); state.requery(); NativeByteBuffer data = new NativeByteBuffer(draft.getObjectSize()); draft.toStream(data); state.bindLong(1, draft.id); state.bindLong(2, draft.date); state.bindByteBuffer(3, data); + int type = 0; + if (draft.isEdit) { + type = 1; + } else if (draft.isError) { + type = 2; + } + state.bindInteger(4, type); state.step(); data.reuse(); state.dispose(); @@ -166,6 +209,8 @@ private void prepare(StoryEntry entry) { return; } + if (entry.draftId == 0) + entry.draftId = Utilities.random.nextLong(); entry.draftDate = System.currentTimeMillis(); entry.isDraft = true; @@ -211,8 +256,7 @@ public void append(StoryEntry entry) { return; } prepare(entry); - final long id = Utilities.random.nextLong(); - entry.draftId = id; + entry.draftId = Utilities.random.nextLong(); final StoryDraft draft = new StoryDraft(entry); drafts.remove(entry); drafts.add(0, entry); @@ -221,7 +265,7 @@ public void append(StoryEntry entry) { private void append(StoryDraft draft) { final MessagesStorage storage = MessagesStorage.getInstance(currentAccount); - FileLog.d("StoryDraft append " + draft.id + " (edit=" + draft.edit + (draft.edit ? ", storyId=" + draft.editStoryId + ", " + (draft.editDocumentId != 0 ? "documentId=" + draft.editDocumentId : "photoId=" + draft.editPhotoId) + ", expireDate=" + draft.editExpireDate : "") + ", now="+System.currentTimeMillis()+")"); + FileLog.d("StoryDraft append " + draft.id + " (edit=" + draft.isEdit + (draft.isEdit ? ", storyId=" + draft.editStoryId + ", " + (draft.editDocumentId != 0 ? "documentId=" + draft.editDocumentId : "photoId=" + draft.editPhotoId) + ", expireDate=" + draft.editExpireDate : "") + ", now="+System.currentTimeMillis()+")"); storage.getStorageQueue().postRunnable(() -> { SQLitePreparedStatement state = null; try { @@ -230,13 +274,20 @@ private void append(StoryDraft draft) { return; } - state = database.executeFast("INSERT INTO story_drafts VALUES (?, ?, ?)"); + state = database.executeFast("INSERT INTO story_drafts VALUES (?, ?, ?, ?)"); state.requery(); NativeByteBuffer data = new NativeByteBuffer(draft.getObjectSize()); draft.toStream(data); state.bindLong(1, draft.id); state.bindLong(2, draft.date); state.bindByteBuffer(3, data); + int type = 0; + if (draft.isEdit) { + type = 1; + } else if (draft.isError) { + type = 2; + } + state.bindInteger(4, type); state.step(); data.reuse(); state.dispose(); @@ -294,7 +345,7 @@ public void saveForEdit(StoryEntry entry, long dialogId, TLRPC.StoryItem storyIt final long id = Utilities.random.nextLong(); entry.draftId = id; final StoryDraft draft = new StoryDraft(entry); - draft.edit = entry.isEdit = true; + draft.isEdit = entry.isEdit = true; draft.editStoryPeerId = entry.editStoryPeerId = dialogId; draft.editStoryId = entry.editStoryId = storyItem.id; draft.editExpireDate = entry.editExpireDate = storyItem.expire_date * 1000L; @@ -393,6 +444,7 @@ public static class StoryDraft { public long id; public long date; public String thumb; + public String fullThumb; public boolean isVideo; public String file; @@ -426,17 +478,21 @@ public static class StoryDraft { private final ArrayList parts = new ArrayList<>(); - public boolean edit; + public boolean isEdit; public int editStoryId; public long editStoryPeerId; public long editDocumentId; public long editPhotoId; public long editExpireDate; + public boolean isError; + public TLRPC.TL_error error; + public StoryDraft(@NonNull StoryEntry entry) { this.id = entry.draftId; this.date = entry.draftDate; this.thumb = entry.draftThumbFile == null ? "" : entry.draftThumbFile.toString(); + this.fullThumb = entry.uploadThumbFile == null ? "" : entry.uploadThumbFile.toString(); this.isVideo = entry.isVideo; this.file = entry.file == null ? "" : entry.file.toString(); this.fileDeletable = entry.fileDeletable; @@ -467,6 +523,8 @@ public StoryDraft(@NonNull StoryEntry entry) { this.period = entry.period; this.parts.clear(); this.parts.addAll(entry.parts); + this.isError = entry.isError; + this.error = entry.error; } public StoryEntry toEntry() { @@ -474,9 +532,12 @@ public StoryEntry toEntry() { entry.draftId = id; entry.isDraft = true; entry.draftDate = date; - if (thumb != null) { + if (!TextUtils.isEmpty(thumb)) { entry.draftThumbFile = new File(thumb); } + if (!TextUtils.isEmpty(fullThumb)) { + entry.uploadThumbFile = new File(fullThumb); + } entry.isVideo = isVideo; if (file != null) { entry.file = new File(file); @@ -530,12 +591,14 @@ public StoryEntry toEntry() { for (int i = 0; i < parts.size(); ++i) { entry.partsMaxId = Math.max(entry.partsMaxId, parts.get(i).id); } - entry.isEdit = edit; + entry.isEdit = isEdit; entry.editStoryId = editStoryId; entry.editStoryPeerId = editStoryPeerId; entry.editExpireDate = editExpireDate; entry.editPhotoId = editPhotoId; entry.editDocumentId = editDocumentId; + entry.isError = isError; + entry.error = error; return entry; } @@ -606,13 +669,20 @@ public void toStream(AbstractSerializedData stream) { for (int i = 0; i < parts.size(); ++i) { parts.get(i).serializeToStream(stream); } - stream.writeBool(edit); + stream.writeBool(isEdit); stream.writeInt32(editStoryId); stream.writeInt64(editStoryPeerId); stream.writeInt64(editExpireDate); stream.writeInt64(editPhotoId); stream.writeInt64(editDocumentId); stream.writeString(paintEntitiesFilePath); + stream.writeBool(isError); + if (error == null) { + stream.writeInt32(TLRPC.TL_null.constructor); + } else { + error.serializeToStream(stream); + } + stream.writeString(fullThumb); } public int getObjectSize() { @@ -745,7 +815,7 @@ public StoryDraft(@NonNull AbstractSerializedData stream, boolean exception) { } } if (stream.remaining() > 0) { - edit = stream.readBool(exception); + isEdit = stream.readBool(exception); editStoryId = stream.readInt32(exception); editStoryPeerId = stream.readInt64(exception); editExpireDate = stream.readInt64(exception); @@ -758,6 +828,16 @@ public StoryDraft(@NonNull AbstractSerializedData stream, boolean exception) { paintEntitiesFilePath = null; } } + if (stream.remaining() > 0) { + isError = stream.readBool(exception); + magic = stream.readInt32(exception); + if (magic == TLRPC.TL_null.constructor) { + error = null; + } else { + error = TLRPC.TL_error.TLdeserialize(stream, magic, exception); + } + fullThumb = stream.readString(exception); + } } } } 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 2d18cd04c5..25bcae58f1 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 @@ -454,7 +454,7 @@ public void onTextChanged(EditText editText) { if (!onlyPhotos) { ArrayList draftArray = MessagesController.getInstance(currentAccount).getStoriesController().getDraftsController().drafts; for (StoryEntry draft : draftArray) { - if (!draft.isEdit) { + if (!draft.isEdit && !draft.isError) { drafts.add(draft); } } @@ -1406,7 +1406,7 @@ public void updateDrafts() { if (!onlyPhotos) { ArrayList draftArray = MessagesController.getInstance(currentAccount).getStoriesController().getDraftsController().drafts; for (StoryEntry draft : draftArray) { - if (!draft.isEdit) { + if (!draft.isEdit && !draft.isError) { drafts.add(draft); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java index 00884e51eb..5ac582fcad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PaintView.java @@ -3531,6 +3531,7 @@ public boolean onEntitySelected(EntityView entityView) { @Override public void onEntityDragEnd(boolean delete) { updatePreviewViewTranslationY(); + forceChanges = true; } @Override 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 60a10ea929..e1b163f9ef 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 @@ -65,6 +65,9 @@ public class StoryEntry extends IStoryPart { public boolean editedMedia, editedCaption, editedPrivacy; public ArrayList editedMediaAreas; + public boolean isError; + public TLRPC.TL_error error; + public long editDocumentId; public long editPhotoId; public long editExpireDate; @@ -828,9 +831,10 @@ public static class HDRInfo { public float minlum; public int getHDRType() { - if (maxlum <= 0 && minlum <= 0) { - return 0; - } else if (colorStandard == MediaFormat.COLOR_STANDARD_BT2020) { +// if (maxlum <= 0 && minlum <= 0) { +// return 0; +// } else + if (colorStandard == MediaFormat.COLOR_STANDARD_BT2020) { if (colorTransfer == MediaFormat.COLOR_TRANSFER_HLG) { return 1; } else if (colorTransfer == MediaFormat.COLOR_TRANSFER_ST2084) { 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 56c41c453a..d2c5aaca5d 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 @@ -413,7 +413,7 @@ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newStat } else { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(id); TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(id); - if (chatFull != null && chatFull.participants != null && !chatFull.participants.participants.isEmpty()) { + if (chatFull != null && chatFull.participants != null && chatFull.participants.participants != null && !chatFull.participants.participants.isEmpty() && chatFull.participants.participants.size() >= (chatFull.participants_count - 1)) { selectChat(id, chatFull.participants); } else { if (progressDialog != null) { @@ -427,7 +427,7 @@ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newStat storage.getStorageQueue().postRunnable(() -> { boolean isChannel = ChatObject.isChannel(chat); TLRPC.ChatFull info = storage.loadChatInfoInQueue(id, isChannel, true, true, 0); - if (info == null || info.participants == null) { + if (info == null || info.participants == null || info.participants.participants != null && info.participants.participants.size() < (info.participants_count - 1)) { AndroidUtilities.runOnUIThread(() -> { if (isChannel) { MessagesController.getInstance(currentAccount).loadChannelParticipants(id, participants -> { @@ -1599,7 +1599,11 @@ public void updateCheckboxes(boolean animated) { ItemInner item = items.get(position); UserCell cell = (UserCell) child; cell.setChecked(item.checked || item.halfChecked, animated); - cell.setCheckboxAlpha(item.halfChecked && !item.checked ? .5f : 1f, animated); + if (item.chat != null) { + cell.setCheckboxAlpha(getParticipantsCount(item.chat) > 200 ? .3f : 1f, animated); + } else { + cell.setCheckboxAlpha(item.halfChecked && !item.checked ? .5f : 1f, animated); + } } } @@ -1929,6 +1933,8 @@ public void bindView(View view, int position, int viewType) { smallChatsParticipantsCount.putAll(participantsCountByChat); }); }); + + MessagesController.getInstance(currentAccount).getStoriesController().loadBlocklist(false); } private void init(Context context) { @@ -2499,7 +2505,7 @@ private ArrayList getUsers(boolean onlyContacts, boolean includeSmallC } } else if (includeSmallChats && DialogObject.isChatDialog(dialog.id)) { TLRPC.Chat chat = messagesController.getChat(-dialog.id); - if (chat == null || ChatObject.isForum(chat) || ChatObject.isChannelAndNotMegaGroup(chat)) { + if (chat == null || ChatObject.isChannelAndNotMegaGroup(chat)) { continue; } // int participants_count = getParticipantsCount(chat); @@ -2583,7 +2589,7 @@ public UserCell(Context context, Theme.ResourcesProvider resourcesProvider) { avatarDrawable.setRoundRadius(AndroidUtilities.dp(40)); imageView = new BackupImageView(context); - imageView.setRoundRadius(AndroidUtilities.dp(40)); + imageView.setRoundRadius(AndroidUtilities.dp(20)); addView(imageView, LayoutHelper.createFrame(40, 40, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 53, 0, 53, 0)); titleTextView = new SimpleTextView(context); @@ -2651,6 +2657,7 @@ public void setCheckboxAlpha(float alpha, boolean animated) { public void setUser(TLRPC.User user) { avatarDrawable.setInfo(user); + imageView.setRoundRadius(dp(20)); imageView.setForUserOrChat(user, avatarDrawable); CharSequence text = UserObject.getUserName(user); @@ -2667,6 +2674,7 @@ public void setUser(TLRPC.User user) { public void setChat(TLRPC.Chat chat, int participants_count) { avatarDrawable.setInfo(chat); + imageView.setRoundRadius(dp(ChatObject.isForum(chat) ? 12 : 20)); imageView.setForUserOrChat(chat, avatarDrawable); CharSequence text = chat.title; @@ -2778,6 +2786,7 @@ public void setType(int type, int count, TLRPC.User singleUser) { checkBox.setVisibility(View.GONE); radioButton.setVisibility(View.VISIBLE); imageView.setImageDrawable(avatarDrawable); + imageView.setRoundRadius(dp(20)); } private void setSubtitle(CharSequence text) { 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 78625309b1..909e7c72be 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 @@ -1609,6 +1609,9 @@ protected void drawBlurBitmap(Bitmap bitmap, float amount) { @Override protected boolean captionLimitToast() { + if (MessagesController.getInstance(currentAccount).premiumLocked) { + return false; + } Bulletin visibleBulletin = Bulletin.getVisibleBulletin(); if (visibleBulletin != null && visibleBulletin.tag == 2) { return false; @@ -2108,9 +2111,9 @@ private File prepareThumb(StoryEntry storyEntry, boolean forDraft) { if (storyEntry == null || previewView.getWidth() <= 0 || previewView.getHeight() <= 0) { return null; } - if (!forDraft && !storyEntry.wouldBeVideo() && !storyEntry.isEdit) { - return null; - } +// if (!forDraft && !storyEntry.wouldBeVideo() && !storyEntry.isEdit) { +// return null; +// } File file = forDraft ? storyEntry.draftThumbFile : storyEntry.uploadThumbFile; if (file != null) { file.delete(); @@ -3069,7 +3072,7 @@ private void onNavigateStart(int fromPage, int toPage) { // privacySelector.setStoryPeriod(outputEntry == null || !UserConfig.getInstance(currentAccount).isPremium() ? 86400 : outputEntry.period); captionEdit.setPeriod(outputEntry == null ? 86400 : outputEntry.period, false); - captionEdit.setPeriodVisible(outputEntry == null || !outputEntry.isEdit); + captionEdit.setPeriodVisible(!MessagesController.getInstance(currentAccount).premiumLocked && (outputEntry == null || !outputEntry.isEdit)); } if (toPage == PAGE_PREVIEW) { videoError = false; @@ -3224,11 +3227,14 @@ public void switchToEditMode(int editMode, boolean animated) { createFilterPhotoView(); // animatePhotoFilterTexture(true, animated); previewTouchable = photoFilterView; - photoFilterView.getToolsView().setAlpha(0f); - photoFilterView.getToolsView().setVisibility(View.VISIBLE); - animators.add(ObjectAnimator.ofFloat(photoFilterView.getToolsView(), View.TRANSLATION_Y, 0)); - animators.add(ObjectAnimator.ofFloat(photoFilterView.getToolsView(), View.ALPHA, 1)); - TextureView textureView = photoFilterView.getMyTextureView(); + View toolsView = photoFilterView != null ? photoFilterView.getToolsView() : null; + if (toolsView != null) { + toolsView.setAlpha(0f); + toolsView.setVisibility(View.VISIBLE); + animators.add(ObjectAnimator.ofFloat(toolsView, View.TRANSLATION_Y, 0)); + animators.add(ObjectAnimator.ofFloat(toolsView, View.ALPHA, 1)); + } + TextureView textureView = photoFilterView != null ? photoFilterView.getMyTextureView() : null; if (textureView != null) { animators.add(ObjectAnimator.ofFloat(textureView, View.ALPHA, 1)); } diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index 90bc621e51..5641cabd0d 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -62,6 +62,7 @@ The deletion process was cancelled for your account %1$s. You may close this window now. Your login code is **%1$s**. Enter it in the Telegram app where you are trying to log in.\n\nDo not give this code to anyone. You can request an SMS in %1$d:%2$02d + You can request a new SMS in %1$d:%2$02d Get the code via SMS You can request a voice call in %1$d:%2$02d Call me to dictate the code @@ -6686,6 +6687,10 @@ Uploading story error My Story Uploading… + Failed + failed to upload + Couldn’t upload + Try Again Story Message sent. Just now @@ -7101,7 +7106,7 @@ %d likes %d likes You can post **%1$d** stories in **24** hours.\nSubscribe to **Telegram Premium** to increase this limit to **%2$d**. - Sorry, you can’t post more than **%1$d** stories. + Sorry, you can’t post more than **%1$d** stories in **24** hours. You can post **%1$d** stories in a week.\nSubscribe to **Telegram Premium** to increase this limit to **%2$d**. Sorry, you can’t post more than **%1$d** stories in a week. You can post **%1$d** stories in a month.\nSubscribe to **Telegram Premium** to increase this limit to **%2$d**.