From ad863779f799ea51c37d4a41e76fd7006339ef3e Mon Sep 17 00:00:00 2001 From: DrKLO Date: Fri, 10 Oct 2014 21:16:39 +0400 Subject: [PATCH] Different improvements --- TMessagesProj/build.gradle | 4 +- .../org/telegram/android/ImageLoader.java | 4 + .../org/telegram/android/MessageObject.java | 8 +- .../telegram/android/MessagesController.java | 15 +- .../org/telegram/android/MessagesStorage.java | 15 +- .../telegram/android/NotificationCenter.java | 1 + .../java/org/telegram/messenger/TLRPC.java | 1 + .../org/telegram/ui/Cells/ChatBaseCell.java | 5 + .../org/telegram/ui/Cells/ChatMediaCell.java | 27 +-- .../java/org/telegram/ui/ChatActivity.java | 193 +++++++++++++----- .../java/org/telegram/ui/PhotoViewer.java | 4 +- .../org/telegram/ui/SecretPhotoViewer.java | 111 +++++++++- .../org/telegram/ui/Views/LayoutListView.java | 18 ++ .../src/main/res/drawable-hdpi/circle1.png | Bin 0 -> 1569 bytes .../src/main/res/drawable-ldpi/circle1.png | Bin 0 -> 1216 bytes .../src/main/res/drawable-mdpi/circle1.png | Bin 0 -> 1344 bytes .../src/main/res/drawable-xhdpi/circle1.png | Bin 0 -> 1815 bytes .../src/main/res/drawable-xxhdpi/circle1.png | Bin 0 -> 2347 bytes 18 files changed, 302 insertions(+), 104 deletions(-) create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/circle1.png create mode 100755 TMessagesProj/src/main/res/drawable-ldpi/circle1.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/circle1.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/circle1.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/circle1.png diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 52181cf0..a0173758 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -80,7 +80,7 @@ android { defaultConfig { minSdkVersion 8 targetSdkVersion 19 - versionCode 355 - versionName "1.9.4" + versionCode 357 + versionName "1.9.5" } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java index 2d542493..cdee9073 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java @@ -831,6 +831,10 @@ public class ImageLoader { }); } + public void putImageToCache(BitmapDrawable bitmap, String key) { + memCache.put(key, bitmap); + } + public void loadImage(final TLRPC.FileLocation fileLocation, final String httpUrl, final ImageReceiver imageView, final int size, final boolean cacheOnly) { if ((fileLocation == null && httpUrl == null) || imageView == null || (fileLocation != null && !(fileLocation instanceof TLRPC.TL_fileLocation) && !(fileLocation instanceof TLRPC.TL_fileEncryptedLocation))) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java index dad8b492..f01e0b35 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java @@ -616,7 +616,7 @@ public class MessageObject { } public boolean isSecretMedia() { - return messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageOwner.ttl != 0; + return messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageOwner.ttl != 0 && messageOwner.ttl <= 60; } public static void setIsUnread(TLRPC.Message message, boolean unread) { @@ -672,12 +672,8 @@ public class MessageObject { String str; if (secondsLeft < 60) { str = secondsLeft + "s"; - } else if (secondsLeft < 60 * 60) { - str = secondsLeft / 60 + "m"; - } else if (secondsLeft < 60 * 60 * 24) { - str = secondsLeft / 60 / 60 + "h"; } else { - str = secondsLeft / 60 / 60 / 24 + "d"; + str = secondsLeft / 60 + "m"; } return str; } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java index 1fdba71a..da42b019 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java @@ -17,6 +17,7 @@ import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.os.Build; import android.text.Html; +import android.util.SparseArray; import org.telegram.messenger.BuffersStorage; import org.telegram.messenger.ByteBufferDesc; @@ -502,7 +503,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - public void didAddedNewTask(final int minDate) { + public void didAddedNewTask(final int minDate, final SparseArray> mids) { Utilities.stageQueue.postRunnable(new Runnable() { @Override public void run() { @@ -511,6 +512,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } }); + AndroidUtilities.RunOnUIThread(new Runnable() { + @Override + public void run() { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.didCreatedNewDeleteTask, mids); + } + }); } public void getNewDeleteTask(final ArrayList oldTask) { @@ -3552,7 +3559,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter newMessage.media.photo.date = newMessage.date; newMessage.media.photo.caption = ""; newMessage.media.photo.geo = new TLRPC.TL_geoPointEmpty(); - if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 5000 && decryptedMessage.media.thumb_w < 100 && decryptedMessage.media.thumb_h < 100) { + if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { TLRPC.TL_photoCachedSize small = new TLRPC.TL_photoCachedSize(); small.w = decryptedMessage.media.thumb_w; small.h = decryptedMessage.media.thumb_h; @@ -3581,7 +3588,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } newMessage.media = new TLRPC.TL_messageMediaVideo(); newMessage.media.video = new TLRPC.TL_videoEncrypted(); - if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 5000 && decryptedMessage.media.thumb_w < 100 && decryptedMessage.media.thumb_h < 100) { + if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { newMessage.media.video.thumb = new TLRPC.TL_photoCachedSize(); newMessage.media.video.thumb.bytes = decryptedMessage.media.thumb; newMessage.media.video.thumb.w = decryptedMessage.media.thumb_w; @@ -3623,7 +3630,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter newMessage.media.document.size = message.file.size; newMessage.media.document.key = decryptedMessage.media.key; newMessage.media.document.iv = decryptedMessage.media.iv; - if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 5000 && decryptedMessage.media.thumb_w < 100 && decryptedMessage.media.thumb_h < 100) { + if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { newMessage.media.document.thumb = new TLRPC.TL_photoCachedSize(); newMessage.media.document.thumb.bytes = decryptedMessage.media.thumb; newMessage.media.document.thumb.w = decryptedMessage.media.thumb_w; diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java index b93081e0..592b6e29 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java @@ -882,7 +882,7 @@ public class MessagesStorage { state.dispose(); database.commitTransaction(); database.executeFast(String.format(Locale.US, "UPDATE messages SET ttl = 0 WHERE mid IN(%s)", mids.toString())).stepThis().dispose(); - MessagesController.getInstance().didAddedNewTask(minDate); + MessagesController.getInstance().didAddedNewTask(minDate, messages); } } catch (Exception e) { FileLog.e("tmessages", e); @@ -2432,15 +2432,10 @@ public class MessagesStorage { } private int getMessageMediaType(TLRPC.Message message) { - if (message.media == null) { - return 0; - } else if (message.media instanceof TLRPC.TL_messageMediaPhoto) { + if (message.media instanceof TLRPC.TL_messageMediaPhoto && message.ttl != 0 && message.ttl <= 60) { return 1; - } else if (message.media instanceof TLRPC.TL_messageMediaVideo) { - return 2; - } else { - return 0; } + return 0; } private void putMessagesInternal(final ArrayList messages, final boolean withTransaction, final boolean isBroadcast, final int downloadMask) { @@ -2478,7 +2473,7 @@ public class MessagesStorage { messagesIdsMap.put(message.id, dialog_id); } - if (message.ttl == 0 && (message.media instanceof TLRPC.TL_messageMediaVideo || message.media instanceof TLRPC.TL_messageMediaPhoto)) { + if (message.media instanceof TLRPC.TL_messageMediaVideo || message.media instanceof TLRPC.TL_messageMediaPhoto && (message.ttl == 0 || message.ttl > 60)) { if (messageMediaIds.length() > 0) { messageMediaIds.append(","); } @@ -2562,7 +2557,7 @@ public class MessagesStorage { state3.step(); } - if (message.ttl == 0 && (message.media instanceof TLRPC.TL_messageMediaVideo || message.media instanceof TLRPC.TL_messageMediaPhoto)) { + if (message.media instanceof TLRPC.TL_messageMediaVideo || message.media instanceof TLRPC.TL_messageMediaPhoto && (message.ttl == 0 || message.ttl > 60)) { state2.requery(); state2.bindInteger(1, messageId); state2.bindLong(2, dialog_id); diff --git a/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java index 87298e13..2a53670a 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java @@ -41,6 +41,7 @@ public class NotificationCenter { public static final int openedChatChanged = 29; public static final int hideEmojiKeyboard = 30; public static final int stopEncodingService = 31; + public static final int didCreatedNewDeleteTask = 32; public static final int wallpapersDidLoaded = 171; public static final int closeOtherAppActivities = 702; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java index e86ad58f..eb33d919 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java @@ -9333,6 +9333,7 @@ public class TLRPC { public byte[] auth_key; public int user_id; public int ttl; + public int layer; } public static class FileLocation extends TLObject { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java index 2577049d..3ce74277 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java @@ -118,6 +118,7 @@ public class ChatBaseCell extends BaseCell { private CheckForTap pendingCheckForTap = null; private int last_send_state = 0; + private int last_delete_date = 0; private final class CheckForTap implements Runnable { public void run() { @@ -219,6 +220,9 @@ public class ChatBaseCell extends BaseCell { if (last_send_state != currentMessageObject.messageOwner.send_state) { return true; } + if (last_delete_date != currentMessageObject.messageOwner.destroyTime) { + return true; + } TLRPC.User newUser = MessagesController.getInstance().getUser(currentMessageObject.messageOwner.from_id); TLRPC.FileLocation newPhoto = null; @@ -251,6 +255,7 @@ public class ChatBaseCell extends BaseCell { public void setMessageObject(MessageObject messageObject) { currentMessageObject = messageObject; last_send_state = messageObject.messageOwner.send_state; + last_delete_date = messageObject.messageOwner.destroyTime; isPressed = false; isCheckPressed = true; isAvatarVisible = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java index f1abc028..467f0371 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java @@ -42,8 +42,6 @@ import java.util.Locale; public class ChatMediaCell extends ChatBaseCell implements MediaController.FileDownloadProgressListener { public static interface ChatMediaCellDelegate { - public abstract boolean didPressedImage(ChatMediaCell cell); - public abstract void didUnpressedImage(ChatMediaCell cell); public abstract void didClickedImage(ChatMediaCell cell); public abstract void didPressedOther(ChatMediaCell cell); } @@ -85,7 +83,6 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD private boolean otherPressed = false; private int buttonX; private int buttonY; - private boolean listenForUnpressed = false; private StaticLayout infoLayout; private int infoWidth; @@ -212,10 +209,8 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } } } - listenForUnpressed = false; - if (imagePressed && mediaDelegate != null && mediaDelegate.didPressedImage(this)) { + if (imagePressed && currentMessageObject.isSecretMedia()) { imagePressed = false; - listenForUnpressed = true; } else if (result) { startCheckLongPress(); } @@ -242,8 +237,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } else if (imagePressed) { if (event.getAction() == MotionEvent.ACTION_UP) { imagePressed = false; - playSoundEffect(SoundEffectConstants.CLICK); - didClickedImage(); + if (buttonState == -1 || buttonState == 2 || buttonState == 3) { + playSoundEffect(SoundEffectConstants.CLICK); + didClickedImage(); + } invalidate(); } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { imagePressed = false; @@ -277,14 +274,6 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } } } - } else if (listenForUnpressed) { - if (event.getAction() == MotionEvent.ACTION_POINTER_UP || event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { - if (listenForUnpressed && mediaDelegate != null) { - mediaDelegate.didUnpressedImage(this); - } - listenForUnpressed = false; - } - result = true; } } if (!result) { @@ -575,6 +564,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD w = timeWidthTotal; } + if (currentMessageObject.isSecretMedia()) { + w = h = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f); + } + photoWidth = w; photoHeight = h; backgroundWidth = w + AndroidUtilities.dp(12); @@ -785,7 +778,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } private void updateSecretTimeText() { - if (currentMessageObject == null) { + if (currentMessageObject == null || currentMessageObject.isOut()) { return; } String str = currentMessageObject.getSecretTimeString(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 151f2b02..16284f91 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -32,6 +32,7 @@ import android.os.Bundle; import android.provider.MediaStore; import android.text.Html; import android.text.TextUtils; +import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; @@ -175,6 +176,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private String startVideoEdit = null; private Runnable openSecretPhotoRunnable = null; + private float startX = 0; + private float startY = 0; private final static int copy = 1; private final static int forward = 2; @@ -188,6 +191,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private final static int attach_location = 10; private final static int chat_menu_avatar = 11; + AdapterView.OnItemLongClickListener onItemLongClickListener = new AdapterView.OnItemLongClickListener() { + @Override + public boolean onItemLongClick(AdapterView adapter, View view, int position, long id) { + if (!actionBarLayer.isActionModeShowed()) { + createMenu(view, false); + } + return true; + } + }; + + AdapterView.OnItemClickListener onItemClickListener = new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + if (actionBarLayer.isActionModeShowed()) { + processRowSelect(view); + return; + } + createMenu(view, true); + } + }; + public ChatActivity(Bundle args) { super(args); } @@ -350,6 +374,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.getInstance().addObserver(this, NotificationCenter.screenshotTook); NotificationCenter.getInstance().addObserver(this, NotificationCenter.blockedUsersDidLoaded); NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileNewChunkAvailable); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.didCreatedNewDeleteTask); super.onFragmentCreate(); @@ -397,6 +422,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.getInstance().removeObserver(this, NotificationCenter.screenshotTook); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.blockedUsersDidLoaded); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.FileNewChunkAvailable); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didCreatedNewDeleteTask); if (AndroidUtilities.isTablet()) { NotificationCenter.getInstance().postNotificationName(NotificationCenter.openedChatChanged, dialog_id, true); } @@ -746,17 +772,103 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not emptyView.setText(LocaleController.getString("GotAQuestion", R.string.GotAQuestion)); } - chatListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + chatListView.setOnItemLongClickListener(onItemLongClickListener); + chatListView.setOnItemClickListener(onItemClickListener); + + final Rect scrollRect = new Rect(); + + chatListView.setOnInterceptTouchEventListener(new LayoutListView.OnInterceptTouchEventListener() { @Override - public boolean onItemLongClick(AdapterView adapter, View view, int position, long id) { - if (!actionBarLayer.isActionModeShowed()) { - createMenu(view, false); + public boolean onInterceptTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + int x = (int)event.getX(); + int y = (int)event.getY(); + int count = chatListView.getChildCount(); + Rect rect = new Rect(); + for (int a = 0; a < count; a++) { + View view = chatListView.getChildAt(a); + int top = view.getTop(); + int bottom = view.getBottom(); + view.getLocalVisibleRect(rect); + if (top > y || bottom < y) { + continue; + } + if (!(view instanceof ChatMediaCell)) { + break; + } + final ChatMediaCell cell = (ChatMediaCell)view; + final MessageObject messageObject = cell.getMessageObject(); + if (messageObject == null || !messageObject.isSecretMedia() || !cell.getPhotoImage().isInsideImage(x, y - top)) { + break; + } + startX = x; + startY = y; + openSecretPhotoRunnable = new Runnable() { + @Override + public void run() { + if (openSecretPhotoRunnable == null) { + return; + } + chatListView.requestDisallowInterceptTouchEvent(true); + chatListView.setOnItemLongClickListener(null); + chatListView.setOnItemClickListener(null); + chatListView.setLongClickable(false); + openSecretPhotoRunnable = null; + if (!messageObject.isOut() && messageObject.messageOwner.destroyTime == 0) { + MessagesController.getInstance().markMessageAsRead(dialog_id, messageObject.messageOwner.random_id); + messageObject.messageOwner.destroyTime = messageObject.messageOwner.ttl + ConnectionsManager.getInstance().getCurrentTime(); + cell.invalidate(); + } + SecretPhotoViewer.getInstance().setParentActivity(getParentActivity()); + SecretPhotoViewer.getInstance().openPhoto(messageObject); + } + }; + AndroidUtilities.RunOnUIThread(openSecretPhotoRunnable, 100); + return true; + } } - return true; + return false; } }); - final Rect scrollRect = new Rect(); + chatListView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_POINTER_UP) { + if (openSecretPhotoRunnable != null) { + AndroidUtilities.CancelRunOnUIThread(openSecretPhotoRunnable); + openSecretPhotoRunnable = null; + } else { + if (SecretPhotoViewer.getInstance().isVisible()) { + AndroidUtilities.RunOnUIThread(new Runnable() { + @Override + public void run() { + chatListView.setOnItemLongClickListener(onItemLongClickListener); + chatListView.setOnItemClickListener(onItemClickListener); + chatListView.setLongClickable(true); + } + }); + SecretPhotoViewer.getInstance().closePhoto(); + } + } + } else if (event.getAction() != MotionEvent.ACTION_DOWN) { + if (SecretPhotoViewer.getInstance().isVisible()) { + return true; + } else if (openSecretPhotoRunnable != null) { + if (event.getAction() == MotionEvent.ACTION_MOVE) { + if (Math.hypot(startX - event.getX(), startY - event.getY()) > AndroidUtilities.dp(5)) { + AndroidUtilities.CancelRunOnUIThread(openSecretPhotoRunnable); + openSecretPhotoRunnable = null; + } + } else { + AndroidUtilities.CancelRunOnUIThread(openSecretPhotoRunnable); + openSecretPhotoRunnable = null; + } + } + } + return false; + } + }); chatListView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override @@ -856,17 +968,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); - chatListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView adapterView, View view, int i, long l) { - if (actionBarLayer.isActionModeShowed()) { - processRowSelect(view); - return; - } - createMenu(view, true); - } - }); - updateBottomOverlay(); chatActivityEnterView.setContainerView(getParentActivity(), fragmentView); @@ -2396,6 +2497,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateVisibleRows(); } } + } else if (id == NotificationCenter.didCreatedNewDeleteTask) { + SparseArray> mids = (SparseArray>)args[0]; + boolean changed = false; + for(int i = 0; i < mids.size(); i++) { + int key = mids.keyAt(i); + ArrayList arr = mids.get(key); + for (Integer mid : arr) { + MessageObject messageObject = messagesDict.get(mid); + if (messageObject != null) { + messageObject.messageOwner.destroyTime = key; + changed = true; + } + } + } + if (changed) { + updateVisibleRows(); + } } } @@ -2574,6 +2692,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); } + + chatListView.setOnItemLongClickListener(onItemLongClickListener); + chatListView.setOnItemClickListener(onItemClickListener); + chatListView.setLongClickable(true); } @Override @@ -3505,43 +3627,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void didPressedOther(ChatMediaCell cell) { createMenu(cell, true); } - - @Override - public boolean didPressedImage(final ChatMediaCell cell) { - final MessageObject messageObject = cell.getMessageObject(); - if (messageObject == null || !messageObject.isSecretMedia()) { - return false; - } - openSecretPhotoRunnable = new Runnable() { - @Override - public void run() { - if (openSecretPhotoRunnable == null) { - return; - } - chatListView.requestDisallowInterceptTouchEvent(true); - openSecretPhotoRunnable = null; - if (!messageObject.isOut() && messageObject.messageOwner.destroyTime == 0) { - MessagesController.getInstance().markMessageAsRead(dialog_id, message.messageOwner.random_id); - messageObject.messageOwner.destroyTime = messageObject.messageOwner.ttl + ConnectionsManager.getInstance().getCurrentTime(); - cell.invalidate(); - } - SecretPhotoViewer.getInstance().setParentActivity(getParentActivity()); - SecretPhotoViewer.getInstance().openPhoto(messageObject); - } - }; - AndroidUtilities.RunOnUIThread(openSecretPhotoRunnable, 100); - return true; - } - - @Override - public void didUnpressedImage(ChatMediaCell cell) { - if (openSecretPhotoRunnable != null) { - AndroidUtilities.CancelRunOnUIThread(openSecretPhotoRunnable); - openSecretPhotoRunnable = null; - } else { - SecretPhotoViewer.getInstance().closePhoto(); - } - } }; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 8140abcd..7fdf85c4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -234,7 +234,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat public int getSelectedCount(); } - private static class FrameLayoutTouchListener extends FrameLayout { + private class FrameLayoutTouchListener extends FrameLayout { public FrameLayoutTouchListener(Context context) { super(context); } @@ -251,7 +251,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } - private static class FrameLayoutDrawer extends FrameLayout { + private class FrameLayoutDrawer extends FrameLayout { public FrameLayoutDrawer(Context context) { super(context); setWillNotDraw(false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java index b7e585ff..3dd8e29d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java @@ -11,27 +11,36 @@ package org.telegram.ui; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.RectF; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.util.SparseArray; import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; import android.view.WindowManager; import android.widget.FrameLayout; import org.telegram.android.AndroidUtilities; +import org.telegram.android.ImageLoader; import org.telegram.android.ImageReceiver; import org.telegram.android.MessageObject; import org.telegram.android.NotificationCenter; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; +import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; +import java.io.File; import java.util.ArrayList; public class SecretPhotoViewer implements NotificationCenter.NotificationCenterDelegate { @@ -48,6 +57,18 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD } } + private class FrameLayoutTouchListener extends FrameLayout { + public FrameLayoutTouchListener(Context context) { + super(context); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + FileLog.e("tmessages", event.toString()); + return super.onTouchEvent(event); + } + } + private class SecretDeleteTimer extends FrameLayout { private String currentInfoString; private int infoWidth; @@ -55,6 +76,7 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD private StaticLayout infoLayout = null; private Paint deleteProgressPaint; private RectF deleteProgressRect = new RectF(); + private Drawable drawable = null; public SecretDeleteTimer(Context context) { super(context); @@ -66,6 +88,8 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD deleteProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG); deleteProgressPaint.setColor(0xffe6e6e6); + + drawable = getResources().getDrawable(R.drawable.circle1); } private void updateSecretTimeText() { @@ -88,14 +112,20 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - deleteProgressRect.set(getMeasuredWidth() - AndroidUtilities.dp(27), 0, getMeasuredWidth(), AndroidUtilities.dp(27)); + deleteProgressRect.set(getMeasuredWidth() - AndroidUtilities.dp(30), AndroidUtilities.dp(2), getMeasuredWidth() - AndroidUtilities.dp(2), AndroidUtilities.dp(30)); } @Override protected void onDraw(Canvas canvas) { - if (currentMessageObject == null) { + if (currentMessageObject == null || currentMessageObject.messageOwner.destroyTime == 0) { return; } + + if (drawable != null) { + drawable.setBounds(getMeasuredWidth() - AndroidUtilities.dp(32), 0, getMeasuredWidth(), AndroidUtilities.dp(32)); + drawable.draw(canvas); + } + long msTime = System.currentTimeMillis() + ConnectionsManager.getInstance().getTimeDifference() * 1000; float progress = Math.max(0, (long)currentMessageObject.messageOwner.destroyTime * 1000 - msTime) / (currentMessageObject.messageOwner.ttl * 1000.0f); canvas.drawArc(deleteProgressRect, -90, -360 * progress, true, deleteProgressPaint); @@ -107,7 +137,7 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD if (infoLayout != null) { canvas.save(); - canvas.translate(getMeasuredWidth() - AndroidUtilities.dp(34) - infoWidth, AndroidUtilities.dp(5)); + canvas.translate(getMeasuredWidth() - AndroidUtilities.dp(38) - infoWidth, AndroidUtilities.dp(7)); infoLayout.draw(canvas); canvas.restore(); } @@ -116,10 +146,11 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD private Activity parentActivity; private WindowManager.LayoutParams windowLayoutParams; - private FrameLayout windowView; + private FrameLayoutTouchListener windowView; private FrameLayoutDrawer containerView; private ImageReceiver centerImage = new ImageReceiver(); private SecretDeleteTimer secretDeleteTimer; + private boolean isVisible = false; private MessageObject currentMessageObject = null; @@ -148,6 +179,22 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD if (markAsDeletedMessages.contains(currentMessageObject.messageOwner.id)) { closePhoto(); } + } else if (id == NotificationCenter.didCreatedNewDeleteTask) { + if (currentMessageObject == null || secretDeleteTimer == null) { + return; + } + SparseArray> mids = (SparseArray>)args[0]; + for(int i = 0; i < mids.size(); i++) { + int key = mids.keyAt(i); + ArrayList arr = mids.get(key); + for (Integer mid : arr) { + if (currentMessageObject.messageOwner.id == mid) { + currentMessageObject.messageOwner.destroyTime = key; + secretDeleteTimer.invalidate(); + return; + } + } + } } } @@ -157,9 +204,10 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD } parentActivity = activity; - windowView = new FrameLayout(activity); + windowView = new FrameLayoutTouchListener(activity); windowView.setBackgroundColor(0xff000000); - windowView.setFocusable(false); + windowView.setFocusable(true); + windowView.setFocusableInTouchMode(true); containerView = new FrameLayoutDrawer(activity); containerView.setFocusable(false); @@ -169,13 +217,22 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD layoutParams.height = FrameLayout.LayoutParams.MATCH_PARENT; layoutParams.gravity = Gravity.TOP | Gravity.LEFT; containerView.setLayoutParams(layoutParams); + containerView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_POINTER_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { + closePhoto(); + } + return true; + } + }); secretDeleteTimer = new SecretDeleteTimer(activity); containerView.addView(secretDeleteTimer); layoutParams = (FrameLayout.LayoutParams)secretDeleteTimer.getLayoutParams(); layoutParams.gravity = Gravity.TOP | Gravity.RIGHT; layoutParams.width = AndroidUtilities.dp(100); - layoutParams.height = AndroidUtilities.dp(27); + layoutParams.height = AndroidUtilities.dp(32); layoutParams.rightMargin = AndroidUtilities.dp(19); layoutParams.topMargin = AndroidUtilities.dp(19); secretDeleteTimer.setLayoutParams(layoutParams); @@ -197,13 +254,34 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD } NotificationCenter.getInstance().addObserver(this, NotificationCenter.messagesDeleted); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.didCreatedNewDeleteTask); TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(messageObject.messageOwner.media.photo.sizes, AndroidUtilities.getPhotoSize()); int size = sizeFull.size; if (size == 0) { size = -1; } - centerImage.setImage(sizeFull.location, null, null, size, false); + BitmapDrawable drawable = ImageLoader.getInstance().getImageFromMemory(sizeFull.location, null, null, null); + if (drawable == null) { + File file = FileLoader.getPathToAttach(sizeFull); + Bitmap bitmap = null; + try { + bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); + } catch (Throwable e) { + ImageLoader.getInstance().clearMemory(); + bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); + } + if (bitmap != null) { + drawable = new BitmapDrawable(bitmap); + ImageLoader.getInstance().putImageToCache(drawable, sizeFull.location.volume_id + "_" + sizeFull.location.local_id); + } + } + if (drawable != null) { + centerImage.setImageBitmap(drawable); + } else { + centerImage.setImage(sizeFull.location, null, null, size, false); + } + currentMessageObject = messageObject; AndroidUtilities.lockOrientation(parentActivity); @@ -220,16 +298,28 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); wm.addView(windowView, windowLayoutParams); secretDeleteTimer.invalidate(); + isVisible = true; + } + + public boolean isVisible() { + return isVisible; } public void closePhoto() { NotificationCenter.getInstance().removeObserver(this, NotificationCenter.messagesDeleted); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didCreatedNewDeleteTask); if (parentActivity == null) { return; } currentMessageObject = null; + isVisible = false; AndroidUtilities.unlockOrientation(parentActivity); - centerImage.setImageBitmap((Bitmap)null); + AndroidUtilities.RunOnUIThread(new Runnable() { + @Override + public void run() { + centerImage.setImageBitmap((Bitmap)null); + } + }); try { if (windowView.getParent() != null) { WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); @@ -242,6 +332,9 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD public void destroyPhotoViewer() { NotificationCenter.getInstance().removeObserver(this, NotificationCenter.messagesDeleted); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didCreatedNewDeleteTask); + isVisible = false; + currentMessageObject = null; if (parentActivity == null || windowView == null) { return; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/LayoutListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Views/LayoutListView.java index fa037f10..a475bc3c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/LayoutListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Views/LayoutListView.java @@ -10,11 +10,17 @@ package org.telegram.ui.Views; import android.content.Context; import android.util.AttributeSet; +import android.view.MotionEvent; import android.view.View; import android.widget.ListView; public class LayoutListView extends ListView { + public static interface OnInterceptTouchEventListener { + public abstract boolean onInterceptTouchEvent(MotionEvent event); + } + + private OnInterceptTouchEventListener onInterceptTouchEventListener; private int height = -1; public LayoutListView(Context context) { @@ -29,6 +35,18 @@ public class LayoutListView extends ListView { super(context, attrs, defStyle); } + public void setOnInterceptTouchEventListener(OnInterceptTouchEventListener listener) { + onInterceptTouchEventListener = listener; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (onInterceptTouchEventListener != null) { + return onInterceptTouchEventListener.onInterceptTouchEvent(ev); + } + return super.onInterceptTouchEvent(ev); + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { View v = getChildAt(getChildCount() - 1); diff --git a/TMessagesProj/src/main/res/drawable-hdpi/circle1.png b/TMessagesProj/src/main/res/drawable-hdpi/circle1.png new file mode 100755 index 0000000000000000000000000000000000000000..7587e047b4d6d05caeca421d1289768055d4bc56 GIT binary patch literal 1569 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y zG%_=W>2=9ZF3nBND}m`vLFhHZsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6s4IL(9V zO~LIJ6P$YWfsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tef(LTNxObrh2+KhE&|T zGV8pzw4=yzb?M2E`lm#Fec&&0TT6FVlZXoYZ~lsaFE92#*L|_}dXsMMLJ?uxEe{+6 zJ+p3$tO+yB`ttjR`KHLQ$#3$^KJWWrd19B<{hKo@joM-6+skmY@0BfcHy7s+?Bf3yze^eOKOGjhe-x{h+hUZ;Qqrwt9*CY#DR(n_9Z! zu56pWCrI?KLI_#hLAz#UhV){x~eF zufy-`?Hi-ktZ`5~@y|m22@hXnt=eS~_NKbFQG{LdvMIYvan6-3L>5=7ug+U;pOI&Q0Fd>v^o+ zgzxzH`yKoDtL$Djr{g7(9?aczdgH1%W~)nc8=mX_5faV&bNzSS!m!>RwJ-W+7q2xL z?q8<7E}mIsl~5hK@+rTA?uuHQ*J=H>YU0Xr@P8xo{Zs+-`=2+J0=Cx0UajmubpFP& zM@{>(1j5{YbLFg3i#ILsj{mmc%(nYa3MQJTR_;&#ydg|{Rczp-ih$7g?H4VVbIY}z jdu_H`tL3%Xb|xN%Us*Ld=S3j3^P6c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDi`ZeeO@=3-=O;^yLJXy|I<;pArS>TK*} zXyIxE)9aF-T$-DjR|3v4~Pj*wm=R%;iu*SQ+p9GS-%oci)3J6H1TwC45_%a zW!lEQ%+xH5w_zIJ)<(v-ZGA!5PmcXz@~rq;==eqs7~w(R5#natHM43E9xpI&*O z{9~N(Bc|mXuFsgid^&%krupY4uNUc)1h2RJV~@|e8r;f%YU$%mnr3(9wd^(ebzNWF c_@sS+VSiP)Xy?)pXHc2q>FVdQ&MBb@0BSR$VE_OC literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/circle1.png b/TMessagesProj/src/main/res/drawable-mdpi/circle1.png new file mode 100755 index 0000000000000000000000000000000000000000..1590ab4e2aa4a3fb92f3a5c81cc4bf7024c2238f GIT binary patch literal 1344 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y2=9ZF3nBND}m`vLFhHcsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6p(IL(9V zO~LIJL!5f`fsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tfv~zX<}et+~Vot7*cWT z$aG)t!wv#%+h4njRB!lpp-bWI!9^19S*r!>Tg<=iU-{tZ{RQkt@41|D)Vi@a>;t#f z#;or52V9(_4yomp#aCz~dOtr~R+hd@;fg7*)B?U$336vX+)}S#?q9%d^}ze7J2%(; zNCw>vjLSsM)-_8PFwWa7HG?I30jHXa8Ly-CoTm9EY%kW9JGj2MC~U!|f3bCkc{EFP zj??sK2dtjE+n;1$z02;pFn-FB><3~$3fVLcmN|MpQ8x-?zMddry5TI}=dg*7?_F-@ z$*m2ZA$(M;op;N>!Yi9Pl5*MDWFByRUetY7ky(3=%raNc`x9!m-wyK4+VghP3N6$7 z6`7%2lP*k?(bVbY;n6uJe`1GFX2ANC1?d+Z{EK?GE!C6U5uB@F+WqU8--MQVtjuu} zT9y>&DfnidF#PYe;k@{zO^VEK6RsZ?zc_QD@WsbwwQJO63THog7BSEM0Au~JvZHqL zr?1NR1YA&_Cn)s1$!`0((s$2GdDYr4K2Tc7zhv%?M_-qEtXm@ZckT2CDpnJgNcx?= zvt^fNdvJe$)U$^rYs%V>edg+azIoxtKe9G0$BLI~{nkFf5U?z8(t#Dnqd;Yvr>mdK II;Vst08B09nE(I) literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/circle1.png b/TMessagesProj/src/main/res/drawable-xhdpi/circle1.png new file mode 100755 index 0000000000000000000000000000000000000000..8ba4640c07375e889b890dead57014990dc94147 GIT binary patch literal 1815 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 w99bjWalg>q^rbqFbw