update to 10.1.0 (3919)

This commit is contained in:
xaxtix 2023-09-22 18:40:36 +04:00
parent 6b4602c20a
commit 750eedfc96
137 changed files with 9539 additions and 2271 deletions

View file

@ -17,12 +17,14 @@ configurations.all {
}
dependencies {
implementation 'androidx.fragment:fragment:1.2.0'
implementation 'androidx.core:core:1.10.1'
implementation 'androidx.palette:palette:1.0.0'
implementation 'androidx.exifinterface:exifinterface:1.3.3'
implementation 'androidx.exifinterface:exifinterface:1.3.6'
implementation 'androidx.dynamicanimation:dynamicanimation:1.0.0'
implementation 'androidx.multidex:multidex:2.0.1'
implementation "androidx.sharetarget:sharetarget:1.2.0"
implementation 'androidx.interpolator:interpolator:1.0.0'
compileOnly 'org.checkerframework:checker-qual:2.5.2'
compileOnly 'org.checkerframework:checker-compat-qual:2.5.0'
@ -138,6 +140,19 @@ android {
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
}
HA_hardcore {
debuggable false
jniDebuggable false
minifyEnabled true
multiDexEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../TMessagesProj/proguard-rules.pro'
ndk.debugSymbolLevel = 'FULL'
buildConfigField "String", "APP_CENTER_HASH", "\"" + getProps("APP_CENTER_HASH_HARDCORE") + "\""
buildConfigField "boolean", "DEBUG_VERSION", "true"
buildConfigField "boolean", "DEBUG_PRIVATE_VERSION", "true"
buildConfigField "boolean", "BUILD_HOST_IS_WINDOWS", isWindows
}
standalone {
debuggable false
jniDebuggable false

View file

@ -236,7 +236,11 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
.setInterpolator(getRemoveInterpolator())
.alpha(0)
.scaleX(1f - animateByScale(view))
.scaleY(1f - animateByScale(view))
.scaleY(1f - animateByScale(view));
if (Build.VERSION.SDK_INT >= 19) {
animation.setUpdateListener(animation1 -> onRemoveAnimationUpdate(holder));
}
animation
.setListener(
new AnimatorListenerAdapter() {
@Override
@ -284,7 +288,11 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
.scaleY(1f)
.setDuration(getAddDuration())
.setStartDelay(getAddDelay())
.setInterpolator(getAddInterpolator())
.setInterpolator(getAddInterpolator());
if (Build.VERSION.SDK_INT >= 19) {
animation.setUpdateListener(animation1 -> onAddAnimationUpdate(holder));
}
animation
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
@ -342,6 +350,14 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
}
protected void onAddAnimationUpdate(RecyclerView.ViewHolder holder) {
}
protected void onRemoveAnimationUpdate(RecyclerView.ViewHolder holder) {
}
protected void beforeAnimateMoveImpl(final RecyclerView.ViewHolder holder) {
}

View file

@ -785,6 +785,16 @@ public class AndroidUtilities {
return new float[] {xOffset, yOffset};
}
public static void doOnLayout(View view, Runnable runnable) {
view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
view.removeOnLayoutChangeListener(this);
runnable.run();
}
});
}
private static class LinkSpec {
String url;
int start;

View file

@ -44,7 +44,7 @@ import java.io.File;
public class ApplicationLoader extends Application {
private static ApplicationLoader applicationLoaderInstance;
public static ApplicationLoader applicationLoaderInstance;
@SuppressLint("StaticFieldLeak")
public static volatile Context applicationContext;
@ -555,4 +555,11 @@ public class ApplicationLoader extends Application {
}
public boolean checkApkInstallPermissions(final Context context) {
return false;
}
public boolean openApkInstall(Activity activity, TLRPC.Document document) {
return false;
}
}

View file

@ -24,8 +24,8 @@ public class BuildVars {
public static boolean USE_CLOUD_STRINGS = true;
public static boolean CHECK_UPDATES = true;
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
public static int BUILD_VERSION = 3872;
public static String BUILD_VERSION_STRING = "10.0.9";
public static int BUILD_VERSION = 3919;
public static String BUILD_VERSION_STRING = "10.1.0";
public static int APP_ID = 4;
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";
@ -33,6 +33,7 @@ public class BuildVars {
public static String SAFETYNET_KEY = "AIzaSyDqt8P-7F7CPCseMkOiVRgb1LY8RN1bvH8";
public static String SMS_HASH = isStandaloneApp() ? "w0lkcmTZkKh" : (DEBUG_VERSION ? "O2P2z+/jBpJ" : "oLeq9AcOZkT");
public static String PLAYSTORE_APP_URL = "https://play.google.com/store/apps/details?id=org.telegram.messenger";
public static String HUAWEI_STORE_URL = "https://appgallery.huawei.com/app/C101184875";
public static String GOOGLE_AUTH_CLIENT_ID = "760348033671-81kmi3pi84p11ub8hp9a1funsv0rn2p9.apps.googleusercontent.com";
public static String HUAWEI_APP_ID = "101184875";

View file

@ -0,0 +1,108 @@
package org.telegram.messenger;
import com.google.android.exoplayer2.util.Consumer;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.Bulletin;
import org.telegram.ui.Components.BulletinFactory;
public class ChannelBoostsController {
private final int currentAccount;
private final MessagesController messagesController;
private final ConnectionsManager connectionsManager;
public final static int BOOSTS_FOR_LEVEL_1 = 1;
public final static int BOOSTS_FOR_LEVEL_2 = 1;
public ChannelBoostsController(int currentAccount) {
this.currentAccount = currentAccount;
messagesController = MessagesController.getInstance(currentAccount);
connectionsManager = ConnectionsManager.getInstance(currentAccount);
}
public void getBoostsStats(long dialogId, Consumer<TLRPC.TL_stories_boostsStatus> consumer) {
TLRPC.TL_stories_getBoostsStatus req = new TLRPC.TL_stories_getBoostsStatus();
req.peer = messagesController.getInputPeer(dialogId);
connectionsManager.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (response != null) {
consumer.accept((TLRPC.TL_stories_boostsStatus) response);
} else {
BulletinFactory.showForError(error);
consumer.accept(null);
}
}));
}
public void userCanBoostChannel(long dialogId, Consumer<CanApplyBoost> consumer) {
TLRPC.TL_stories_canApplyBoost req = new TLRPC.TL_stories_canApplyBoost();
req.peer = messagesController.getInputPeer(dialogId);
connectionsManager.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
CanApplyBoost canApplyBoost = new CanApplyBoost();
if (response != null) {
canApplyBoost.canApply = true;
if (response instanceof TLRPC.TL_stories_canApplyBoostReplace) {
TLRPC.TL_stories_canApplyBoostReplace canApplyBoostReplace = (TLRPC.TL_stories_canApplyBoostReplace) response;
messagesController.putChats(canApplyBoostReplace.chats, false);
canApplyBoost.replaceDialogId = DialogObject.getPeerDialogId(canApplyBoostReplace.current_boost);
if (canApplyBoost.replaceDialogId == 0 && canApplyBoostReplace.chats.size() > 0) {
canApplyBoost.replaceDialogId = -canApplyBoostReplace.chats.get(0).id;
}
}
} else {
if (error != null) {
if (error.text.equals("SAME_BOOST_ALREADY_ACTIVE") || error.text.equals("BOOST_NOT_MODIFIED")) {
canApplyBoost.alreadyActive = true;
} else if (error.text.equals("PREMIUM_GIFTED_NOT_ALLOWED")) {
canApplyBoost.giftedPremium = true;
} else if (error.text.startsWith("FLOOD_WAIT")) {
canApplyBoost.floodWait = Utilities.parseInt(error.text);
canApplyBoost.lastCheckTime = System.currentTimeMillis();
}
}
}
consumer.accept(canApplyBoost);
}), ConnectionsManager.RequestFlagDoNotWaitFloodWait);
}
public void applyBoost(long dialogId) {
TLRPC.TL_stories_applyBoost req = new TLRPC.TL_stories_applyBoost();
req.peer = messagesController.getInputPeer(dialogId);
connectionsManager.sendRequest(req, (response, error) -> {
});
}
public int getTotalBooststToLevel(int level) {
int count = 0;
if (level >= 1) {
count += BOOSTS_FOR_LEVEL_1;
}
if (level >= 2) {
count += BOOSTS_FOR_LEVEL_2;
}
return count;
}
public static class CanApplyBoost {
public boolean canApply;
public long replaceDialogId;
public boolean alreadyActive;
public int floodWait;
public boolean giftedPremium;
private long lastCheckTime;
public void checkTime() {
floodWait -= (System.currentTimeMillis() - lastCheckTime) / 1000;
lastCheckTime = System.currentTimeMillis();
if (floodWait < 0) {
floodWait = 0;
canApply = true;
}
}
}
}

View file

@ -87,7 +87,7 @@ public class ChatMessagesMetadataController {
continue;
}
long storyDialogId = storyItem.dialogId;
req.user_id = chatActivity.getMessagesController().getInputUser(storyDialogId);
req.peer = chatActivity.getMessagesController().getInputPeer(storyDialogId);
req.id.add(storyItem.id);
int storyId = storyItem.id;
int reqId = chatActivity.getConnectionsManager().sendRequest(req, (response, error) -> {

View file

@ -2864,6 +2864,9 @@ public class ContactsController extends BaseController {
}
public static String formatName(TLRPC.User user) {
if (user == null) {
return "";
}
return formatName(user.first_name, user.last_name, 0);
}

View file

@ -1370,6 +1370,12 @@ public class DatabaseMigrationHelper {
version = 133;
}
if (version == 133) {
database.executeFast("ALTER TABLE unread_push_messages ADD COLUMN topicId INTEGER default 0").stepThis().dispose();
database.executeFast("PRAGMA user_version = 134").stepThis().dispose();
version = 134;
}
return version;
}

View file

@ -1169,6 +1169,10 @@ public class FileLoader extends BaseController {
}
public File getPathToMessage(TLRPC.Message message, boolean useFileDatabaseQueue) {
return getPathToMessage(message, useFileDatabaseQueue, false);
}
public File getPathToMessage(TLRPC.Message message, boolean useFileDatabaseQueue, boolean saveAsFile) {
if (message == null) {
return new File("");
}
@ -1184,7 +1188,7 @@ public class FileLoader extends BaseController {
}
} else {
if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaDocument) {
return getPathToAttach(MessageObject.getMedia(message).document, null, MessageObject.getMedia(message).ttl_seconds != 0, useFileDatabaseQueue);
return getPathToAttach(MessageObject.getMedia(message).document, null,null, MessageObject.getMedia(message).ttl_seconds != 0, useFileDatabaseQueue, saveAsFile);
} else if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaPhoto) {
ArrayList<TLRPC.PhotoSize> sizes = MessageObject.getMedia(message).photo.sizes;
if (sizes.size() > 0) {
@ -1221,21 +1225,22 @@ public class FileLoader extends BaseController {
}
public File getPathToAttach(TLObject attach, String ext, boolean forceCache) {
return getPathToAttach(attach, null, ext, forceCache, true);
return getPathToAttach(attach, null, ext, forceCache, true, false);
}
public File getPathToAttach(TLObject attach, String ext, boolean forceCache, boolean useFileDatabaseQueue) {
return getPathToAttach(attach, null, ext, forceCache, useFileDatabaseQueue);
return getPathToAttach(attach, null, ext, forceCache, useFileDatabaseQueue, false);
}
/**
* Return real file name. Used before file.exist()
*/
public File getPathToAttach(TLObject attach, String size, String ext, boolean forceCache, boolean useFileDatabaseQueue) {
public File getPathToAttach(TLObject attach, String size, String ext, boolean forceCache, boolean useFileDatabaseQueue, boolean saveAsFile) {
File dir = null;
long documentId = 0;
int dcId = 0;
int type = 0;
String fileName = null;
if (forceCache) {
dir = getDirectory(MEDIA_DIR_CACHE);
} else {
@ -1252,7 +1257,13 @@ public class FileLoader extends BaseController {
} else if (MessageObject.isVideoDocument(document)) {
type = MEDIA_DIR_VIDEO;
} else {
type = MEDIA_DIR_DOCUMENT;
String documentFileName = getDocumentFileName(document);
if (saveAsFile && !TextUtils.isEmpty(documentFileName)) {
fileName = documentFileName;
type = MEDIA_DIR_FILES;
} else {
type = MEDIA_DIR_DOCUMENT;
}
}
}
documentId = document.id;
@ -1323,7 +1334,10 @@ public class FileLoader extends BaseController {
return new File(path);
}
}
return new File(dir, getAttachFileName(attach, ext));
if (fileName == null) {
fileName = getAttachFileName(attach, ext);
}
return new File(dir, fileName);
}
public FilePathDatabase getFileDatabase() {

View file

@ -352,7 +352,7 @@ public class FileRefController extends BaseController {
if (parentObject instanceof TLRPC.StoryItem) {
TLRPC.StoryItem storyItem = (TLRPC.StoryItem) parentObject;
TLRPC.TL_stories_getStoriesByID req = new TLRPC.TL_stories_getStoriesByID();
req.user_id = getMessagesController().getInputUser(storyItem.dialogId);
req.peer = getMessagesController().getInputPeer(storyItem.dialogId);
req.id.add(storyItem.id);
getConnectionsManager().sendRequest(req, (response, error) -> {
onRequestComplete(locationKey, parentKey, response, error, true, false);
@ -911,35 +911,7 @@ public class FileRefController extends BaseController {
}
} else if (response instanceof TLRPC.TL_help_appUpdate) {
TLRPC.TL_help_appUpdate appUpdate = (TLRPC.TL_help_appUpdate) response;
try {
SharedConfig.pendingAppUpdate = appUpdate;
SharedConfig.saveConfig();
} catch (Exception e) {
FileLog.e(e);
}
try {
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.appUpdateAvailable);
} catch (Exception e) {
FileLog.e(e);
}
try {
if (appUpdate.document != null) {
result = appUpdate.document.file_reference;
TLRPC.TL_inputDocumentFileLocation location = new TLRPC.TL_inputDocumentFileLocation();
location.id = appUpdate.document.id;
location.access_hash = appUpdate.document.access_hash;
location.file_reference = appUpdate.document.file_reference;
location.thumb_size = "";
locationReplacement = new TLRPC.InputFileLocation[1];
locationReplacement[0] = location;
}
} catch (Exception e) {
result = null;
FileLog.e(e);
}
if (result == null) {
result = getFileReference(appUpdate.document, requester.location, needReplacement, locationReplacement);
}
result = getFileReference(appUpdate.document, requester.location, needReplacement, locationReplacement);
if (result == null) {
result = getFileReference(appUpdate.sticker, requester.location, needReplacement, locationReplacement);
}
@ -1091,7 +1063,7 @@ public class FileRefController extends BaseController {
TLRPC.StoryItem storyItem = (TLRPC.StoryItem) operation.parentObject;
if (newStoryItem == null) {
TLRPC.TL_updateStory story = new TLRPC.TL_updateStory();
story.user_id = storyItem.dialogId;
story.peer = getMessagesController().getPeer(storyItem.dialogId);
story.story = new TLRPC.TL_storyItemDeleted();
story.story.id = storyItem.id;
ArrayList<TLRPC.Update> updates = new ArrayList<>();

View file

@ -54,6 +54,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
List<ImageReceiver> preloadReceivers;
private boolean allowCrossfadeWithImage = true;
private boolean allowDrawWhileCacheGenerating;
private ArrayList<Decorator> decorators;
public boolean updateThumbShaderMatrix() {
if (currentThumbDrawable != null && thumbShader != null) {
@ -1080,6 +1081,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (lottieDrawable != null) {
lottieDrawable.removeParentView(this);
}
if (decorators != null) {
for (int i = 0; i < decorators.size(); i++) {
decorators.get(i).onDetachedFromWidnow();
}
}
}
public boolean setBackupImage() {
@ -1163,6 +1169,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (staticThumbDrawable instanceof AttachableDrawable) {
((AttachableDrawable) staticThumbDrawable).onAttachedToWindow(this);
}
if (decorators != null) {
for (int i = 0; i < decorators.size(); i++) {
decorators.get(i).onAttachedToWindow(this);
}
}
return false;
}
@ -2028,6 +2039,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (gradientBitmap != null && currentImageKey != null) {
canvas.restore();
}
if (result && isVisible && decorators != null) {
for (int i = 0; i < decorators.size(); i++) {
decorators.get(i).onDraw(canvas, this);
}
}
return result;
}
@ -3142,6 +3158,26 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
return holder;
}
public void clearDecorators() {
if (decorators != null) {
if (attachedToWindow) {
for (int i = 0; i < decorators.size(); i++) {
decorators.get(i).onDetachedFromWidnow();
}
}
decorators.clear();
}
}
public void addDecorator(Decorator decorator) {
if (decorators == null) {
decorators = new ArrayList<>();
}
decorators.add(decorator);
if (attachedToWindow) {
decorator.onAttachedToWindow(this);
}
}
public static class BackgroundThreadDrawHolder {
public boolean animationNotReady;
public float overrideAlpha;
@ -3224,4 +3260,14 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
super(bitmap);
}
}
public static abstract class Decorator {
protected abstract void onDraw(Canvas canvas, ImageReceiver imageReceiver);
public void onAttachedToWindow(ImageReceiver imageReceiver) {
}
public void onDetachedFromWidnow() {
}
}
}

View file

@ -2040,14 +2040,14 @@ public class LocaleController {
public static String stringForMessageListDate(long date) {
try {
date *= 1000;
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
rightNow.setTimeInMillis(date);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
if (Math.abs(System.currentTimeMillis() - date) >= 31536000000L) {
return getInstance().formatterYear.format(new Date(date));
} else {
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
rightNow.setTimeInMillis(date);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dayDiff = dateDay - day;
if (dayDiff == 0 || dayDiff == -1 && System.currentTimeMillis() - date < 60 * 60 * 8 * 1000) {
return getInstance().formatterDay.format(new Date(date));

View file

@ -4068,7 +4068,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
}
}
if (path == null || path.length() == 0) {
path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner).toString();
path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner, true, !isMusic).toString();
}
File sourceFile = new File(path);
if (!sourceFile.exists()) {
@ -4122,7 +4122,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
}
}
if (path == null || path.length() == 0) {
path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner).toString();
path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner, true, !isMusic).toString();
}
File sourceFile = new File(path);
if (!sourceFile.exists()) {

View file

@ -94,6 +94,7 @@ import java.util.regex.Pattern;
public class MediaDataController extends BaseController {
public final static String ATTACH_MENU_BOT_ANIMATED_ICON_KEY = "android_animated",
ATTACH_MENU_BOT_STATIC_ICON_KEY = "default_static",
ATTACH_MENU_BOT_SIDE_MENU_ICON_KEY = "android_side_menu_static",
ATTACH_MENU_BOT_PLACEHOLDER_STATIC_KEY = "placeholder_static",
ATTACH_MENU_BOT_COLOR_LIGHT_ICON = "light_icon",
ATTACH_MENU_BOT_COLOR_LIGHT_TEXT = "light_text",
@ -1568,6 +1569,16 @@ public class MediaDataController extends BaseController {
return null;
}
@Nullable
public static TLRPC.TL_attachMenuBotIcon getSideAttachMenuBotIcon(@NonNull TLRPC.TL_attachMenuBot bot) {
for (TLRPC.TL_attachMenuBotIcon icon : bot.icons) {
if (icon.name.equals(ATTACH_MENU_BOT_SIDE_MENU_ICON_KEY)) {
return icon;
}
}
return null;
}
@Nullable
public static TLRPC.TL_attachMenuBotIcon getPlaceholderStaticAttachMenuBotIcon(@NonNull TLRPC.TL_attachMenuBot bot) {
for (TLRPC.TL_attachMenuBotIcon icon : bot.icons) {
@ -5469,7 +5480,7 @@ public class MediaDataController extends BaseController {
}
if (messageObject.type == MessageObject.TYPE_STORY || messageObject.type == MessageObject.TYPE_STORY_MENTION) {
if (messageObject.messageOwner.media.storyItem == null) {
long storyDialogId = messageObject.messageOwner.media.user_id;
long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.media.peer);
if (messagesWithUnknownStories == null) {
messagesWithUnknownStories = new LongSparseArray<>();
}
@ -5480,7 +5491,7 @@ public class MediaDataController extends BaseController {
}
array.add(messageObject);
} else {
long storyDialogId = messageObject.messageOwner.media.user_id;
long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.media.peer);
messageObject.messageOwner.media.storyItem = StoriesStorage.checkExpiredStateLocal(currentAccount, storyDialogId, messageObject.messageOwner.media.storyItem);
}
} else if (messageObject.getId() > 0 && messageObject.isReplyToStory()) {
@ -5554,7 +5565,7 @@ public class MediaDataController extends BaseController {
if (attr instanceof TLRPC.TL_webPageAttributeStory) {
TLRPC.TL_webPageAttributeStory attrStory = (TLRPC.TL_webPageAttributeStory) attr;
if (attrStory.storyItem == null) {
long storyDialogId = attrStory.user_id;
long storyDialogId = DialogObject.getPeerDialogId(attrStory.peer);
if (messagesWithUnknownStories == null) {
messagesWithUnknownStories = new LongSparseArray<>();
}
@ -5565,7 +5576,7 @@ public class MediaDataController extends BaseController {
}
array.add(messageObject);
} else {
long storyDialogId = attrStory.user_id;
long storyDialogId = DialogObject.getPeerDialogId(attrStory.peer);
attrStory.storyItem = StoriesStorage.checkExpiredStateLocal(currentAccount, storyDialogId, attrStory.storyItem);
}
}
@ -7235,6 +7246,7 @@ public class MediaDataController extends BaseController {
public void applyAttachMenuBot(TLRPC.TL_attachMenuBotsBot attachMenuBot) {
attachMenuBots.bots.add(attachMenuBot.bot);
loadAttachMenuBots(false, true);
}
public boolean botInAttachMenu(long id) {

View file

@ -233,7 +233,6 @@ public class MessageObject {
public int lastLineWidth;
public int textWidth;
public int textHeight;
public int captionHeight;
public boolean hasRtl;
public float textXOffset;
@ -1647,6 +1646,18 @@ public class MessageObject {
rights.append('\n').append(n.edit_messages ? '+' : '-').append(' ');
rights.append(LocaleController.getString("EventLogPromotedEditMessages", R.string.EventLogPromotedEditMessages));
}
if (o.post_stories != n.post_stories) {
rights.append('\n').append(n.post_stories ? '+' : '-').append(' ');
rights.append(LocaleController.getString("EventLogPromotedPostStories", R.string.EventLogPromotedPostStories));
}
if (o.edit_stories != n.edit_stories) {
rights.append('\n').append(n.edit_messages ? '+' : '-').append(' ');
rights.append(LocaleController.getString("EventLogPromotedEditStories", R.string.EventLogPromotedEditStories));
}
if (o.delete_stories != n.delete_stories) {
rights.append('\n').append(n.delete_stories ? '+' : '-').append(' ');
rights.append(LocaleController.getString("EventLogPromotedDeleteStories", R.string.EventLogPromotedDeleteStories));
}
}
if (o.delete_messages != n.delete_messages) {
rights.append('\n').append(n.delete_messages ? '+' : '-').append(' ');
@ -4295,8 +4306,8 @@ public class MessageObject {
public static boolean canPreviewDocument(TLRPC.Document document) {
if (document != null && document.mime_type != null) {
String mime = document.mime_type.toLowerCase();
if (isDocumentHasThumb(document) && (mime.equals("image/png") || mime.equals("image/jpg") || mime.equals("image/jpeg")) || (Build.VERSION.SDK_INT >= 26 && (mime.equals("image/heic")))) {
String mime = document.mime_type;
if (isDocumentHasThumb(document) && (mime.equalsIgnoreCase("image/png") || mime.equalsIgnoreCase("image/jpg") || mime.equalsIgnoreCase("image/jpeg")) || (Build.VERSION.SDK_INT >= 26 && (mime.equalsIgnoreCase("image/heic")))) {
for (int a = 0; a < document.attributes.size(); a++) {
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
if (attribute instanceof TLRPC.TL_documentAttributeImageSize) {
@ -4872,28 +4883,6 @@ public class MessageObject {
caption = Emoji.replaceEmoji(text, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
caption = replaceAnimatedEmoji(caption, entities, Theme.chat_msgTextPaint.getFontMetricsInt(), false);
int maxWidth = getMaxMessageTextWidth();
final float lineSpacing = 1f;
final float lineAdd = 0;
Layout.Alignment align = Layout.Alignment.ALIGN_NORMAL;
StaticLayout captionLayout = null;
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StaticLayout.Builder builder =
StaticLayout.Builder.obtain(caption, 0, caption.length(), Theme.chat_msgTextPaint, maxWidth)
.setLineSpacing(lineAdd, lineSpacing)
.setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY)
.setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE)
.setAlignment(align);
captionLayout = builder.build();
} else {
captionLayout = new StaticLayout(caption, Theme.chat_msgTextPaint, maxWidth, align, lineSpacing, lineAdd, false);
}
} catch (Exception e) {
FileLog.e(e);
}
captionHeight = captionLayout == null ? 0 : captionLayout.getHeight();
boolean hasEntities;
if (messageOwner.send_state != MESSAGE_SEND_STATE_SENT) {
hasEntities = false;
@ -6900,10 +6889,6 @@ public class MessageObject {
photoHeight = h;
}
if (caption != null && !TextUtils.isEmpty(caption)) {
photoHeight += captionHeight;
}
return photoHeight + AndroidUtilities.dp(14);
}
}
@ -8080,7 +8065,7 @@ public class MessageObject {
webpage.type = "telegram_story";
TLRPC.TL_webPageAttributeStory attr = new TLRPC.TL_webPageAttributeStory();
attr.id = messageOwner.media.id;
attr.user_id = messageOwner.media.user_id;
attr.peer = MessagesController.getInstance(currentAccount).getPeer(messageOwner.media.user_id);
if (messageOwner.media.storyItem != null) {
attr.flags |= 1;
attr.storyItem = messageOwner.media.storyItem;

View file

@ -146,6 +146,7 @@ public class MessagesController extends BaseController implements NotificationCe
private boolean hasArchivedChats;
private boolean hasStories;
public long storiesChangelogUserId = 777000;
private ChannelBoostsController channelBoostsControler;
public static TLRPC.Peer getPeerFromInputPeer(TLRPC.InputPeer peer) {
if (peer.chat_id != 0) {
@ -163,6 +164,19 @@ public class MessagesController extends BaseController implements NotificationCe
}
}
public ChannelBoostsController getBoostsController() {
if (channelBoostsControler != null) {
return channelBoostsControler;
}
synchronized (lockObjects[currentAccount]) {
if (channelBoostsControler != null) {
return channelBoostsControler;
}
channelBoostsControler = new ChannelBoostsController(currentAccount);
}
return channelBoostsControler;
}
class ChatlistUpdatesStat {
public ChatlistUpdatesStat() {
this.loading = true;
@ -4708,6 +4722,9 @@ public class MessagesController extends BaseController implements NotificationCe
} else {
oldChat.flags |= 16384;
}
if (!chat.stories_hidden_min) {
chat.stories_hidden = oldChat.stories_hidden;
}
if (oldFlags != newFlags || oldFlags2 != newFlags2) {
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.channelRightsUpdated, chat));
}
@ -14788,7 +14805,8 @@ public class MessagesController extends BaseController implements NotificationCe
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateReadStories) {
TLRPC.TL_updateReadStories updateReadStories = (TLRPC.TL_updateReadStories) baseUpdate;
getStoriesController().markStoriesAsReadFromServer(updateReadStories.user_id, updateReadStories.max_id);
long dialogId = DialogObject.getPeerDialogId(updateReadStories.peer);
getStoriesController().markStoriesAsReadFromServer(dialogId, updateReadStories.max_id);
} else if (baseUpdate instanceof TLRPC.TL_updatePeerSettings) {
TLRPC.TL_updatePeerSettings update = (TLRPC.TL_updatePeerSettings) baseUpdate;
if (contactsIds == null) {
@ -16308,7 +16326,9 @@ public class MessagesController extends BaseController implements NotificationCe
}
}
} else if (baseUpdate instanceof TLRPC.TL_updateSentStoryReaction) {
getStoriesController().updateStoryReaction(((TLRPC.TL_updateSentStoryReaction) baseUpdate).user_id, ((TLRPC.TL_updateSentStoryReaction) baseUpdate).story_id, ((TLRPC.TL_updateSentStoryReaction) baseUpdate).reaction);
TLRPC.TL_updateSentStoryReaction updateReaction = (TLRPC.TL_updateSentStoryReaction) baseUpdate;
long dialogId = DialogObject.getPeerDialogId(updateReaction.peer);
getStoriesController().updateStoryReaction(dialogId, updateReaction.story_id, updateReaction.reaction);
}
}
if (editor != null) {

View file

@ -96,7 +96,7 @@ public class MessagesStorage extends BaseController {
}
}
public final static int LAST_DB_VERSION = 133;
public final static int LAST_DB_VERSION = 134;
private boolean databaseMigrationInProgress;
public boolean showClearDatabaseAlert;
private LongSparseIntArray dialogIsForum = new LongSparseIntArray();
@ -619,7 +619,7 @@ public class MessagesStorage extends BaseController {
database.executeFast("CREATE TABLE wallpapers2(uid INTEGER PRIMARY KEY, data BLOB, num INTEGER)").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS wallpapers_num ON wallpapers2(num);").stepThis().dispose();
database.executeFast("CREATE TABLE unread_push_messages(uid INTEGER, mid INTEGER, random INTEGER, date INTEGER, data BLOB, fm TEXT, name TEXT, uname TEXT, flags INTEGER, PRIMARY KEY(uid, mid))").stepThis().dispose();
database.executeFast("CREATE TABLE unread_push_messages(uid INTEGER, mid INTEGER, random INTEGER, date INTEGER, data BLOB, fm TEXT, name TEXT, uname TEXT, flags INTEGER, topicId INTEGER, PRIMARY KEY(uid, mid))").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS unread_push_messages_idx_date ON unread_push_messages(date);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS unread_push_messages_idx_random ON unread_push_messages(random);").stepThis().dispose();
@ -1273,7 +1273,7 @@ public class MessagesStorage extends BaseController {
flags |= 2;
}
SQLitePreparedStatement state = database.executeFast("REPLACE INTO unread_push_messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
SQLitePreparedStatement state = database.executeFast("REPLACE INTO unread_push_messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
state.requery();
state.bindLong(1, message.getDialogId());
state.bindInteger(2, message.getId());
@ -1296,6 +1296,7 @@ public class MessagesStorage extends BaseController {
state.bindString(8, message.localUserName);
}
state.bindInteger(9, flags);
state.bindInteger(10, MessageObject.getTopicId(message.messageOwner, false));
state.step();
data.reuse();
@ -3510,7 +3511,7 @@ public class MessagesStorage extends BaseController {
cursor = null;
database.executeFast("DELETE FROM unread_push_messages WHERE date <= " + maxDate).stepThis().dispose();
cursor = database.queryFinalized("SELECT data, mid, date, uid, random, fm, name, uname, flags FROM unread_push_messages WHERE 1 ORDER BY date DESC LIMIT 50");
cursor = database.queryFinalized("SELECT data, mid, date, uid, random, fm, name, uname, flags, topicId FROM unread_push_messages WHERE 1 ORDER BY date DESC LIMIT 50");
while (cursor.next()) {
NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) {
@ -3524,6 +3525,7 @@ public class MessagesStorage extends BaseController {
String name = cursor.isNull(6) ? null : cursor.stringValue(6);
String userName = cursor.isNull(7) ? null : cursor.stringValue(7);
int flags = cursor.intValue(8);
int topicId = cursor.intValue(9);
if (MessageObject.getFromChatId(message) == 0) {
if (DialogObject.isUserDialog(message.dialog_id)) {
message.from_id = new TLRPC.TL_peerUser();
@ -3539,6 +3541,11 @@ public class MessagesStorage extends BaseController {
chatsToLoad.add(-message.dialog_id);
}
}
if (topicId != 0) {
message.reply_to = new TLRPC.TL_messageReplyHeader();
message.reply_to.forum_topic = true;
message.reply_to.reply_to_top_id = topicId;
}
pushMessages.add(new MessageObject(currentAccount, message, messageText, name, userName, (flags & 1) != 0, (flags & 2) != 0, (message.flags & 0x80000000) != 0, false));
addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad, null);
@ -14230,6 +14237,15 @@ public class MessagesStorage extends BaseController {
}
}
}
if (message.media.peer != null) {
long dialogId = DialogObject.getPeerDialogId(message.media.peer);
if (dialogId > 0) {
usersToLoad.add(dialogId);
}
if (dialogId < 0) {
chatsToLoad.add(-dialogId);
}
}
}
if (message.replies != null) {
for (int a = 0, N = message.replies.recent_repliers.size(); a < N; a++) {

View file

@ -3692,6 +3692,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
TLRPC.TL_messageMediaStory mediaStory = new MessageMediaStoryFull();
mediaStory.id = sendingStory.id;
mediaStory.user_id = sendingStory.dialogId;
mediaStory.peer = getMessagesController().getPeer(sendingStory.dialogId);
mediaStory.storyItem = sendingStory;
newMsg.media = mediaStory;
type = MEDIA_TYPE_STORY;
@ -4278,7 +4279,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} else if (type == MEDIA_TYPE_STORY) {
TLRPC.TL_inputMediaStory inputMediaStory = new TLRPC.TL_inputMediaStory();
inputMediaStory.id = sendingStory.id;
inputMediaStory.user_id = MessagesController.getInstance(currentAccount).getInputUser(sendingStory.dialogId);
inputMediaStory.peer = MessagesController.getInstance(currentAccount).getInputPeer(sendingStory.dialogId);
inputMedia = inputMediaStory;
}

View file

@ -234,6 +234,9 @@ public class SharedConfig {
public static int searchMessagesAsListHintShows;
public static int textSelectionHintShows;
public static int scheduledOrNoSoundHintShows;
public static long scheduledOrNoSoundHintSeenAt;
public static int scheduledHintShows;
public static long scheduledHintSeenAt;
public static int lockRecordAudioVideoHint;
public static boolean forwardingOptionsHintShown;
public static boolean searchMessagesAsListUsed;
@ -430,6 +433,9 @@ public class SharedConfig {
editor.putBoolean("sortFilesByName", sortFilesByName);
editor.putInt("textSelectionHintShows", textSelectionHintShows);
editor.putInt("scheduledOrNoSoundHintShows", scheduledOrNoSoundHintShows);
editor.putLong("scheduledOrNoSoundHintSeenAt", scheduledOrNoSoundHintSeenAt);
editor.putInt("scheduledHintShows", scheduledHintShows);
editor.putLong("scheduledHintSeenAt", scheduledHintSeenAt);
editor.putBoolean("forwardingOptionsHintShown", forwardingOptionsHintShown);
editor.putInt("lockRecordAudioVideoHint", lockRecordAudioVideoHint);
editor.putString("storageCacheDir", !TextUtils.isEmpty(storageCacheDir) ? storageCacheDir : "");
@ -605,6 +611,9 @@ public class SharedConfig {
storyReactionsLongPressHint = preferences.getBoolean("storyReactionsLongPressHint", false);
textSelectionHintShows = preferences.getInt("textSelectionHintShows", 0);
scheduledOrNoSoundHintShows = preferences.getInt("scheduledOrNoSoundHintShows", 0);
scheduledOrNoSoundHintSeenAt = preferences.getLong("scheduledOrNoSoundHintSeenAt", 0);
scheduledHintShows = preferences.getInt("scheduledHintShows", 0);
scheduledHintSeenAt = preferences.getLong("scheduledHintSeenAt", 0);
forwardingOptionsHintShown = preferences.getBoolean("forwardingOptionsHintShown", false);
lockRecordAudioVideoHint = preferences.getInt("lockRecordAudioVideoHint", 0);
disableVoiceAudioEffects = preferences.getBoolean("disableVoiceAudioEffects", false);
@ -824,6 +833,9 @@ public class SharedConfig {
lastUpdateVersion = BuildVars.BUILD_VERSION_STRING;
textSelectionHintShows = 0;
scheduledOrNoSoundHintShows = 0;
scheduledOrNoSoundHintSeenAt = 0;
scheduledHintShows = 0;
scheduledHintSeenAt = 0;
lockRecordAudioVideoHint = 0;
forwardingOptionsHintShown = false;
messageSeenHintCount = 3;
@ -887,10 +899,21 @@ public class SharedConfig {
editor.apply();
}
public static void increaseScheduledOrNoSuoundHintShowed() {
public static void increaseScheduledOrNoSoundHintShowed() {
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
SharedPreferences.Editor editor = preferences.edit();
scheduledOrNoSoundHintSeenAt = System.currentTimeMillis();
editor.putInt("scheduledOrNoSoundHintShows", ++scheduledOrNoSoundHintShows);
editor.putLong("scheduledOrNoSoundHintSeenAt", scheduledOrNoSoundHintSeenAt);
editor.apply();
}
public static void increaseScheduledHintShowed() {
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
SharedPreferences.Editor editor = preferences.edit();
scheduledHintSeenAt = System.currentTimeMillis();
editor.putInt("scheduledHintShows", ++scheduledHintShows);
editor.putLong("scheduledHintSeenAt", scheduledHintSeenAt);
editor.apply();
}
@ -909,6 +932,13 @@ public class SharedConfig {
editor.apply();
}
public static void removeScheduledHint() {
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("scheduledHintShows", 3);
editor.apply();
}
public static void increaseLockRecordAudioVideoHintShowed() {
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
SharedPreferences.Editor editor = preferences.edit();

View file

@ -284,19 +284,42 @@ public class VideoEditedInfo {
entity.rotation = rotation;
entity.width = width;
entity.height = height;
entity.additionalHeight = additionalHeight;
entity.text = text;
entity.entities.addAll(entities);
if (entities != null) {
entity.entities = new ArrayList<>();
entity.entities.addAll(entities);
}
entity.color = color;
entity.fontSize = fontSize;
entity.textTypeface = textTypeface;
entity.textTypefaceKey = textTypefaceKey;
entity.textAlign = textAlign;
entity.viewWidth = viewWidth;
entity.viewHeight = viewHeight;
entity.roundRadius = roundRadius;
entity.scale = scale;
entity.textViewWidth = textViewWidth;
entity.textViewHeight = textViewHeight;
entity.textViewX = textViewX;
entity.textViewY = textViewY;
entity.textAlign = textAlign;
entity.textTypeface = textTypeface;
entity.document = document;
entity.parentObject = parentObject;
entity.metadata = metadata;
entity.ptr = ptr;
entity.currentFrame = currentFrame;
entity.framesPerDraw = framesPerDraw;
entity.bitmap = bitmap;
entity.view = view;
entity.canvas = canvas;
entity.animatedFileDrawable = animatedFileDrawable;
entity.roundRadiusCanvas = roundRadiusCanvas;
entity.mediaArea = mediaArea;
entity.mediaGeo = mediaGeo;
entity.density = density;
entity.W = W;
entity.H = H;
entity.visibleReaction = visibleReaction;
return entity;
}
}

View file

@ -68,7 +68,9 @@ public class AudioBufferConverter {
}
private void checkChannels(int inputChannelCount, int outputChannelCount){
// Check channel count.
if (inputChannelCount == 6 && outputChannelCount == 2) {
return;
}
if (inputChannelCount != 1 && inputChannelCount != 2) {
throw new UnsupportedOperationException("Input channel count (" + inputChannelCount + ") not supported.");
}

View file

@ -1,6 +1,7 @@
package org.telegram.messenger.video;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.SurfaceTexture;
import android.net.Uri;
@ -251,6 +252,15 @@ public class VideoPlayerHolderBase {
return;
}
paused = true;
prepareStub();
dispatchQueue.postRunnable(() -> {
if (videoPlayer != null) {
videoPlayer.pause();
}
});
}
public void prepareStub() {
if (surfaceView != null && firstFrameRendered && surfaceView.getHolder().getSurface().isValid()) {
stubAvailable = true;
if (playerStubBitmap == null) {
@ -259,13 +269,11 @@ public class VideoPlayerHolderBase {
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
AndroidUtilities.getBitmapFromSurface(surfaceView, playerStubBitmap);
if (playerStubBitmap.getPixel(0, 0) == Color.TRANSPARENT) {
stubAvailable = false;
}
}
}
dispatchQueue.postRunnable(() -> {
if (videoPlayer != null) {
videoPlayer.pause();
}
});
}
public void play() {

View file

@ -9,7 +9,9 @@ public class DefaultAudioRemixer implements AudioRemixer {
@Override
public void remix(@NonNull ShortBuffer inputBuffer, int inputChannelCount, @NonNull ShortBuffer outputBuffer, int outputChannelCount) {
AudioRemixer remixer;
if (inputChannelCount > outputChannelCount) {
if (inputChannelCount == 6 && outputChannelCount == 2) {
remixer = AudioRemixer.PASSTHROUGH;
} else if (inputChannelCount > outputChannelCount) {
remixer = DOWNMIX;
} else if (inputChannelCount < outputChannelCount) {
remixer = AudioRemixer.UPMIX;
@ -22,7 +24,9 @@ public class DefaultAudioRemixer implements AudioRemixer {
@Override
public int getRemixedSize(int inputSize, int inputChannelCount, int outputChannelCount) {
AudioRemixer remixer;
if (inputChannelCount > outputChannelCount) {
if (inputChannelCount == 6 && outputChannelCount == 2) {
remixer = AudioRemixer.PASSTHROUGH;
} else if (inputChannelCount > outputChannelCount) {
remixer = DOWNMIX;
} else if (inputChannelCount < outputChannelCount) {
remixer = AudioRemixer.UPMIX;

View file

@ -14,31 +14,12 @@ public class DownMixAudioRemixer implements AudioRemixer {
@Override
public void remix(@NonNull ShortBuffer inputBuffer, int inputChannelCount, @NonNull ShortBuffer outputBuffer, int outputChannelCount) {
// Down-mix stereo to mono
// Viktor Toth's algorithm -
// See: http://www.vttoth.com/CMS/index.php/technical-notes/68
// http://stackoverflow.com/a/25102339
final int inRemaining = inputBuffer.remaining() / 2;
final int outSpace = outputBuffer.remaining();
final int samplesToBeProcessed = Math.min(inRemaining, outSpace);
for (int i = 0; i < samplesToBeProcessed; ++i) {
// Convert to unsigned
final int a = inputBuffer.get() + SIGNED_SHORT_LIMIT;
final int b = inputBuffer.get() + SIGNED_SHORT_LIMIT;
int m;
// Pick the equation
if ((a < SIGNED_SHORT_LIMIT) || (b < SIGNED_SHORT_LIMIT)) {
// Viktor's first equation when both sources are "quiet"
// (i.e. less than middle of the dynamic range)
m = a * b / SIGNED_SHORT_LIMIT;
} else {
// Viktor's second equation when one or both sources are loud
m = 2 * (a + b) - (a * b) / SIGNED_SHORT_LIMIT - UNSIGNED_SHORT_MAX;
}
// Convert output back to signed short
if (m == UNSIGNED_SHORT_MAX + 1) m = UNSIGNED_SHORT_MAX;
outputBuffer.put((short) (m - SIGNED_SHORT_LIMIT));
outputBuffer.put(mix(inputBuffer.get(), inputBuffer.get()));
}
}
@ -46,4 +27,28 @@ public class DownMixAudioRemixer implements AudioRemixer {
public int getRemixedSize(int inputSize, int inputChannelCount, int outputChannelCount) {
return inputSize / 2;
}
private short mix(short input1, short input2) {
// Down-mix stereo to mono
// Viktor Toth's algorithm -
// See: http://www.vttoth.com/CMS/index.php/technical-notes/68
// http://stackoverflow.com/a/25102339
// Convert to unsigned
final int a = input1 + SIGNED_SHORT_LIMIT;
final int b = input2 + SIGNED_SHORT_LIMIT;
int m;
// Pick the equation
if ((a < SIGNED_SHORT_LIMIT) || (b < SIGNED_SHORT_LIMIT)) {
// Viktor's first equation when both sources are "quiet"
// (i.e. less than middle of the dynamic range)
m = a * b / SIGNED_SHORT_LIMIT;
} else {
// Viktor's second equation when one or both sources are loud
m = 2 * (a + b) - (a * b) / SIGNED_SHORT_LIMIT - UNSIGNED_SHORT_MAX;
}
// Convert output back to signed short
if (m == UNSIGNED_SHORT_MAX + 1) m = UNSIGNED_SHORT_MAX;
return (short) (m - SIGNED_SHORT_LIMIT);
}
}

View file

@ -12,7 +12,9 @@ public class DefaultAudioResampler implements AudioResampler {
@Override
public void resample(@NonNull ShortBuffer inputBuffer, int inputSampleRate, @NonNull ShortBuffer outputBuffer, int outputSampleRate, int channels) {
if (inputSampleRate < outputSampleRate) {
if (inputSampleRate == 6 && outputSampleRate == 2) {
PASSTHROUGH.resample(inputBuffer, inputSampleRate, outputBuffer, outputSampleRate, channels);
} else if (inputSampleRate < outputSampleRate) {
UPSAMPLE.resample(inputBuffer, inputSampleRate, outputBuffer, outputSampleRate, channels);
} else if (inputSampleRate > outputSampleRate) {
DOWNSAMPLE.resample(inputBuffer, inputSampleRate, outputBuffer, outputSampleRate, channels);

File diff suppressed because it is too large Load diff

View file

@ -69,6 +69,7 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F
public boolean highlightActionButtons = false;
private boolean attached;
private boolean isSheet;
@Override
public void setHighlightActionButtons(boolean highlightActionButtons) {
@ -440,6 +441,16 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F
}
}
@Override
public void setIsSheet(boolean isSheet) {
this.isSheet = isSheet;
}
@Override
public boolean isSheet() {
return isSheet;
}
@Override
public void onConfigurationChanged(android.content.res.Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@ -1213,7 +1224,7 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F
return false;
}
if (BuildVars.LOGS_ENABLED) {
FileLog.d("present fragment " + fragment.getClass().getSimpleName());
FileLog.d("present fragment " + fragment.getClass().getSimpleName() + " args=" + fragment.getArguments());
}
StoryViewer.closeGlobalInstances();
if (inPreviewMode && transitionAnimationPreviewMode) {

View file

@ -393,6 +393,7 @@ public abstract class BaseFragment {
actionBar.onResume();
}
if (storyViewer != null) {
storyViewer.onResume();
storyViewer.updatePlayingMode();
}
if (overlayStoryViewer != null) {
@ -814,11 +815,13 @@ public abstract class BaseFragment {
}
BottomSheet[] bottomSheet = new BottomSheet[1];
INavigationLayout[] actionBarLayout = new INavigationLayout[]{INavigationLayout.newLayout(getParentActivity(), () -> bottomSheet[0])};
LaunchActivity.instance.sheetFragmentsStack.add(actionBarLayout[0]);
bottomSheet[0] = new BottomSheet(getParentActivity(), true, fragment.getResourceProvider()) {
{
drawNavigationBar = true;
actionBarLayout[0].setFragmentStack(new ArrayList<>());
actionBarLayout[0].addFragmentToStack(fragment);
actionBarLayout[0].setIsSheet(true);
actionBarLayout[0].showLastFragment();
actionBarLayout[0].getView().setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0);
containerView = actionBarLayout[0].getView();
@ -836,6 +839,7 @@ public abstract class BaseFragment {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fixNavigationBar(Theme.getColor(Theme.key_dialogBackgroundGray, fragment.getResourceProvider()));
AndroidUtilities.setLightStatusBar(getWindow(), fragment.isLightStatusBar());
}
@Override
@ -860,6 +864,7 @@ public abstract class BaseFragment {
}
}
super.dismiss();
LaunchActivity.instance.sheetFragmentsStack.remove(actionBarLayout[0]);
actionBarLayout[0] = null;
}
@ -1052,6 +1057,9 @@ public abstract class BaseFragment {
public StoryViewer getOrCreateStoryViewer() {
if (storyViewer == null) {
storyViewer = new StoryViewer(this);
if (parentLayout.isSheet()) {
storyViewer.fromBottomSheet = true;
}
}
return storyViewer;
}

View file

@ -277,6 +277,10 @@ public interface INavigationLayout {
return null;
}
void setIsSheet(boolean isSheet);
boolean isSheet();
interface INavigationLayoutDelegate {
default boolean needPresentFragment(INavigationLayout layout, NavigationParams params) {
return needPresentFragment(params.fragment, params.removeLast, params.noAnimation, layout);

View file

@ -68,7 +68,7 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter {
private boolean hasGps;
private boolean isEmpty;
public boolean hasStories;
public ArrayList<TLRPC.TL_userStories> userStories = new ArrayList<>();
public ArrayList<TLRPC.PeerStories> userStories = new ArrayList<>();
DialogStoriesCell dialogStoriesCell;
BaseFragment fragment;
@ -84,7 +84,7 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter {
this.fragment = fragment;
}
public void setStories(ArrayList<TLRPC.TL_userStories> stories, boolean animated) {
public void setStories(ArrayList<TLRPC.PeerStories> stories, boolean animated) {
// boolean hasStories = !stories.isEmpty();
// userStories.clear();
// userStories.addAll(stories);
@ -194,7 +194,7 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter {
if (position == userStories.size()) {
return "Header";
} else {
return userStories.get(position).user_id;
return DialogObject.getPeerDialogId(userStories.get(position).peer);
}
} else if (hasStories && section > 1) {
section--;
@ -517,7 +517,7 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter {
userCell.setAvatarPadding(6);
userCell.storyParams.drawSegments = true;
StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController();
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(userStories.get(position).user_id);
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(DialogObject.getPeerDialogId(userStories.get(position).peer));
if (storiesController.hasUnreadStories(user.id)) {
int newStories = storiesController.getUnreadStoriesCount(user.id);
userCell.setData(user, ContactsController.formatName(user), LocaleController.formatPluralString("NewStories", newStories, newStories).toLowerCase(), 0);
@ -703,7 +703,7 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter {
public void removeStory(long dialogId) {
for (int i = 0; i < userStories.size(); i++) {
if (userStories.get(i).user_id == dialogId) {
if (DialogObject.getPeerDialogId(userStories.get(i).peer) == dialogId) {
userStories.remove(i);
if (userStories.isEmpty()) {

View file

@ -1100,11 +1100,12 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
if (storiesController.getHiddenList().isEmpty()) {
return;
}
boolean unreadOnly = storiesController.getUnreadState(storiesController.getHiddenList().get(0).user_id) != StoriesController.STATE_READ;
boolean unreadOnly = storiesController.getUnreadState(DialogObject.getPeerDialogId(storiesController.getHiddenList().get(0).peer)) != StoriesController.STATE_READ;
ArrayList<Long> peerIds = new ArrayList<>();
for (int i = 0; i < storiesController.getHiddenList().size(); i++) {
if (!unreadOnly || storiesController.getUnreadState(storiesController.getHiddenList().get(i).user_id) != StoriesController.STATE_READ) {
peerIds.add(storiesController.getHiddenList().get(i).user_id);
long dialogId = DialogObject.getPeerDialogId(storiesController.getHiddenList().get(i).peer);
if (!unreadOnly || storiesController.getUnreadState(dialogId) != StoriesController.STATE_READ) {
peerIds.add(dialogId);
}
}
@ -1323,6 +1324,10 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
height -= AndroidUtilities.statusBarHeight;
if (parentFragment.hasStories && !collapsedView && !isTransitionSupport) {
height -= ActionBar.getCurrentActionBarHeight();
if (getParent() instanceof DialogsActivity.DialogsRecyclerView) {
DialogsActivity.DialogsRecyclerView dialogsRecyclerView = (DialogsActivity.DialogsRecyclerView) getParent();
height -= dialogsRecyclerView.additionalPadding;
}
} else if (collapsedView) {
height -= paddingTop;
}
@ -1333,6 +1338,10 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
height -= AndroidUtilities.statusBarHeight;
if (parentFragment.hasStories && !collapsedView && !isTransitionSupport) {
height -= ActionBar.getCurrentActionBarHeight();
if (getParent() instanceof DialogsActivity.DialogsRecyclerView) {
DialogsActivity.DialogsRecyclerView dialogsRecyclerView = (DialogsActivity.DialogsRecyclerView) getParent();
height -= dialogsRecyclerView.additionalPadding;
}
} else if (collapsedView) {
height -= paddingTop;
}

View file

@ -319,7 +319,6 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter {
}
showDivider = true;
}
boolean needDivider = false;
if (MessagesController.getInstance(UserConfig.selectedAccount).storiesEnabled()) {
items.add(new Item(16, LocaleController.getString("ProfileMyStories", R.string.ProfileMyStories), R.drawable.msg_menu_stories));
showDivider = true;

View file

@ -420,6 +420,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD
DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this);
previousWidth = 0;
imageReceiver.setAutoRepeatCount(0);
imageReceiver.clearDecorators();
if (messageObject.isStoryMention()) {
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(messageObject.messageOwner.media.user_id);
avatarDrawable.setInfo(user);

View file

@ -4317,6 +4317,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
photoImage.setCrossfadeDuration(ImageReceiver.DEFAULT_CROSSFADE_DURATION);
photoImage.setCrossfadeByScale(0);
photoImage.setGradientBitmap(null);
photoImage.clearDecorators();
lastTranslated = messageObject.translated;
lastSendState = messageObject.messageOwner.send_state;
lastDeleteDate = messageObject.messageOwner.destroyTime;
@ -4688,7 +4689,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
TLRPC.StoryItem storyItem = null;
TLRPC.ThemeSettings androidThemeSettings = null;
if (!drawInstantView) {
if ("telegram_livestream".equals(webpageType)) {
if ("telegram_channel_boost".equals(webpageType)) {
drawInstantView = true;
drawInstantViewType = 18;
} else if ("telegram_livestream".equals(webpageType)) {
drawInstantView = true;
drawInstantViewType = 11;
} else if ("telegram_voicechat".equals(webpageType)) {
@ -4751,7 +4755,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
storyItem = attribute.storyItem;
if (storyItem != null) {
storyItem.messageId = messageObject.getId();
storyItem.dialogId = attribute.user_id;
storyItem.dialogId = DialogObject.getPeerDialogId(attribute.peer);
if (storyItem instanceof TLRPC.TL_storyItemDeleted) {
drawInstantView = false;
hasLinkPreview = false;
@ -4977,8 +4981,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
"article".equals(type) || "telegram_bot".equals(type) ||
"telegram_user".equals(type) || "telegram_channel".equals(type) ||
"telegram_megagroup".equals(type) || "telegram_voicechat".equals(type) ||
"telegram_livestream".equals(type);
smallImage = !slideshow && (!drawInstantView || drawInstantViewType == 1 || drawInstantViewType == 2 || drawInstantViewType == 9 || drawInstantViewType == 11 || drawInstantViewType == 13) && document == null && isSmallImageType;
"telegram_livestream".equals(type) || "telegram_channel_boost".equals(type);
smallImage = !slideshow && (!drawInstantView || drawInstantViewType == 1 || drawInstantViewType == 2 || drawInstantViewType == 9 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 18) && document == null && isSmallImageType;
isSmallImage = smallImage && type != null && currentMessageObject.photoThumbs != null;
} else if (hasInvoicePreview) {
TLRPC.TL_messageMediaInvoice invoice = (TLRPC.TL_messageMediaInvoice) MessageObject.getMedia(messageObject.messageOwner);
@ -5011,7 +5015,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
isSmallImage = false;
smallImage = false;
}
if (drawInstantViewType == 11) {
if (drawInstantViewType == 18) {
site_name = LocaleController.getString("BoostChannel", R.string.BoostChannel);
} else if (drawInstantViewType == 11) {
site_name = LocaleController.getString("VoipChannelVoiceChat", R.string.VoipChannelVoiceChat);
} else if (drawInstantViewType == 9) {
site_name = LocaleController.getString("VoipGroupVoiceChat", R.string.VoipGroupVoiceChat);
@ -9060,6 +9066,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
str = LocaleController.getString("OpenLink").toUpperCase();
} else if (drawInstantViewType == 17) {
str = LocaleController.getString("ViewStory").toUpperCase();
} else if (drawInstantViewType == 18) {
str = LocaleController.getString("BoostLinkButton", R.string.BoostLinkButton);
} else {
str = LocaleController.getString("InstantView", R.string.InstantView);
}
@ -10610,7 +10618,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
linkPreviewY += currentMessageObject.textHeight + AndroidUtilities.dp(4);
}
if (drawPhotoImage && drawInstantView && drawInstantViewType != 9 && drawInstantViewType != 2 && drawInstantViewType != 13 && drawInstantViewType != 11 && drawInstantViewType != 1 || drawInstantViewType == 6 && imageBackgroundColor != 0) {
if (drawPhotoImage && drawInstantView && drawInstantViewType != 9 && drawInstantViewType != 2 && drawInstantViewType != 13 && drawInstantViewType != 11 && drawInstantViewType != 1 && drawInstantViewType != 18 || drawInstantViewType == 6 && imageBackgroundColor != 0) {
if (linkPreviewY != startY) {
linkPreviewY += AndroidUtilities.dp(2);
}
@ -10791,7 +10799,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
linkPreviewY += descriptionLayout.getLineBottom(descriptionLayout.getLineCount() - 1);
}
if (drawPhotoImage && (!drawInstantView || drawInstantViewType == 9 || drawInstantViewType == 2 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 1)) {
if (drawPhotoImage && (!drawInstantView || drawInstantViewType == 9 || drawInstantViewType == 2 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 1 || drawInstantViewType == 18)) {
if (linkPreviewY != startY) {
linkPreviewY += AndroidUtilities.dp(2);
}
@ -12897,7 +12905,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
CharSequence lastLine;
if (messageObject.type == MessageObject.TYPE_STORY) {
currentForwardNameString = forwardedString = LocaleController.getString("ForwardedStory", R.string.ForwardedStory);
lastLine = AndroidUtilities.replaceTags(LocaleController.formatString("ForwardedStoryFrom", R.string.ForwardedStoryFrom, getNameFromDialogId(messageObject.messageOwner.media.user_id)));
long storyDialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.media.peer);
if (storyDialogId > 0) {
currentForwardUser = MessagesController.getInstance(currentAccount).getUser(storyDialogId);
} else {
currentForwardChannel = MessagesController.getInstance(currentAccount).getChat(-storyDialogId);
}
String name = getNameFromDialogId(storyDialogId);
if (storyDialogId < 0 && currentForwardChannel == null) {
name = LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate);
}
lastLine = AndroidUtilities.replaceTags(LocaleController.formatString("ForwardedStoryFrom", R.string.ForwardedStoryFrom, name));
forwardedNameWidth = getMaxNameWidth();
} else {
if (currentForwardChannel != null) {
@ -15399,6 +15417,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
invalidate();
}
public boolean isCheckBoxVisible() {
return checkBoxVisible || checkBoxAnimationInProgress;
}
public void setChecked(boolean checked, boolean allChecked, boolean animated) {
if (checkBox != null) {
checkBox.setChecked(allChecked, animated);

View file

@ -143,7 +143,7 @@ public class DrawerActionCell extends FrameLayout {
} else {
textView.setText(bot.short_name);
}
TLRPC.TL_attachMenuBotIcon botIcon = MediaDataController.getSideMenuBotIcon(bot);
TLRPC.TL_attachMenuBotIcon botIcon = MediaDataController.getSideAttachMenuBotIcon(bot);
if (botIcon != null) {
imageView.setImage(ImageLocation.getForDocument(botIcon.icon), "24_24", (Drawable) null, bot);
} else {

View file

@ -53,6 +53,7 @@ import org.telegram.ui.Components.FlickerLoadingView;
import org.telegram.ui.Components.spoilers.SpoilerEffect;
import org.telegram.ui.Components.spoilers.SpoilerEffect2;
import org.telegram.ui.PhotoViewer;
import org.telegram.ui.Stories.StoryWidgetsImageDecorator;
import org.telegram.ui.Stories.recorder.DominantColors;
public class SharedPhotoVideoCell2 extends FrameLayout {
@ -192,6 +193,7 @@ public class SharedPhotoVideoCell2 extends FrameLayout {
videoText = null;
videoInfoLayot = null;
showVideoLayout = false;
imageReceiver.clearDecorators();
if (!TextUtils.isEmpty(restrictionReason)) {
showImageStub = true;
} else if (messageObject.storyItem != null && messageObject.storyItem.media instanceof TLRPC.TL_messageMediaUnsupported) {
@ -270,6 +272,9 @@ public class SharedPhotoVideoCell2 extends FrameLayout {
if (imageReceiver.getBitmap() != null && currentMessageObject.hasMediaSpoilers() && !currentMessageObject.isMediaSpoilersRevealed) {
blurImageReceiver.setImageBitmap(Utilities.stackBlurBitmapMax(imageReceiver.getBitmap()));
}
if (messageObject != null && messageObject.storyItem != null) {
imageReceiver.addDecorator(new StoryWidgetsImageDecorator(messageObject.storyItem));
}
invalidate();
}

View file

@ -66,6 +66,8 @@ public class UnconfirmedAuthHintCell extends FrameLayout {
public UnconfirmedAuthHintCell(Context context) {
super(context);
setClickable(true);
linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.VERTICAL);

View file

@ -0,0 +1,383 @@
package org.telegram.ui;
import static org.telegram.messenger.AndroidUtilities.dp;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.FixedHeightEmptyCell;
import org.telegram.ui.Cells.ManageChatTextCell;
import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Cells.UserCell;
import org.telegram.ui.Charts.view_data.ChartHeaderView;
import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LinkActionView;
import org.telegram.ui.Components.ListView.AdapterWithDiffUtils;
import org.telegram.ui.Components.Premium.LimitPreviewView;
import org.telegram.ui.Components.RLottieImageView;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Stories.ChannelBoostUtilities;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;
public class ChannelBoostLayout extends FrameLayout {
private final static int OVERVIEW_TYPE = 0;
private final static int HEADER_VIEW_TYPE = 1;
private final static int DIVIDER_VIEW_TYPE = 2;
private final static int LINK_VIEW_TYPE = 3;
private final static int BOOST_VIEW = 4;
private final static int USER_VIEW_TYPE = 5;
private final static int DIVIDER_TEXT_VIEW_TYPE = 6;
private final static int EMPTY_VIEW_8DP = 7;
private final static int NO_USERS_HINT = 8;
private final static int SHOW_MORE_VIEW_TYPE = 9;
private final long dialogId;
int currentAccount = UserConfig.selectedAccount;
BaseFragment fragment;
TLRPC.TL_stories_boostsStatus boostsStatus;
private final Theme.ResourcesProvider resourcesProvider;
ArrayList<TLRPC.TL_booster> boosters = new ArrayList<>();
boolean hasNext;
int nextRemaining;
ArrayList<ItemInternal> items = new ArrayList<>();
AdapterWithDiffUtils adapter = new AdapterWithDiffUtils() {
@Override
public boolean isEnabled(RecyclerView.ViewHolder holder) {
return items.get(holder.getAdapterPosition()).selectable;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case BOOST_VIEW:
LimitPreviewView limitPreviewView = new LimitPreviewView(getContext(), R.drawable.filled_limit_boost, 10, 0, resourcesProvider);
limitPreviewView.isStatistic = true;
view = limitPreviewView;
Drawable shadowDrawable = Theme.getThemedDrawable(getContext(), R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider));
Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray));
CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true);
view.setPadding(0, dp(20), 0, AndroidUtilities.dp(20));
view.setBackground(combinedDrawable);
limitPreviewView.setBoosts(boostsStatus, false);
break;
case DIVIDER_TEXT_VIEW_TYPE:
view = new TextInfoPrivacyCell(parent.getContext(), 12, resourcesProvider);
shadowDrawable = Theme.getThemedDrawable(getContext(), R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider));
background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray));
combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true);
view.setBackground(combinedDrawable);
break;
case DIVIDER_VIEW_TYPE:
view = new ShadowSectionCell(parent.getContext(), 12, Theme.getColor(Theme.key_windowBackgroundGray));
break;
case OVERVIEW_TYPE:
view = new StatisticActivity.OverviewCell(getContext());
break;
case HEADER_VIEW_TYPE:
view = new ChartHeaderView(getContext());
view.setPadding(view.getPaddingLeft(), AndroidUtilities.dp(16), view.getRight(), AndroidUtilities.dp(16));
break;
case LINK_VIEW_TYPE:
LinkActionView linkActionView = new LinkActionView(getContext(), fragment, null, 0, false, false);
view = linkActionView;
linkActionView.hideOptions();
linkActionView.setLink(ChannelBoostUtilities.createLink(currentAccount, dialogId));
view.setPadding(AndroidUtilities.dp(11), 0, AndroidUtilities.dp(11), AndroidUtilities.dp(24));
break;
case USER_VIEW_TYPE:
view = new UserCell(getContext(), 0, 0, false);
break;
case EMPTY_VIEW_8DP:
view = new FixedHeightEmptyCell(getContext(), 8);
break;
case NO_USERS_HINT:
FrameLayout frameLayout = new FrameLayout(getContext()) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY));
}
};
TextView textView = new TextView(getContext());
textView.setText(LocaleController.getString("NoBoostersHint", R.string.NoBoostersHint));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText));
textView.setGravity(Gravity.CENTER);
frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 7, 0, 0));
view = frameLayout;
break;
case SHOW_MORE_VIEW_TYPE:
ManageChatTextCell actionCell = new ManageChatTextCell(getContext());
actionCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton);
// actionCell.setText(LocaleController.getString("ShowMore", R.string.ShowMore), null, R.drawable.arrow_more, false);
view = actionCell;
break;
default:
throw new UnsupportedOperationException();
}
view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return new RecyclerListView.Holder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == BOOST_VIEW) {
} else if (holder.getItemViewType() == HEADER_VIEW_TYPE) {
ChartHeaderView headerCell = (ChartHeaderView) holder.itemView;
headerCell.setTitle(items.get(position).title);
headerCell.showDate(false);
} else if (holder.getItemViewType() == OVERVIEW_TYPE) {
StatisticActivity.OverviewCell overviewCell = (StatisticActivity.OverviewCell) holder.itemView;
overviewCell.setData(0, Integer.toString(boostsStatus.level), null, LocaleController.getString("BoostsLevel2", R.string.BoostsLevel2));
if (boostsStatus.premium_audience != null || boostsStatus.premium_audience.total == 0) {
overviewCell.setData(1, "~" + (int) boostsStatus.premium_audience.part, String.format(Locale.US, "%.1f", (float) boostsStatus.premium_audience.part / (float) boostsStatus.premium_audience.total) + "%", LocaleController.getString("PremiumSubscribers", R.string.PremiumSubscribers));
} else {
overviewCell.setData(1, "~0", "0%", LocaleController.getString("PremiumSubscribers", R.string.PremiumSubscribers));
}
overviewCell.setData(2, String.valueOf(boostsStatus.boosts), null, LocaleController.getString("BoostsExisting", R.string.BoostsExisting));
overviewCell.setData(3, String.valueOf(boostsStatus.next_level_boosts - boostsStatus.boosts), null, LocaleController.getString("BoostsToLevel", R.string.BoostsToLevel));
} else if (holder.getItemViewType() == USER_VIEW_TYPE) {
TLRPC.TL_booster booster = items.get(position).booster;
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(booster.user_id);
UserCell userCell = (UserCell) holder.itemView;
String str = LocaleController.formatString("BoostExpireOn", R.string.BoostExpireOn, LocaleController.formatDate(booster.expires));
userCell.setData(user, ContactsController.formatName(user), str, 0);
} else if (holder.getItemViewType() == DIVIDER_TEXT_VIEW_TYPE) {
TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView;
privacyCell.setText(items.get(position).title);
} else if (holder.getItemViewType() == SHOW_MORE_VIEW_TYPE) {
ManageChatTextCell actionCell = (ManageChatTextCell) holder.itemView;
actionCell.setText(LocaleController.formatPluralString("ShowVotes", nextRemaining), null, R.drawable.arrow_more, false);
}
}
@Override
public int getItemCount() {
return items.size();
}
@Override
public int getItemViewType(int position) {
return items.get(position).viewType;
}
};
RecyclerListView listView;
boolean usersLoading;
private LinearLayout progressLayout;
public ChannelBoostLayout(BaseFragment fragment, long dialogId, Theme.ResourcesProvider resourcesProvider) {
super(fragment.getContext());
this.fragment = fragment;
Context context = fragment.getContext();
this.resourcesProvider = resourcesProvider;
this.dialogId = dialogId;
listView = new RecyclerListView(context);
listView.setLayoutManager(new LinearLayoutManager(context));
DefaultItemAnimator defaultItemAnimator = new DefaultItemAnimator();
defaultItemAnimator.setSupportsChangeAnimations(false);
defaultItemAnimator.setDelayAnimations(false);
listView.setItemAnimator(defaultItemAnimator);
listView.setOnItemClickListener((view, position) -> {
if (view instanceof UserCell) {
UserCell cell = (UserCell) view;
fragment.presentFragment(ProfileActivity.of(cell.getDialogId()));
}
if (items.get(position).viewType == SHOW_MORE_VIEW_TYPE) {
loadUsers();
}
});
addView(listView);
loadStatistic();
listView.setAdapter(adapter);
updateRows(false);
createEmptyView(getContext());
progressLayout.setAlpha(0);
progressLayout.animate().alpha(1f).setDuration(200).setStartDelay(500).start();
}
private void updateRows(boolean animated) {
ArrayList<ItemInternal> oldItems = new ArrayList<>(items);
items.clear();
if (boostsStatus != null) {
items.add(new ItemInternal(BOOST_VIEW, false));
items.add(new ItemInternal(HEADER_VIEW_TYPE, LocaleController.getString("StatisticOverview", R.string.StatisticOverview)));
items.add(new ItemInternal(OVERVIEW_TYPE, true));
items.add(new ItemInternal(DIVIDER_VIEW_TYPE, false));
items.add(new ItemInternal(HEADER_VIEW_TYPE, LocaleController.getString("Boosters", R.string.Boosters)));
if (boosters.isEmpty()) {
items.add(new ItemInternal(NO_USERS_HINT, false));
items.add(new ItemInternal(DIVIDER_VIEW_TYPE, false));
} else {
for (int i = 0; i < boosters.size(); i++) {
items.add(new ItemInternal(USER_VIEW_TYPE, boosters.get(i)));
}
if (hasNext) {
items.add(new ItemInternal(SHOW_MORE_VIEW_TYPE, false));
} else {
items.add(new ItemInternal(EMPTY_VIEW_8DP, false));
}
items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostersInfoDescription", R.string.BoostersInfoDescription)));
}
items.add(new ItemInternal(HEADER_VIEW_TYPE, LocaleController.getString("LinkForBoosting", R.string.LinkForBoosting)));
items.add(new ItemInternal(LINK_VIEW_TYPE, false));
}
if (animated) {
adapter.setItems(oldItems, items);
} else {
adapter.notifyDataSetChanged();
}
}
private void loadStatistic() {
MessagesController.getInstance(currentAccount).getBoostsController().getBoostsStats(dialogId, tl_stories_boostsStatus -> AndroidUtilities.runOnUIThread(() -> {
boostsStatus = tl_stories_boostsStatus;
progressLayout.animate().cancel();
progressLayout.animate().alpha(0).setDuration(100).setStartDelay(0).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
progressLayout.setVisibility(View.GONE);
}
});
updateRows(true);
loadUsers();
}));
}
private void loadUsers() {
if (usersLoading) {
return;
}
usersLoading = true;
TLRPC.TL_stories_getBoostersList listReq = new TLRPC.TL_stories_getBoostersList();
listReq.limit = 25;
listReq.offset = "";
listReq.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId);
ConnectionsManager.getInstance(currentAccount).sendRequest(listReq, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
usersLoading = false;
if (response != null) {
TLRPC.TL_stories_boostersList list = (TLRPC.TL_stories_boostersList) response;
boosters.addAll(list.boosters);
hasNext = !TextUtils.isEmpty(list.next_offset) && boosters.size() < list.count;
nextRemaining = list.count - boosters.size();
updateRows(true);
}
}), ConnectionsManager.RequestFlagFailOnServerErrors);
}
private class ItemInternal extends AdapterWithDiffUtils.Item {
String title;
TLRPC.TL_booster booster;
public ItemInternal(int viewType, String title) {
super(viewType, false);
this.title = title;
}
public ItemInternal(int viewType, TLRPC.TL_booster booster) {
super(viewType, false);
this.booster = booster;
}
public ItemInternal(int viewType, boolean selectable) {
super(viewType, selectable);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ItemInternal that = (ItemInternal) o;
if (booster != null && that.booster != null) {
return booster.user_id == that.booster.user_id;
} else {
return true;
}
}
@Override
public int hashCode() {
return Objects.hash(title, booster);
}
}
public void createEmptyView(Context context) {
progressLayout = new LinearLayout(context);
progressLayout.setOrientation(LinearLayout.VERTICAL);
RLottieImageView imageView = new RLottieImageView(context);
imageView.setAutoRepeat(true);
imageView.setAnimation(R.raw.statistic_preload, 120, 120);
imageView.playAnimation();
TextView loadingTitle = new TextView(context);
loadingTitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
loadingTitle.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
loadingTitle.setTextColor(Theme.getColor(Theme.key_player_actionBarTitle));
loadingTitle.setTag(Theme.key_player_actionBarTitle);
loadingTitle.setText(LocaleController.getString("LoadingStats", R.string.LoadingStats));
loadingTitle.setGravity(Gravity.CENTER_HORIZONTAL);
TextView loadingSubtitle = new TextView(context);
loadingSubtitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
loadingSubtitle.setTextColor(Theme.getColor(Theme.key_player_actionBarSubtitle));
loadingSubtitle.setTag(Theme.key_player_actionBarSubtitle);
loadingSubtitle.setText(LocaleController.getString("LoadingStatsDescription", R.string.LoadingStatsDescription));
loadingSubtitle.setGravity(Gravity.CENTER_HORIZONTAL);
progressLayout.addView(imageView, LayoutHelper.createLinear(120, 120, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 20));
progressLayout.addView(loadingTitle, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 10));
progressLayout.addView(loadingSubtitle, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL));
addView(progressLayout, LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 30));
}
}

View file

@ -316,6 +316,7 @@ import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -469,6 +470,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private HintView mediaBanTooltip;
private HintView searchAsListHint;
private HintView scheduledOrNoSoundHint;
private boolean scheduledOrNoSoundHintShown;
private HintView scheduledHint;
private boolean scheduledHintShown;
private boolean searchAsListHintShown;
private HintView fwdRestrictedTopHint;
private HintView fwdRestrictedBottomHint;
@ -1811,6 +1815,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
emojiAnimationsOverlay.cancelAllAnimations();
}
ReactionsEffectOverlay.dismissAll();
if (TextUtils.isEmpty(text)) {
hideSendButtonHints();
AndroidUtilities.cancelRunOnUIThread(showScheduledHintRunnable);
} else if (!bigChange){
showScheduledHint();
}
}
@Override
@ -2007,6 +2017,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (scheduledOrNoSoundHint != null) {
scheduledOrNoSoundHint.hide();
}
if (scheduledHint != null) {
scheduledHint.hide();
}
}
@Override
@ -2077,16 +2090,38 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (anchor == null || chatActivityEnterView.getEditField() == null || chatActivityEnterView.getEditField().getText().length() < 5) {
return;
}
SharedConfig.increaseScheduledOrNoSuoundHintShowed();
SharedConfig.increaseScheduledOrNoSoundHintShowed();
if (scheduledOrNoSoundHint == null) {
scheduledOrNoSoundHint = new HintView(getParentActivity(), 4, themeDelegate);
scheduledOrNoSoundHint.setShowingDuration(5000);
scheduledOrNoSoundHint.createCloseButton();
scheduledOrNoSoundHint.setAlpha(0);
scheduledOrNoSoundHint.setVisibility(View.INVISIBLE);
scheduledOrNoSoundHint.setText(LocaleController.getString("ScheduledOrNoSoundHint", R.string.ScheduledOrNoSoundHint));
contentView.addView(scheduledOrNoSoundHint, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0));
}
scheduledOrNoSoundHint.showForView(anchor, true);
scheduledOrNoSoundHintShown = true;
};
private final Runnable showScheduledHintRunnable = () -> {
if (getParentActivity() == null || fragmentView == null || chatActivityEnterView == null) {
return;
}
View anchor = chatActivityEnterView.getSendButton();
if (anchor == null || chatActivityEnterView.getEditField() == null || chatActivityEnterView.getEditField().getText().length() == 0) {
return;
}
SharedConfig.increaseScheduledHintShowed();
if (scheduledHint == null) {
scheduledHint = new HintView(getParentActivity(), 4, themeDelegate);
scheduledHint.createCloseButton();
scheduledHint.setAlpha(0);
scheduledHint.setVisibility(View.INVISIBLE);
scheduledHint.setText(LocaleController.getString("ScheduledHint", R.string.ScheduledHint));
contentView.addView(scheduledHint, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 10, 0, 10, 0));
}
scheduledHint.showForView(anchor, true);
scheduledHintShown = true;
};
public ChatActivity(Bundle args) {
@ -2825,6 +2860,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
selectedMessagesCanStarIds[a].clear();
}
scheduledOrNoSoundHint = null;
scheduledHint = null;
infoTopView = null;
aspectRatioFrameLayout = null;
videoTextureView = null;
@ -4931,9 +4967,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
float tx = cell.getSlidingOffsetX() + cell.getCheckBoxTranslation();
int y = (int) ((replaceAnimation ? child.getTop() : child.getY()) + cell.getLayoutHeight() + cell.getTransitionParams().deltaBottom);
int maxY = chatListView.getMeasuredHeight() - chatListView.getPaddingBottom();
boolean canUpdateTx = cell.isCheckBoxVisible() && tx == 0;
if (cell.isPlayingRound() || cell.getTransitionParams().animatePlayingRound) {
if (cell.getTransitionParams().animatePlayingRound) {
float progressLocal = cell.getTransitionParams().animateChangeProgress;
@ -5000,6 +5036,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
top = view.getTop();
if (view instanceof ChatMessageCell) {
cell = (ChatMessageCell) view;
float newTx = cell.getSlidingOffsetX() + cell.getCheckBoxTranslation();
if (canUpdateTx && newTx > 0) {
tx = newTx;
}
if (!cell.drawPinnedTop()) {
break;
} else {
@ -5017,6 +5057,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
top = holder.itemView.getTop();
if (holder.itemView instanceof ChatMessageCell) {
cell = (ChatMessageCell) holder.itemView;
float newTx = cell.getSlidingOffsetX() + cell.getCheckBoxTranslation();
if (canUpdateTx && newTx > 0) {
tx = newTx;
}
if (!cell.drawPinnedTop()) {
break;
} else {
@ -9398,11 +9442,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
private boolean approved;
public void processInlineBotWebView(TLRPC.TL_inlineBotWebView object) {
BotWebViewSheet webViewSheet = new BotWebViewSheet(getContext(), getResourceProvider());
webViewSheet.setParentActivity(getParentActivity());
webViewSheet.requestWebView(currentAccount, currentUser != null ? currentUser.id : currentChat.id, mentionContainer.getAdapter().getFoundContextBot().id, object.text, object.url, BotWebViewSheet.TYPE_SIMPLE_WEB_VIEW_BUTTON, 0, false, BotWebViewSheet.FLAG_FROM_INLINE_SWITCH);
webViewSheet.show();
final Runnable open = () -> {
BotWebViewSheet webViewSheet = new BotWebViewSheet(getContext(), getResourceProvider());
webViewSheet.setParentActivity(getParentActivity());
webViewSheet.requestWebView(currentAccount, currentUser != null ? currentUser.id : currentChat.id, mentionContainer.getAdapter().getFoundContextBot().id, object.text, object.url, BotWebViewSheet.TYPE_SIMPLE_WEB_VIEW_BUTTON, 0, false, BotWebViewSheet.FLAG_FROM_INLINE_SWITCH);
webViewSheet.show();
};
if (approved) {
open.run();
} else {
WebAppDisclaimerAlert.show(getContext(), ignored -> {
approved = true;
open.run();
}, null);
}
}
public void processInlineBotContextPM(TLRPC.TL_inlineBotSwitchPM object) {
@ -9850,6 +9905,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (scheduledOrNoSoundHint != null) {
scheduledOrNoSoundHint.hide();
}
if (scheduledHint != null) {
scheduledHint.hide();
}
}
if (fwdRestrictedBottomHint != null) {
fwdRestrictedBottomHint.hide();
@ -9874,6 +9932,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
private void hideSendButtonHints() {
if (scheduledOrNoSoundHint != null) {
scheduledOrNoSoundHint.hide();
}
if (scheduledHint != null) {
scheduledHint.hide();
}
}
private void showSlowModeHint(View view, boolean show, CharSequence time) {
if (getParentActivity() == null || fragmentView == null || !show && (slowModeHint == null || slowModeHint.getVisibility() != View.VISIBLE)) {
return;
@ -9923,9 +9990,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
searchAsListHint.showForView(searchCountText, true);
}
private void showScheduledHint() {
boolean disableNoSound = (UserObject.isUserSelf(currentUser) || (chatInfo != null && chatInfo.slowmode_next_send_date > 0) && chatMode == 0);
if (scheduledHintShown || scheduledOrNoSoundHintShown || disableNoSound || SharedConfig.scheduledHintShows >= 3) {
return;
}
AndroidUtilities.cancelRunOnUIThread(showScheduledHintRunnable);
AndroidUtilities.runOnUIThread(showScheduledHintRunnable, 4000);
}
private void showScheduledOrNoSoundHint() {
boolean disableNoSound = (UserObject.isUserSelf(currentUser) || (chatInfo != null && chatInfo.slowmode_next_send_date > 0) && chatMode == 0);
if (SharedConfig.scheduledOrNoSoundHintShows >= 3 || System.currentTimeMillis() % 4 != 0 || disableNoSound) {
long scheduledOrNoSoundHintTimeFromLastSeen = System.currentTimeMillis() - SharedConfig.scheduledOrNoSoundHintSeenAt;
long scheduledHintTimeFromLastSeen = System.currentTimeMillis() - SharedConfig.scheduledHintSeenAt;
if (disableNoSound || SharedConfig.scheduledOrNoSoundHintShows >= 3 || scheduledOrNoSoundHintTimeFromLastSeen < 86400000L || scheduledHintTimeFromLastSeen < 86400000L) {
return;
}
AndroidUtilities.cancelRunOnUIThread(showScheduledOrNoSoundRunnable);
@ -13072,6 +13150,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
updateTextureViewPosition(false, false);
updatePagedownButtonsPosition();
if (scheduledOrNoSoundHint != null && scheduledOrNoSoundHint.isShowing()) {
scheduledOrNoSoundHint.updatePosition();
}
if (scheduledHint != null && scheduledHint.isShowing()) {
scheduledHint.updatePosition();
}
int restoreToCount = -1;
if (switchingFromTopics) {
restoreToCount = canvas.saveLayerAlpha(0, actionBar.getBottom(), getMeasuredWidth(), getMeasuredHeight(), (int) (255 * switchingFromTopicsProgress), Canvas.ALL_SAVE_FLAG);
@ -14978,6 +15062,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
@Override
public void onApplyCaption(CharSequence caption) {
chatActivityEnterView.setFieldText(caption, true);
}
@Override
public boolean closeKeyboard() {
if (chatActivityEnterView != null && isKeyboardVisible()) {
@ -29049,6 +29138,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
AndroidUtilities.showKeyboard(searchItem.getSearchField());
removeKeyboardPositionBeforeTransition();
}, 500);
hideSendButtonHints();
}
@Override
@ -29891,7 +29981,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (message.type == MessageObject.TYPE_STORY) {
if (message.messageOwner.media.storyItem != null && !(message.messageOwner.media.storyItem instanceof TLRPC.TL_storyItemDeleted)) {
TLRPC.StoryItem storyItem = message.messageOwner.media.storyItem;
storyItem.dialogId = message.messageOwner.media.user_id;
storyItem.dialogId = DialogObject.getPeerDialogId(message.messageOwner.media.peer);
storyItem.messageId = message.getId();
storyItem.messageType = 2;
StoriesUtilities.applyViewedUser(storyItem, currentUser);
@ -30079,7 +30169,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (webPage.attributes.get(i) instanceof TLRPC.TL_webPageAttributeStory) {
TLRPC.TL_webPageAttributeStory story = (TLRPC.TL_webPageAttributeStory) webPage.attributes.get(i);
if (story.storyItem != null) {
story.storyItem.dialogId = story.user_id;
story.storyItem.dialogId = DialogObject.getPeerDialogId(story.peer);
story.storyItem.messageId = messageObject.getId();
story.storyItem.messageType = 1;
getOrCreateStoryViewer().open(getContext(), story.storyItem, StoriesListPlaceProvider.of(chatListView));

View file

@ -140,6 +140,7 @@ public class ChatRightsEditActivity extends BaseFragment {
private int sendMessagesRow;
private int sendMediaRow;
private boolean sendMediaExpanded;
private int sendPhotosRow;
private int sendVideosRow;
private int sendMusicRow;
@ -153,6 +154,17 @@ public class ChatRightsEditActivity extends BaseFragment {
private int untilSectionRow;
private int untilDateRow;
private int channelMessagesRow;
private boolean channelMessagesExpanded;
private int channelPostMessagesRow;
private int channelEditMessagesRow;
private int channelDeleteMessagesRow;
private int channelStoriesRow;
private boolean channelStoriesExpanded;
private int channelPostStoriesRow;
private int channelEditStoriesRow;
private int channelDeleteStoriesRow;
private ChatRightsEditActivityDelegate delegate;
private String botHash;
@ -164,7 +176,6 @@ public class ChatRightsEditActivity extends BaseFragment {
public static final int TYPE_ADD_BOT = 2;
private boolean closingKeyboardAfterFinish = false;
private boolean sendMediaExpanded;
public interface ChatRightsEditActivityDelegate {
void didSetRights(int rights, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, String rank);
@ -181,6 +192,7 @@ public class ChatRightsEditActivity extends BaseFragment {
currentUser = MessagesController.getInstance(currentAccount).getUser(userId);
currentType = type;
canEdit = edit;
channelMessagesExpanded = channelStoriesExpanded = !canEdit;
botHash = addingNewBotHash;
currentChat = MessagesController.getInstance(currentAccount).getChat(chatId);
if (rank == null) {
@ -214,6 +226,9 @@ public class ChatRightsEditActivity extends BaseFragment {
rightsAdmin.edit_messages = rightsAdmin.edit_messages || botDefaultRights.edit_messages;
rightsAdmin.manage_call = rightsAdmin.manage_call || botDefaultRights.manage_call;
rightsAdmin.manage_topics = rightsAdmin.manage_topics || botDefaultRights.manage_topics;
rightsAdmin.post_stories = rightsAdmin.post_stories || botDefaultRights.post_stories;
rightsAdmin.edit_stories = rightsAdmin.edit_stories || botDefaultRights.edit_stories;
rightsAdmin.delete_stories = rightsAdmin.delete_stories || botDefaultRights.delete_stories;
rightsAdmin.other = rightsAdmin.other || botDefaultRights.other;
}
}
@ -237,6 +252,9 @@ public class ChatRightsEditActivity extends BaseFragment {
adminRights.invite_users = myAdminRights.invite_users;
adminRights.pin_messages = myAdminRights.pin_messages;
adminRights.manage_topics = myAdminRights.manage_topics;
adminRights.post_stories = myAdminRights.post_stories;
adminRights.edit_stories = myAdminRights.edit_stories;
adminRights.delete_stories = myAdminRights.delete_stories;
adminRights.other = myAdminRights.other;
initialIsSet = false;
}
@ -252,6 +270,9 @@ public class ChatRightsEditActivity extends BaseFragment {
adminRights.invite_users = rightsAdmin.invite_users;
adminRights.pin_messages = rightsAdmin.pin_messages;
adminRights.manage_topics = rightsAdmin.manage_topics;
adminRights.post_stories = rightsAdmin.post_stories;
adminRights.edit_stories = rightsAdmin.edit_stories;
adminRights.delete_stories = rightsAdmin.delete_stories;
adminRights.add_admins = rightsAdmin.add_admins;
adminRights.anonymous = rightsAdmin.anonymous;
adminRights.other = rightsAdmin.other;
@ -410,6 +431,9 @@ public class ChatRightsEditActivity extends BaseFragment {
adminRights.add_admins = a.add_admins || b.add_admins;
adminRights.manage_call = a.manage_call || b.manage_call;
adminRights.manage_topics = a.manage_topics || b.manage_topics;
adminRights.post_stories = a.post_stories || b.post_stories;
adminRights.edit_stories = a.edit_stories || b.edit_stories;
adminRights.delete_stories = a.delete_stories || b.delete_stories;
return adminRights;
}
@ -418,7 +442,8 @@ public class ChatRightsEditActivity extends BaseFragment {
TLRPC.TL_chatAdminRights adminRights = new TLRPC.TL_chatAdminRights();
adminRights.change_info = adminRights.post_messages = adminRights.edit_messages =
adminRights.delete_messages = adminRights.ban_users = adminRights.invite_users =
adminRights.pin_messages = adminRights.add_admins = adminRights.manage_call = adminRights.manage_topics = value;
adminRights.pin_messages = adminRights.add_admins = adminRights.manage_call = adminRights.manage_topics =
adminRights.post_stories = adminRights.edit_stories = adminRights.delete_stories = value;
return adminRights;
}
@ -527,15 +552,6 @@ public class ChatRightsEditActivity extends BaseFragment {
return;
}
if (position == sendMediaRow) {
// if (allDefaultMediaBanned()) {
// new AlertDialog.Builder(getParentActivity())
// .setTitle(LocaleController.getString("UserRestrictionsCantModify", R.string.UserRestrictionsCantModify))
// .setMessage(LocaleController.getString("UserRestrictionsCantModifyEnabled", R.string.UserRestrictionsCantModifyEnabled))
// .setPositiveButton(LocaleController.getString("OK", R.string.OK), null)
// .create()
// .show();
// return;
// }
sendMediaExpanded = !sendMediaExpanded;
updateRows(false);
if (sendMediaExpanded) {
@ -544,6 +560,26 @@ public class ChatRightsEditActivity extends BaseFragment {
listViewAdapter.notifyItemRangeRemoved(sendMediaRow + 1, 9);
}
return;
} else if (position == channelMessagesRow) {
channelMessagesExpanded = !channelMessagesExpanded;
updateRows(false);
listViewAdapter.notifyItemChanged(channelMessagesRow);
if (channelMessagesExpanded) {
listViewAdapter.notifyItemRangeInserted(channelMessagesRow + 1, 3);
} else {
listViewAdapter.notifyItemRangeRemoved(channelMessagesRow + 1, 3);
}
return;
} else if (position == channelStoriesRow) {
channelStoriesExpanded = !channelStoriesExpanded;
updateRows(false);
listViewAdapter.notifyItemChanged(channelStoriesRow);
if (channelStoriesExpanded) {
listViewAdapter.notifyItemRangeInserted(channelStoriesRow + 1, 3);
} else {
listViewAdapter.notifyItemRangeRemoved(channelStoriesRow + 1, 3);
}
return;
}
if (position == 0) {
Bundle args = new Bundle();
@ -714,7 +750,29 @@ public class ChatRightsEditActivity extends BaseFragment {
showDialog(builder.create());
} else if (view instanceof CheckBoxCell) {
CheckBoxCell checkBoxCell = (CheckBoxCell) view;
if (currentType == TYPE_BANNED && bannedRights != null) {
if (position == channelPostMessagesRow || position == channelEditMessagesRow || position == channelDeleteMessagesRow) {
boolean value;
if (position == channelPostMessagesRow) {
value = adminRights.post_messages = !adminRights.post_messages;
} else if (position == channelEditMessagesRow) {
value = adminRights.edit_messages = !adminRights.edit_messages;
} else {
value = adminRights.delete_messages = !adminRights.delete_messages;
}
listViewAdapter.notifyItemChanged(channelMessagesRow);
checkBoxCell.setChecked(value, true);
} else if (position == channelPostStoriesRow || position == channelEditStoriesRow || position == channelDeleteStoriesRow) {
boolean value;
if (position == channelPostStoriesRow) {
value = adminRights.post_stories = !adminRights.post_stories;
} else if (position == channelEditStoriesRow) {
value = adminRights.edit_stories = !adminRights.edit_stories;
} else {
value = adminRights.delete_stories = !adminRights.delete_stories;
}
listViewAdapter.notifyItemChanged(channelStoriesRow);
checkBoxCell.setChecked(value, true);
} else if (currentType == TYPE_BANNED && bannedRights != null) {
boolean disabled = !checkBoxCell.isChecked();
boolean value = false;
@ -875,7 +933,7 @@ public class ChatRightsEditActivity extends BaseFragment {
private boolean hasAllAdminRights() {
if (isChannel) {
return adminRights.change_info && adminRights.post_messages && adminRights.edit_messages && adminRights.delete_messages && adminRights.invite_users && adminRights.add_admins && adminRights.manage_call;
return adminRights.change_info && adminRights.post_messages && adminRights.edit_messages && adminRights.delete_messages && adminRights.invite_users && adminRights.add_admins && adminRights.manage_call && adminRights.post_stories && adminRights.edit_stories && adminRights.delete_stories;
} else {
return adminRights.change_info && adminRights.delete_messages && adminRights.ban_users && adminRights.invite_users && adminRights.pin_messages && adminRights.add_admins && adminRights.manage_call && (!isForum || adminRights.manage_topics);
}
@ -1020,7 +1078,7 @@ public class ChatRightsEditActivity extends BaseFragment {
}), ConnectionsManager.RequestFlagWithoutLogin);
} else if (error.text.equals("CHANNELS_TOO_MUCH")) {
if (getParentActivity() != null && !AccountInstance.getInstance(currentAccount).getUserConfig().isPremium()) {
showDialog(new LimitReachedBottomSheet(this, getParentActivity(), LimitReachedBottomSheet.TYPE_TO0_MANY_COMMUNITIES, currentAccount, getResourceProvider()));
showDialog(new LimitReachedBottomSheet(this, getParentActivity(), LimitReachedBottomSheet.TYPE_TO0_MANY_COMMUNITIES, currentAccount, null));
} else {
presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_EDIT));
}
@ -1068,6 +1126,15 @@ public class ChatRightsEditActivity extends BaseFragment {
sendMessagesRow = -1;
sendMediaRow = -1;
channelMessagesRow = -1;
channelPostMessagesRow = -1;
channelEditMessagesRow = -1;
channelDeleteMessagesRow = -1;
channelStoriesRow = -1;
channelPostStoriesRow = -1;
channelEditStoriesRow = -1;
channelDeleteStoriesRow = -1;
sendPhotosRow = -1;
sendVideosRow = -1;
sendMusicRow = -1;
@ -1088,9 +1155,18 @@ public class ChatRightsEditActivity extends BaseFragment {
if (currentType == TYPE_ADMIN || currentType == TYPE_ADD_BOT) {
if (isChannel) {
changeInfoRow = rowCount++;
postMessagesRow = rowCount++;
editMesagesRow = rowCount++;
deleteMessagesRow = rowCount++;
channelMessagesRow = rowCount++;
if (channelMessagesExpanded) {
channelPostMessagesRow = rowCount++;
channelEditMessagesRow = rowCount++;
channelDeleteMessagesRow = rowCount++;
}
channelStoriesRow = rowCount++;
if (channelStoriesExpanded) {
channelPostStoriesRow = rowCount++;
channelEditStoriesRow = rowCount++;
channelDeleteStoriesRow = rowCount++;
}
addUsersRow = rowCount++;
startVoiceChatRow = rowCount++;
addAdminsRow = rowCount++;
@ -1224,7 +1300,7 @@ public class ChatRightsEditActivity extends BaseFragment {
}
if (!adminRights.change_info && !adminRights.post_messages && !adminRights.edit_messages &&
!adminRights.delete_messages && !adminRights.ban_users && !adminRights.invite_users && (!isForum || !adminRights.manage_topics) &&
!adminRights.pin_messages && !adminRights.add_admins && !adminRights.anonymous && !adminRights.manage_call) {
!adminRights.pin_messages && !adminRights.add_admins && !adminRights.anonymous && !adminRights.manage_call && (!isChannel || !adminRights.post_stories && !adminRights.edit_stories && !adminRights.delete_stories)) {
adminRights.other = true;
} else {
adminRights.other = false;
@ -1240,6 +1316,7 @@ public class ChatRightsEditActivity extends BaseFragment {
adminRights.change_info || adminRights.post_messages || adminRights.edit_messages ||
adminRights.delete_messages || adminRights.ban_users || adminRights.invite_users || (isForum && adminRights.manage_topics) ||
adminRights.pin_messages || adminRights.add_admins || adminRights.anonymous || adminRights.manage_call ||
isChannel && (adminRights.post_stories || adminRights.edit_stories || adminRights.delete_stories) ||
adminRights.other ? 1 : 0, adminRights, bannedRights, currentRank);
finishFragment();
}
@ -1453,6 +1530,14 @@ public class ChatRightsEditActivity extends BaseFragment {
if (position == sendVoiceRow) return 33;
if (position == sendRoundRow) return 34;
if (position == sendMediaRow) return 35;
if (position == channelMessagesRow) return 36;
if (position == channelPostMessagesRow) return 37;
if (position == channelEditMessagesRow) return 38;
if (position == channelDeleteMessagesRow) return 39;
if (position == channelStoriesRow) return 40;
if (position == channelPostStoriesRow) return 41;
if (position == channelEditStoriesRow) return 42;
if (position == channelDeleteStoriesRow) return 43;
return 0;
} else {
return super.getItemId(position);
@ -1498,6 +1583,12 @@ public class ChatRightsEditActivity extends BaseFragment {
return myAdminRights.pin_messages && (defaultBannedRights == null || defaultBannedRights.pin_messages);
} else if (position == manageTopicsRow) {
return myAdminRights.manage_topics;
} else if (position == channelPostStoriesRow) {
return myAdminRights.post_stories;
} else if (position == channelEditStoriesRow) {
return myAdminRights.edit_stories;
} else if (position == channelDeleteStoriesRow) {
return myAdminRights.delete_stories;
}
}
}
@ -1594,6 +1685,7 @@ public class ChatRightsEditActivity extends BaseFragment {
break;
case VIEW_TYPE_INNER_CHECK:
CheckBoxCell checkBoxCell = new CheckBoxCell(mContext, 4, 21, getResourceProvider());
checkBoxCell.setPad(1);
checkBoxCell.getCheckBoxRound().setDrawBackgroundAsArc(14);
checkBoxCell.getCheckBoxRound().setColor(Theme.key_switch2TrackChecked, Theme.key_radioBackground, Theme.key_checkboxCheck);
checkBoxCell.setEnabled(true);
@ -1638,6 +1730,18 @@ public class ChatRightsEditActivity extends BaseFragment {
} else if (position == sendRoundRow) {
checkBoxCell.setText(LocaleController.getString("SendMediaPermissionRound", R.string.SendMediaPermissionRound), "", !bannedRights.send_roundvideos && !defaultBannedRights.send_roundvideos, true, animated);
checkBoxCell.setIcon(defaultBannedRights.send_roundvideos ? R.drawable.permission_locked : 0);
} else if (position == channelPostMessagesRow) {
checkBoxCell.setText(LocaleController.getString(R.string.EditAdminPostMessages), "", adminRights.post_messages, true, animated);
} else if (position == channelEditMessagesRow) {
checkBoxCell.setText(LocaleController.getString(R.string.EditAdminEditMessages), "", adminRights.edit_messages, true, animated);
} else if (position == channelDeleteMessagesRow) {
checkBoxCell.setText(LocaleController.getString(R.string.EditAdminDeleteMessages), "", adminRights.delete_messages, true, animated);
} else if (position == channelPostStoriesRow) {
checkBoxCell.setText(LocaleController.getString(R.string.EditAdminPostStories), "", adminRights.post_stories, true, animated);
} else if (position == channelEditStoriesRow) {
checkBoxCell.setText(LocaleController.getString(R.string.EditAdminEditStories), "", adminRights.edit_stories, true, animated);
} else if (position == channelDeleteStoriesRow) {
checkBoxCell.setText(LocaleController.getString(R.string.EditAdminDeleteStories), "", adminRights.delete_stories, true, animated);
}
break;
case VIEW_TYPE_USER_CELL:
@ -1719,6 +1823,22 @@ public class ChatRightsEditActivity extends BaseFragment {
setSendMediaEnabled(checked);
});
checkCell.setIcon(allDefaultMediaBanned() ? R.drawable.permission_locked : 0);
} else if (position == channelMessagesRow) {
int count = getChannelMessagesSelectedCount();
checkCell.setTextAndCheck(LocaleController.getString(R.string.ChannelManageMessages), count > 0, true, true);
checkCell.setCollapseArrow(String.format(Locale.US, "%d/3", count), !channelMessagesExpanded, () -> {
boolean checked = checkCell.isChecked();
checkCell.setChecked(checked);
setChannelMessagesEnabled(checked);
});
} else if (position == channelStoriesRow) {
int count = getChannelStoriesSelectedCount();
checkCell.setTextAndCheck(LocaleController.getString(R.string.ChannelManageStories), count > 0, true, true);
checkCell.setCollapseArrow(String.format(Locale.US, "%d/3", count), !channelStoriesExpanded, () -> {
boolean checked = checkCell.isChecked();
checkCell.setChecked(checked);
setChannelStoriesEnabled(checked);
});
} else if (position == manageRow) {
checkCell.setTextAndCheck(LocaleController.getString("ManageGroup", R.string.ManageGroup), asAdmin, true);
checkCell.setIcon(myAdminRights.add_admins || isCreator ? 0 : R.drawable.permission_locked);
@ -1890,7 +2010,7 @@ public class ChatRightsEditActivity extends BaseFragment {
public int getItemViewType(int position) {
if (isExpandableSendMediaRow(position)) {
return VIEW_TYPE_INNER_CHECK;
} else if (position == sendMediaRow) {
} else if (position == sendMediaRow || position == channelMessagesRow || position == channelStoriesRow) {
return VIEW_TYPE_EXPANDABLE_SWITCH;
} else if (position == 0) {
return VIEW_TYPE_USER_CELL;
@ -1900,7 +2020,8 @@ public class ChatRightsEditActivity extends BaseFragment {
return VIEW_TYPE_HEADER_CELL;
} else if (position == changeInfoRow || position == postMessagesRow || position == editMesagesRow || position == deleteMessagesRow ||
position == addAdminsRow || position == banUsersRow || position == addUsersRow || position == pinMessagesRow ||
position == sendMessagesRow || position == anonymousRow || position == startVoiceChatRow || position == manageRow || position == manageTopicsRow) {
position == sendMessagesRow || position == anonymousRow || position == startVoiceChatRow || position == manageRow || position == manageTopicsRow
) {
return VIEW_TYPE_SWITCH_CELL;
} else if (position == cantEditInfoRow || position == rankInfoRow) {
return VIEW_TYPE_INFO_CELL;
@ -1962,6 +2083,48 @@ public class ChatRightsEditActivity extends BaseFragment {
return i;
}
private int getChannelMessagesSelectedCount() {
int i = 0;
if (adminRights.post_messages) {
i++;
}
if (adminRights.edit_messages) {
i++;
}
if (adminRights.delete_messages) {
i++;
}
return i;
}
private void setChannelMessagesEnabled(boolean enabled) {
adminRights.post_messages = !enabled;
adminRights.edit_messages = !enabled;
adminRights.delete_messages = !enabled;
AndroidUtilities.updateVisibleRows(listView);
}
private int getChannelStoriesSelectedCount() {
int i = 0;
if (adminRights.post_stories) {
i++;
}
if (adminRights.edit_stories) {
i++;
}
if (adminRights.delete_stories) {
i++;
}
return i;
}
private void setChannelStoriesEnabled(boolean enabled) {
adminRights.post_stories = !enabled;
adminRights.edit_stories = !enabled;
adminRights.delete_stories = !enabled;
AndroidUtilities.updateVisibleRows(listView);
}
private boolean allDefaultMediaBanned() {
return defaultBannedRights.send_photos && defaultBannedRights.send_videos && defaultBannedRights.send_stickers
&& defaultBannedRights.send_audios && defaultBannedRights.send_docs && defaultBannedRights.send_voices &&
@ -1970,8 +2133,10 @@ public class ChatRightsEditActivity extends BaseFragment {
private boolean isExpandableSendMediaRow(int position) {
if (position == sendStickersRow || position == embedLinksRow || position == sendPollsRow ||
position == sendPhotosRow || position == sendVideosRow || position == sendFilesRow ||
position == sendMusicRow || position == sendRoundRow || position == sendVoiceRow) {
position == sendPhotosRow || position == sendVideosRow || position == sendFilesRow ||
position == sendMusicRow || position == sendRoundRow || position == sendVoiceRow ||
position == channelPostMessagesRow || position == channelEditMessagesRow || position == channelDeleteMessagesRow ||
position == channelPostStoriesRow || position == channelEditStoriesRow || position == channelDeleteStoriesRow) {
return true;
}
return false;

View file

@ -4183,7 +4183,7 @@ public class AlertsCreator {
}
if (storyId != 0) {
TLRPC.TL_stories_report request = new TLRPC.TL_stories_report();
request.user_id = MessagesController.getInstance(UserConfig.selectedAccount).getInputUser(peer.user_id);
request.peer = MessagesController.getInstance(UserConfig.selectedAccount).getInputPeer(peer.user_id);
request.id.add(storyId);
request.message = message;
request.reason = reason;
@ -4341,7 +4341,7 @@ public class AlertsCreator {
if (storyId != 0) {
TLRPC.TL_stories_report request = new TLRPC.TL_stories_report();
request.id.add(storyId);
request.user_id = MessagesController.getInstance(UserConfig.selectedAccount).getInputUser(dialog_id);
request.peer = MessagesController.getInstance(UserConfig.selectedAccount).getInputPeer(dialog_id);
request.message = "";
if (type == REPORT_TYPE_SPAM) {
request.reason = new TLRPC.TL_inputReportReasonSpam();

View file

@ -662,28 +662,6 @@ public class AnimatedEmojiDrawable extends Drawable {
imageReceiver.draw(canvas);
}
public void drawRaw(Canvas canvas, boolean nextFrame, int fps) {
if (imageReceiver == null) {
return;
}
if (imageReceiver.getLottieAnimation() != null) {
RLottieDrawable rlottie = imageReceiver.getLottieAnimation();
if (nextFrame) {
int inc = (int) Math.round((float) rlottie.getFramesCount() / (rlottie.getDuration() / 1000f) / 30f);
rlottie.currentFrame = (rlottie.currentFrame + inc) % rlottie.getFramesCount();
}
rlottie.setBounds(getBounds());
rlottie.drawFrame(canvas, rlottie.currentFrame);
} else if (imageReceiver.getAnimation() != null) {
AnimatedFileDrawable webp = imageReceiver.getAnimation();
webp.drawFrame(canvas, nextFrame ? fps / 30 : 0);
} else {
imageReceiver.setImageCoords(getBounds());
imageReceiver.setAlpha(alpha);
imageReceiver.draw(canvas);
}
}
public void draw(Canvas canvas, Rect drawableBounds, float alpha) {
if (imageReceiver == null) {
return;

View file

@ -220,40 +220,6 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
}
}
public static void drawRawAnimatedEmojis(Canvas canvas, Layout layout, EmojiGroupedSpans stack, float offset, List<SpoilerEffect> spoilers, float boundTop, float boundBottom, float drawingYOffset, float alpha, int fps) {
if (canvas == null || layout == null || stack == null) {
return;
}
boolean needRestore = false;
if (Emoji.emojiDrawingYOffset != 0 || offset != 0) {
needRestore = true;
canvas.save();
canvas.translate(0, Emoji.emojiDrawingYOffset + AndroidUtilities.dp(20 * offset));
}
stack.rawIndex++;
for (int k = 0; k < stack.holders.size(); ++k) {
AnimatedEmojiHolder holder = stack.holders.get(k);
float halfSide = holder.span.measuredSize / 2f;
float cx, cy;
cx = holder.span.lastDrawnCx;
cy = holder.span.lastDrawnCy;
holder.drawableBounds.set((int) (cx - halfSide), (int) (cy - halfSide), (int) (cx + halfSide), (int) (cy + halfSide));
holder.drawable.setBounds(holder.drawableBounds);
boolean nextFrame = false;
if (holder.drawable.rawDrawIndex < stack.rawIndex) {
holder.drawable.rawDrawIndex = stack.rawIndex;
nextFrame = true;
}
holder.drawable.drawRaw(canvas, nextFrame, fps);
}
if (needRestore) {
canvas.restore();
}
}
private static boolean isInsideSpoiler(Layout layout, int start, int end) {
if (layout == null || !(layout.getText() instanceof Spanned)) {
return false;

View file

@ -6,12 +6,10 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri;
import android.os.Build;
import android.text.SpannableStringBuilder;
import android.util.TypedValue;
@ -23,25 +21,21 @@ import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.TextView;
import androidx.core.content.FileProvider;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.browser.Browser;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.voip.CellFlickerDrawable;
import java.io.File;
import java.util.Locale;
public class BlockingUpdateView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
@ -145,16 +139,22 @@ public class BlockingUpdateView extends FrameLayout implements NotificationCente
acceptButton.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0);
addView(acceptButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 45));
acceptButton.setOnClickListener(view1 -> {
if (!checkApkInstallPermissions(getContext())) {
return;
}
if (appUpdate.document instanceof TLRPC.TL_document) {
if (!openApkInstall((Activity) getContext(), appUpdate.document)) {
FileLoader.getInstance(accountNum).loadFile(appUpdate.document, "update", FileLoader.PRIORITY_HIGH, 1);
showProgress(true);
if (BuildVars.isStandaloneApp() || BuildVars.DEBUG_VERSION) {
if (!ApplicationLoader.applicationLoaderInstance.checkApkInstallPermissions(getContext())) {
return;
}
} else if (appUpdate.url != null) {
Browser.openUrl(getContext(), appUpdate.url);
if (appUpdate.document instanceof TLRPC.TL_document) {
if (!ApplicationLoader.applicationLoaderInstance.openApkInstall((Activity) getContext(), appUpdate.document)) {
FileLoader.getInstance(accountNum).loadFile(appUpdate.document, "update", FileLoader.PRIORITY_HIGH, 1);
showProgress(true);
}
} else if (appUpdate.url != null) {
Browser.openUrl(getContext(), appUpdate.url);
}
} else if (BuildVars.isHuaweiStoreApp()){
Browser.openUrl(context, BuildVars.HUAWEI_STORE_URL);
} else {
Browser.openUrl(context, BuildVars.PLAYSTORE_APP_URL);
}
});
@ -209,7 +209,7 @@ public class BlockingUpdateView extends FrameLayout implements NotificationCente
String location = (String) args[0];
if (fileName != null && fileName.equals(location)) {
showProgress(false);
openApkInstall((Activity) getContext(), appUpdate.document);
ApplicationLoader.applicationLoaderInstance.openApkInstall((Activity) getContext(), appUpdate.document);
}
} else if (id == NotificationCenter.fileLoadFailed) {
String location = (String) args[0];
@ -227,39 +227,7 @@ public class BlockingUpdateView extends FrameLayout implements NotificationCente
}
}
public static boolean checkApkInstallPermissions(final Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !ApplicationLoader.applicationContext.getPackageManager().canRequestPackageInstalls()) {
AlertsCreator.createApkRestrictedDialog(context, null).show();
return false;
}
return true;
}
public static boolean openApkInstall(Activity activity, TLRPC.Document document) {
boolean exists = false;
try {
String fileName = FileLoader.getAttachFileName(document);
File f = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true);
if (exists = f.exists()) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (Build.VERSION.SDK_INT >= 24) {
intent.setDataAndType(FileProvider.getUriForFile(activity, ApplicationLoader.getApplicationId() + ".provider", f), "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(f), "application/vnd.android.package-archive");
}
try {
activity.startActivityForResult(intent, 500);
} catch (Exception e) {
FileLog.e(e);
}
}
} catch (Exception e) {
FileLog.e(e);
}
return exists;
}
private void showProgress(final boolean show) {
if (progressAnimation != null) {
@ -332,7 +300,7 @@ public class BlockingUpdateView extends FrameLayout implements NotificationCente
NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileLoaded);
NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileLoadFailed);
NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileLoadProgressChanged);
if (check) {
if (check && BuildVars.isStandaloneApp()) {
TLRPC.TL_help_getAppUpdate req = new TLRPC.TL_help_getAppUpdate();
try {
req.source = ApplicationLoader.applicationContext.getPackageManager().getInstallerPackageName(ApplicationLoader.applicationContext.getPackageName());

View file

@ -931,14 +931,11 @@ public class BlurringShader {
return true;
}
public Drawable makeDrawable(float offsetX, float offsetY, Drawable base) {
public Drawable makeDrawable(float offsetX, float offsetY, Drawable base, float r) {
return new Drawable() {
float alpha = 1f;
private final Paint dimPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
{
dimPaint.setColor(0x52000000);
}
@Nullable
private Paint getPaint() {
@ -971,22 +968,47 @@ public class BlurringShader {
Rect bounds = getBounds();
if (paint != null) {
canvas.saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, 0xFF, Canvas.ALL_SAVE_FLAG);
if (base != null) {
canvas.saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, 0xFF, Canvas.ALL_SAVE_FLAG);
base.setBounds(bounds);
base.draw(canvas);
canvas.drawRect(bounds, paint);
canvas.restore();
getPadding(AndroidUtilities.rectTmp2);
AndroidUtilities.rectTmp.set(
bounds.left + AndroidUtilities.rectTmp2.left,
bounds.top + AndroidUtilities.rectTmp2.top,
bounds.right - AndroidUtilities.rectTmp2.right,
bounds.bottom - AndroidUtilities.rectTmp2.bottom
);
dimPaint.setColor(0x66000000);
canvas.drawRoundRect(AndroidUtilities.rectTmp, r, r, dimPaint);
} else {
if (r > 0) {
AndroidUtilities.rectTmp.set(bounds);
canvas.drawRoundRect(AndroidUtilities.rectTmp, r, r, paint);
} else {
canvas.drawRect(bounds, paint);
}
dimPaint.setColor(0x66000000);
if (r > 0) {
AndroidUtilities.rectTmp.set(bounds);
canvas.drawRoundRect(AndroidUtilities.rectTmp, r, r, dimPaint);
} else {
canvas.drawRect(bounds, dimPaint);
}
}
} else if (base != null) {
base.setBounds(bounds);
base.draw(canvas);
canvas.drawRect(bounds, paint);
canvas.restore();
getPadding(AndroidUtilities.rectTmp2);
AndroidUtilities.rectTmp.set(
bounds.left + AndroidUtilities.rectTmp2.left,
bounds.top + AndroidUtilities.rectTmp2.top,
bounds.right - AndroidUtilities.rectTmp2.right,
bounds.bottom - AndroidUtilities.rectTmp2.bottom
);
canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(6), dp(6), dimPaint);
} else {
base.setBounds(bounds);
base.draw(canvas);
dimPaint.setColor(-14145495);
if (r > 0) {
AndroidUtilities.rectTmp.set(bounds);
canvas.drawRoundRect(AndroidUtilities.rectTmp, r, r, dimPaint);
} else {
canvas.drawRect(bounds, dimPaint);
}
}
}
@ -1005,7 +1027,12 @@ public class BlurringShader {
@Override
public boolean getPadding(@NonNull Rect padding) {
return base.getPadding(padding);
if (base != null) {
return base.getPadding(padding);
} else {
padding.set(0, 0, 0, 0);
return true;
}
}
};
}

View file

@ -44,6 +44,8 @@ public class BottomPagerTabs extends View {
final RectF clickRect = new RectF();
final AnimatedFloat nonscrollingT = new AnimatedFloat(BottomPagerTabs.this, 0, 200, CubicBezierInterpolator.EASE_OUT_QUINT);
public int customEndFrameMid;
public int customEndFrameEnd;
public Tab(int i, int resId, CharSequence text) {
this.i = i;
@ -70,29 +72,27 @@ public class BottomPagerTabs extends View {
return;
}
if (i == 0) {
// 0 - 20
// 20 - 40
if (tabs[i].customEndFrameMid != 0) {
if (active) {
drawable.setCustomEndFrame(20);
if (drawable.getCurrentFrame() >= 38) {
drawable.setCustomEndFrame(customEndFrameMid);
if (drawable.getCurrentFrame() >= customEndFrameEnd - 2) {
drawable.setCurrentFrame(0, false);
}
if (drawable.getCurrentFrame() <= 20) {
if (drawable.getCurrentFrame() <= customEndFrameMid) {
drawable.start();
} else {
drawable.setCurrentFrame(20);
drawable.setCurrentFrame(customEndFrameMid);
}
} else {
if (drawable.getCurrentFrame() >= 19) {
drawable.setCustomEndFrame(39);
if (drawable.getCurrentFrame() >= customEndFrameMid - 1) {
drawable.setCustomEndFrame(customEndFrameEnd - 1);
drawable.start();
} else {
drawable.setCustomEndFrame(0);
drawable.setCurrentFrame(0);
}
}
} else if (i == 1 && active) {
} else if (active) {
drawable.setCurrentFrame(0);
if (animated) {
drawable.start();

View file

@ -22,6 +22,7 @@ import androidx.core.graphics.ColorUtils;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.DialogObject;
import org.telegram.messenger.LocaleController;
@ -68,6 +69,18 @@ public final class BulletinFactory {
return BulletinFactory.of(baseFragment);
}
public static void showForError(TLRPC.TL_error error) {
BulletinFactory bulletinFactory = BulletinFactory.global();
if (bulletinFactory == null) {
return;
}
if (BuildVars.DEBUG_VERSION) {
bulletinFactory.createErrorBulletin(error.code + " " + error.text).show();
} else {
bulletinFactory.createErrorBulletin(LocaleController.getString("UnknownError", R.string.UnknownError)).show();
}
}
public enum FileType {
PHOTO("PhotoSavedHint", R.string.PhotoSavedHint, Icon.SAVED_TO_GALLERY),

View file

@ -11,19 +11,27 @@ import android.view.animation.OvershootInterpolator;
public class ButtonBounce {
private View view;
private final float durationMultiplier;
private final float durationPressMultiplier;
private final float durationReleaseMultiplier;
private final float overshoot;
private long releaseDelay = 0;
public ButtonBounce(View viewToInvalidate) {
view = viewToInvalidate;
durationMultiplier = 1f;
durationPressMultiplier = durationReleaseMultiplier = 1f;
overshoot = 5.0f;
}
public ButtonBounce(View viewToInvalidate, float durationMultiplier, float overshoot) {
view = viewToInvalidate;
this.durationMultiplier = durationMultiplier;
this.durationPressMultiplier = this.durationReleaseMultiplier = durationMultiplier;
this.overshoot = overshoot;
}
public ButtonBounce(View viewToInvalidate, float durationPressMultiplier, float durationReleaseMultiplier, float overshoot) {
view = viewToInvalidate;
this.durationPressMultiplier = durationPressMultiplier;
this.durationReleaseMultiplier = durationReleaseMultiplier;
this.overshoot = overshoot;
}
@ -65,11 +73,11 @@ public class ButtonBounce {
});
if (isPressed) {
animator.setInterpolator(CubicBezierInterpolator.DEFAULT);
animator.setDuration((long) (60 * durationMultiplier));
animator.setDuration((long) (60 * durationPressMultiplier));
animator.setStartDelay(0);
} else {
animator.setInterpolator(new OvershootInterpolator(overshoot));
animator.setDuration((long) (350 * durationMultiplier));
animator.setDuration((long) (350 * durationReleaseMultiplier));
animator.setStartDelay(releaseDelay);
}
animator.start();

View file

@ -3654,6 +3654,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}, resourcesProvider);
});
sendPopupLayout.addView(scheduleButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48));
SharedConfig.removeScheduledHint();
if (!self && dialog_id > 0) {
sendWhenOnlineButton = new ActionBarMenuSubItem(getContext(), true, !sendWithoutSoundButtonValue, resourcesProvider);
sendWhenOnlineButton.setTextAndIcon(LocaleController.getString("SendWhenOnline", R.string.SendWhenOnline), R.drawable.msg_online);

View file

@ -34,6 +34,7 @@ import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextWatcher;
@ -76,6 +77,7 @@ import org.telegram.messenger.ContactsController;
import org.telegram.messenger.DialogObject;
import org.telegram.messenger.DocumentObject;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaController;
@ -110,6 +112,8 @@ import org.telegram.ui.PaymentFormActivity;
import org.telegram.ui.PhotoPickerActivity;
import org.telegram.ui.PhotoPickerSearchActivity;
import org.telegram.ui.PremiumPreviewFragment;
import org.telegram.ui.Stories.DarkThemeResourceProvider;
import org.telegram.ui.Stories.recorder.CaptionContainerView;
import java.io.File;
import java.util.ArrayList;
@ -2463,6 +2467,12 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
if ((count - before) >= 1) {
processChange = true;
}
if (mentionContainer == null) {
createMentionsContainer();
}
if (mentionContainer.getAdapter() != null) {
mentionContainer.getAdapter().searchUsernameOrHashtag(charSequence, commentTextView.getEditText().getSelectionStart(), null, false, false);
}
}
@Override
@ -2796,6 +2806,13 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
public void updateCommentTextViewPosition() {
commentTextView.getLocationOnScreen(commentTextViewLocation);
if (mentionContainer != null) {
float y = -commentTextView.getHeight();
if (mentionContainer.getY() != y) {
mentionContainer.setTranslationY(y);
mentionContainer.invalidate();
}
}
}
public int getCommentTextViewTop() {
@ -4661,4 +4678,72 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
public void setDocumentsDelegate(ChatAttachAlertDocumentLayout.DocumentSelectActivityDelegate documentsDelegate) {
this.documentsDelegate = documentsDelegate;
}
private void replaceWithText(int start, int len, CharSequence text, boolean parseEmoji) {
if (commentTextView == null) {
return;
}
try {
SpannableStringBuilder builder = new SpannableStringBuilder(commentTextView.getText());
builder.replace(start, start + len, text);
if (parseEmoji) {
Emoji.replaceEmoji(builder, commentTextView.getEditText().getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false);
}
commentTextView.setText(builder);
commentTextView.setSelection(start + text.length());
} catch (Exception e) {
FileLog.e(e);
}
}
public MentionsContainerView mentionContainer;
private void createMentionsContainer() {
mentionContainer = new MentionsContainerView(getContext(), UserConfig.getInstance(currentAccount).getClientUserId(), 0, LaunchActivity.getLastFragment(), null, resourcesProvider) {
@Override
protected void onScrolled(boolean atTop, boolean atBottom) {
if (photoLayout != null) {
photoLayout.checkCameraViewPosition();
}
}
@Override
protected void onAnimationScroll() {
if (photoLayout != null) {
photoLayout.checkCameraViewPosition();
}
}
};
setupMentionContainer();
mentionContainer.withDelegate(new MentionsContainerView.Delegate() {
@Override
public void replaceText(int start, int len, CharSequence replacingString, boolean allowShort) {
replaceWithText(start, len, replacingString, allowShort);
}
@Override
public Paint.FontMetricsInt getFontMetrics() {
return commentTextView.getEditText().getPaint().getFontMetricsInt();
}
});
containerView.addView(mentionContainer, containerView.indexOfChild(frameLayout2), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.BOTTOM));
mentionContainer.setTranslationY(-commentTextView.getHeight());
setupMentionContainer();
}
protected void setupMentionContainer() {
mentionContainer.getAdapter().setAllowStickers(false);
mentionContainer.getAdapter().setAllowBots(false);
mentionContainer.getAdapter().setAllowChats(false);
mentionContainer.getAdapter().setSearchInDailogs(true);
if (baseFragment instanceof ChatActivity) {
mentionContainer.getAdapter().setChatInfo(((ChatActivity) baseFragment).getCurrentChatInfo());
mentionContainer.getAdapter().setNeedUsernames(((ChatActivity) baseFragment).getCurrentChat() != null);
} else {
mentionContainer.getAdapter().setChatInfo(null);
mentionContainer.getAdapter().setNeedUsernames(false);
}
mentionContainer.getAdapter().setNeedBotContext(false);
}
}

View file

@ -36,6 +36,7 @@ import android.os.Build;
import android.provider.MediaStore;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.util.TypedValue;
import android.view.Gravity;
@ -2167,7 +2168,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
if (Build.VERSION.SDK_INT >= 21) {
super.dispatchDraw(canvas);
} else {
int maxY = (int) Math.min(parentAlert.getCommentTextViewTop() + currentPanTranslationY + parentAlert.getContainerView().getTranslationY() - cameraView.getTranslationY(), getMeasuredHeight());
int maxY = (int) Math.min(parentAlert.getCommentTextViewTop() + currentPanTranslationY + parentAlert.getContainerView().getTranslationY() - cameraView.getTranslationY() - (parentAlert.mentionContainer != null ? parentAlert.mentionContainer.clipBottom() + AndroidUtilities.dp(8) : 0), getMeasuredHeight());
if (cameraAnimationInProgress) {
AndroidUtilities.rectTmp.set(animationClipLeft + cameraViewOffsetX * (1f - cameraOpenProgress), animationClipTop + cameraViewOffsetY * (1f - cameraOpenProgress), animationClipRight, Math.min(maxY, animationClipBottom));
} else if (!cameraAnimationInProgress && !cameraOpened) {
@ -2204,7 +2205,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
cameraView.setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
int maxY = (int) Math.min(parentAlert.getCommentTextViewTop() + currentPanTranslationY + parentAlert.getContainerView().getTranslationY() - cameraView.getTranslationY(), view.getMeasuredHeight());
int maxY = (int) Math.min(parentAlert.getCommentTextViewTop() - (parentAlert.mentionContainer != null ? parentAlert.mentionContainer.clipBottom() + AndroidUtilities.dp(8) : 0) + currentPanTranslationY + parentAlert.getContainerView().getTranslationY() - cameraView.getTranslationY(), view.getMeasuredHeight());
if (cameraOpened) {
maxY = view.getMeasuredHeight();
} else if (cameraAnimationInProgress) {
@ -2764,9 +2765,12 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
int containerHeight = parentAlert.getSheetContainer().getMeasuredHeight();
maxY = (int) (containerHeight - parentAlert.buttonsRecyclerView.getMeasuredHeight() + parentAlert.buttonsRecyclerView.getTranslationY());
if (parentAlert.mentionContainer != null) {
maxY -= parentAlert.mentionContainer.clipBottom() - AndroidUtilities.dp(6);
}
if (topLocal + child.getMeasuredHeight() > maxY) {
cameraViewOffsetBottomY = topLocal + child.getMeasuredHeight() - maxY;
cameraViewOffsetBottomY = Math.min(-AndroidUtilities.dp(5), topLocal - maxY) + child.getMeasuredHeight();
} else {
cameraViewOffsetBottomY = 0;
}

View file

@ -148,6 +148,9 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent
final boolean avatarClickable = parentFragment != null && parentFragment.getChatMode() == 0 && !UserObject.isReplyUser(parentFragment.getCurrentUser());
avatarImageView = new BackupImageView(context) {
StoriesUtilities.AvatarStoryParams params = new StoriesUtilities.AvatarStoryParams(true);
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
@ -160,6 +163,19 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent
info.setVisibleToUser(false);
}
}
@Override
protected void onDraw(Canvas canvas) {
if (allowDrawStories && animatedEmojiDrawable == null) {
params.originalAvatarRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
params.drawSegments = true;
params.drawInside = true;
params.resourcesProvider = resourcesProvider;
StoriesUtilities.drawAvatarWithStory(parentFragment.getDialogId(), canvas, imageReceiver, params);
} else {
super.onDraw(canvas);
}
}
};
if (baseFragment instanceof ChatActivity || baseFragment instanceof TopicsFragment) {
sharedMediaPreloader = new SharedMediaLayout.SharedMediaPreloader(baseFragment);

View file

@ -13,6 +13,7 @@ import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Build;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
@ -993,54 +994,37 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen
if (entities != null && !entities.isEmpty()) {
float[] point = new float[4];
float newScale = 1.0f / sc * scale * stateScale;
float widthScale = b.getWidth() / (float) canvasBitmap.getWidth();
newScale *= widthScale;
TextPaintView textPaintView = null;
for (int a = 0, N = entities.size(); a < N; a++) {
VideoEditedInfo.MediaEntity entity = entities.get(a);
point[0] = entity.x * b.getWidth() + entity.viewWidth * entity.scale / 2;
point[1] = entity.y * b.getHeight() + entity.viewHeight * entity.scale / 2;
point[0] = (entity.x + entity.width / 2) * b.getWidth();
point[1] = (entity.y + entity.height / 2) * b.getHeight();
point[2] = entity.textViewX * b.getWidth();
point[3] = entity.textViewY * b.getHeight();
matrix.mapPoints(point);
if (entity.type == 0) {
entity.viewWidth = entity.viewHeight = canvasBitmap.getWidth() / 2;
} else if (entity.type == 1) {
entity.fontSize = canvasBitmap.getWidth() / 9;
if (textPaintView == null) {
textPaintView = new TextPaintView(context, new Point(0, 0), entity.fontSize, "", new Swatch(Color.BLACK, 0.85f, 0.1f), 0);
textPaintView.setMaxWidth(canvasBitmap.getWidth() - 20);
}
int type;
if ((entity.subType & 1) != 0) {
type = 0;
} else if ((entity.subType & 4) != 0) {
type = 2;
} else {
type = 1;
}
textPaintView.setType(type);
textPaintView.setText(entity.text);
textPaintView.measure(MeasureSpec.makeMeasureSpec(canvasBitmap.getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(canvasBitmap.getHeight(), MeasureSpec.AT_MOST));
entity.viewWidth = textPaintView.getMeasuredWidth();
entity.viewHeight = textPaintView.getMeasuredHeight();
final int w = contentWidth, h = contentHeight;
int bw = b.getWidth(), bh = b.getHeight();
if (orientationOnly == 90 || orientationOnly == 270) {
bw = b.getHeight();
bh = b.getWidth();
}
entity.scale *= newScale;
if (entity.type == VideoEditedInfo.MediaEntity.TYPE_TEXT) {
entity.width = entity.width * w / canvasBitmap.getWidth() * scale * stateScale;
entity.height = entity.height * h / canvasBitmap.getHeight() * scale * stateScale;
} else {
entity.viewWidth = (int) (entity.viewWidth / (float) w * bw);
entity.viewHeight = (int) (entity.viewHeight / (float) h * bh);
entity.x = (point[0] - entity.viewWidth * entity.scale / 2) / canvasBitmap.getWidth();
entity.y = (point[1] - entity.viewHeight * entity.scale / 2) / canvasBitmap.getHeight();
entity.width = entity.width * w / bw * scale * stateScale;
entity.height = entity.height * h / bh * scale * stateScale;
}
entity.x = point[0] / canvasBitmap.getWidth() - entity.width / 2;
entity.y = point[1] / canvasBitmap.getHeight() - entity.height / 2;
entity.textViewX = point[2] / canvasBitmap.getWidth();
entity.textViewY = point[3] / canvasBitmap.getHeight();
entity.width = entity.viewWidth * entity.scale / canvasBitmap.getWidth();
entity.height = entity.viewHeight * entity.scale / canvasBitmap.getHeight();
entity.textViewWidth = entity.viewWidth / (float) canvasBitmap.getWidth();
entity.textViewHeight = entity.viewHeight / (float) canvasBitmap.getHeight();
entity.rotation -= (rotation + orientationOnly) * (Math.PI / 180);
}
}

View file

@ -137,8 +137,9 @@ public class HintView extends FrameLayout {
imageView.setImageResource(R.drawable.msg_mini_close_tooltip);
imageView.setScaleType(ImageView.ScaleType.CENTER);
imageView.setColorFilter(new PorterDuffColorFilter(ColorUtils.setAlphaComponent(getThemedColor(Theme.key_chat_gifSaveHintText), 125), PorterDuff.Mode.MULTIPLY));
imageView.setOnClickListener(v -> hide(true));
addView(imageView, LayoutHelper.createFrame(34, 34, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 0, isTopArrow ? 3 : 0, 0, isTopArrow ? 0 : 3));
setOnClickListener(v -> hide(true));
}
public void setBackgroundColor(int background, int text) {

View file

@ -1,5 +1,7 @@
package org.telegram.ui.Components;
import static org.telegram.messenger.AndroidUtilities.dp;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
@ -150,7 +152,7 @@ public class ItemOptions {
}
ActionBarMenuSubItem subItem = new ActionBarMenuSubItem(context, false, false, resourcesProvider);
subItem.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18 + (LocaleController.isRTL ? 0 : 8)), 0);
subItem.setPadding(dp(18), 0, dp(18 + (LocaleController.isRTL ? 0 : 8)), 0);
subItem.setTextAndIcon(text, iconResId);
subItem.setColors(Theme.getColor(textColorKey, resourcesProvider), Theme.getColor(iconColorKey, resourcesProvider));
@ -165,7 +167,7 @@ public class ItemOptions {
}
});
if (minWidthDp > 0) {
subItem.setMinimumWidth(AndroidUtilities.dp(minWidthDp));
subItem.setMinimumWidth(dp(minWidthDp));
lastLayout.addView(subItem, LayoutHelper.createLinear(minWidthDp, LayoutHelper.WRAP_CONTENT));
} else {
lastLayout.addView(subItem, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
@ -276,10 +278,10 @@ public class ItemOptions {
final TextView textView = new TextView(context);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSizeDp);
textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider));
textView.setPadding(AndroidUtilities.dp(13), AndroidUtilities.dp(8), AndroidUtilities.dp(13), AndroidUtilities.dp(8));
textView.setPadding(dp(13), dp(8), dp(13), dp(8));
textView.setText(text);
textView.setTag(R.id.fit_width_tag, 1);
textView.setMaxWidth(AndroidUtilities.dp(200));
textView.setMaxWidth(dp(200));
lastLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
return this;
}
@ -323,7 +325,7 @@ public class ItemOptions {
if (layout instanceof ActionBarPopupWindow.ActionBarPopupWindowLayout) {
layout.setBackgroundDrawable(
new BlurringShader.StoryBlurDrawer(blurManager, layout, BlurringShader.StoryBlurDrawer.BLUR_TYPE_MENU_BACKGROUND)
.makeDrawable(offsetX + ox + layout.getX(), offsetY + oy + layout.getY(), baseDrawable)
.makeDrawable(offsetX + ox + layout.getX(), offsetY + oy + layout.getY(), baseDrawable, dp(6))
);
} else {
for (int i = 0; i < layout.getChildCount(); ++i) {
@ -331,7 +333,7 @@ public class ItemOptions {
if (child instanceof ActionBarPopupWindow.ActionBarPopupWindowLayout) {
child.setBackgroundDrawable(
new BlurringShader.StoryBlurDrawer(blurManager, child, BlurringShader.StoryBlurDrawer.BLUR_TYPE_MENU_BACKGROUND)
.makeDrawable(offsetX + ox + layout.getX() + child.getX(), offsetY + oy + layout.getY() + child.getY(), baseDrawable)
.makeDrawable(offsetX + ox + layout.getX() + child.getX(), offsetY + oy + layout.getY() + child.getY(), baseDrawable, dp(6))
);
}
}
@ -388,7 +390,7 @@ public class ItemOptions {
if (child instanceof ActionBarPopupWindow.ActionBarPopupWindowLayout) {
ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout = (ActionBarPopupWindow.ActionBarPopupWindowLayout) child;
for (int i = 0; i < popupLayout.getItemsCount(); ++i) {
popupLayout.getItemAt(i).setMinimumWidth(AndroidUtilities.dp(minWidthDp));
popupLayout.getItemAt(i).setMinimumWidth(dp(minWidthDp));
}
}
}
@ -460,7 +462,7 @@ public class ItemOptions {
}
int Y;
if (scrimView != null) {
if (forceTop || y + layout.getMeasuredHeight() + AndroidUtilities.dp(16) > AndroidUtilities.displaySize.y) {
if (forceTop || y + layout.getMeasuredHeight() + dp(16) > AndroidUtilities.displaySize.y) {
// put above scrimView
y -= scrimView.getMeasuredHeight();
y -= layout.getMeasuredHeight();

View file

@ -435,6 +435,13 @@ public class LinkActionView extends LinearLayout {
}
}
public void hideOptions() {
optionsView.setVisibility(View.GONE);
linkView.setGravity(Gravity.CENTER);
removeView.setVisibility(View.GONE);
avatarsContainer.setVisibility(View.GONE);
}
private class AvatarsContainer extends FrameLayout {
TextView countTextView;

View file

@ -467,7 +467,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
getMessagesController().getStoriesController().updateStoriesInLists(dialogId, storyItems);
final boolean[] undone = new boolean[] { false };
applyBulletin = () -> {
getMessagesController().getStoriesController().updateStoriesPinned(storyItems, pin, null);
getMessagesController().getStoriesController().updateStoriesPinned(dialogId, storyItems, pin, null);
};
final Runnable undo = () -> {
undone[0] = true;
@ -1159,10 +1159,13 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha
@Override
public Tab[] createTabs() {
return new Tab[] {
Tab[] tabs = new Tab[] {
new Tab(0, R.raw.msg_stories_saved, LocaleController.getString("ProfileMyStoriesTab", R.string.ProfileMyStoriesTab)),
new Tab(1, R.raw.msg_stories_archive, LocaleController.getString("ProfileStoriesArchiveTab", R.string.ProfileStoriesArchiveTab))
};
tabs[0].customEndFrameMid = 20;
tabs[0].customEndFrameEnd = 40;
return tabs;
}
}

View file

@ -270,6 +270,10 @@ public class MentionsContainerView extends BlurredFrameLayout implements Notific
}
protected void onAnimationScroll() {
}
public MentionsListView getListView() {
return listView;
}
@ -321,6 +325,7 @@ public class MentionsContainerView extends BlurredFrameLayout implements Notific
containerPadding = AndroidUtilities.dp(2 + (topPadding ? 2 : 0));
float r = AndroidUtilities.dp(6);
float wasContainerTop = containerTop;
if (reversed) {
int paddingViewTop = paddedAdapter.paddingViewAttached ? paddedAdapter.paddingView.getTop() : getHeight();
float top = Math.max(0, paddingViewTop + listView.getTranslationY()) + containerPadding;
@ -344,6 +349,9 @@ public class MentionsContainerView extends BlurredFrameLayout implements Notific
rect.bottom += (int) r;
}
}
if (Math.abs(wasContainerTop - containerTop) > 0.1f) {
onAnimationScroll();
}
if (paint == null) {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
@ -504,6 +512,7 @@ public class MentionsContainerView extends BlurredFrameLayout implements Notific
);
listViewTranslationAnimator.addUpdateListener((anm, val, vel) -> {
listView.setTranslationY(val);
onAnimationScroll();
hideT = AndroidUtilities.lerp(fromHideT, toHideT, (val - fromTranslation) / (toTranslation - fromTranslation));
});
if (forceZeroHeight) {

View file

@ -1,6 +1,7 @@
package org.telegram.ui.Components.Paint.Views;
import android.content.Context;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
@ -12,6 +13,8 @@ import org.telegram.messenger.AndroidUtilities;
public class EntitiesContainerView extends FrameLayout {
public boolean drawForThumb;
public interface EntitiesContainerViewDelegate {
boolean shouldReceiveTouches();
void onEntityDeselect();
@ -98,4 +101,12 @@ public class EntitiesContainerView extends FrameLayout {
super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
}
}
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (drawForThumb && child instanceof ReactionWidgetEntityView) {
return true;
}
return super.drawChild(canvas, child, drawingTime);
}
}

View file

@ -10,6 +10,7 @@ import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.os.Build;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
@ -485,7 +486,7 @@ public class EntityView extends FrameLayout {
if (parent != null) {
int newStickyX = STICKY_NONE;
if (!lastIsMultitouch) {
if (Math.abs(position.x - parent.getMeasuredWidth() / 2f) <= dp(STICKY_TRIGGER_DP) && position.y < parent.getMeasuredHeight() - dp(112 + 64)) {
if (Math.abs(position.x - parent.getMeasuredWidth() / 2f) <= dp(STICKY_TRIGGER_DP) && position.y < parent.getMeasuredHeight() - dp(112)) {
newStickyX = STICKY_CENTER;
} else if (Math.abs(position.x - (width() / 2f + getStickyPaddingLeft()) * getScaleX() - dp(STICKY_PADDING_X_DP)) <= dp(STICKY_TRIGGER_DP)) {
newStickyX = STICKY_START;
@ -773,6 +774,10 @@ public class EntityView extends FrameLayout {
}
}
public boolean isSelectedProgress() {
return isSelected() || selectT > 0;
}
private ViewGroup lastSelectionContainer;
public void select(ViewGroup selectionContainer) {
updateSelect(lastSelectionContainer = selectionContainer, true);

View file

@ -234,8 +234,8 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
return -9539985;
} else if (key == Theme.key_chat_emojiPanelIcon) {
return -9539985;
} else if (key == Theme.key_chat_emojiPanelIconSelected) {
return 0xffffffff;
// } else if (key == Theme.key_chat_emojiPanelIconSelected) {
// return -10177041;
} else if (key == Theme.key_windowBackgroundWhiteBlackText) {
return -1;
} else if (key == Theme.key_featuredStickers_addedIcon) {
@ -459,6 +459,14 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
}
CharSequence charSequence = text;
charSequence = Emoji.replaceEmoji(charSequence, textPaintView.getFontMetricsInt(), (int) (textPaintView.getFontSize() * .8f), false);
if (charSequence instanceof Spanned) {
Emoji.EmojiSpan[] spans = ((Spanned) charSequence).getSpans(0, charSequence.length(), Emoji.EmojiSpan.class);
if (spans != null) {
for (int i = 0; i < spans.length; ++i) {
spans[i].scale = .85f;
}
}
}
textPaintView.setText(charSequence);
setTextAlignment(textPaintView, entity.textAlign);
Swatch swatch = textPaintView.getSwatch();
@ -471,8 +479,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
view.setX(entity.x * paintingSize.width - entity.viewWidth * (1 - entity.scale) / 2);
view.setY(entity.y * paintingSize.height - entity.viewHeight * (1 - entity.scale) / 2);
view.setPosition(new Point(view.getX() + entity.viewWidth / 2f, view.getY() + entity.viewHeight / 2f));
view.setScaleX(entity.scale);
view.setScaleY(entity.scale);
view.setScale(entity.scale);
view.setRotation((float) (-entity.rotation / Math.PI * 180));
}
}
@ -934,11 +941,13 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
return currentEntityView instanceof TextPaintView;
}
public float getSelectedEntityCenterY() {
public float getSelectedEntityBottom() {
if (currentEntityView == null) {
return getY() + entitiesView.getTop() + entitiesView.getMeasuredHeight() / 2f;
return getY() + entitiesView.getMeasuredHeight();
}
return getY() + entitiesView.getTop() + currentEntityView.getPositionY();
int[] loc = new int[2];
currentEntityView.getLocationInWindow(loc);
return loc[1] + currentEntityView.getHeight() * entitiesView.getScaleY();
}
private TextPaintView createText(boolean select) {
@ -1148,7 +1157,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
int w = (int) (vw * currentCropState.cropPw * child.getScaleX() / currentCropState.cropScale);
int h = (int) (vh * currentCropState.cropPh * child.getScaleY() / currentCropState.cropScale);
float x = (float) Math.ceil((getMeasuredWidth() - w) / 2f) + transformX;
float y = (getMeasuredHeight() - actionBarHeight2 - AndroidUtilities.dp(48) + getAdditionalBottom() - h) / 2f + AndroidUtilities.dp(8) + status + transformY;
float y = (getMeasuredHeight() - emojiPadding - actionBarHeight2 - AndroidUtilities.dp(48) + getAdditionalBottom() - h) / 2f + AndroidUtilities.dp(8) + status + transformY;
canvas.clipRect(Math.max(0, x), Math.max(0, y), Math.min(x + w, getMeasuredWidth()), Math.min(getMeasuredHeight(), y + h));
restore = true;
@ -1403,9 +1412,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
entitiesView.setScaleX(baseScale);
entitiesView.setScaleY(baseScale);
entitiesView.measure(MeasureSpec.makeMeasureSpec((int) paintingSize.width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) paintingSize.height, MeasureSpec.EXACTLY));
if (currentEntityView != null) {
currentEntityView.updateSelectionView();
}
updateEntitiesSelections();
selectionContainerView.measure(MeasureSpec.makeMeasureSpec((int) renderWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) renderHeight, MeasureSpec.EXACTLY));
measureChild(bottomLayout, widthMeasureSpec, heightMeasureSpec);
measureChild(weightChooserView, widthMeasureSpec, heightMeasureSpec);
@ -1939,9 +1946,19 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
view.setRotation(rotation);
view.invalidate();
}
updateEntitiesSelections();
invalidate();
}
public void updateEntitiesSelections() {
for (int i = 0; i < entitiesView.getChildCount(); ++i) {
View child = entitiesView.getChildAt(i);
if (child == currentEntityView || child instanceof EntityView && ((EntityView) child).isSelectedProgress()) {
((EntityView) child).updateSelectionView();
}
}
}
@Override
public List<TLRPC.InputDocument> getMasks() {
ArrayList<TLRPC.InputDocument> result = null;
@ -2479,6 +2496,26 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh
parent.addView(editView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 48));
}
if (entityView instanceof StickerView) {
TextView flipView = new TextView(getContext());
flipView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem));
flipView.setBackgroundDrawable(Theme.getSelectorDrawable(false));
flipView.setGravity(Gravity.CENTER_VERTICAL);
flipView.setEllipsize(TextUtils.TruncateAt.END);
flipView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(16), 0);
flipView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
flipView.setTag(2);
flipView.setText(LocaleController.getString("Flip", R.string.Flip));
flipView.setOnClickListener(v -> {
((StickerView) entityView).mirror(true);
if (popupWindow != null && popupWindow.isShowing()) {
popupWindow.dismiss(true);
}
});
parent.addView(flipView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 48));
}
TextView duplicateView = new TextView(getContext());
duplicateView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem));
duplicateView.setBackgroundDrawable(Theme.getSelectorDrawable(false));

View file

@ -0,0 +1,377 @@
package org.telegram.ui.Components.Paint.Views;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.RectF;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.MediaDataController;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.AnimatedFloat;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.Point;
import org.telegram.ui.Components.Reactions.ReactionImageHolder;
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
import org.telegram.ui.Components.Rect;
import org.telegram.ui.Components.Size;
import org.telegram.ui.Stories.StoryReactionWidgetBackground;
import java.util.List;
import java.util.Objects;
public class ReactionWidgetEntityView extends EntityView {
Size baseSize;
StoryReactionWidgetBackground storyReactionWidgetBackground = new StoryReactionWidgetBackground(this);
StoryReactionWidgetBackground outBackground = new StoryReactionWidgetBackground(this);
ReactionImageHolder reactionHolder = new ReactionImageHolder(this);
ReactionImageHolder nextReactionHolder = new ReactionImageHolder(this);
ReactionsLayoutInBubble.VisibleReaction currentReaction;
AnimatedFloat progressToNext = new AnimatedFloat(this);
AnimatedFloat crossfadeBackgrounds = new AnimatedFloat(this);
boolean mirror;
private float drawScale = 1f;
int filterColor;
public ReactionWidgetEntityView(Context context, Point pos, Size baseSize) {
super(context, pos);
this.baseSize = baseSize;
crossfadeBackgrounds.set(1f, true);
progressToNext.set(1f, true);
List<TLRPC.TL_availableReaction> availableReactions = MediaDataController.getInstance(UserConfig.selectedAccount).getReactionsList();
reactionHolder.setVisibleReaction(currentReaction = ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(findHeartReaction(availableReactions)));
updatePosition();
}
private String findHeartReaction(List<TLRPC.TL_availableReaction> availableReactions) {
for (int i = 0; i < availableReactions.size(); i++) {
if (availableReactions.get(i).title.equals("Red Heart")) {
return availableReactions.get(i).reaction;
}
}
return availableReactions.get(0).reaction;
}
protected void updatePosition() {
float halfWidth = baseSize.width / 2.0f;
float halfHeight = baseSize.height / 2.0f;
setX(getPositionX() - halfWidth);
setY(getPositionY() - halfHeight);
updateSelectionView();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(MeasureSpec.makeMeasureSpec((int) baseSize.width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) baseSize.height, MeasureSpec.EXACTLY));
}
@Override
protected void dispatchDraw(Canvas canvas) {
int padding = getPadding();
float crossfade = crossfadeBackgrounds.set(1f);
if (crossfade == 1f) {
outBackground = null;
}
canvas.save();
canvas.scale(drawScale, drawScale, getMeasuredWidth() / 2f, getMeasuredHeight() / 2f);
if (outBackground != null) {
outBackground.setAlpha((int) (255 * (1f - crossfade)));
outBackground.setBounds(padding, padding, (int) baseSize.width - padding, (int) baseSize.height - padding);
outBackground.draw(canvas);
}
storyReactionWidgetBackground.setAlpha((int) (255 * crossfade));
storyReactionWidgetBackground.setBounds(padding, padding, (int) baseSize.width - padding, (int) baseSize.height - padding);
storyReactionWidgetBackground.draw(canvas);
float imageSize = storyReactionWidgetBackground.getBounds().width() * 0.61f;
AndroidUtilities.rectTmp2.set(
(int) (storyReactionWidgetBackground.getBounds().centerX() - imageSize / 2f),
(int) (storyReactionWidgetBackground.getBounds().centerY() - imageSize / 2f),
(int) (storyReactionWidgetBackground.getBounds().centerX() + imageSize / 2f),
(int) (storyReactionWidgetBackground.getBounds().centerY() + imageSize / 2f)
);
float progress = progressToNext.set(1);
reactionHolder.setBounds(AndroidUtilities.rectTmp2);
nextReactionHolder.setBounds(AndroidUtilities.rectTmp2);
reactionHolder.setColor(storyReactionWidgetBackground.isDarkStyle() ? Color.WHITE : Color.BLACK);
if (progress == 1) {
reactionHolder.draw(canvas);
} else {
canvas.save();
canvas.scale(1f - progress, 1f - progress, AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.top);
nextReactionHolder.setAlpha(1f - progress);
nextReactionHolder.draw(canvas);
canvas.restore();
canvas.save();
canvas.scale(progress, progress, AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.bottom);
reactionHolder.setAlpha(progress);
reactionHolder.draw(canvas);
canvas.restore();
}
canvas.restore();
}
public int getPadding() {
return (int) ((baseSize.height - AndroidUtilities.dp(84)) / 2f);
}
@Override
protected Rect getSelectionBounds() {
ViewGroup parentView = (ViewGroup) getParent();
if (parentView == null) {
return new Rect();
}
float scale = parentView.getScaleX();
float side = getMeasuredWidth() * (getScale() + 0.4f);
return new Rect((getPositionX() - side / 2.0f) * scale, (getPositionY() - side / 2.0f) * scale, side * scale, side * scale);
}
@Override
protected SelectionView createSelectionView() {
return new StickerViewSelectionView(getContext());
}
public void setCurrentReaction(ReactionsLayoutInBubble.VisibleReaction visibleReaction, boolean animated) {
if (Objects.equals(currentReaction, visibleReaction)) {
return;
}
if (!animated) {
currentReaction = visibleReaction;
reactionHolder.setVisibleReaction(currentReaction);
invalidate();
} else {
currentReaction = visibleReaction;
nextReactionHolder.setVisibleReaction(currentReaction);
ReactionImageHolder k = reactionHolder;
reactionHolder = nextReactionHolder;
nextReactionHolder = k;
progressToNext.set(0, true);
invalidate();
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
reactionHolder.onAttachedToWindow(true);
nextReactionHolder.onAttachedToWindow(true);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
reactionHolder.onAttachedToWindow(false);
nextReactionHolder.onAttachedToWindow(false);
}
public ReactionsLayoutInBubble.VisibleReaction getCurrentReaction() {
return currentReaction;
}
public void mirror(boolean animate) {
mirror = !mirror;
if (!animate) {
storyReactionWidgetBackground.setMirror(mirror, animate);
} else {
boolean[] mirrored = new boolean[] {false};
ValueAnimator animator = ValueAnimator.ofFloat(0, 1f);
animator.addUpdateListener(animation -> {
float progress = (float) animation.getAnimatedValue();
if (progress < 0.5f) {
setRotationY(90 * (progress / 0.5f));
drawScale = 0.7f + 0.3f * (1f - (progress / 0.5f));
invalidate();
} else {
if (!mirrored[0]) {
mirrored[0] = true;
storyReactionWidgetBackground.setMirror(mirror, false);
}
progress -= 0.5f;
setRotationY(-90 * (1f - progress / 0.5f));
drawScale = 0.7f + 0.3f * (progress / 0.5f);
invalidate();
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (!mirrored[0]) {
mirrored[0] = true;
storyReactionWidgetBackground.setMirror(mirror, false);
}
setRotationY(0);
drawScale = 1f;
}
});
animator.setInterpolator(CubicBezierInterpolator.EASE_OUT);
animator.setDuration(350);
animator.start();
}
}
public void changeStyle(boolean animated) {
if (!animated) {
storyReactionWidgetBackground.nextStyle();
} else {
outBackground = storyReactionWidgetBackground;
storyReactionWidgetBackground = new StoryReactionWidgetBackground(this);
if (!outBackground.isDarkStyle()) {
storyReactionWidgetBackground.nextStyle();
}
storyReactionWidgetBackground.setMirror(mirror, false);
storyReactionWidgetBackground.updateShadowLayer(getScaleX());
crossfadeBackgrounds.set(0, true);
}
invalidate();
}
public boolean isMirrored() {
return mirror;
}
public boolean isDark() {
return storyReactionWidgetBackground.isDarkStyle();
}
// private void animateBounce() {
// AnimatorSet animatorSet = new AnimatorSet();
// ValueAnimator inAnimator = ValueAnimator.ofFloat(1, 1.05f);
// inAnimator.setDuration(100);
// inAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT);
//
// ValueAnimator outAnimator = ValueAnimator.ofFloat(1.05f, 1f);
// outAnimator.setDuration(250);
// outAnimator.setInterpolator(new OvershootInterpolator());
//
// ValueAnimator.AnimatorUpdateListener updater = animation -> {
// bounceScale = (float) animation.getAnimatedValue();
// invalidate();
// };
// setClipInParent(false);
// inAnimator.addUpdateListener(updater);
// outAnimator.addUpdateListener(updater);
// animatorSet.playSequentially(inAnimator, outAnimator);
// animatorSet.addListener(new AnimatorListenerAdapter() {
// @Override
// public void onAnimationEnd(Animator animation) {
// bounceScale = 1f;
// invalidate();
// setClipInParent(true);
// }
// });
// animatorSet.start();
//
// if (animationRunnable != null) {
// AndroidUtilities.cancelRunOnUIThread(animationRunnable);
// animationRunnable.run();
// animationRunnable = null;
// }
// }
public class StickerViewSelectionView extends SelectionView {
private RectF arcRect = new RectF();
public StickerViewSelectionView(Context context) {
super(context);
}
@Override
protected int pointInsideHandle(float x, float y) {
float thickness = AndroidUtilities.dp(1.0f);
float radius = AndroidUtilities.dp(19.5f);
float inset = radius + thickness;
float middle = inset + (getMeasuredHeight() - inset * 2) / 2.0f;
if (x > inset - radius && y > middle - radius && x < inset + radius && y < middle + radius) {
return SELECTION_LEFT_HANDLE;
} else if (x > inset + (getMeasuredWidth() - inset * 2) - radius && y > middle - radius && x < inset + (getMeasuredWidth() - inset * 2) + radius && y < middle + radius) {
return SELECTION_RIGHT_HANDLE;
}
float selectionRadius = getMeasuredWidth() / 2.0f;
if (Math.pow(x - selectionRadius, 2) + Math.pow(y - selectionRadius, 2) < Math.pow(selectionRadius, 2)) {
return SELECTION_WHOLE_HANDLE;
}
return 0;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int count = canvas.getSaveCount();
float alpha = getShowAlpha();
if (alpha <= 0) {
return;
} else if (alpha < 1) {
canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), (int) (0xFF * alpha), Canvas.ALL_SAVE_FLAG);
}
float thickness = AndroidUtilities.dp(1.0f);
float radius = AndroidUtilities.dpf2(5.66f);
float inset = radius + thickness + AndroidUtilities.dp(15);
float mainRadius = getMeasuredWidth() / 2 - inset;
arcRect.set(inset, inset, inset + mainRadius * 2, inset + mainRadius * 2);
canvas.drawArc(arcRect, 0, 180, false, paint);
canvas.drawArc(arcRect, 180, 180, false, paint);
canvas.drawCircle(inset, inset + mainRadius, radius, dotStrokePaint);
canvas.drawCircle(inset, inset + mainRadius, radius - AndroidUtilities.dp(1), dotPaint);
canvas.drawCircle(inset + mainRadius * 2, inset + mainRadius, radius, dotStrokePaint);
canvas.drawCircle(inset + mainRadius * 2, inset + mainRadius, radius - AndroidUtilities.dp(1), dotPaint);
canvas.restoreToCount(count);
}
}
@Override
public boolean allowLongPressOnSelected() {
return true;
}
@Override
public void setScaleX(float scaleX) {
if (getScaleX() != scaleX) {
super.setScaleX(scaleX);
storyReactionWidgetBackground.updateShadowLayer(scaleX);
invalidate();
}
}
@Override
protected float getMaxScale() {
return 1.8f;
}
@Override
protected float getMinScale() {
return 0.5f;
}
@Override
protected boolean allowHaptic() {
return false;
}
}

View file

@ -3,6 +3,7 @@ package org.telegram.ui.Components.Paint.Views;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.FrameLayout;

View file

@ -34,6 +34,7 @@ import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
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.Components.ColoredImageSpan;
import org.telegram.ui.Components.CubicBezierInterpolator;
@ -44,6 +45,9 @@ import java.util.ArrayList;
public class LimitPreviewView extends LinearLayout {
private float percent;
private final int premiumLimit;
private int currentValue;
public int gradientTotalHeight;
boolean wasAnimation;
CounterView limitIcon;
@ -69,6 +73,10 @@ public class LimitPreviewView extends LinearLayout {
private boolean isBoostsStyle;
Theme.ResourcesProvider resourcesProvider;
private boolean animateIncrease;
private int animateIncreaseWidth;
float limitIconRotation;
public boolean isStatistic;
public LimitPreviewView(@NonNull Context context, int icon, int currentValue, int premiumLimit, Theme.ResourcesProvider resourcesProvider) {
@ -79,8 +87,10 @@ public class LimitPreviewView extends LinearLayout {
public LimitPreviewView(@NonNull Context context, int icon, int currentValue, int premiumLimit, float inputPercent, Theme.ResourcesProvider resourcesProvider) {
super(context);
this.resourcesProvider = resourcesProvider;
final float percent = MathUtils.clamp(inputPercent, 0.1f, 0.9f);
this.percent = MathUtils.clamp(inputPercent, 0.1f, 0.9f);
this.icon = icon;
this.currentValue = currentValue;
this.premiumLimit = premiumLimit;
setOrientation(VERTICAL);
setClipChildren(false);
setClipToPadding(false);
@ -88,7 +98,7 @@ public class LimitPreviewView extends LinearLayout {
setPadding(0, dp(16), 0, 0);
limitIcon = new CounterView(context);
setIconValue(currentValue);
setIconValue(currentValue, false);
limitIcon.setPadding(dp(24), dp(6), dp(24), dp(14));
addView(limitIcon, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.LEFT));
@ -145,7 +155,11 @@ public class LimitPreviewView extends LinearLayout {
@Override
protected void dispatchDraw(Canvas canvas) {
if (isBoostsStyle) {
grayPaint.setColor(Theme.getColor(Theme.key_graySection, resourcesProvider));
if (isStatistic) {
grayPaint.setColor(Theme.getColor(Theme.key_listSelector, resourcesProvider));
} else {
grayPaint.setColor(Theme.getColor(Theme.key_graySection, resourcesProvider));
}
} else {
grayPaint.setColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider));
}
@ -200,16 +214,35 @@ public class LimitPreviewView extends LinearLayout {
MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
);
final int minWidth2 = Math.max(premiumLayout.getMeasuredWidth(), dp(24) + premiumText.getMeasuredWidth() + (premiumCount.getVisibility() == View.VISIBLE ? dp(24) + premiumCount.getMeasuredWidth() : 0));
width1 = (int) Utilities.clamp(width * percent, width - minWidth2, minWidth1);
defaultLayout.measure(
MeasureSpec.makeMeasureSpec(width1, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
);
premiumLayout.measure(
MeasureSpec.makeMeasureSpec(width - width1, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
);
if (isBoostsStyle) {
if (percent == 0) {
width1 = 0;
premiumCount.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
defaultText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
} else if (percent < 1f) {
float leftWidth = defaultLayout.getMeasuredWidth() - AndroidUtilities.dp(8);
float rightWidth = premiumLayout.getMeasuredWidth() - AndroidUtilities.dp(8);
float availableWidth = width - leftWidth - rightWidth;
width1 = (int) (leftWidth + availableWidth * percent);
premiumCount.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
defaultText.setTextColor(Color.WHITE);
} else {
width1 = width;
premiumCount.setTextColor(Color.WHITE);
defaultText.setTextColor(Color.WHITE);
}
} else {
final int minWidth2 = Math.max(premiumLayout.getMeasuredWidth(), dp(24) + premiumText.getMeasuredWidth() + (premiumCount.getVisibility() == View.VISIBLE ? dp(24) + premiumCount.getMeasuredWidth() : 0));
width1 = (int) Utilities.clamp(width * percent, width - minWidth2, minWidth1);
defaultLayout.measure(
MeasureSpec.makeMeasureSpec(width1, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
);
premiumLayout.measure(
MeasureSpec.makeMeasureSpec(width - width1, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
);
}
setMeasuredDimension(width, height);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@ -234,11 +267,12 @@ public class LimitPreviewView extends LinearLayout {
addView(limitsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 30, 0, 0, 14, icon == 0 ? 0 : 12, 14, 0));
}
public void setIconValue(int currentValue) {
public void setIconValue(int currentValue, boolean animated) {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("d ").setSpan(new ColoredImageSpan(icon), 0, 1, 0);
spannableStringBuilder.append(Integer.toString(currentValue));
limitIcon.setText(spannableStringBuilder);
limitIcon.setText(spannableStringBuilder, animated);
limitIcon.requestLayout();
}
private float getGlobalXOffset() {
@ -267,12 +301,18 @@ public class LimitPreviewView extends LinearLayout {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (!wasAnimation && limitIcon != null && animationCanPlay && !premiumLocked) {
if (animateIncrease || (!wasAnimation && limitIcon != null && animationCanPlay && !premiumLocked)) {
int padding = dp(14);
float fromX = 0;
boolean animateIncreaseFinal = animateIncrease;
animateIncrease = false;
float fromX = animateIncreaseFinal ? limitIcon.getTranslationX() : 0;
float toX = padding + Math.max(width1, (getMeasuredWidth() - padding * 2) * position) - limitIcon.getMeasuredWidth() / 2f;
float fromProgressCenter = 0.5f;
float toProgressCenter = 0.5f;
if (toX < padding) {
toX = padding;
fromProgressCenter = toProgressCenter = 0f;
}
if (toX > getMeasuredWidth() - padding - limitIcon.getMeasuredWidth()) {
toX = getMeasuredWidth() - padding - limitIcon.getMeasuredWidth();
toProgressCenter = 1f;
@ -281,13 +321,20 @@ public class LimitPreviewView extends LinearLayout {
limitIcon.setTranslationX(fromX);
limitIcon.setPivotX(limitIcon.getMeasuredWidth() / 2f);
limitIcon.setPivotY(limitIcon.getMeasuredHeight());
limitIcon.setScaleX(0);
limitIcon.setScaleY(0);
limitIcon.createAnimationLayouts();
if (!animateIncreaseFinal) {
limitIcon.setScaleX(0);
limitIcon.setScaleY(0);
limitIcon.createAnimationLayouts();
}
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f);
float finalToX = toX;
float finalToProgressCenter = toProgressCenter;
float toWidth = width1;
if (animateIncreaseFinal) {
width1 = animateIncreaseWidth;
}
float finalFromProgressCenter = fromProgressCenter;
valueAnimator.addUpdateListener(animation -> {
float v = (float) animation.getAnimatedValue();
float moveValue = Math.min(1f, v);
@ -296,25 +343,47 @@ public class LimitPreviewView extends LinearLayout {
wasHaptic = true;
limitIcon.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
}
limitIcon.setRotation((v - 1f) * 60);
limitIcon.setRotation(limitIconRotation + (v - 1f) * 60);
} else {
limitIcon.setRotation(0);
limitIcon.setRotation(limitIconRotation);
}
limitIcon.setTranslationX(fromX * (1f - moveValue) + finalToX * moveValue);
float arrowCenter = fromProgressCenter * (1f - moveValue) + finalToProgressCenter * moveValue;
float arrowCenter = finalFromProgressCenter * (1f - moveValue) + finalToProgressCenter * moveValue;
limitIcon.setArrowCenter(arrowCenter);
float scale = Math.min(1, moveValue * 2f);
limitIcon.setScaleX(scale);
limitIcon.setScaleY(scale);
if (!animateIncreaseFinal) {
limitIcon.setScaleX(scale);
limitIcon.setScaleY(scale);
} else {
width1 = (int) AndroidUtilities.lerp(animateIncreaseWidth, toWidth, moveValue);
limitsContainer.invalidate();
}
limitIcon.setPivotX(limitIcon.getMeasuredWidth() * arrowCenter);
});
valueAnimator.setInterpolator(new OvershootInterpolator());
valueAnimator.setDuration(1000);
valueAnimator.setStartDelay(200);
if (animateIncreaseFinal) {
ValueAnimator valueAnimator1 = ValueAnimator.ofFloat(0, 1f);
valueAnimator1.addUpdateListener(animation -> {
float p = (float) animation.getAnimatedValue();
float k = 0.5f;
float angle = -7;
limitIconRotation = p < k ? p / k * angle : angle * (1f - (p - k) / (1f - k));
});
valueAnimator1.setDuration(500);
valueAnimator1.start();
valueAnimator.setDuration(600);
} else {
valueAnimator.setDuration(1000);
valueAnimator.setStartDelay(200);
}
valueAnimator.start();
wasAnimation = true;
} else if (isBoostsStyle) {
limitIcon.setAlpha(1f);
limitIcon.setScaleX(1f);
limitIcon.setScaleY(1f);
} else if (premiumLocked) {
int padding = dp(14);
float toX = padding + (getMeasuredWidth() - padding * 2) * 0.5f - limitIcon.getMeasuredWidth() / 2f;
@ -331,7 +400,7 @@ public class LimitPreviewView extends LinearLayout {
limitIcon.setScaleY(1f);
}
limitIcon.setTranslationX(toX);
} else if (limitIcon != null){
} else if (limitIcon != null) {
limitIcon.setAlpha(0);
}
}
@ -342,14 +411,14 @@ public class LimitPreviewView extends LinearLayout {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("d ").setSpan(new ColoredImageSpan(icon), 0, 1, 0);
spannableStringBuilder.append(UserConfig.getInstance(UserConfig.selectedAccount).isPremium() ? "4 GB" : "2 GB");
limitIcon.setText(spannableStringBuilder);
limitIcon.setText(spannableStringBuilder, false);
}
premiumCount.setText("4 GB");
} else if (type == LimitReachedBottomSheet.TYPE_ADD_MEMBERS_RESTRICTED) {
if (limitIcon != null) {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("d").setSpan(new ColoredImageSpan(icon), 0, 1, 0);
limitIcon.setText(spannableStringBuilder);
limitIcon.setText(spannableStringBuilder, false);
}
premiumCount.setText("");
}
@ -382,6 +451,41 @@ public class LimitPreviewView extends LinearLayout {
premiumLocked = true;
}
public void setBoosts(TLRPC.TL_stories_boostsStatus boosts, boolean boosted) {
int k = boosts.current_level_boosts;
boolean isZeroLevelBoosts = boosts.current_level_boosts == boosts.boosts;
if ((isZeroLevelBoosts && boosted) || boosts.next_level_boosts == 0) {
percent = 1f;
defaultText.setText(LocaleController.formatString("BoostsLevel", R.string.BoostsLevel, boosts.level - 1));
premiumCount.setText(LocaleController.formatString("BoostsLevel", R.string.BoostsLevel, boosts.level));
} else {
percent = MathUtils.clamp((boosts.boosts - k) / (float) (boosts.next_level_boosts - k), 0, 1f);
defaultText.setText(LocaleController.formatString("BoostsLevel", R.string.BoostsLevel, boosts.level));
premiumCount.setText(LocaleController.formatString("BoostsLevel", R.string.BoostsLevel, boosts.level + 1));
}
setType(LimitReachedBottomSheet.TYPE_BOOSTS);
defaultCount.setVisibility(View.GONE);
premiumText.setVisibility(View.GONE);
premiumCount.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
defaultText.setTextColor(Color.WHITE);
setIconValue(boosts.boosts, false);
isBoostsStyle = true;
}
public void increaseCurrentValue(int value, int maxValue) {
currentValue++;
percent = MathUtils.clamp(value / (float) maxValue, 0f, 1f);
animateIncrease = true;
animateIncreaseWidth = width1;
setIconValue(currentValue, true);
limitsContainer.requestLayout();
requestLayout();
}
private class CounterView extends View {
Path path = new Path();
@ -418,12 +522,14 @@ public class LimitPreviewView extends LinearLayout {
int h = getMeasuredHeight() - dp(8);
float widthHalf = getMeasuredWidth() * arrowCenter;
float x2 = Utilities.clamp(widthHalf + dp(8), getMeasuredWidth(), 0);
float x3 = Utilities.clamp(widthHalf + dp(10), getMeasuredWidth(), 0);
float x3 = Utilities.clamp(widthHalf + dp(10), getMeasuredWidth(), AndroidUtilities.dp(24));
float x4 = Utilities.clamp(widthHalf - dp(24), getMeasuredWidth(), 0);
float x5 = Utilities.clamp(widthHalf - dp(8), getMeasuredWidth(), 0);
path.rewind();
path.moveTo(widthHalf - dp(24), h - h / 2f - dp(2));
path.lineTo(widthHalf - dp(24), h);
path.lineTo(widthHalf - dp(8), h);
path.moveTo(x4, h - h / 2f - dp(2));
path.lineTo(x4, h);
path.lineTo(x5, h);
path.lineTo(widthHalf, h + dp(8));
if (arrowCenter < 0.7f) {
path.lineTo(x2, h);
@ -476,7 +582,13 @@ public class LimitPreviewView extends LinearLayout {
for (int i = 0; i < animatedLayouts.size(); i++) {
AnimatedLayout animatedLayout = animatedLayouts.get(i);
canvas.save();
if (animatedLayout.direction) {
if (animatedLayout.replace) {
canvas.translate(x + animatedLayout.x, y + h * (animatedLayout.progress) - h * (1 - animatedLayout.staticLayouts.size()));
for (int j = 0; j < animatedLayout.staticLayouts.size(); j++) {
canvas.translate(0, -h);
animatedLayout.staticLayouts.get(j).draw(canvas);
}
} else if (animatedLayout.direction) {
canvas.translate(x + animatedLayout.x, y - h * 10 * animatedLayout.progress + h * (10 - animatedLayout.staticLayouts.size()));
for (int j = 0; j < animatedLayout.staticLayouts.size(); j++) {
canvas.translate(0, h);
@ -506,6 +618,9 @@ public class LimitPreviewView extends LinearLayout {
void createAnimationLayouts() {
animatedLayouts.clear();
if (isBoostsStyle && currentValue == 0) {
return;
}
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text);
boolean direction = true;
@ -561,6 +676,55 @@ public class LimitPreviewView extends LinearLayout {
}
}
void createAnimationLayoutsDiff(CharSequence oldText) {
animatedLayouts.clear();
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text);
int directionCount = 0;
for (int i = text.length() - 1; i >= 0; i--) {
char oldChar = i < oldText.length() ? oldText.charAt(i) : ' ';
if (oldChar != text.charAt(i) && Character.isDigit(text.charAt(i))) {
AnimatedLayout animatedLayout = new AnimatedLayout();
animatedLayouts.add(animatedLayout);
animatedLayout.x = textLayout.getSecondaryHorizontal(i);
animatedLayout.replace = true;
if (directionCount >= 1) {
directionCount = 0;
}
directionCount++;
StaticLayout staticLayoutOld = new StaticLayout("" + oldChar, textPaint, (int) textWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
animatedLayout.staticLayouts.add(staticLayoutOld);
StaticLayout staticLayout = new StaticLayout("" + text.charAt(i), textPaint, (int) textWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
animatedLayout.staticLayouts.add(staticLayout);
spannableStringBuilder.setSpan(new EmptyStubSpan(), i, i + 1, 0);
}
}
animatedStableLayout = new StaticLayout(spannableStringBuilder, textPaint, (int) textWidth + dp(12), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
for (int i = 0; i < animatedLayouts.size(); i++) {
animationInProgress = true;
AnimatedLayout layout = animatedLayouts.get(i);
layout.valueAnimator = ValueAnimator.ofFloat(0, 1f);
layout.valueAnimator.addUpdateListener(animation -> {
layout.progress = (float) animation.getAnimatedValue();
invalidate();
});
layout.valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
layout.valueAnimator = null;
checkAnimationComplete();
}
});
layout.valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT);
layout.valueAnimator.setDuration(250);
layout.valueAnimator.setStartDelay((animatedLayouts.size() - 1 - i) * 60L);
layout.valueAnimator.start();
}
}
private void checkAnimationComplete() {
for (int i = 0; i < animatedLayouts.size(); i++) {
if (animatedLayouts.get(i).valueAnimator != null) {
@ -572,8 +736,14 @@ public class LimitPreviewView extends LinearLayout {
invalidate();
}
public void setText(CharSequence text) {
this.text = text;
public void setText(CharSequence text, boolean animated) {
if (!animated) {
this.text = text;
} else {
CharSequence oldText = this.text;
this.text = text;
createAnimationLayoutsDiff(oldText);
}
}
public void setArrowCenter(float v) {
@ -585,6 +755,7 @@ public class LimitPreviewView extends LinearLayout {
}
private class AnimatedLayout {
public boolean replace;
ArrayList<StaticLayout> staticLayouts = new ArrayList<>();
float progress;
public boolean direction;

View file

@ -1,26 +1,41 @@
package org.telegram.ui.Components.Premium;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.transition.TransitionManager;
import android.transition.TransitionSet;
import android.transition.TransitionValues;
import android.transition.Visibility;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.checkerframework.checker.units.qual.A;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChannelBoostsController;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.LocaleController;
@ -37,14 +52,22 @@ import org.telegram.ui.Cells.AdminedChannelCell;
import org.telegram.ui.Cells.GroupCreateUserCell;
import org.telegram.ui.Cells.HeaderCell;
import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.ChatActivity;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.BottomSheetWithRecyclerListView;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.Components.ColoredImageSpan;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.FireworksOverlay;
import org.telegram.ui.Components.FlickerLoadingView;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RecyclerItemsEnterAnimator;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.ScaleStateListAnimator;
import org.telegram.ui.LaunchActivity;
import org.telegram.ui.PremiumPreviewFragment;
import org.telegram.ui.Stories.ChannelBoostUtilities;
import java.util.ArrayList;
import java.util.HashSet;
@ -71,10 +94,16 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
public static final int TYPE_STORIES_WEEK = 15;
public static final int TYPE_STORIES_MONTH = 16;
public static final int TYPE_BOOSTS = 17;
public static final int TYPE_BOOSTS_FOR_POSTING = 18;
public static final int TYPE_BOOSTS_FOR_USERS = 19;
private boolean canSendLink;
private int linkRow = -1;
private long dialogId;
private TLRPC.TL_stories_boostsStatus boostsStatus;
private ChannelBoostsController.CanApplyBoost canApplyBoost;
private HeaderView headerView;
private boolean isCurrentChat;
public static String limitTypeToServerString(int type) {
switch (type) {
@ -135,6 +164,8 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
LimitParams limitParams;
private boolean isVeryLargeFile;
private TLRPC.Chat fromChat;
FireworksOverlay fireworksOverlay;
Runnable statisticClickRunnable;
public LimitReachedBottomSheet(BaseFragment fragment, Context context, int type, int currentAccount, Theme.ResourcesProvider resourcesProvider) {
super(fragment, false, hasFixedSize(type), false, resourcesProvider);
@ -150,6 +181,10 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
loadInactiveChannels();
}
updatePremiumButtonText();
if (type == TYPE_BOOSTS_FOR_USERS) {
fireworksOverlay = new FireworksOverlay(getContext());
container.addView(fireworksOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
}
}
@Override
@ -209,6 +244,125 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
if (type == TYPE_ADD_MEMBERS_RESTRICTED) {
return;
}
if (type == TYPE_BOOSTS_FOR_USERS) {
canApplyBoost.checkTime();
if (!UserConfig.getInstance(currentAccount).isPremium()) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(LocaleController.getString("PremiumNeeded", R.string.PremiumNeeded));
builder.setSubtitle(AndroidUtilities.replaceTags(LocaleController.getString("PremiumNeededForBoosting", R.string.PremiumNeededForBoosting)));
builder.setPositiveButton(LocaleController.getString("CheckPhoneNumberYes", R.string.CheckPhoneNumberYes), (dialog, which) -> {
PremiumFeatureBottomSheet featureBottomSheet = new PremiumFeatureBottomSheet(parentFragment, PremiumPreviewFragment.PREMIUM_FEATURE_STORIES, false);
parentFragment.showDialog(featureBottomSheet);
LimitReachedBottomSheet.this.dismiss();
dialog.dismiss();
});
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (dialog, which) -> dialog.dismiss());
builder.show();
} else if (canApplyBoost.canApply && canApplyBoost.replaceDialogId == 0) {
boostChannel();
} else if (canApplyBoost.giftedPremium) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(LocaleController.getString("CantBoostWithGiftedPremium", R.string.CantBoostWithGiftedPremium));
builder.setSubtitle(AndroidUtilities.replaceTags(LocaleController.formatString("CantBoostWithGiftedPremiumDescription ", R.string.CantBoostWithGiftedPremiumDescription)));
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> {
dialog.dismiss();
});
builder.show();
} else if (canApplyBoost.canApply) {
FrameLayout frameLayout = new FrameLayout(getContext());
BackupImageView fromAvatar = new BackupImageView(getContext());
fromAvatar.setRoundRadius(AndroidUtilities.dp(30));
frameLayout.addView(fromAvatar, LayoutHelper.createFrame(60, 60));
frameLayout.setClipChildren(false);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Theme.getColor(Theme.key_dialogBackground));
Drawable boostDrawable = ContextCompat.getDrawable(getContext(), R.drawable.filled_limit_boost);
View boostIcon = new View(getContext()) {
@Override
protected void onDraw(Canvas canvas) {
float cx = getMeasuredWidth() / 2f;
float cy = getMeasuredHeight() / 2f;
canvas.drawCircle(cx, cy, getMeasuredWidth() / 2f, paint);
PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -AndroidUtilities.dp(10), 0);
canvas.drawCircle(cx, cy, getMeasuredWidth() / 2f - AndroidUtilities.dp(2), PremiumGradient.getInstance().getMainGradientPaint());
float iconSizeHalf = AndroidUtilities.dp(18) / 2f;
boostDrawable.setBounds(
(int) (cx - iconSizeHalf),
(int) (cy - iconSizeHalf),
(int) (cx + iconSizeHalf),
(int) (cy + iconSizeHalf)
);
boostDrawable.draw(canvas);
}
};
frameLayout.addView(boostIcon, LayoutHelper.createFrame(28, 28, 0, 34, 34, 0, 0));
ImageView imageView = new ImageView(getContext());
imageView.setImageResource(R.drawable.msg_arrow_avatar);
imageView.setColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon));
frameLayout.addView(imageView, LayoutHelper.createFrame(24, 24, Gravity.CENTER));
BackupImageView toAvatar = new BackupImageView(getContext());
toAvatar.setRoundRadius(AndroidUtilities.dp(30));
frameLayout.addView(toAvatar, LayoutHelper.createFrame(60, 60, 0, 60 + 36, 0, 0, 0));
FrameLayout containerLayout = new FrameLayout(getContext());
containerLayout.addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 60, Gravity.CENTER_HORIZONTAL));
containerLayout.setClipChildren(false);
TextView textView = new TextView(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
textView.setLetterSpacing(0.025f);
}
textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
containerLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 24, 80, 24, 0));
AvatarDrawable fromAvatarDrawable = new AvatarDrawable();
TLRPC.Chat fromChat = MessagesController.getInstance(currentAccount).getChat(-canApplyBoost.replaceDialogId);
fromAvatarDrawable.setInfo(fromChat);
fromAvatar.setForUserOrChat(fromChat, fromAvatarDrawable);
AvatarDrawable toAvatarDrawable = new AvatarDrawable();
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId);
toAvatarDrawable.setInfo(chat);
toAvatar.setForUserOrChat(chat, toAvatarDrawable);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setView(containerLayout);
textView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("ReplaceBoostChannelDescription", R.string.ReplaceBoostChannelDescription,fromChat.title, chat.title)));
builder.setPositiveButton(LocaleController.getString("Replace", R.string.Replace), (dialog, which) -> {
dialog.dismiss();
boostChannel();
});
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (dialog, which) -> dialog.dismiss());
builder.show();
} else if (canApplyBoost.floodWait != 0) {
String timeString;
int time = canApplyBoost.floodWait;
if (time < 60) {
timeString = LocaleController.formatPluralString("Seconds", time);
} else if (time < 60 * 60){
timeString = LocaleController.formatPluralString("Minutes", time / 60);
} else if (time / 60 / 60 > 2) {
timeString = LocaleController.formatPluralString("Hours", time / 60 / 60);
} else {
timeString = LocaleController.formatPluralString("Hours", time / 60 / 60) + " " + LocaleController.formatPluralString("Minutes", time % 60);
}
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(LocaleController.getString("CantBoostTooOften", R.string.CantBoostTooOften));
builder.setSubtitle(AndroidUtilities.replaceTags(LocaleController.formatString("CantBoostTooOftenDescription", R.string.CantBoostTooOftenDescription, timeString)));
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> {
dialog.dismiss();
});
builder.show();
}
return;
}
if (type == TYPE_BOOSTS_FOR_POSTING) {
AndroidUtilities.addToClipboard(getBoostLink());
dismiss();
return;
}
if (UserConfig.getInstance(currentAccount).isPremium() || MessagesController.getInstance(currentAccount).premiumLocked || isVeryLargeFile) {
dismiss();
return;
@ -226,6 +380,10 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
dismiss();
});
premiumButtonView.overlayTextView.setOnClickListener(v -> {
if (type == TYPE_BOOSTS_FOR_USERS) {
dismiss();
return;
}
if (type == TYPE_ADD_MEMBERS_RESTRICTED) {
if (selectedChats.isEmpty()) {
dismiss();
@ -246,6 +404,49 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
enterAnimator = new RecyclerItemsEnterAnimator(recyclerListView, true);
}
private void boostChannel() {
TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(new Visibility() {
@Override
public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) {
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(view, View.ALPHA, 0, 1f),
ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, AndroidUtilities.dp(20), 0)
);
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
return set;
}
@Override
public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues) {
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(view, View.ALPHA, view.getAlpha(), 0f),
ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, 0, -AndroidUtilities.dp(20))
);
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
return set;
}
});
transitionSet.setOrdering(TransitionSet.ORDERING_TOGETHER);
TransitionManager.beginDelayedTransition(headerView, transitionSet);
MessagesController.getInstance(currentAccount).getBoostsController().applyBoost(dialogId);
limitPreviewView.increaseCurrentValue((boostsStatus.boosts + 1) - boostsStatus.next_level_boosts * boostsStatus.level, boostsStatus.next_level_boosts - boostsStatus.next_level_boosts * boostsStatus.level);
boostsStatus.boosts++;
if (boostsStatus.next_level_boosts == boostsStatus.boosts) {
boostsStatus.level += 1;
boostsStatus.current_level_boosts = boostsStatus.boosts;
}
canApplyBoost.alreadyActive = true;
headerView.recreateTitleAndDescription();
headerView.title.setText(getBoostsTitleString());
headerView.description.setText(AndroidUtilities.replaceTags(getBoostsDescriptionString()));
updateButton();
fireworksOverlay.start();
fireworksOverlay.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
}
private void sendInviteMessages() {
String link = null;
TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(fromChat.id);
@ -267,7 +468,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
}
AndroidUtilities.runOnUIThread(() -> {
BulletinFactory factory = BulletinFactory.global();
if (factory != null) {
if (factory != null) {
if (selectedChats.size() == 1) {
TLRPC.User user = (TLRPC.User) selectedChats.iterator().next();
factory.createSimpleBulletin(R.raw.voip_invite,
@ -284,7 +485,14 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
}
public void updatePremiumButtonText() {
if (UserConfig.getInstance(currentAccount).isPremium() || MessagesController.getInstance(currentAccount).premiumLocked || isVeryLargeFile) {
if (type == TYPE_BOOSTS_FOR_USERS) {
premiumButtonView.buttonTextView.setText(LocaleController.getString("BoostChannel", R.string.BoostChannel));
} else if (type == TYPE_BOOSTS_FOR_POSTING) {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder("d ");
spannableStringBuilder.setSpan(new ColoredImageSpan(R.drawable.msg_copy_filled), 0, 1, 0);
spannableStringBuilder.append(LocaleController.getString("CopyLink", R.string.CopyLink));
premiumButtonView.buttonTextView.setText(spannableStringBuilder);
} else if (UserConfig.getInstance(currentAccount).isPremium() || MessagesController.getInstance(currentAccount).premiumLocked || isVeryLargeFile) {
premiumButtonView.buttonTextView.setText(LocaleController.getString("OK", R.string.OK));
premiumButtonView.hideIcon();
} else {
@ -293,9 +501,9 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
if (limitParams.defaultLimit + 1 == limitParams.premiumLimit) {
premiumButtonView.setIcon(R.raw.addone_icon);
} else if (
limitParams.defaultLimit != 0 && limitParams.premiumLimit != 0 &&
limitParams.premiumLimit / (float) limitParams.defaultLimit >= 1.6f &&
limitParams.premiumLimit / (float) limitParams.defaultLimit <= 2.5f
limitParams.defaultLimit != 0 && limitParams.premiumLimit != 0 &&
limitParams.premiumLimit / (float) limitParams.defaultLimit >= 1.6f &&
limitParams.premiumLimit / (float) limitParams.defaultLimit <= 2.5f
) {
premiumButtonView.setIcon(R.raw.double_icon);
} else {
@ -339,7 +547,13 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
}
private void updateButton() {
if (type == TYPE_ADD_MEMBERS_RESTRICTED) {
if (type == TYPE_BOOSTS_FOR_USERS) {
if (canApplyBoost.alreadyActive) {
premiumButtonView.setOverlayText(LocaleController.getString("OK", R.string.OK), true, true);
} else {
premiumButtonView.clearOverlayText();
}
} else if (type == TYPE_ADD_MEMBERS_RESTRICTED) {
premiumButtonView.checkCounterView();
if (!canSendLink) {
premiumButtonView.setOverlayText(LocaleController.getString("Close", R.string.Close), true, true);
@ -369,7 +583,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
if (type == TYPE_PIN_DIALOGS || type == TYPE_FOLDERS || type == TYPE_CHATS_IN_FOLDER ||
type == TYPE_LARGE_FILE || type == TYPE_ACCOUNTS || type == TYPE_FOLDER_INVITES ||
type == TYPE_SHARED_FOLDERS || type == TYPE_STORIES_COUNT || type == TYPE_STORIES_WEEK ||
type == TYPE_STORIES_MONTH) {
type == TYPE_STORIES_MONTH || type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_USERS) {
return true;
}
return false;
@ -403,21 +617,35 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
case 7:
FrameLayout frameLayout = new FrameLayout(getContext());
TextView linkView = new TextView(context);
linkView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(13), AndroidUtilities.dp(40), AndroidUtilities.dp(13));
linkView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(13), AndroidUtilities.dp(50), AndroidUtilities.dp(13));
linkView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
linkView.setEllipsize(TextUtils.TruncateAt.MIDDLE);
linkView.setSingleLine(true);
frameLayout.addView(linkView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 11, 0, 11, 0));
linkView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(8), Theme.getColor(Theme.key_graySection, resourcesProvider), ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector, resourcesProvider), (int) (255 * 0.3f))));
linkView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
linkView.setOnClickListener(v -> {
AndroidUtilities.addToClipboard(getBoostLink());
});
if (statisticClickRunnable != null) {
ImageView imageView = new ImageView(getContext());
imageView.setImageResource(R.drawable.msg_stats);
imageView.setColorFilter(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider));
imageView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8));
imageView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(20), 0, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector, resourcesProvider), (int) (255 * 0.3f))));
frameLayout.addView(imageView, LayoutHelper.createFrame(40, 40 ,Gravity.RIGHT | Gravity.CENTER_VERTICAL, 15, 0, 15, 0));
imageView.setOnClickListener(v -> {
statisticClickRunnable.run();
dismiss();
});
}
linkView.setText(getBoostLink());
linkView.setGravity(Gravity.CENTER);
view = frameLayout;
break;
default:
case 0:
view = new HeaderView(context);
view = headerView = new HeaderView(context);
break;
case 1:
view = new AdminedChannelCell(context, new View.OnClickListener() {
@ -532,8 +760,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
}
private String getBoostLink() {
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId);
return "https://" + ChatObject.getPublicUsername(chat) +"?boost";
return ChannelBoostUtilities.createLink(currentAccount, dialogId);
}
public void setCurrentValue(int currentValue) {
@ -561,8 +788,25 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
this.dialogId = dialogId;
}
public void setBoostsStats(TLRPC.TL_stories_boostsStatus boostsStatus, boolean isCurrentChat) {
this.boostsStatus = boostsStatus;
this.isCurrentChat = isCurrentChat;
}
public void setCanApplyBoost(ChannelBoostsController.CanApplyBoost canApplyBoost) {
this.canApplyBoost = canApplyBoost;
updateButton();
}
public void showStatisticButtonInLink(Runnable runnable) {
this.statisticClickRunnable = runnable;
}
private class HeaderView extends LinearLayout {
TextView title;
TextView description;
@SuppressLint("SetTextI18n")
public HeaderView(Context context) {
super(context);
@ -573,7 +817,14 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
int icon = limitParams.icon;
String descriptionStr;
boolean premiumLocked = MessagesController.getInstance(currentAccount).premiumLocked;
if (type == TYPE_ADD_MEMBERS_RESTRICTED) {
if (type == TYPE_BOOSTS_FOR_USERS) {
descriptionStr = getBoostsDescriptionString();
} else if (type == TYPE_BOOSTS_FOR_POSTING) {
descriptionStr = LocaleController.formatString(
"ChannelNeedBoostsDescription", R.string.ChannelNeedBoostsDescription,
LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts, boostsStatus.next_level_boosts)
);
} else if (type == TYPE_ADD_MEMBERS_RESTRICTED) {
premiumLocked = true;
if (!canSendLink) {
if (ChatObject.isChannelAndNotMegaGroup(fromChat)) {
@ -654,21 +905,31 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
percent = defaultLimit / (float) premiumLimit;
if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_USERS) {
currentValue = 0;
}
limitPreviewView = new LimitPreviewView(context, icon, currentValue, premiumLimit, percent, resourcesProvider);
limitPreviewView.setBagePosition(position);
limitPreviewView.setType(type);
limitPreviewView.defaultCount.setVisibility(View.GONE);
if (premiumLocked) {
limitPreviewView.setPremiumLocked();
if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_USERS) {
if (boostsStatus != null) {
limitPreviewView.setBoosts(boostsStatus, canApplyBoost != null && canApplyBoost.alreadyActive);
}
} else {
if (UserConfig.getInstance(currentAccount).isPremium() || isVeryLargeFile) {
limitPreviewView.premiumCount.setVisibility(View.GONE);
if (type == TYPE_LARGE_FILE) {
limitPreviewView.defaultCount.setText("2 GB");
} else {
limitPreviewView.defaultCount.setText(Integer.toString(defaultLimit));
limitPreviewView.setBagePosition(position);
limitPreviewView.setType(type);
limitPreviewView.defaultCount.setVisibility(View.GONE);
if (premiumLocked) {
limitPreviewView.setPremiumLocked();
} else {
if (UserConfig.getInstance(currentAccount).isPremium() || isVeryLargeFile) {
limitPreviewView.premiumCount.setVisibility(View.GONE);
if (type == TYPE_LARGE_FILE) {
limitPreviewView.defaultCount.setText("2 GB");
} else {
limitPreviewView.defaultCount.setText(Integer.toString(defaultLimit));
}
limitPreviewView.defaultCount.setVisibility(View.VISIBLE);
}
limitPreviewView.defaultCount.setVisibility(View.VISIBLE);
}
}
@ -676,12 +937,15 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
limitPreviewView.setDelayedAnimation();
}
addView(limitPreviewView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 0, 0, 0));
TextView title = new TextView(context);
title = new TextView(context);
title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
if (type == TYPE_ADD_MEMBERS_RESTRICTED) {
if (type == TYPE_BOOSTS_FOR_USERS) {
title.setText(getBoostsTitleString());
} else if (type == TYPE_BOOSTS_FOR_POSTING) {
title.setText(LocaleController.getString("BoostingEnableStories", R.string.BoostingEnableStories));
} else if (type == TYPE_ADD_MEMBERS_RESTRICTED) {
if (canSendLink) {
title.setText(LocaleController.getString("ChannelInviteViaLink", R.string.ChannelInviteViaLink));
} else {
@ -694,9 +958,35 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
}
title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
title.setGravity(Gravity.CENTER);
addView(title, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, premiumLocked ? 8 : 22, 0, 10));
TextView description = new TextView(context);
if (type == TYPE_BOOSTS_FOR_USERS && !isCurrentChat) {
FrameLayout frameLayout = new FrameLayout(getContext());
frameLayout.setBackground(Theme.createRoundRectDrawable(AndroidUtilities.dp(14), Theme.getColor(Theme.key_windowBackgroundGray)));
BackupImageView backupImageView = new BackupImageView(getContext());
backupImageView.setRoundRadius(AndroidUtilities.dp(14));
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId);
AvatarDrawable avatarDrawable = new AvatarDrawable();
avatarDrawable.setInfo(chat);
backupImageView.setForUserOrChat(chat, avatarDrawable);
frameLayout.addView(backupImageView, LayoutHelper.createFrame(28, 28));
TextView textView = new TextView(getContext());
textView.setText(chat.title);
textView.setSingleLine(true);
textView.setMaxLines(1);
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 36, 0, 8, 0));
addView(frameLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 28, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 12));
ScaleStateListAnimator.apply(frameLayout);
frameLayout.setOnClickListener(v -> {
getBaseFragment().presentFragment(ChatActivity.of(dialogId));
dismiss();
});
}
description = new TextView(context);
description.setText(AndroidUtilities.replaceTags(descriptionStr));
description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
description.setGravity(Gravity.CENTER_HORIZONTAL);
@ -705,6 +995,86 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
updatePremiumButtonText();
}
public void recreateTitleAndDescription() {
int titleIndex = indexOfChild(title);
int descriptionIndex = indexOfChild(description);
removeView(title);
title = new TextView(getContext());
title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
title.setGravity(Gravity.CENTER);
addView(title, titleIndex, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 22, 0, 10));
removeView(description);
description = new TextView(getContext());
description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
description.setGravity(Gravity.CENTER_HORIZONTAL);
description.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
addView(description, descriptionIndex, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 24, 0, 24, 24));
}
}
private String getBoostsTitleString() {
if (boostsStatus.level > 0 && !canApplyBoost.alreadyActive) {
return LocaleController.getString("HelpUpgradeChannel", R.string.HelpUpgradeChannel);
} else if (boostsStatus.next_level_boosts == 0) {
return LocaleController.formatString("BoostsMaxLevelReached", R.string.BoostsMaxLevelReached);
} else if (isCurrentChat) {
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId);
if (canApplyBoost.alreadyActive) {
return LocaleController.formatString("YouBoostedChannel2", R.string.YouBoostedChannel2, chat.title);
} else {
return LocaleController.formatString("BoostingEnableStoriesForChannel2", R.string.BoostingEnableStoriesForChannel2, chat.title);
}
} else {
if (canApplyBoost.alreadyActive) {
return LocaleController.getString("YouBoostedChannel", R.string.YouBoostedChannel);
} else {
return LocaleController.getString("BoostingEnableStoriesForChannel", R.string.BoostingEnableStoriesForChannel);
}
}
}
private String getBoostsDescriptionString() {
boolean isZeroBoostsForNextLevel = boostsStatus.boosts == boostsStatus.current_level_boosts;
if (isZeroBoostsForNextLevel && canApplyBoost.alreadyActive) {
if (boostsStatus.level == 1) {
return LocaleController.formatString("ChannelBoostsJustReachedLevel1", R.string.ChannelBoostsJustReachedLevel1);
} else {
return LocaleController.formatString("ChannelBoostsJustReachedLevelNext", R.string.ChannelBoostsJustReachedLevelNext,
boostsStatus.level,
LocaleController.formatPluralString("BoostStories", boostsStatus.level));
}
} else {
if (canApplyBoost.alreadyActive) {
if (boostsStatus.level == 0) {
return LocaleController.formatString(
"ChannelNeedBoostsAlreadyBoostedDescriptionLevel1", R.string.ChannelNeedBoostsAlreadyBoostedDescriptionLevel1,
LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts)
);
} else {
return LocaleController.formatString("ChannelNeedBoostsDescriptionLevelNext", R.string.ChannelNeedBoostsDescriptionLevelNext,
LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts),
LocaleController.formatPluralString("BoostStories", boostsStatus.level)
);
}
} else {
if (boostsStatus.level == 0) {
return LocaleController.formatString(
"ChannelNeedBoostsDescriptionLevel1", R.string.ChannelNeedBoostsDescriptionLevel1,
LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts)
);
} else {
return LocaleController.formatString("ChannelNeedBoostsDescriptionLevelNext", R.string.ChannelNeedBoostsDescriptionLevelNext,
LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts),
LocaleController.formatPluralString("BoostStories", boostsStatus.level)
);
}
}
}
}
private static LimitParams getLimitParams(int type, int currentAccount) {
@ -800,6 +1170,13 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
limitParams.descriptionStr = LocaleController.formatString("LimitReachedStoriesMonthly", R.string.LimitReachedStoriesMonthly, limitParams.defaultLimit, limitParams.premiumLimit);
limitParams.descriptionStrPremium = LocaleController.formatString("LimitReachedStoriesMonthlyPremium", R.string.LimitReachedStoriesMonthlyPremium, limitParams.premiumLimit);
limitParams.descriptionStrLocked = LocaleController.formatString("LimitReachedStoriesMonthlyPremium", R.string.LimitReachedStoriesMonthlyPremium, limitParams.defaultLimit);
} else if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_USERS) {
limitParams.defaultLimit = MessagesController.getInstance(currentAccount).storiesSentMonthlyLimitDefault;
limitParams.premiumLimit = MessagesController.getInstance(currentAccount).storiesSentMonthlyLimitPremium;
limitParams.icon = R.drawable.filled_limit_boost;
limitParams.descriptionStr = LocaleController.formatString("LimitReachedStoriesMonthly", R.string.LimitReachedStoriesMonthly, limitParams.defaultLimit, limitParams.premiumLimit);
limitParams.descriptionStrPremium = LocaleController.formatString("LimitReachedStoriesMonthlyPremium", R.string.LimitReachedStoriesMonthlyPremium, limitParams.premiumLimit);
limitParams.descriptionStrLocked = LocaleController.formatString("LimitReachedStoriesMonthlyPremium", R.string.LimitReachedStoriesMonthlyPremium, limitParams.defaultLimit);
}
return limitParams;
}
@ -833,7 +1210,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
}
int currentValue = Math.max(chats.size(), limitParams.defaultLimit);
limitPreviewView.setIconValue(currentValue);
limitPreviewView.setIconValue(currentValue, false);
limitPreviewView.setBagePosition(currentValue / (float) limitParams.premiumLimit);
limitPreviewView.startDelayedAnimation();
}));
@ -868,6 +1245,9 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
}
}
}
if (type == TYPE_BOOSTS_FOR_POSTING) {
linkRow = rowCount++;
}
notifyDataSetChanged();
}
@ -976,7 +1356,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView {
}
int currentValue = Math.max(inactiveChats.size(), limitParams.defaultLimit);
if (limitPreviewView != null) {
limitPreviewView.setIconValue(currentValue);
limitPreviewView.setIconValue(currentValue, false);
limitPreviewView.setBagePosition(currentValue / (float) limitParams.premiumLimit);
limitPreviewView.startDelayedAnimation();
}

View file

@ -1365,15 +1365,23 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable, Bitma
}
private int rawBackgroundBitmapFrame = -1;
public void drawFrame(Canvas canvas, int frame) {
if (rawBackgroundBitmapFrame != frame || backgroundBitmap == null) {
if (backgroundBitmap == null) {
backgroundBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
private Bitmap rawBackgroundBitmap;
public void cacheFrame(int frame) {
if (rawBackgroundBitmapFrame != frame || rawBackgroundBitmap == null) {
if (rawBackgroundBitmap == null) {
rawBackgroundBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
}
int result = getFrame(nativePtr, rawBackgroundBitmapFrame = frame, backgroundBitmap, width, height, backgroundBitmap.getRowBytes(), true);
int result = getFrame(nativePtr, rawBackgroundBitmapFrame = frame, rawBackgroundBitmap, width, height, rawBackgroundBitmap.getRowBytes(), true);
}
}
public void drawFrame(Canvas canvas, int frame) {
cacheFrame(frame);
if (rawBackgroundBitmap != null) {
AndroidUtilities.rectTmp2.set(0, 0, width, height);
canvas.drawBitmap(rawBackgroundBitmap, AndroidUtilities.rectTmp2, getBounds(), getPaint());
}
AndroidUtilities.rectTmp2.set(0, 0, width, height);
canvas.drawBitmap(backgroundBitmap, AndroidUtilities.rectTmp2, getBounds(), getPaint());
}
@Override

View file

@ -342,19 +342,21 @@ public class ChatSelectionReactionMenuOverlay extends FrameLayout {
private void animateVisible(boolean visible) {
if (visible) {
currentPrimaryObject = findPrimaryObject();
checkCreateReactionsLayout();
invalidatePosition(false);
setVisibility(VISIBLE);
if (reactionsContainerLayout.isEnabled()) {
messageSet = true;
reactionsContainerLayout.setMessage(currentPrimaryObject, parentFragment.getCurrentChatInfo());
reactionsContainerLayout.startEnterAnimation(false);
} else {
messageSet = false;
reactionsContainerLayout.setTransitionProgress(1f);
}
post(() -> {
currentPrimaryObject = findPrimaryObject();
checkCreateReactionsLayout();
invalidatePosition(false);
if (reactionsContainerLayout.isEnabled()) {
messageSet = true;
reactionsContainerLayout.setMessage(currentPrimaryObject, parentFragment.getCurrentChatInfo());
reactionsContainerLayout.startEnterAnimation(false);
} else {
messageSet = false;
reactionsContainerLayout.setTransitionProgress(1f);
}
});
} else {
messageSet = false;
ValueAnimator animator = ValueAnimator.ofFloat(1, 0).setDuration(150);

View file

@ -258,10 +258,10 @@ public class CustomEmojiReactionsWindow {
containerView.addView(selectAnimatedEmojiDialog, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 0, 0));
windowView.addView(containerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 16, 16, 16, 16));
windowView.setClipChildren(false);
if (type == TYPE_STORY) {
if (type == TYPE_STORY || (reactionsContainerLayout.getDelegate() != null && reactionsContainerLayout.getDelegate().drawBackground())) {
selectAnimatedEmojiDialog.setBackgroundDelegate((canvas, left, top, right, bottom, x, y) -> {
AndroidUtilities.rectTmp.set(left, top, right, bottom);
reactionsContainerLayout.getDelegate().drawRoundRect(canvas, AndroidUtilities.rectTmp, 0, containerView.getX() + x, containerView.getY() - AndroidUtilities.statusBarHeight + y);
reactionsContainerLayout.getDelegate().drawRoundRect(canvas, AndroidUtilities.rectTmp, 0, containerView.getX() + x, getBlurOffset() + y, 255,true);
});
}
if (attachToParent) {
@ -715,7 +715,7 @@ public class CustomEmojiReactionsWindow {
@Override
public void invalidate() {
super.invalidate();
if (type == TYPE_STORY) {
if (type == TYPE_STORY || (reactionsContainerLayout != null && reactionsContainerLayout.getDelegate() != null && reactionsContainerLayout.getDelegate().drawBackground())) {
selectAnimatedEmojiDialog.invalidateSearchBox();
}
}
@ -759,8 +759,8 @@ public class CustomEmojiReactionsWindow {
transitionReactions.clear();
if (type == TYPE_STORY) {
reactionsContainerLayout.getDelegate().drawRoundRect(canvas, drawingRect, radius, getX(), getY() - AndroidUtilities.statusBarHeight);
if (type == TYPE_STORY || (reactionsContainerLayout.getDelegate() != null && reactionsContainerLayout.getDelegate().drawBackground())) {
reactionsContainerLayout.getDelegate().drawRoundRect(canvas, drawingRect, radius, getX(), getBlurOffset(), 255, true);
} else {
shadow.setAlpha((int) (Utilities.clamp(progressClpamped / 0.05f, 1f, 0f) * 255));
shadow.setBounds((int) drawingRect.left - shadowPad.left, (int) drawingRect.top - shadowPad.top, (int) drawingRect.right + shadowPad.right, (int) drawingRect.bottom + shadowPad.bottom);

View file

@ -31,9 +31,12 @@ public class ReactionImageHolder {
ReactionsLayoutInBubble.VisibleReaction reaction;
private final int currentAccount = UserConfig.selectedAccount;
ReactionsLayoutInBubble.VisibleReaction currentReaction;
private final View parent;
private View parent;
private boolean attached;
float alpha = 1f;
private boolean isStatic;
int lastColorForFilter;
ColorFilter colorFilter;
public ReactionImageHolder(View parent) {
this.parent = parent;
@ -52,20 +55,28 @@ public class ReactionImageHolder {
}
this.currentReaction = currentReaction;
String filter = "60_60";
if (isStatic) {
filter += "_firstframe";
}
if (currentReaction.emojicon != null) {
TLRPC.TL_availableReaction defaultReaction = MediaDataController.getInstance(currentAccount).getReactionsMap().get(currentReaction.emojicon);
if (defaultReaction != null) {
SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(defaultReaction.select_animation, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f);
imageReceiver.setImage(ImageLocation.getForDocument(defaultReaction.select_animation), "60_60", null, null, svgThumb, 0, "tgs", currentReaction, 0);
imageReceiver.setImage(ImageLocation.getForDocument(defaultReaction.select_animation), filter, null, null, svgThumb, 0, "tgs", currentReaction, 0);
// imageReceiver.setAllowStartAnimation(false);
// imageReceiver.setAutoRepeatCount(1);
}
} else {
animatedEmojiDrawable = new AnimatedEmojiDrawable(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES_LARGE, UserConfig.selectedAccount, currentReaction.documentId);
int type = AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES_LARGE;
if (isStatic) {
type = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW_STATIC;
}
animatedEmojiDrawable = new AnimatedEmojiDrawable(type, UserConfig.selectedAccount, currentReaction.documentId);
if (attached) {
animatedEmojiDrawable.addView(parent);
}
animatedEmojiDrawable.setColorFilter(new PorterDuffColorFilter(Color.BLACK, PorterDuff.Mode.SRC_ATOP));
animatedEmojiDrawable.setColorFilter(colorFilter = new PorterDuffColorFilter(lastColorForFilter = Color.BLACK, PorterDuff.Mode.SRC_ATOP));
}
}
@ -74,6 +85,7 @@ public class ReactionImageHolder {
if (animatedEmojiDrawable.getImageReceiver() != null) {
animatedEmojiDrawable.getImageReceiver().setRoundRadius((int) (bounds.width() * 0.1f));
}
animatedEmojiDrawable.setColorFilter(colorFilter);
animatedEmojiDrawable.setBounds(bounds);
animatedEmojiDrawable.setAlpha((int) (255 * alpha));
animatedEmojiDrawable.draw(canvas);
@ -110,4 +122,32 @@ public class ReactionImageHolder {
public void play() {
imageReceiver.startAnimation();
}
public void setParent(View parentView) {
if (this.parent == parentView) {
return;
}
if (attached) {
onAttachedToWindow(false);
this.parent = parentView;
onAttachedToWindow(true);
} else {
this.parent = parentView;
}
}
public void setStatic() {
isStatic = true;
}
public void setColor(int color) {
if (lastColorForFilter != color) {
lastColorForFilter = color;
colorFilter = new PorterDuffColorFilter(lastColorForFilter, PorterDuff.Mode.SRC_ATOP);
if (parent != null) {
parent.invalidate();
}
}
}
}

View file

@ -56,4 +56,36 @@ public class ReactionsUtils {
}
return "";
}
public static void applyForStoryViews(TLRPC.Reaction oldReaction, TLRPC.Reaction newReaction, TLRPC.StoryViews views) {
boolean found = false;
if (views == null) {
return;
}
for (int i = 0; i < views.reactions.size(); i++) {
TLRPC.ReactionCount reactionCount = views.reactions.get(i);
if (oldReaction != null) {
if (compare(reactionCount.reaction, oldReaction)) {
reactionCount.count--;
if (reactionCount.count <= 0) {
views.reactions.remove(i);
i--;
continue;
}
}
}
if (newReaction != null) {
if (compare(reactionCount.reaction, newReaction)) {
reactionCount.count++;
found = true;
}
}
}
if (!found) {
TLRPC.ReactionCount reactionCount = new TLRPC.TL_reactionCount();
reactionCount.count = 1;
reactionCount.reaction = newReaction;
views.reactions.add(reactionCount);
}
}
}

View file

@ -716,8 +716,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
float sc = transitionProgress;
canvas.scale(sc, sc, pivotX, getHeight() / 2f);
}
if (type == TYPE_STORY) {
delegate.drawRoundRect(canvas, rect, radius, getX(), getY());
if (type == TYPE_STORY || delegate.drawBackground()) {
delegate.drawRoundRect(canvas, rect, radius, getX(), getY(), 255, false);
} else {
canvas.drawRoundRect(rect, radius, radius, bgPaint);
}
@ -887,7 +887,12 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
bgPaint.setAlpha(alpha);
shadow.setBounds((int) (cx - br - sPad * cPr), (int) (cy - br - sPad * cPr), (int) (cx + br + sPad * cPr), (int) (cy + br + sPad * cPr));
shadow.draw(canvas);
canvas.drawCircle(cx, cy, br, bgPaint);
if (delegate.drawBackground()) {
rectF.set(cx - br, cy - br, cx + br, cy + br);
delegate.drawRoundRect(canvas, rectF, br, getX(), getY(), alpha, false);
} else {
canvas.drawCircle(cx, cy, br, bgPaint);
}
cx = LocaleController.isRTL || mirrorX ? bigCircleOffset - bigCircleRadius : getWidth() - bigCircleOffset + bigCircleRadius;
cx += bubblesOffset;
@ -896,7 +901,12 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
sPad = -AndroidUtilities.dp(1);
shadow.setBounds((int) (cx - br - sPad * cPr), (int) (cy - br - sPad * cPr), (int) (cx + br + sPad * cPr), (int) (cy + br + sPad * cPr));
shadow.draw(canvas);
canvas.drawCircle(cx, cy, sr, bgPaint);
if (delegate.drawBackground()) {
rectF.set(cx - sr, cy - sr, cx + sr, cy + sr);
delegate.drawRoundRect(canvas, rectF, sr, getX(), getY(), alpha, false);
} else {
canvas.drawCircle(cx, cy, sr, bgPaint);
}
canvas.restore();
shadow.setAlpha(255);
@ -1868,7 +1878,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
}
default void drawRoundRect(Canvas canvas, RectF rect, float radius, float offsetX, float offsetY) {
default void drawRoundRect(Canvas canvas, RectF rect, float radius, float offsetX, float offsetY, int alpha, boolean isWindow) {
}
@ -1879,6 +1889,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio
default void onEmojiWindowDismissed() {
}
default boolean drawBackground() {
return false;
}
}
@Override

View file

@ -1263,7 +1263,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
int[] mediaCount = preloader.getLastMediaCount();
topicId = sharedMediaPreloader.topicId;
hasMedia = new int[]{mediaCount[0], mediaCount[1], mediaCount[2], mediaCount[3], mediaCount[4], mediaCount[5], topicId == 0 ? commonGroupsCount : 0};
if (userInfo != null && userInfo.stories_pinned_available || isStoriesView()) {
if (userInfo != null && userInfo.stories_pinned_available || chatInfo != null && chatInfo.stories_pinned_available || isStoriesView()) {
initialTab = getInitialTab();
} else if (membersFirst && topicId == 0) {
initialTab = TAB_GROUPUSERS;
@ -1497,6 +1497,28 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
}
});
if (info != null && !isStoriesView()) {
TLRPC.Chat chat = MessagesController.getInstance(profileActivity.getCurrentAccount()).getChat(info.id);
if (chat != null && chat.admin_rights != null && chat.admin_rights.edit_stories) {
ActionBarMenuSubItem openArchiveItem = new ActionBarMenuSubItem(context, false, true, resourcesProvider);
openArchiveItem.setTextAndIcon(LocaleController.getString(R.string.OpenChannelArchiveStories), R.drawable.msg_archive);
openArchiveItem.setOnClickListener(e -> {
Bundle args = new Bundle();
args.putInt("type", MediaActivity.TYPE_ARCHIVED_CHANNEL_STORIES);
args.putLong("dialog_id", -info.id);
MediaActivity fragment = new MediaActivity(args, null);
fragment.setChatInfo(info);
profileActivity.presentFragment(fragment);
if (optionsWindow != null) {
optionsWindow.dismiss();
}
});
popupLayout.addView(openArchiveItem);
}
}
if (hasDifferentTypes) {
popupLayout.addView(dividerView);
ActionBarMenuSubItem showPhotosItem = new ActionBarMenuSubItem(context, true, false, false, resourcesProvider);
@ -4717,6 +4739,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
}
public void setChatInfo(TLRPC.ChatFull chatInfo) {
boolean stories_pinned_available = this.info != null && this.info.stories_pinned_available;
info = chatInfo;
if (info != null && info.migrated_from_chat_id != 0 && mergeDialogId == 0) {
mergeDialogId = -info.migrated_from_chat_id;
@ -4725,6 +4748,13 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
sharedMediaData[a].endReached[1] = false;
}
}
if (info != null && (stories_pinned_available != info.stories_pinned_available)) {
if (scrollSlidingTextTabStrip != null) {
scrollSlidingTextTabStrip.setInitialTabId(isArchivedOnlyStoriesView() ? TAB_ARCHIVED_STORIES : TAB_STORIES);
}
updateTabs(true);
switchToCurrentSelectedMode(false);
}
}
public void setUserInfo(TLRPC.UserFull userInfo) {
@ -4813,7 +4843,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
animated = false;
}
int changed = 0;
if ((DialogObject.isUserDialog(dialog_id) && !DialogObject.isEncryptedDialog(dialog_id) && (userInfo != null && userInfo.stories_pinned_available || isStoriesView()) && includeStories()) != scrollSlidingTextTabStrip.hasTab(TAB_STORIES)) {
if (((DialogObject.isUserDialog(dialog_id) || DialogObject.isChatDialog(dialog_id)) && !DialogObject.isEncryptedDialog(dialog_id) && (userInfo != null && userInfo.stories_pinned_available || info != null && info.stories_pinned_available || isStoriesView()) && includeStories()) != scrollSlidingTextTabStrip.hasTab(TAB_STORIES)) {
changed++;
}
if (!isStoriesView()) {
@ -4887,15 +4917,22 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter
if (changed > 3) {
idToView = null;
}
if (DialogObject.isUserDialog(dialog_id) && !DialogObject.isEncryptedDialog(dialog_id) && (userInfo != null && userInfo.stories_pinned_available || isStoriesView()) && includeStories()) {
if (!scrollSlidingTextTabStrip.hasTab(TAB_STORIES)) {
scrollSlidingTextTabStrip.addTextTab(TAB_STORIES, LocaleController.getString("ProfileStories", R.string.ProfileStories), idToView);
}
if (isStoriesView()) {
if ((DialogObject.isUserDialog(dialog_id) || DialogObject.isChatDialog(dialog_id)) && !DialogObject.isEncryptedDialog(dialog_id) && (userInfo != null && userInfo.stories_pinned_available || info != null && info.stories_pinned_available || isStoriesView()) && includeStories()) {
if (isArchivedOnlyStoriesView()) {
if (!scrollSlidingTextTabStrip.hasTab(TAB_ARCHIVED_STORIES)) {
scrollSlidingTextTabStrip.addTextTab(TAB_ARCHIVED_STORIES, LocaleController.getString("ProfileStories", R.string.ProfileStories), idToView);
}
scrollSlidingTextTabStrip.animationDuration = 420;
} else {
if (!scrollSlidingTextTabStrip.hasTab(TAB_STORIES)) {
scrollSlidingTextTabStrip.addTextTab(TAB_STORIES, LocaleController.getString("ProfileStories", R.string.ProfileStories), idToView);
}
if (isStoriesView()) {
if (!scrollSlidingTextTabStrip.hasTab(TAB_ARCHIVED_STORIES)) {
scrollSlidingTextTabStrip.addTextTab(TAB_ARCHIVED_STORIES, LocaleController.getString("ProfileStories", R.string.ProfileStories), idToView);
}
scrollSlidingTextTabStrip.animationDuration = 420;
}
}
}
if (!isStoriesView()) {

View file

@ -56,7 +56,7 @@ public class ViewPagerFixed extends FrameLayout {
private Theme.ResourcesProvider resourcesProvider;
public int currentPosition;
public float currentProgress;
public float currentProgress = 1f;
int nextPosition;
protected View[] viewPages;
private int[] viewTypes;
@ -478,9 +478,9 @@ public class ViewPagerFixed extends FrameLayout {
viewPages[1].setTranslationX(animatingForward ? viewPages[0].getMeasuredWidth() : -viewPages[0].getMeasuredWidth());
}
nextPosition = 0;
currentProgress = 0;
currentProgress = 1f;
if (tabsView != null) {
tabsView.selectTab(currentPosition, 0, 0);
tabsView.selectTab(nextPosition, currentPosition, currentProgress);
}
onTabAnimationUpdate(false);
}
@ -708,6 +708,10 @@ public class ViewPagerFixed extends FrameLayout {
}
public void setPosition(int position) {
if (adapter == null) {
currentPosition = position;
onTabAnimationUpdate(false);
}
if (tabsAnimation != null) {
tabsAnimation.cancel();
}

View file

@ -65,7 +65,7 @@ public class SpoilerEffect extends Drawable {
private Stack<Particle> particlesPool = new Stack<>();
private int maxParticles;
float[][] particlePoints = new float[ALPHAS.length][MAX_PARTICLES_PER_ENTITY * 2];
float[][] particlePoints = new float[ALPHAS.length][MAX_PARTICLES_PER_ENTITY * 5];
private float[] particleRands = new float[RAND_REPEAT];
private int[] renderCount = new int[ALPHAS.length];
@ -99,6 +99,7 @@ public class SpoilerEffect extends Drawable {
private int lastColor;
public boolean drawPoints;
private static Paint xRefPaint;
private int bitmapSize;
private static int measureParticlesPerCharacter() {
switch (SharedConfig.getDevicePerformanceClass()) {
@ -320,11 +321,6 @@ public class SpoilerEffect extends Drawable {
float hdt = particle.velocity * dt / 500f;
particle.x += particle.vecX * hdt;
particle.y += particle.vecY * hdt;
int alphaIndex = particle.alpha;
particlePoints[alphaIndex][renderCount[alphaIndex] * 2] = particle.x;
particlePoints[alphaIndex][renderCount[alphaIndex] * 2 + 1] = particle.y;
renderCount[alphaIndex]++;
}
if (particles.size() < maxParticles) {
@ -358,27 +354,56 @@ public class SpoilerEffect extends Drawable {
newParticle.alpha = Utilities.fastRandom.nextInt(ALPHAS.length);
particles.add(newParticle);
int alphaIndex = newParticle.alpha;
particlePoints[alphaIndex][renderCount[alphaIndex] * 2] = newParticle.x;
particlePoints[alphaIndex][renderCount[alphaIndex] * 2 + 1] = newParticle.y;
renderCount[alphaIndex]++;
}
}
for (int a = enableAlpha ? 0 : ALPHAS.length - 1; a < ALPHAS.length; a++) {
int renderCount = 0;
int off = 0;
float paintW = particlePaints[a].getStrokeWidth() / 2f;
for (int i = 0; i < particles.size(); i++) {
Particle p = particles.get(i);
if (visibleRect != null && !visibleRect.contains(p.x, p.y) || p.alpha != a && enableAlpha) {
off++;
continue;
}
particlePoints[a][(i - off) * 2] = p.x;
particlePoints[a][(i - off) * 2 + 1] = p.y;
particlePoints[a][renderCount] = p.x;
particlePoints[a][renderCount + 1] = p.y;
renderCount += 2;
if (p.x < paintW) {
if (renderCount >= particlePoints[a].length - 2) {
continue;
}
particlePoints[a][renderCount] = p.x + bitmapSize;
particlePoints[a][renderCount + 1] = p.y;
renderCount += 2;
}
if (p.x > bitmapSize - paintW) {
if (renderCount >= particlePoints[a].length - 2) {
continue;
}
particlePoints[a][renderCount] = p.x - bitmapSize;
particlePoints[a][renderCount + 1] = p.y;
renderCount += 2;
}
if (p.y < paintW) {
if (renderCount >= particlePoints[a].length - 2) {
continue;
}
particlePoints[a][renderCount] = p.x;
particlePoints[a][renderCount + 1] = p.y + bitmapSize;
renderCount += 2;
}
if (p.y > bitmapSize - paintW) {
if (renderCount >= particlePoints[a].length - 2) {
continue;
}
particlePoints[a][renderCount] = p.x;
particlePoints[a][renderCount + 1] = p.y - bitmapSize;
renderCount += 2;
}
}
canvas.drawPoints(particlePoints[a], 0, renderCount, particlePaints[a]);
}
@ -756,6 +781,10 @@ public class SpoilerEffect extends Drawable {
}
}
public void setSize(int bitmapSize) {
this.bitmapSize = bitmapSize;
}
private static class Particle {
private float x, y;
private float vecX, vecY;

View file

@ -540,28 +540,20 @@ public class SpoilerEffect2 {
}
private void die() {
try {
if (particlesData != null) {
GLES31.glDeleteBuffers(2, particlesData, 0);
particlesData = null;
}
if (drawProgram != 0) {
GLES31.glDeleteProgram(drawProgram);
drawProgram = 0;
}
if (egl != null) {
egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
egl.eglDestroySurface(eglDisplay, eglSurface);
egl.eglDestroyContext(eglDisplay, eglContext);
}
} catch (Exception e) {
FileLog.e(e);
if (particlesData != null) {
GLES31.glDeleteBuffers(2, particlesData, 0);
particlesData = null;
}
try {
surfaceTexture.release();
} catch (Exception e) {
FileLog.e(e);
if (drawProgram != 0) {
GLES31.glDeleteProgram(drawProgram);
drawProgram = 0;
}
if (egl != null) {
egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
egl.eglDestroySurface(eglDisplay, eglSurface);
egl.eglDestroyContext(eglDisplay, eglContext);
}
surfaceTexture.release();
checkGlErrors();
}

View file

@ -59,6 +59,7 @@ public class SpoilerEffectBitmapFactory {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
SpoilerEffect shaderSpoilerEffect = new SpoilerEffect();
shaderSpoilerEffect.setSize(size);
shaderSpoilerEffect.setBounds(step * i, step * j - AndroidUtilities.dp(5), step * i + step + AndroidUtilities.dp(3), step * j + step + AndroidUtilities.dp(5));
shaderSpoilerEffect.drawPoints = true;
shaderSpoilerEffect.particlePoints = new float[SpoilerEffect.ALPHAS.length][particleCount * 2];

View file

@ -83,6 +83,8 @@ import androidx.recyclerview.widget.LinearSmoothScrollerCustom;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import com.google.android.exoplayer2.util.Log;
import org.telegram.messenger.AccountInstance;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.AnimationNotificationsLocker;
@ -197,6 +199,7 @@ import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
import org.telegram.ui.Components.RecyclerAnimationScrollHelper;
import org.telegram.ui.Components.RecyclerItemsEnterAnimator;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.ScaleStateListAnimator;
import org.telegram.ui.Components.SearchViewPager;
import org.telegram.ui.Components.SharedMediaLayout;
import org.telegram.ui.Components.SimpleThemeDescription;
@ -352,6 +355,8 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
private ActionBarMenuItem doneItem;
private ProxyDrawable proxyDrawable;
private HintView2 storyHint;
private boolean canShowStoryHint;
private boolean storyHintShown;
private RLottieImageView floatingButton;
private FrameLayout floatingButtonContainer;
private RLottieImageView floatingButton2;
@ -443,6 +448,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
private DialogsHintCell dialogsHintCell;
private UnconfirmedAuthHintCell authHintCell;
private float authHintCellProgress;
private boolean authHintCellAnimating;
private boolean dialogsHintCellVisible;
private boolean authHintCellVisible;
private Long cacheSize, deviceSize;
@ -1622,6 +1628,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
float animateFromSelectorPosition;
boolean animateSwitchingSelector;
UserListPoller poller;
public int additionalPadding;
public DialogsRecyclerView(Context context, ViewPage page) {
super(context);
@ -1959,15 +1966,24 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
if (hasStories && !actionModeFullyShowed) {
t += AndroidUtilities.dp(DialogStoriesCell.HEIGHT_IN_DP);
}
if (authHintCell != null && authHintCellProgress != 0) {
t += authHintCell.getMeasuredHeight() * authHintCellProgress;
additionalPadding = 0;
if (authHintCell != null && authHintCellProgress != 0 && !authHintCellAnimating) {
t += authHintCell.getMeasuredHeight();
additionalPadding += authHintCell.getMeasuredHeight();
}
setTopGlowOffset(t);
setPadding(0, t, 0, 0);
if (hasStories) {
parentPage.progressView.setPaddingTop(t - AndroidUtilities.dp(DialogStoriesCell.HEIGHT_IN_DP));
} else {
parentPage.progressView.setPaddingTop(t);
if (t != getPaddingTop()) {
setTopGlowOffset(t);
setPadding(0, t, 0, 0);
if (hasStories) {
parentPage.progressView.setPaddingTop(t - AndroidUtilities.dp(DialogStoriesCell.HEIGHT_IN_DP));
} else {
parentPage.progressView.setPaddingTop(t);
}
for (int i = 0; i < getChildCount(); i++) {
if (getChildAt(i) instanceof DialogsAdapter.LastEmptyView) {
getChildAt(i).requestLayout();
}
}
}
ignoreLayout = false;
}
@ -2220,17 +2236,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
if (anchorView != null) {
if (animationSupportListView != null) {
int topPadding = this.topPadding;
// if (hasStories) {
// topPadding -= AndroidUtilities.dp(DialogStoriesCell.HEIGHT_IN_DP);
// }
animationSupportListView.setPadding(getPaddingLeft(), topPadding, getPaddingLeft(), getPaddingBottom());
if (anchorView != null) {
DialogsAdapter adapter = (DialogsAdapter) animationSupportListView.getAdapter();
int p = adapter.findDialogPosition(anchorView.getDialogId());
int offset = (int) (anchorView.getTop() - anchorListView.getPaddingTop() + scrollOffset);
// if (hasStories) {
// offset += AndroidUtilities.dp(DialogStoriesCell.HEIGHT_IN_DP);
// }
if (p >= 0) {
boolean hasArchive = parentPage.dialogsType == DIALOGS_TYPE_DEFAULT && parentPage.archivePullViewState == ARCHIVE_ITEM_STATE_HIDDEN && hasHiddenArchive();
int fixedOffset = adapter.fixScrollGap(this, p, offset, hasArchive, hasStories, canShowFilterTabsView, opened);
@ -2701,7 +2711,13 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
Long emojiStatusId = UserObject.getEmojiStatusDocumentId(user);
if (emojiStatusId != null) {
statusDrawable.set(emojiStatusId, animated);
actionBar.setRightDrawableOnClick(e -> showSelectStatusDialog());
actionBar.setRightDrawableOnClick(e -> {
if (dialogStoriesCellVisible && dialogStoriesCell != null && !dialogStoriesCell.isExpanded()) {
scrollToTop(true, true);
return;
}
showSelectStatusDialog();
});
SelectAnimatedEmojiDialog.preload(currentAccount);
} else if (user != null && MessagesController.getInstance(currentAccount).isPremiumUser(user)) {
if (premiumStar == null) {
@ -2718,7 +2734,13 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
premiumStar.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_profile_verifiedBackground), PorterDuff.Mode.MULTIPLY));
statusDrawable.set(premiumStar, animated);
actionBar.setRightDrawableOnClick(e -> showSelectStatusDialog());
actionBar.setRightDrawableOnClick(e -> {
if (dialogStoriesCellVisible && dialogStoriesCell != null && !dialogStoriesCell.isExpanded()) {
scrollToTop(true, true);
return;
}
showSelectStatusDialog();
});
SelectAnimatedEmojiDialog.preload(currentAccount);
} else {
statusDrawable.set((Drawable) null, animated);
@ -2877,6 +2899,8 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
authHintCellVisible = false;
authHintCellProgress = 0f;
authHintCell = null;
dialogsHintCell = null;
dialogsHintCellVisible = false;
ActionBarMenu menu = actionBar.createMenu();
if (!onlySelect && searchString == null && folderId == 0) {
@ -4410,12 +4434,16 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
StoryRecorder.getInstance(getParentActivity(), currentAccount)
.closeToWhenSent(new StoryRecorder.ClosingViewProvider() {
@Override
public void preLayout(Runnable runnable) {
public void preLayout(long dialogId, Runnable runnable) {
if (dialogStoriesCell != null) {
scrollToTop(false, true);
invalidateScrollY = true;
fragmentView.invalidate();
dialogStoriesCell.scrollToFirstCell();
if (dialogId == 0 || dialogId == getUserConfig().getClientUserId()) {
dialogStoriesCell.scrollToFirstCell();
} else {
dialogStoriesCell.scrollTo(dialogId);
}
viewPages[0].listView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
@ -4430,20 +4458,19 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
@Override
public StoryRecorder.SourceView getView() {
return StoryRecorder.SourceView.fromStoryCell(dialogStoriesCell != null ? dialogStoriesCell.findSelfStoryCell() : null);
public StoryRecorder.SourceView getView(long dialogId) {
return StoryRecorder.SourceView.fromStoryCell(dialogStoriesCell != null ? dialogStoriesCell.findStoryCell(dialogId) : null);
}
})
.open(StoryRecorder.SourceView.fromFloatingButton(floatingButtonContainer), true);
}
});
boolean showStoryHint = false;
if (!isArchive() && initialDialogsType == DIALOGS_TYPE_DEFAULT) {
if (MessagesController.getInstance(currentAccount).getMainSettings().getBoolean("storyhint", true)) {
storyHint = new HintView2(context, HintView2.DIRECTION_RIGHT)
.setRounding(8)
.setDuration(-1)
.setDuration(8_000)
.setCloseButton(true)
.setMaxWidth(165)
.setMultilineText(true)
@ -4452,7 +4479,6 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
.setBgColor(getThemedColor(Theme.key_undo_background))
.setOnHiddenListener(() -> MessagesController.getInstance(currentAccount).getMainSettings().edit().putBoolean("storyhint", false).commit());
contentView.addView(storyHint, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 160, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, 0, 0, 80, 0));
showStoryHint = true;
}
}
@ -4483,9 +4509,6 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
floatingButtonContainer.addView(floatingButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
updateFloatingButtonColor();
updateStoriesPosting();
if (showStoryHint && storyHint != null && storiesEnabled) {
storyHint.show();
}
searchTabsView = null;
@ -5494,38 +5517,60 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
authHintCell.setVisibility(View.VISIBLE);
}
authHintCell.setAlpha(1f);
viewPages[0].listView.requestLayout();
if (fragmentView != null) {
fragmentView.requestLayout();
}
fragmentView.requestLayout();
notificationsLocker.lock();
authHintCellAnimating = true;
ValueAnimator valueAnimator = ValueAnimator.ofFloat(authHintCellProgress, visible ? 1f : 0);
valueAnimator.addUpdateListener(animation -> {
authHintCellProgress = (float) animation.getAnimatedValue();
updateContextViewPosition();
viewPages[0].listView.requestLayout();
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
notificationsLocker.unlock();
if (fragmentView != null) {
fragmentView.requestLayout();
}
authHintCellProgress = visible ? 1f : 0;
if (!visible) {
authHintCell.setVisibility(View.GONE);
int pos = viewPages[0].layoutManager.findFirstVisibleItemPosition();
int childTop = 0;
if (pos != RecyclerView.NO_POSITION) {
childTop = viewPages[0].layoutManager.findViewByPosition(pos).getTop();
childTop += visible ? 0 : -authHintCell.getMeasuredHeight();
}
int finalChildTop = childTop;
AndroidUtilities.doOnLayout(fragmentView, () -> {
float listDy = authHintCell.getMeasuredHeight();
if (!visible) {
View view = viewPages[0].layoutManager.findViewByPosition(pos);
//look at real visible views difference
if (view != null) {
int newTop = view.getTop();
listDy += (finalChildTop - newTop);
}
}
float finalListDy = listDy;
viewPages[0].listView.setTranslationY(finalListDy * authHintCellProgress);
valueAnimator.addUpdateListener(animation -> {
authHintCellProgress = (float) animation.getAnimatedValue();
viewPages[0].listView.setTranslationY(finalListDy * authHintCellProgress);
updateContextViewPosition();
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
notificationsLocker.unlock();
authHintCellAnimating = false;
authHintCellProgress = visible ? 1f : 0;
fragmentView.requestLayout();
viewPages[0].listView.requestLayout();
viewPages[0].listView.setTranslationY(0);
if (!visible) {
authHintCell.setVisibility(View.GONE);
}
}
});
valueAnimator.setDuration(250);
valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
valueAnimator.start();
});
valueAnimator.setDuration(250);
valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT);
valueAnimator.start();
}
}
private void updateDialogsHint() {
if (dialogsHintCell == null || getContext() == null) {
if (dialogsHintCell == null || fragmentView == null || getContext() == null) {
return;
}
if (!getMessagesController().getUnconfirmedAuthController().auths.isEmpty() && folderId == 0 && initialDialogsType == DIALOGS_TYPE_DEFAULT) {
@ -5533,9 +5578,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
dialogsHintCell.setVisibility(View.GONE);
if (authHintCell == null) {
authHintCell = new UnconfirmedAuthHintCell(getContext());
if (fragmentView instanceof ContentView) {
((ContentView) fragmentView).addView(authHintCell);
}
((ContentView) fragmentView).addView(authHintCell);
}
authHintCell.set(DialogsActivity.this, currentAccount);
updateAuthHintCellVisibility(true);
@ -6664,6 +6707,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
}
}
if (storyHint != null) {
storyHint.hide();
}
Bulletin.hideVisible();
return b;
}
@ -6760,6 +6807,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
undoView[0].hide(true, 0);
}
super.onBecomeFullyHidden();
canShowStoryHint = true;
}
@Override
@ -6785,6 +6833,12 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
}
}
updateFloatingButtonOffset();
if (canShowStoryHint && !storyHintShown && storyHint != null && storiesEnabled) {
storyHintShown = true;
canShowStoryHint = false;
storyHint.show();
}
}
private void showArchiveHelp() {
@ -9724,9 +9778,15 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
permissons.add(Manifest.permission.GET_ACCOUNTS);
}
if (Build.VERSION.SDK_INT >= 33) {
permissons.add(Manifest.permission.READ_MEDIA_IMAGES);
permissons.add(Manifest.permission.READ_MEDIA_VIDEO);
permissons.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (activity.checkSelfPermission(Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
permissons.add(Manifest.permission.READ_MEDIA_IMAGES);
}
if (activity.checkSelfPermission(Manifest.permission.READ_MEDIA_VIDEO) != PackageManager.PERMISSION_GRANTED) {
permissons.add(Manifest.permission.READ_MEDIA_VIDEO);
}
if (activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
permissons.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
} else if ((Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
permissons.add(Manifest.permission.READ_EXTERNAL_STORAGE);
permissons.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);

View file

@ -38,6 +38,7 @@ import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.StickerSetBulletinLayout;
import org.telegram.ui.Components.StickersAlert;
import org.telegram.ui.Stories.StoryReactionWidgetView;
import java.util.ArrayList;
import java.util.HashMap;
@ -895,6 +896,82 @@ public class EmojiAnimationsOverlay implements NotificationCenter.NotificationCe
}
}
public boolean showAnimationForWidget(StoryReactionWidgetView widgetView) {
if (drawingObjects.size() > 12) {
return false;
}
ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(widgetView.mediaArea.reaction);
String emoji = visibleReaction.emojicon;
if (emoji == null) {
TLRPC.Document document = AnimatedEmojiDrawable.findDocument(currentAccount, visibleReaction.documentId);
emoji = MessageObject.findAnimatedEmojiEmoticon(document);
}
MessageObject messageObject = null;
float imageH = widgetView.getMeasuredHeight();
float imageW = widgetView.getMeasuredWidth();
View parent = (View) widgetView.getParent();
if (imageW > parent.getWidth() * 0.5f) {
imageH = imageW = parent.getWidth() * 0.4f;
}
// if (imageH <= 0 || imageW <= 0) {
// return false;
// }
emoji = unwrapEmoji(emoji);
int viewId = widgetView.hashCode();
TLRPC.Document viewDocument = null;
boolean isOutOwner = widgetView.getTranslationX() > contentLayout.getMeasuredWidth() / 2f;//view.getMessageObject().isOutOwner();
if (visibleReaction.emojicon != null && createDrawingObject(emoji, viewId, viewDocument, messageObject, -1, false, false, imageW, imageH, isOutOwner)) {
if (!drawingObjects.isEmpty()) {
DrawingObject drawingObject = drawingObjects.get(drawingObjects.size() - 1);
drawingObject.isReaction = true;
drawingObject.lastH = imageH;
drawingObject.lastW = imageW;
drawingObject.lastX = widgetView.getTranslationX() - drawingObject.lastW / 2f;
drawingObject.lastY = widgetView.getTranslationY() - drawingObject.lastW * 1.5f;
if (drawingObject.isOut) {
drawingObject.lastX += -drawingObject.lastW * 1.8f;
} else {
drawingObject.lastX += -drawingObject.lastW * 0.2f;
}
}
return true;
} else if (visibleReaction.documentId != 0 && widgetView.getAnimatedEmojiDrawable() != null) {
int sameAnimationCount = 0;
for (int i = 0; i < drawingObjects.size(); i++) {
if (drawingObjects.get(i).documentId == visibleReaction.documentId) {
sameAnimationCount++;
}
}
if (sameAnimationCount >= 4) {
return false;
}
DrawingObject drawingObject = new DrawingObject();
drawingObject.genericEffect = AnimatedEmojiEffect.createFrom(widgetView.getAnimatedEmojiDrawable(), true, true);
drawingObject.randomOffsetX = imageW / 4 * ((random.nextInt() % 101) / 100f);
drawingObject.randomOffsetY = imageH / 4 * ((random.nextInt() % 101) / 100f);
drawingObject.messageId = viewId;
drawingObject.document = null;
drawingObject.documentId = visibleReaction.documentId;
drawingObject.isOut = isOutOwner;
drawingObject.isReaction = true;
drawingObject.lastH = imageH;
drawingObject.lastW = imageW;
drawingObject.lastX = widgetView.getTranslationX() - drawingObject.lastW / 2f;
drawingObject.lastY = widgetView.getTranslationY() - drawingObject.lastW * 1.5f;
drawingObject.lastX += -drawingObject.lastW * 1.8f;
if (attached) {
drawingObject.genericEffect.setView(contentLayout);
}
drawingObjects.add(drawingObject);
return true;
}
return false;
}
public void setAccount(int currentAccount) {
this.currentAccount = currentAccount;
}

View file

@ -9,6 +9,7 @@
package org.telegram.ui;
import static org.telegram.ui.Components.Premium.LimitReachedBottomSheet.TYPE_ACCOUNTS;
import static org.telegram.ui.Components.Premium.LimitReachedBottomSheet.TYPE_BOOSTS_FOR_USERS;
import android.Manifest;
import android.animation.Animator;
@ -97,6 +98,7 @@ import org.telegram.messenger.AutoDeleteMediaTask;
import org.telegram.messenger.BackupAgent;
import org.telegram.messenger.BotWebViewVibrationEffect;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.ChannelBoostsController;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.ContactsLoadingObserver;
@ -132,6 +134,8 @@ import org.telegram.messenger.voip.VoIPService;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBarLayout;
import org.telegram.ui.ActionBar.ActionBarMenu;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.DrawerLayoutContainer;
@ -219,6 +223,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
public static Runnable onResumeStaticCallback;
private static final String EXTRA_ACTION_TOKEN = "actions.fulfillment.extra.ACTION_TOKEN";
public ArrayList<INavigationLayout> sheetFragmentsStack = new ArrayList<>();
private boolean finished;
private String videoPath;
@ -948,7 +953,6 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
webViewSheet.setParentActivity(this);
webViewSheet.requestWebView(currentAccount, attachMenuBot.bot_id, attachMenuBot.bot_id, attachMenuBot.short_name, null, BotWebViewSheet.TYPE_SIMPLE_WEB_VIEW_BUTTON, 0, false, BotWebViewSheet.FLAG_FROM_SIDE_MENU);
webViewSheet.show();
drawerLayoutContainer.closeDrawer();
}
@Override
@ -2023,6 +2027,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
Integer messageId = null;
Long channelId = null;
Integer threadId = null;
boolean isBoost = false;
Integer commentId = null;
int videoTimestamp = -1;
boolean hasUrl = false;
@ -2201,6 +2206,10 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
messageId = Utilities.parseInt(segments.get(3));
}
}
if (data.getQuery() != null && segments.size() == 2) {
isBoost = data.getQuery().equals("boost");
channelId = Utilities.parseLong(segments.get(1));
}
} else if (path.startsWith("contact/")) {
contactToken = path.substring(8);
} else if (path.startsWith("folder/")) {
@ -2246,6 +2255,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
attachMenuBotChoose = data.getQueryParameter("choose");
attachMenuBotToOpen = data.getQueryParameter("attach");
threadId = Utilities.parseInt(data.getQueryParameter("thread"));
if (data.getQuery() != null) {
isBoost = data.getQuery().equals("boost");
}
// storyId = Utilities.parseInt(data.getQueryParameter("story"));
if (threadId == 0) {
threadId = null;
@ -2674,7 +2686,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
if (message != null && message.startsWith("@")) {
message = " " + message;
}
runLinkRequest(intentAccount[0], username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, login, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, 0, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, startApp, progress, forceNotInternalForApps, storyId);
runLinkRequest(intentAccount[0], username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, login, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, 0, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, startApp, progress, forceNotInternalForApps, storyId, isBoost);
} else {
try (Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null)) {
if (cursor != null) {
@ -3491,9 +3503,10 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
final String botAppStartParam,
final Browser.Progress progress,
final boolean forceNotInternalForApps,
final int storyId) {
final int storyId,
final boolean isBoost) {
if (state == 0 && ChatActivity.SCROLL_DEBUG_DELAY && progress != null) {
Runnable runnable = () -> runLinkRequest(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, 1, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId);
Runnable runnable = () -> runLinkRequest(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, 1, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost);
progress.init();
progress.onCancel(() -> AndroidUtilities.cancelRunOnUIThread(runnable));
AndroidUtilities.runOnUIThread(runnable, 7500);
@ -3503,7 +3516,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
if (account != intentAccount) {
switchToAccount(account, true);
}
runLinkRequest(account, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, 1, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId);
runLinkRequest(account, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, 1, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost);
}).show();
return;
} else if (code != null) {
@ -3685,18 +3698,10 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
TLRPC.TL_messages_getAttachMenuBot getAttachMenuBot = new TLRPC.TL_messages_getAttachMenuBot();
getAttachMenuBot.bot = MessagesController.getInstance(intentAccount).getInputUser(peerId);
ConnectionsManager.getInstance(intentAccount).sendRequest(getAttachMenuBot, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> {
try {
if (dismissLoading != null) {
dismissLoading.run();
}
} catch (Exception e) {
FileLog.e(e);
}
if (response1 instanceof TLRPC.TL_attachMenuBotsBot) {
WebAppDisclaimerAlert.show(this, ignore -> {
user.inactive = false;
MediaDataController.getInstance(currentAccount).applyAttachMenuBot((TLRPC.TL_attachMenuBotsBot) response1);
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, false, storyId, true, user, dismissLoading);
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, false, storyId, isBoost, user, dismissLoading);
TLRPC.TL_messages_toggleBotInAttachMenu botRequest = new TLRPC.TL_messages_toggleBotInAttachMenu();
botRequest.bot = MessagesController.getInstance(intentAccount).getInputUser(peerId);
@ -3712,12 +3717,17 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
}));
} else {
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, false, storyId, false, user, dismissLoading);
processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, false, storyId, isBoost, user, dismissLoading);
}
return;
}
}
if (isBoost) {
processBoostDialog(peerId, dismissLoading);
return;
}
if (setAsAttachBot != null && attachMenuBotToOpen == null) {
TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId);
if (user != null && user.bot) {
@ -3941,7 +3951,6 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
});
presentFragment(fragment);
} else {
long dialog_id;
boolean isBot = false;
Bundle args = new Bundle();
@ -4523,7 +4532,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
}
}));
} else if (channelId != null && messageId != null) {
} else if (channelId != null && (messageId != null || isBoost)) {
if (threadId != null) {
TLRPC.Chat chat = MessagesController.getInstance(intentAccount).getChat(channelId);
if (chat != null) {
@ -4556,9 +4565,13 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
} else {
Bundle args = new Bundle();
args.putLong("chat_id", channelId);
args.putInt("message_id", messageId);
if (messageId != null) {
args.putInt("message_id", messageId);
}
TLRPC.Chat chatLocal = MessagesController.getInstance(currentAccount).getChat(channelId);
if (chatLocal != null && chatLocal.forum) {
if (chatLocal != null && isBoost) {
processBoostDialog(-channelId, dismissLoading);
} else if (chatLocal != null && chatLocal.forum) {
openForumFromLink(-channelId, 0, messageId, () -> {
try {
dismissLoading.run();
@ -4588,7 +4601,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
notFound = false;
MessagesController.getInstance(currentAccount).putChats(res.chats, false);
TLRPC.Chat chat = res.chats.get(0);
if (chat != null && chat.forum) {
if (chat != null && isBoost) {
processBoostDialog(-channelId, null);
} else if (chat != null && chat.forum) {
if (threadId != null) {
openForumFromLink(-channelId, threadId, messageId, null);
} else {
@ -4675,7 +4690,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
final Browser.Progress progress,
final boolean forceNotInternalForApps,
final int storyId,
boolean justAdded,
final boolean isBoost,
TLRPC.User user,
Runnable dismissLoading) {
@ -4689,7 +4704,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
progress.end();
}
if (error1 != null) {
AndroidUtilities.runOnUIThread(() -> runLinkRequest(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, null, null, progress, forceNotInternalForApps, storyId));
AndroidUtilities.runOnUIThread(() -> runLinkRequest(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, null, null, progress, forceNotInternalForApps, storyId, isBoost));
} else {
TLRPC.TL_messages_botApp botApp = (TLRPC.TL_messages_botApp) response1;
AndroidUtilities.runOnUIThread(() -> {
@ -4702,12 +4717,12 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
sheet.setParentActivity(LaunchActivity.this);
sheet.requestWebView(intentAccount, user.id, user.id, null, null, BotWebViewSheet.TYPE_WEB_VIEW_BOT_APP, 0, false, lastFragment, botApp.app, allowWrite.get(), botAppStartParam, user);
sheet.show();
if (justAdded) {
if (botApp.inactive || forceNotInternalForApps) {
sheet.showJustAddedBulletin();
}
};
if (!user.bot_attach_menu && (botApp.inactive || forceNotInternalForApps)) {
if (botApp.inactive || forceNotInternalForApps) {
AlertsCreator.createBotLaunchAlert(lastFragment, botApp, user, allowWrite, loadBotSheet);
} else {
loadBotSheet.run();
@ -4718,6 +4733,36 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
private void processBoostDialog(Long peerId, Runnable dismissLoading) {
ChannelBoostsController boostsController = MessagesController.getInstance(currentAccount).getBoostsController();
boostsController.getBoostsStats(peerId, boostsStatus -> {
if (boostsStatus == null) {
dismissLoading.run();
return;
}
boostsController.userCanBoostChannel(peerId, canApplyBoost -> {
LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(getLastFragment(), this, TYPE_BOOSTS_FOR_USERS, currentAccount, null);
limitReachedBottomSheet.setCanApplyBoost(canApplyBoost);
BaseFragment lastFragment = getLastFragment();
boolean isCurrentChat = false;
if (lastFragment instanceof ChatActivity) {
isCurrentChat = ((ChatActivity) lastFragment).getDialogId() == peerId;
}
limitReachedBottomSheet.setBoostsStats(boostsStatus, isCurrentChat);
limitReachedBottomSheet.setDialogId(peerId);
limitReachedBottomSheet.show();
try {
if (dismissLoading != null) {
dismissLoading.run();
}
} catch (Exception e) {
FileLog.e(e);
}
});
});
}
private void processAttachMenuBot(int intentAccount, long peerId, String attachMenuBotChoose, TLRPC.User user, String setAsAttachBot) {
TLRPC.TL_messages_getAttachMenuBot getAttachMenuBot = new TLRPC.TL_messages_getAttachMenuBot();
getAttachMenuBot.bot = MessagesController.getInstance(intentAccount).getInputUser(peerId);
@ -5124,6 +5169,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
public void checkAppUpdate(boolean force) {
if (!BuildVars.isStandaloneApp()) {
return;
}
if (!force && BuildVars.DEBUG_VERSION || !force && !BuildVars.CHECK_UPDATES) {
return;
}
@ -7508,6 +7556,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
public static BaseFragment getLastFragment() {
if (instance != null && !instance.sheetFragmentsStack.isEmpty()) {
return instance.sheetFragmentsStack.get(instance.sheetFragmentsStack.size() - 1).getLastFragment();
}
if (instance != null && instance.getActionBarLayout() != null) {
return instance.getActionBarLayout().getLastFragment();
}
@ -7649,7 +7700,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
return;
}
StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController();
ArrayList<TLRPC.TL_userStories> stories = new ArrayList<>(onlyArchived ? storiesController.getHiddenList() : storiesController.getDialogListStories());
ArrayList<TLRPC.PeerStories> stories = new ArrayList<>(onlyArchived ? storiesController.getHiddenList() : storiesController.getDialogListStories());
ArrayList<Long> peerIds = new ArrayList<>();
ArrayList<Long> toLoadPeerIds = new ArrayList<>();
final long[] finalDialogIds;
@ -7686,19 +7737,19 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
};
for (int i = 0; i < toLoadPeerIds.size(); ++i) {
long did = toLoadPeerIds.get(i);
TLRPC.TL_stories_getUserStories req = new TLRPC.TL_stories_getUserStories();
req.user_id = messagesController.getInputUser(did);
if (req.user_id instanceof TLRPC.TL_inputUserEmpty) {
TLRPC.TL_stories_getPeerStories req = new TLRPC.TL_stories_getPeerStories();
req.peer = messagesController.getInputPeer(did);
if (req.peer instanceof TLRPC.TL_inputPeerEmpty) {
loaded[0]--;
continue;
}
if (req.user_id == null) {
if (req.peer == null) {
loaded[0]--;
continue;
}
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
if (res instanceof TLRPC.TL_stories_userStories) {
TLRPC.TL_stories_userStories r = (TLRPC.TL_stories_userStories) res;
if (res instanceof TLRPC.TL_stories_peerStories) {
TLRPC.TL_stories_peerStories r = (TLRPC.TL_stories_peerStories) res;
messagesController.putUsers(r.users, false);
messagesController.getStoriesController().putStories(did, r.stories);
whenDone.run();
@ -7710,9 +7761,10 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
} else {
long me = UserConfig.getInstance(currentAccount).getClientUserId();
for (int i = 0; i < stories.size(); ++i) {
TLRPC.TL_userStories userStories = stories.get(i);
if (userStories.user_id != me && !peerIds.contains(userStories.user_id) && storiesController.hasUnreadStories(userStories.user_id)) {
peerIds.add(userStories.user_id);
TLRPC.PeerStories userStories = stories.get(i);
long dialogId = DialogObject.getPeerDialogId(userStories.peer);
if (dialogId != me && !peerIds.contains(dialogId) && storiesController.hasUnreadStories(dialogId)) {
peerIds.add(dialogId);
}
}
if (!peerIds.isEmpty()) {

View file

@ -4018,6 +4018,8 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No
if (currentType == AUTH_TYPE_MESSAGE) {
if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) {
problemText.setText(LocaleController.getString("DidNotGetTheCodePhone", R.string.DidNotGetTheCodePhone));
} else if (nextType == AUTH_TYPE_FRAGMENT_SMS) {
problemText.setText(LocaleController.getString("DidNotGetTheCodeFragment", R.string.DidNotGetTheCodeFragment));
} else if (nextType == 0) {
problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode));
} else {

View file

@ -2398,7 +2398,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
}
});
if (paymentForm.invoice.recurring) {
if (paymentForm.invoice.terms_url != null) {
recurrentAcceptCell = new RecurrentPaymentsAcceptCell(context, getResourceProvider());
recurrentAcceptCell.setChecked(paymentForm.invoice.recurring && isAcceptTermsChecked);
String str = LocaleController.getString(R.string.PaymentCheckoutAcceptRecurrent);
@ -2406,7 +2406,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
int firstIndex = str.indexOf('*'), lastIndex = str.lastIndexOf('*');
if (firstIndex != -1 && lastIndex != -1) {
SpannableString acceptTerms = new SpannableString(str.substring(firstIndex + 1, lastIndex));
acceptTerms.setSpan(new URLSpanNoUnderline(paymentForm.invoice.recurring_terms_url), 0, acceptTerms.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
acceptTerms.setSpan(new URLSpanNoUnderline(paymentForm.invoice.terms_url), 0, acceptTerms.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.replace(firstIndex, lastIndex + 1, acceptTerms);
str = str.substring(0, firstIndex) + acceptTerms + str.substring(lastIndex + 1);
}

View file

@ -1777,10 +1777,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
windowLayoutParams.flags =
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR |
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
} else {
windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
windowView.setFocusable(false);
@ -4607,7 +4604,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
navigationBarLayoutParams.bottomMargin = -navigationBarHeight / 2;
navigationBar.setLayoutParams(navigationBarLayoutParams);
}
containerView.setPadding(insets.left, 0, insets.right, 0);
containerView.setPadding(newInsets.getSystemWindowInsetLeft(), 0, newInsets.getSystemWindowInsetRight(), 0);
if (actionBar != null) {
AndroidUtilities.cancelRunOnUIThread(updateContainerFlagsRunnable);
if (isVisible && animationInProgress == 0) {
@ -4636,10 +4633,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
windowLayoutParams.flags =
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR |
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
} else {
windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
paintingOverlay = new PaintingOverlay(parentActivity);
@ -6045,6 +6039,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
@Override
protected void setupMentionContainer() {
if (parentChatActivity != null) {
return;
}
mentionContainer.getAdapter().setAllowStickers(false);
mentionContainer.getAdapter().setAllowBots(false);
mentionContainer.getAdapter().setAllowChats(false);
mentionContainer.getAdapter().setSearchInDailogs(true);
if (parentChatActivity != null) {
mentionContainer.getAdapter().setChatInfo(parentChatActivity.chatInfo);
mentionContainer.getAdapter().setNeedUsernames(parentChatActivity.currentChat != null);
@ -10534,7 +10535,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
photoPaintView.keyboardVisible = paintKeyboardNotifier.keyboardVisible();
containerView.invalidate();
height = Math.max(height, photoPaintView.getEmojiPadding(false));
translateY(photoPaintView.isCurrentText() && height > 0 ? ((AndroidUtilities.displaySize.y - height) / 2f - photoPaintView.getSelectedEntityCenterY()) / 2.5f : 0);
translateY(photoPaintView.isCurrentText() && height > 0 ? (AndroidUtilities.displaySize.y - height - dp(80) - photoPaintView.getSelectedEntityBottom()) : 0);
if (paintKeyboardAnimator != null) {
paintKeyboardAnimator.cancel();
@ -14270,10 +14271,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
windowLayoutParams.flags =
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR |
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
} else {
windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
if (chatActivity != null && chatActivity.getCurrentEncryptedChat() != null ||
avatarsDialogId != 0 && MessagesController.getInstance(currentAccount).isChatNoForwards(-avatarsDialogId) ||
@ -16991,100 +16989,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
return tempInt;
}
private int[] applyCrop(Matrix matrix, int containerWidth, int containerHeight, int bitmapWidth, int bitmapHeight, float currentScale, CropTransform cropTransform, MediaController.CropState cropState) {
int originalWidth = bitmapWidth;
int originalHeight = bitmapHeight;
float scale = Math.min(containerWidth / (float) originalWidth, containerHeight / (float) originalHeight);
int rotatedWidth = originalWidth;
int rotatedHeight = originalHeight;
int orientation = cropTransform.getOrientation();
if (orientation == 90 || orientation == 270) {
int temp = bitmapWidth;
bitmapWidth = bitmapHeight;
bitmapHeight = temp;
temp = rotatedWidth;
rotatedWidth = rotatedHeight;
rotatedHeight = temp;
}
float cropAnimationValue;
if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT)) {
cropAnimationValue = 1.0f;
} else if (imageMoveAnimation != null && switchingToMode != -1) {
if (currentEditMode == EDIT_MODE_CROP || switchingToMode == EDIT_MODE_CROP || (currentEditMode == EDIT_MODE_FILTER || currentEditMode == EDIT_MODE_PAINT) && switchingToMode == -1) {
cropAnimationValue = 1.0f;
} else if (switchingToMode == EDIT_MODE_NONE) {
cropAnimationValue = animationValue;
} else {
cropAnimationValue = 1.0f - animationValue;
}
} else {
cropAnimationValue = currentEditMode == EDIT_MODE_FILTER || currentEditMode == EDIT_MODE_PAINT ? 0.0f : 1.0f;
}
float cropPw = cropTransform.getCropPw();
float cropPh = cropTransform.getCropPh();
bitmapWidth *= cropPw + (1.0f - cropPw) * (1.0f - cropAnimationValue);
bitmapHeight *= cropPh + (1.0f - cropPh) * (1.0f - cropAnimationValue);
float scaleToFitX = containerWidth / (float) bitmapWidth;
if (scaleToFitX * bitmapHeight > containerHeight) {
scaleToFitX = containerHeight / (float) bitmapHeight;
}
// if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode != EDIT_MODE_CROP || switchingToMode == EDIT_MODE_NONE) && cropState != null) {
// float startW = bitmapWidth * scaleToFitX;
// float startH = bitmapHeight * scaleToFitX;
// float originalScaleToFitX = containerWidth / (float) originalWidth;
// if (originalScaleToFitX * originalHeight > containerHeight) {
// originalScaleToFitX = containerHeight / (float) originalHeight;
// }
// float finalW = originalWidth * originalScaleToFitX / currentScale;
// float finalH = originalHeight * originalScaleToFitX / currentScale;
//
// float w = startW + (finalW - startW) * (1.0f - cropAnimationValue);
// float h = startH + (finalH - startH) * (1.0f - cropAnimationValue);
//
// canvas.clipRect(-w / 2, -h / 2, w / 2, h / 2);
// }
if (sendPhotoType == SELECT_TYPE_AVATAR || cropTransform.hasViewTransform()) {
float cropScale;
if (currentEditMode == EDIT_MODE_CROP || sendPhotoType == SELECT_TYPE_AVATAR) {
float trueScale = 1.0f + (cropTransform.getTrueCropScale() - 1.0f) * (1.0f - cropAnimationValue);
cropScale = cropTransform.getScale() / trueScale;
float scaleToFit = containerWidth / (float) rotatedWidth;
if (scaleToFit * rotatedHeight > containerHeight) {
scaleToFit = containerHeight / (float) rotatedHeight;
}
cropScale *= scaleToFit / scale;
if (sendPhotoType == SELECT_TYPE_AVATAR) {
if (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT) {
cropScale /= 1.0f + (cropTransform.getMinScale() - 1.0f) * (1.0f - cropAnimationValue);
} else if (switchingToMode == EDIT_MODE_NONE) {
cropScale /= cropTransform.getMinScale();
}
}
} else {
cropScale = cropState != null ? cropState.cropScale : 1.0f;
float trueScale = 1.0f + (cropScale - 1.0f) * (1.0f - cropAnimationValue);
cropScale *= scaleToFitX / scale / trueScale;
}
matrix.postTranslate(cropTransform.getCropAreaX() * cropAnimationValue, cropTransform.getCropAreaY() * cropAnimationValue);
matrix.postScale(cropScale, cropScale);
matrix.postTranslate(cropTransform.getCropPx() * rotatedWidth * scale * cropAnimationValue, cropTransform.getCropPy() * rotatedHeight * scale * cropAnimationValue);
float rotation = (cropTransform.getRotation() + orientation);
if (rotation > 180) {
rotation -= 360;
}
if (sendPhotoType == SELECT_TYPE_AVATAR && (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT)) {
matrix.postRotate(rotation);
} else {
matrix.postRotate(rotation * cropAnimationValue);
}
}
tempInt[0] = bitmapWidth;
tempInt[1] = bitmapHeight;
return tempInt;
}
private void onActionClick(boolean download) {
if (currentMessageObject == null && currentBotInlineResult == null && (pageBlocksAdapter == null || currentFileNames[0] == null) && sendPhotoType != SELECT_TYPE_NO_SELECT) {
return;

View file

@ -99,6 +99,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio
private int paymentsClearRow;
private int webSessionsRow;
private int botsDetailRow;
private int botsAndWebsitesShadowRow;
private int contactsSectionRow;
private int contactsDeleteRow;
private int contactsSuggestRow;
@ -119,7 +120,8 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio
private boolean archiveChats;
private boolean[] clear = new boolean[2];
SessionsActivity sessionsActivityPreload;
private SessionsActivity devicesActivityPreload;
private SessionsActivity webSessionsActivityPreload;
@Override
public boolean onFragmentCreate() {
@ -144,13 +146,24 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio
getUserConfig().loadGlobalTTl();
sessionsActivityPreload = new SessionsActivity(0);
sessionsActivityPreload.setDelegate(() -> {
devicesActivityPreload = new SessionsActivity(SessionsActivity.TYPE_DEVICES);
devicesActivityPreload.setDelegate(() -> {
if (listAdapter != null && sessionsRow >= 0) {
listAdapter.notifyItemChanged(sessionsRow);
}
});
sessionsActivityPreload.loadSessions(false);
devicesActivityPreload.loadSessions(false);
webSessionsActivityPreload = new SessionsActivity(SessionsActivity.TYPE_WEB_SESSIONS);
webSessionsActivityPreload.setDelegate(() -> {
if (listAdapter != null) {
int webSessionsCount = webSessionsActivityPreload.getSessionsCount();
if (webSessionsRow < 0 && webSessionsCount > 0) {
updateRows();
}
}
});
webSessionsActivityPreload.loadSessions(false);
return true;
}
@ -245,10 +258,11 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio
} if (position == blockedRow) {
presentFragment(new PrivacyUsersActivity());
} else if (position == sessionsRow) {
sessionsActivityPreload.resetFragment();
presentFragment(sessionsActivityPreload);
devicesActivityPreload.resetFragment();
presentFragment(devicesActivityPreload);
} else if (position == webSessionsRow) {
presentFragment(new SessionsActivity(1));
webSessionsActivityPreload.resetFragment();
presentFragment(webSessionsActivityPreload);
} else if (position == deleteAccountRow) {
if (getParentActivity() == null) {
return;
@ -659,8 +673,15 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio
passportRow = -1;
}
paymentsClearRow = rowCount++;
webSessionsRow = rowCount++;
botsDetailRow = rowCount++;
if (webSessionsActivityPreload != null && webSessionsActivityPreload.getSessionsCount() > 0) {
webSessionsRow = rowCount++;
botsDetailRow = rowCount++;
botsAndWebsitesShadowRow = -1;
} else {
webSessionsRow = -1;
botsDetailRow = -1;
botsAndWebsitesShadowRow = rowCount++;
}
contactsSectionRow = rowCount++;
contactsDeleteRow = rowCount++;
contactsSyncRow = rowCount++;
@ -1107,16 +1128,16 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio
textCell2.setTextAndValueAndIcon(LocaleController.getString("AutoDeleteMessages", R.string.AutoDeleteMessages), value, true, R.drawable.msg2_autodelete, true);
} else if (position == sessionsRow) {
String count = "";
if (sessionsActivityPreload.getSessionsCount() == 0) {
if (devicesActivityPreload.getSessionsCount() == 0) {
if (getMessagesController().lastKnownSessionsCount == 0) {
showLoading = true;
} else {
count = String.format(LocaleController.getInstance().getCurrentLocale(), "%d", getMessagesController().lastKnownSessionsCount);
}
} else {
count = String.format(LocaleController.getInstance().getCurrentLocale(), "%d", sessionsActivityPreload.getSessionsCount());
count = String.format(LocaleController.getInstance().getCurrentLocale(), "%d", devicesActivityPreload.getSessionsCount());
}
getMessagesController().lastKnownSessionsCount = sessionsActivityPreload.getSessionsCount();
getMessagesController().lastKnownSessionsCount = devicesActivityPreload.getSessionsCount();
textCell2.setTextAndValueAndIcon(LocaleController.getString("SessionsTitle", R.string.SessionsTitle), count, true, R.drawable.msg2_devices, false);
} else if (position == emailLoginRow) {
CharSequence val = "";
@ -1186,7 +1207,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio
return 2;
} else if (position == secretWebpageRow || position == contactsSyncRow || position == contactsSuggestRow || position == newChatsRow) {
return 3;
} else if (position == privacyShadowRow) {
} else if (position == privacyShadowRow || position == botsAndWebsitesShadowRow) {
return 4;
} else if (position == autoDeleteMesages || position == sessionsRow || position == emailLoginRow || position == passwordRow || position == passcodeRow || position == blockedRow) {
return 5;

View file

@ -8,6 +8,7 @@
package org.telegram.ui;
import static androidx.core.view.ViewCompat.TYPE_TOUCH;
import static org.telegram.messenger.ContactsController.PRIVACY_RULES_TYPE_ADDED_BY_PHONE;
import android.Manifest;
@ -15,7 +16,9 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.StateListAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Dialog;
@ -31,6 +34,7 @@ import android.content.res.Configuration;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
@ -65,8 +69,10 @@ import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.webkit.WebStorage;
@ -194,6 +200,7 @@ import org.telegram.ui.Components.LinkSpanDrawable;
import org.telegram.ui.Components.MediaActivity;
import org.telegram.ui.Components.Paint.PersistColorPalette;
import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet;
import org.telegram.ui.Components.Premium.LimitReachedBottomSheet;
import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet;
import org.telegram.ui.Components.Premium.PremiumGradient;
import org.telegram.ui.Components.Premium.PremiumPreviewBottomSheet;
@ -216,9 +223,11 @@ import org.telegram.ui.Components.UndoView;
import org.telegram.ui.Components.VectorAvatarThumbDrawable;
import org.telegram.ui.Components.voip.VoIPHelper;
import org.telegram.ui.Stories.ProfileStoriesView;
import org.telegram.ui.Stories.StoriesController;
import org.telegram.ui.Stories.StoriesListPlaceProvider;
import org.telegram.ui.Stories.StoryViewer;
import org.telegram.ui.Stories.recorder.DualCameraView;
import org.telegram.ui.Stories.recorder.StoryRecorder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@ -630,6 +639,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
private boolean hasFallbackPhoto;
private boolean hasCustomPhoto;
private ImageReceiver fallbackImage;
private boolean loadingBoostsStats;
private boolean waitCanSendStoryRequest;
public static ProfileActivity of(long dialogId) {
Bundle bundle = new Bundle();
@ -649,6 +660,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
private final RectF rect = new RectF();
private final Paint placeholderPaint;
public boolean drawAvatar = true;
public float bounceScale = 1f;
private ImageReceiver foregroundImageReceiver;
private float foregroundAlpha;
@ -658,6 +671,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
ProfileGalleryView avatarsViewPager;
private boolean hasStories;
private float progressToInsets = 1f;
public void setAvatarsViewPager(ProfileGalleryView avatarsViewPager) {
this.avatarsViewPager = avatarsViewPager;
@ -736,11 +750,16 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
@Override
protected void onDraw(Canvas canvas) {
ImageReceiver imageReceiver = animatedEmojiDrawable != null ? animatedEmojiDrawable.getImageReceiver() : this.imageReceiver;
canvas.save();
canvas.scale(bounceScale, bounceScale, getMeasuredWidth() / 2f, getMeasuredHeight() / 2f);
if (imageReceiver != null && (foregroundAlpha < 1f || !drawForeground)) {
int inset = hasStories ? (int) AndroidUtilities.dpf2(3.5f) : 0;
float inset = hasStories ? (int) AndroidUtilities.dpf2(3.5f) : 0;
inset *= (1f - progressToExpand);
inset *= progressToInsets;
imageReceiver.setImageCoords(inset, inset, getMeasuredWidth() - inset * 2f, getMeasuredHeight() - inset * 2f);
imageReceiver.draw(canvas);
if (drawAvatar) {
imageReceiver.draw(canvas);
}
}
if (foregroundAlpha > 0f && drawForeground) {
if (foregroundImageReceiver.getDrawable() != null) {
@ -754,6 +773,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
canvas.drawRoundRect(rect, radius, radius, placeholderPaint);
}
}
canvas.restore();
}
@Override
@ -764,6 +784,16 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
}
public void setProgressToStoriesInsets(float progressToInsets) {
if (progressToInsets == this.progressToInsets) {
return;
}
this.progressToInsets = progressToInsets;
//if (hasStories) {
invalidate();
//}
}
public void drawForeground(boolean drawForeground) {
this.drawForeground = drawForeground;
}
@ -1187,6 +1217,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
innerListView.scrollBy(0, dyUnconsumed);
}
}
if (dyConsumed != 0 && type == TYPE_TOUCH) {
hideFloatingButton(dyConsumed > 0);
}
} catch (Throwable e) {
FileLog.e(e);
AndroidUtilities.runOnUIThread(() -> {
@ -1640,6 +1673,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
getNotificationCenter().addObserver(this, NotificationCenter.topicsDidLoaded);
getNotificationCenter().addObserver(this, NotificationCenter.updateSearchSettings);
getNotificationCenter().addObserver(this, NotificationCenter.reloadDialogPhotos);
getNotificationCenter().addObserver(this, NotificationCenter.storiesUpdated);
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
updateRowsIds();
if (listAdapter != null) {
@ -1709,6 +1743,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
getNotificationCenter().removeObserver(this, NotificationCenter.topicsDidLoaded);
getNotificationCenter().removeObserver(this, NotificationCenter.updateSearchSettings);
getNotificationCenter().removeObserver(this, NotificationCenter.reloadDialogPhotos);
getNotificationCenter().removeObserver(this, NotificationCenter.storiesUpdated);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded);
if (avatarsViewPager != null) {
avatarsViewPager.onDestroy();
@ -2125,6 +2160,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
Bundle args = new Bundle();
args.putLong("chat_id", chatId);
args.putBoolean("is_megagroup", chat.megagroup);
if (!chatInfo.can_view_stats) {
args.putBoolean("only_boosts", chat.megagroup);
}
StatisticActivity fragment = new StatisticActivity(args);
presentFragment(fragment);
} else if (id == view_discussion) {
@ -3475,7 +3513,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
getMessagesStorage().clearSentMedia();
SharedConfig.setNoSoundHintShowed(false);
SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit();
editor.remove("archivehint").remove("proximityhint").remove("archivehint_l").remove("speedhint").remove("gifhint").remove("reminderhint").remove("soundHint").remove("themehint").remove("bganimationhint").remove("filterhint").remove("n_0").remove("storyprvhint").remove("storyhint").remove("storyhint2").remove("storydualhint").remove("storysvddualhint").remove("stories_camera").remove("dualcam").remove("dualmatrix").remove("dual_available").remove("archivehint").remove("askNotificationsAfter").remove("askNotificationsDuration").remove("viewoncehint").commit();
editor.remove("archivehint").remove("proximityhint").remove("archivehint_l").remove("speedhint").remove("gifhint").remove("reminderhint").remove("soundHint").remove("themehint").remove("bganimationhint").remove("filterhint").remove("n_0").remove("storyprvhint").remove("storyhint").remove("storyhint2").remove("storydualhint").remove("storysvddualhint").remove("stories_camera").remove("dualcam").remove("dualmatrix").remove("dual_available").remove("archivehint").remove("askNotificationsAfter").remove("askNotificationsDuration").remove("viewoncehint").remove("taptostorysoundhint").commit();
MessagesController.getEmojiSettings(currentAccount).edit().remove("featured_hidden").remove("emoji_featured_hidden").commit();
SharedConfig.textSelectionHintShows = 0;
SharedConfig.lockRecordAudioVideoHint = 0;
@ -4184,21 +4222,31 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
};
mediaCounterTextView.setAlpha(0.0f);
avatarContainer2.addView(mediaCounterTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, 8, 0));
storyView = new ProfileStoriesView(context, currentAccount, userId == 0 ? chatId : userId, avatarContainer, avatarImage, resourcesProvider) {
storyView = new ProfileStoriesView(context, currentAccount, getDialogId(), avatarContainer, avatarImage, resourcesProvider) {
@Override
protected void onTap(StoryViewer.PlaceProvider provider) {
long did = userId == 0 ? chatId : userId;
if (getMessagesController().getStoriesController().hasStories(did)) {
long did = getDialogId();
StoriesController storiesController = getMessagesController().getStoriesController();
if (storiesController.hasStories(did) || storiesController.hasUploadingStories(did) || storiesController.isLastUploadingFailed(did)) {
getOrCreateStoryViewer().open(context, did, provider);
} else if (userInfo != null && userInfo.stories != null && !userInfo.stories.stories.isEmpty() && userId != getUserConfig().clientUserId) {
getOrCreateStoryViewer().open(context, userInfo.stories, provider);
} else if (chatInfo != null && chatInfo.stories != null && !chatInfo.stories.stories.isEmpty()) {
getOrCreateStoryViewer().open(context, chatInfo.stories, provider);
} else {
expandAvatar();
}
}
};
updateStoriesViewBounds(false);
storyView.setUserFull(userInfo);
if (userInfo != null) {
storyView.setStories(userInfo.stories);
} else if (chatInfo != null) {
storyView.setStories(chatInfo.stories);
}
if (avatarImage != null) {
avatarImage.setHasStories(needInsetForStories());
}
avatarContainer2.addView(storyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
updateProfileData(true);
@ -4386,9 +4434,171 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
actionBarBackgroundPaint.setColor(getThemedColor(Theme.key_listSelector));
contentView.blurBehindViews.add(sharedMediaLayout);
updateTtlIcon();
createFloatingActionButton(getContext());
return fragmentView;
}
FrameLayout floatingButtonContainer;
RLottieImageView floatingButton;
boolean floatingHidden;
float floatingButtonHideProgress;
boolean showBoostsAlert;
private final AccelerateDecelerateInterpolator floatingInterpolator = new AccelerateDecelerateInterpolator();
private void createFloatingActionButton(Context context) {
if (getDialogId() > 0L) {
return;
}
StoriesController storiesController = getMessagesController().getStoriesController();
if (!storiesController.canPostStories(getDialogId())) {
return;
} else {
waitCanSendStoryRequest = true;
storiesController.canSendStoryFor(getDialogId(), canSend -> {
waitCanSendStoryRequest = false;
showBoostsAlert = !canSend;
hideFloatingButton(false);
}, false, resourcesProvider);
}
long dialogId = getDialogId();
floatingButtonContainer = new FrameLayout(context);
floatingButtonContainer.setVisibility(View.VISIBLE);
contentView.addView(floatingButtonContainer, LayoutHelper.createFrame((Build.VERSION.SDK_INT >= 21 ? 56 : 60), (Build.VERSION.SDK_INT >= 21 ? 56 : 60), (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.BOTTOM, LocaleController.isRTL ? 14 : 0, 0, LocaleController.isRTL ? 0 : 14, 14));
floatingButtonContainer.setOnClickListener(v -> {
if (showBoostsAlert) {
if (loadingBoostsStats) {
return;
}
MessagesController messagesController = MessagesController.getInstance(currentAccount);
loadingBoostsStats = true;
messagesController.getBoostsController().getBoostsStats(dialogId, boostsStatus -> {
loadingBoostsStats = false;
if (boostsStatus == null) {
return;
}
BaseFragment lastFragment = LaunchActivity.getLastFragment();
LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(lastFragment, lastFragment.getContext(), LimitReachedBottomSheet.TYPE_BOOSTS_FOR_POSTING, currentAccount, resourcesProvider);
limitReachedBottomSheet.setBoostsStats(boostsStatus, false);
limitReachedBottomSheet.setDialogId(dialogId);
limitReachedBottomSheet.showStatisticButtonInLink(() -> {
TLRPC.Chat chat = getMessagesController().getChat(chatId);
Bundle args = new Bundle();
args.putLong("chat_id", chatId);
args.putBoolean("is_megagroup", chat.megagroup);
args.putBoolean("start_from_boosts", true);
if (chatInfo == null || !chatInfo.can_view_stats) {
args.putBoolean("only_boosts", chat.megagroup);
};
StatisticActivity fragment = new StatisticActivity(args);
presentFragment(fragment);
});
limitReachedBottomSheet.show();
});
return;
}
StoryRecorder.getInstance(getParentActivity(), currentAccount)
.selectedPeerId(getDialogId())
.canChangePeer(false)
.closeToWhenSent(new StoryRecorder.ClosingViewProvider() {
@Override
public void preLayout(long dialogId, Runnable runnable) {
avatarImage.setHasStories(needInsetForStories());
if (dialogId == getDialogId()) {
collapseAvatarInstant();
}
AndroidUtilities.runOnUIThread(runnable, 30);
}
@Override
public StoryRecorder.SourceView getView(long dialogId) {
if (dialogId != getDialogId()) {
return null;
}
return StoryRecorder.SourceView.fromAvatarImage(avatarImage);
}
})
.open(StoryRecorder.SourceView.fromFloatingButton(floatingButtonContainer), true);
});
floatingButton = new RLottieImageView(context);
floatingButton.setScaleType(ImageView.ScaleType.CENTER);
floatingButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_actionIcon), PorterDuff.Mode.MULTIPLY));
if (Build.VERSION.SDK_INT >= 21) {
StateListAnimator animator = new StateListAnimator();
animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(floatingButtonContainer, View.TRANSLATION_Z, AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200));
animator.addState(new int[]{}, ObjectAnimator.ofFloat(floatingButtonContainer, View.TRANSLATION_Z, AndroidUtilities.dp(4), AndroidUtilities.dp(2)).setDuration(200));
floatingButtonContainer.setStateListAnimator(animator);
floatingButtonContainer.setOutlineProvider(new ViewOutlineProvider() {
@SuppressLint("NewApi")
@Override
public void getOutline(View view, Outline outline) {
outline.setOval(0, 0, AndroidUtilities.dp(56), AndroidUtilities.dp(56));
}
});
}
floatingButtonContainer.addView(floatingButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
floatingButton.setAnimation(R.raw.write_contacts_fab_icon_camera, 56, 56);
floatingButtonContainer.setContentDescription(LocaleController.getString("AccDescrCaptureStory", R.string.AccDescrCaptureStory));
updateFloatingButtonColor();
}
private void collapseAvatarInstant() {
if (allowPullingDown && currentExpandAnimatorValue > 0) {
layoutManager.scrollToPositionWithOffset(0, AndroidUtilities.dp(88) - listView.getPaddingTop());
listView.post(() -> {
needLayout(true);
if (expandAnimator.isRunning()) {
expandAnimator.cancel();
}
setAvatarExpandProgress(1f);
});
}
}
private void updateFloatingButtonColor() {
if (getParentActivity() == null) {
return;
}
Drawable drawable;
if (floatingButtonContainer != null) {
drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_chats_actionBackground), Theme.getColor(Theme.key_chats_actionPressedBackground));
if (Build.VERSION.SDK_INT < 21) {
Drawable shadowDrawable = ContextCompat.getDrawable(getParentActivity(), R.drawable.floating_shadow).mutate();
shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY));
CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0);
combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56));
drawable = combinedDrawable;
}
floatingButtonContainer.setBackground(drawable);
}
}
private void hideFloatingButton(boolean hide) {
if (floatingHidden == hide || floatingButtonContainer == null || waitCanSendStoryRequest) {
return;
}
floatingHidden = hide;
AnimatorSet animatorSet = new AnimatorSet();
ValueAnimator valueAnimator = ValueAnimator.ofFloat(floatingButtonHideProgress, floatingHidden ? 1f : 0f);
valueAnimator.addUpdateListener(animation -> {
floatingButtonHideProgress = (float) animation.getAnimatedValue();
updateFloatingButtonOffset();
});
animatorSet.playTogether(valueAnimator);
animatorSet.setDuration(300);
animatorSet.setInterpolator(floatingInterpolator);
floatingButtonContainer.setClickable(!hide);
animatorSet.start();
}
private void updateFloatingButtonOffset() {
if (floatingButtonContainer != null) {
floatingButtonContainer.setTranslationY(AndroidUtilities.dp(100) * floatingButtonHideProgress);
}
}
private boolean expandAvatar() {
if (!AndroidUtilities.isTablet() && !isInLandscapeMode && avatarImage.getImageReceiver().hasNotThumb() && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) {
openingAvatar = true;
@ -6324,6 +6534,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
if (chatInfo != null && (chatInfo.call == null && !hasVoiceChatItem || chatInfo.call != null && hasVoiceChatItem)) {
createActionBarMenu(false);
}
if (storyView != null && chatInfo != null) {
storyView.setStories(chatInfo.stories);
}
if (avatarImage != null) {
avatarImage.setHasStories(needInsetForStories());
}
}
} else if (id == NotificationCenter.chatInfoDidLoad) {
TLRPC.ChatFull chatFull = (TLRPC.ChatFull) args[0];
@ -6355,6 +6571,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
updateAutoDeleteItem();
updateTtlIcon();
if (storyView != null && chatInfo != null) {
storyView.setStories(chatInfo.stories);
}
if (avatarImage != null) {
avatarImage.setHasStories(needInsetForStories());
}
if (sharedMediaLayout != null) {
sharedMediaLayout.setChatInfo(chatInfo);
}
}
} else if (id == NotificationCenter.closeChats) {
removeSelfFromStack(true);
@ -6369,7 +6594,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
if (uid == userId) {
userInfo = (TLRPC.UserFull) args[1];
if (storyView != null) {
storyView.setUserFull(userInfo);
storyView.setStories(userInfo.stories);
}
if (avatarImage != null) {
avatarImage.setHasStories(needInsetForStories());
}
if (sharedMediaLayout != null) {
sharedMediaLayout.setUserInfo(userInfo);
@ -6447,6 +6675,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
} else if (id == NotificationCenter.reloadDialogPhotos) {
updateProfileData(false);
} else if (id == NotificationCenter.storiesUpdated) {
if (avatarImage != null) {
avatarImage.setHasStories(needInsetForStories());
}
}
}
@ -6697,7 +6929,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
public void setAvatarAnimationProgress(float progress) {
avatarAnimationProgress = currentExpandAnimatorValue = progress;
checkPhotoDescriptionAlpha();
if (playProfileAnimation == 2) {
avatarImage.setProgressToExpand(progress);
}
@ -6766,6 +6997,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
if (aboutLinkCell != null) {
aboutLinkCell.invalidate();
}
if (getDialogId() > 0) {
if (avatarImage != null) {
avatarImage.setProgressToStoriesInsets(avatarAnimationProgress);
}
if (storyView != null) {
storyView.setProgressToStoriesInsets(avatarAnimationProgress);
}
}
}
boolean profileTransitionInProgress;
@ -6879,6 +7119,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
ttlIconView.setAlpha(0f);
animators.add(ObjectAnimator.ofFloat(ttlIconView, View.ALPHA, 1.0f));
}
if (floatingButtonContainer != null) {
floatingButtonContainer.setAlpha(0f);
animators.add(ObjectAnimator.ofFloat(floatingButtonContainer, View.ALPHA, 1.0f));
}
boolean onlineTextCrosafade = false;
@ -6943,6 +7187,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
if (ttlIconView != null) {
animators.add(ObjectAnimator.ofFloat(ttlIconView, View.ALPHA, ttlIconView.getAlpha(), 0.0f));
}
if (floatingButtonContainer != null) {
animators.add(ObjectAnimator.ofFloat(floatingButtonContainer, View.ALPHA, 0.0f));
}
boolean crossfadeOnlineText = false;
BaseFragment previousFragment = parentLayout.getFragmentStack().size() > 1 ? parentLayout.getFragmentStack().get(parentLayout.getFragmentStack().size() - 2) : null;
if (previousFragment instanceof ChatActivity) {
@ -7071,17 +7318,26 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
if (avatarsViewPager != null && !isTopic) {
avatarsViewPager.setChatInfo(chatInfo);
}
if (storyView != null && chatInfo != null) {
storyView.setStories(chatInfo.stories);
}
if (avatarImage != null) {
avatarImage.setHasStories(needInsetForStories());
}
fetchUsersFromChannelInfo();
}
private boolean needInsetForStories() {
return getDialogId() < 0 && getMessagesController().getStoriesController().hasStories(getDialogId());
return getMessagesController().getStoriesController().hasStories(getDialogId());
}
public void setUserInfo(TLRPC.UserFull value) {
userInfo = value;
if (storyView != null) {
storyView.setUserFull(userInfo);
storyView.setStories(userInfo.stories);
}
if (avatarImage != null) {
avatarImage.setHasStories(needInsetForStories());
}
if (sharedMediaLayout != null) {
sharedMediaLayout.setUserInfo(userInfo);
@ -7224,6 +7480,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
if (!hasMedia && userInfo != null) {
hasMedia = userInfo.stories_pinned_available;
}
if (!hasMedia && chatInfo != null) {
hasMedia = chatInfo.stories_pinned_available;
}
if (userId != 0) {
if (LocaleController.isRTL) {
@ -8166,7 +8425,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
otherItem.addSubItem(call_item, R.drawable.msg_voicechat, chat.megagroup && !chat.gigagroup ? LocaleController.getString("StartVoipChat", R.string.StartVoipChat) : LocaleController.getString("StartVoipChannel", R.string.StartVoipChannel));
hasVoiceChatItem = true;
}
if (chatInfo.can_view_stats && topicId == 0) {
if ((chatInfo.can_view_stats || getMessagesController().getStoriesController().canPostStories(getDialogId())) && topicId == 0) {
otherItem.addSubItem(statistics, R.drawable.msg_stats, LocaleController.getString("Statistics", R.string.Statistics));
}
ChatObject.Call call = getMessagesController().getGroupCall(chatId, false);
@ -8184,6 +8443,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
otherItem.addSubItem(delete_topic, R.drawable.msg_delete, LocaleController.getPluralString("DeleteTopics", 1));
}
} else {
if (chat.creator || chat.admin_rights != null && chat.admin_rights.edit_stories) {
otherItem.addSubItem(channel_stories, R.drawable.msg_archive, LocaleController.getString(R.string.OpenChannelArchiveStories));
}
if (ChatObject.isPublic(chat)) {
otherItem.addSubItem(share, R.drawable.msg_share, LocaleController.getString("BotShare", R.string.BotShare));
}

View file

@ -106,6 +106,7 @@ import java.util.List;
public class QrActivity extends BaseFragment {
private static final ArrayMap<String, int[]> qrColorsMap = new ArrayMap<>();
private static final int LOGO_OPTIMAL_FRAME = 33;
private static List<EmojiThemes> cachedThemes;
static {
@ -380,6 +381,7 @@ public class QrActivity extends BaseFragment {
}
fragmentView.postDelayed(() -> {
onItemSelected(currentTheme, 0, true);
logoImageView.getAnimatedDrawable().cacheFrame(LOGO_OPTIMAL_FRAME);
}, 17);
}, 25);
@ -714,10 +716,8 @@ public class QrActivity extends BaseFragment {
themeLayout.setVisibility(View.GONE);
closeImageView.setVisibility(View.GONE);
logoImageView.stopAnimation();
logoImageView.setVisibility(View.GONE);
RLottieDrawable drawable = logoImageView.getAnimatedDrawable();
int currentFrame = drawable.getCurrentFrame();
drawable.setCurrentFrame(33, false);
if (qrView != null) {
qrView.setForShare(true);
@ -726,12 +726,13 @@ public class QrActivity extends BaseFragment {
fragmentView.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
fragmentView.layout(0, 0, width, height);
fragmentView.draw(canvas);
drawable.setBounds(logoImageView.getLeft(), logoImageView.getTop(), logoImageView.getRight(), logoImageView.getBottom());
drawable.drawFrame(canvas, LOGO_OPTIMAL_FRAME);
canvas.setBitmap(null);
themeLayout.setVisibility(View.VISIBLE);
closeImageView.setVisibility(View.VISIBLE);
drawable.setCurrentFrame(currentFrame, false);
logoImageView.playAnimation();
logoImageView.setVisibility(View.VISIBLE);
ViewGroup parent = (ViewGroup) fragmentView.getParent();
fragmentView.layout(0, 0, parent.getWidth(), parent.getHeight());

View file

@ -1652,9 +1652,8 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD
@Override
public void onAnimationEnd(Animator animation) {
if (photoAnimationEndRunnable != null) {
Runnable r = photoAnimationEndRunnable;
photoAnimationEndRunnable.run();
photoAnimationEndRunnable = null;
r.run();
}
}
});
@ -1966,9 +1965,8 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD
if (photoAnimationInProgress != 0) {
if (Math.abs(photoTransitionAnimationStartTime - System.currentTimeMillis()) >= 500) {
if (photoAnimationEndRunnable != null) {
Runnable r = photoAnimationEndRunnable;
photoAnimationEndRunnable.run();
photoAnimationEndRunnable = null;
r.run();
}
photoAnimationInProgress = 0;
}
@ -2119,9 +2117,8 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD
isVisible = false;
AndroidUtilities.runOnUIThread(() -> {
if (photoAnimationEndRunnable != null) {
Runnable r = photoAnimationEndRunnable;
photoAnimationEndRunnable.run();
photoAnimationEndRunnable = null;
r.run();
}
});
}
@ -2163,9 +2160,8 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD
@Override
public void onAnimationEnd(Animator animation) {
if (photoAnimationEndRunnable != null) {
Runnable r = photoAnimationEndRunnable;
photoAnimationEndRunnable.run();
photoAnimationEndRunnable = null;
r.run();
}
}
});

View file

@ -81,6 +81,9 @@ import java.util.Objects;
public class SessionsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
public static final int TYPE_DEVICES = 0;
public static final int TYPE_WEB_SESSIONS = 1;
private ListAdapter listAdapter;
private RecyclerListView listView;
private EmptyTextProgressView emptyView;
@ -603,6 +606,10 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter
listAdapter.notifyDataSetChanged();
}
if (delegate != null) {
delegate.sessionsLoaded();
}
if (repeatLoad > 0) {
repeatLoad--;
if (repeatLoad > 0) {
@ -1243,7 +1250,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter
}
}
int getSessionsCount() {
public int getSessionsCount() {
if (sessions.size() == 0 && loading) {
return 0;
}

View file

@ -17,6 +17,7 @@ import android.os.Bundle;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@ -38,6 +39,7 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.LruCache;
import org.telegram.messenger.MessageObject;
@ -75,6 +77,7 @@ import org.telegram.ui.Charts.data.StackLinearChartData;
import org.telegram.ui.Charts.view_data.ChartHeaderView;
import org.telegram.ui.Charts.view_data.LineViewData;
import org.telegram.ui.Charts.view_data.TransitionParams;
import org.telegram.ui.Components.BottomPagerTabs;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.Components.ChatAvatarContainer;
import org.telegram.ui.Components.CombinedDrawable;
@ -83,6 +86,8 @@ import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RLottieImageView;
import org.telegram.ui.Components.RadialProgressView;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.ViewPagerFixed;
import org.telegram.ui.Components.voip.VoIPHelper;
import java.util.ArrayList;
import java.util.Arrays;
@ -90,7 +95,8 @@ import java.util.Locale;
public class StatisticActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
private final TLRPC.ChatFull chat;
private TLRPC.ChatFull chat;
private final long chatId;
//mutual
private ChartViewData growthData;
@ -133,15 +139,21 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
private BaseChartView.SharedUiComponents sharedUi;
private LinearLayout progressLayout;
private final boolean isMegagroup;
private boolean startFromBoosts;
private long maxDateOverview;
private long minDateOverview;
private AlertDialog[] progressDialog = new AlertDialog[1];
private ViewPagerFixed viewPagerFixed;
private ChannelBoostLayout boosLayout;
private boolean onlyBoostsStat;
public StatisticActivity(Bundle args) {
super(args);
long chatId = args.getLong("chat_id");
chatId = args.getLong("chat_id");
isMegagroup = args.getBoolean("is_megagroup", false);
startFromBoosts = args.getBoolean("start_from_boosts", false);
onlyBoostsStat = args.getBoolean("only_boosts", false);
this.chat = getMessagesController().getChatFull(chatId);
}
@ -164,16 +176,28 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
@Override
public boolean onFragmentCreate() {
getNotificationCenter().addObserver(this, NotificationCenter.messagesDidLoad);
getNotificationCenter().addObserver(this, NotificationCenter.chatInfoDidLoad);
if (chat != null) {
loadStatistic();
} else {
MessagesController.getInstance(currentAccount).loadFullChat(chatId, classGuid, true);
}
return super.onFragmentCreate();
}
private void loadStatistic() {
if (onlyBoostsStat) {
return;
}
TLObject req;
if (isMegagroup) {
TLRPC.TL_stats_getMegagroupStats getMegagroupStats = new TLRPC.TL_stats_getMegagroupStats();
req = getMegagroupStats;
getMegagroupStats.channel = MessagesController.getInstance(currentAccount).getInputChannel(chat.id);
getMegagroupStats.channel = MessagesController.getInstance(currentAccount).getInputChannel(chatId);
} else {
TLRPC.TL_stats_getBroadcastStats getBroadcastStats = new TLRPC.TL_stats_getBroadcastStats();
req = getBroadcastStats;
getBroadcastStats.channel = MessagesController.getInstance(currentAccount).getInputChannel(chat.id);
getBroadcastStats.channel = MessagesController.getInstance(currentAccount).getInputChannel(chatId);
}
@ -212,7 +236,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
if (recentPostsAll.size() > 0) {
int lastPostId = recentPostsAll.get(0).counters.msg_id;
int count = recentPostsAll.size();
getMessagesStorage().getMessages(-chat.id, 0, false, count, lastPostId, 0, 0, classGuid, 0, false, 0, 0, true, false, null);
getMessagesStorage().getMessages(-chatId, 0, false, count, lastPostId, 0, 0, classGuid, 0, false, 0, 0, true, false, null);
}
AndroidUtilities.runOnUIThread(() -> {
@ -298,7 +322,6 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
}, null, null, 0, chat.stats_dc, ConnectionsManager.ConnectionTypeGeneric, true);
getConnectionsManager().bindRequestToGuid(reqId, classGuid);
return super.onFragmentCreate();
}
private void dataLoaded(ChartViewData[] chartsViewData) {
@ -331,6 +354,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
@Override
public void onFragmentDestroy() {
getNotificationCenter().removeObserver(this, NotificationCenter.messagesDidLoad);
getNotificationCenter().removeObserver(this, NotificationCenter.chatInfoDidLoad);
if (progressDialog[0] != null) {
progressDialog[0].dismiss();
progressDialog[0] = null;
@ -381,14 +405,102 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
diffUtilsCallback.update();
}
}
} else if (id == NotificationCenter.chatInfoDidLoad) {
TLRPC.ChatFull chatFull = (TLRPC.ChatFull) args[0];
if (chatFull.id == chatId) {
if (chat == null) {
chat = chatFull;
loadStatistic();
}
}
}
}
@Override
public View createView(Context context) {
sharedUi = new BaseChartView.SharedUiComponents();
FrameLayout frameLayout = new FrameLayout(context);
fragmentView = frameLayout;
boolean isChannel = ChatObject.isChannelAndNotMegaGroup(chatId, currentAccount);
BottomPagerTabs storiesTabsView = new BottomPagerTabs(context, getResourceProvider()) {
@Override
public Tab[] createTabs() {
Tab[] tabs = new Tab[]{
new Tab(0, R.raw.stats, LocaleController.getString("Statistics", R.string.Statistics)),
new Tab(1, R.raw.boosts, LocaleController.getString("Boosts", R.string.Boosts))
};
tabs[1].customEndFrameMid = 25;
tabs[1].customEndFrameEnd = 49;
return tabs;
}
};
viewPagerFixed = new ViewPagerFixed(getContext()) {
@Override
protected void onTabAnimationUpdate(boolean manual) {
if (manual) {
return;
}
float progress = currentProgress;
if (currentPosition == 0) {
progress = 1f - progress;
}
storiesTabsView.setScrolling(true);
storiesTabsView.setProgress(progress);
}
};
storiesTabsView.setOnTabClick(position -> {
if (viewPagerFixed.scrollToPosition(position)) {
storiesTabsView.setScrolling(false);
storiesTabsView.setProgress(position);
}
});
FrameLayout statisticLayout = new FrameLayout(context);
if (isChannel) {
boosLayout = new ChannelBoostLayout(StatisticActivity.this, -chatId, getResourceProvider());
}
boolean showTabs = isChannel && !onlyBoostsStat;
if (showTabs && startFromBoosts) {
viewPagerFixed.setPosition(1);
}
viewPagerFixed.setAdapter(new ViewPagerFixed.Adapter() {
@Override
public int getItemCount() {
if (onlyBoostsStat) {
return 1;
}
if (isChannel) {
return 2;
}
return 1;
}
@Override
public View createView(int viewType) {
if (onlyBoostsStat) {
return boosLayout;
}
return viewType == 0 ? statisticLayout : boosLayout;
}
@Override
public int getItemViewType(int position) {
return position;
}
@Override
public void bindView(View view, int position, int viewType) {
}
});
FrameLayout contentLayout = new FrameLayout(getContext());
contentLayout.addView(viewPagerFixed, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 0, 0, 0, showTabs ? 64 : 0));
if (showTabs) {
contentLayout.addView(storiesTabsView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL));
}
fragmentView = contentLayout;
recyclerListView = new RecyclerListView(context) {
int lastH;
@ -429,7 +541,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
progressLayout.addView(loadingTitle, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 10));
progressLayout.addView(loadingSubtitle, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL));
frameLayout.addView(progressLayout, LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 30));
statisticLayout.addView(progressLayout, LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 0, 0, 30));
if (adapter == null) {
@ -509,7 +621,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
presentFragment(activity);
} else if (i == 1) {
Bundle bundle = new Bundle();
bundle.putLong("chat_id", chat.id);
bundle.putLong("chat_id", chatId);
bundle.putInt("message_id", messageObject.getId());
bundle.putBoolean("need_remove_previous_same_chat_activity", false);
ChatActivity chatActivity = new ChatActivity(bundle);
@ -535,17 +647,17 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
return false;
});
frameLayout.addView(recyclerListView);
statisticLayout.addView(recyclerListView);
avatarContainer = new ChatAvatarContainer(context, null, false);
avatarContainer.setOccupyStatusBar(!AndroidUtilities.isTablet());
actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !inPreviewMode ? 56 : 0, 0, 40, 0));
TLRPC.Chat chatLocal = getMessagesController().getChat(chat.id);
TLRPC.Chat chatLocal = getMessagesController().getChat(chatId);
avatarContainer.setChatAvatar(chatLocal);
avatarContainer.setTitle(chatLocal.title);
avatarContainer.setSubtitle(LocaleController.getString("Statistics", R.string.Statistics));
avatarContainer.hideSubtitle();
actionBar.setBackButtonDrawable(new BackDrawable(false));
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
@ -1867,7 +1979,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
}
}
}
req.channel = MessagesController.getInstance(currentAccount).getInputChannel(chat.id);
req.channel = MessagesController.getInstance(currentAccount).getInputChannel(chatId);
messagesIsLoading = true;
getConnectionsManager().sendRequest(req, (response, error) -> {
@ -2319,7 +2431,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
dif = (int) (stats.viewers.current - stats.viewers.previous);
difPercent = stats.viewers.previous == 0 ? 0 : Math.abs(dif / (float) stats.viewers.previous * 100f);
viewingMembersTitle = LocaleController.getString("ViewingMembers", R.string.ViewingMembers);
viewingMembersTitle = LocaleController.getString("ViewingMembers", R.string.ViewingMembers);
viewingMembersPrimary = AndroidUtilities.formatWholeNumber((int) stats.viewers.current, 0);
if (dif == 0 || difPercent == 0) {
@ -2444,6 +2556,14 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
updateColors();
}
public void setData(int index, String primary, String secondary, String title) {
this.primary[index].setText(primary);
this.secondary[index].setText(secondary);
this.title[index].setText(title);
updateColors();
}
private void updateColors() {
for (int i = 0; i < 4; i++) {
primary[i].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
@ -2702,4 +2822,12 @@ public class StatisticActivity extends BaseFragment implements NotificationCente
int color = Theme.getColor(Theme.key_windowBackgroundWhite);
return ColorUtils.calculateLuminance(color) > 0.7f;
}
@Override
public boolean isSwipeBackEnabled(MotionEvent event) {
if (viewPagerFixed != null && (viewPagerFixed.currentPosition != 0 || viewPagerFixed.currentProgress != 1f)) {
return false;
}
return super.isSwipeBackEnabled(event);
}
}

View file

@ -0,0 +1,19 @@
package org.telegram.ui.Stories;
import android.text.TextUtils;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.MessagesController;
import org.telegram.tgnet.TLRPC;
public class ChannelBoostUtilities {
public static String createLink(int currentAccount, long dialogId) {
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId);
String username = ChatObject.getPublicUsername(chat);
if (!TextUtils.isEmpty(username)) {
return "https://t.me/" + ChatObject.getPublicUsername(chat) + "?boost";
} else {
return "https://t.me/c/" + -dialogId + "?boost";
}
}
}

View file

@ -34,10 +34,9 @@ import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.exoplayer2.util.Log;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.BotWebViewVibrationEffect;
import org.telegram.messenger.DialogObject;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.LocaleController;
@ -126,7 +125,6 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
DefaultItemAnimator itemAnimator;
LinearLayoutManager layoutManager;
AnimatedTextView titleView;
boolean progressWasDrawn;
boolean drawCircleForce;
ArrayList<Runnable> afterNextLayout = new ArrayList<>();
private float collapsedProgress1 = -1;
@ -206,14 +204,11 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
openStoryForCell(cell, false);
};
recyclerListView.setOnItemClickListener(itemClickListener);
recyclerListView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListener() {
@Override
public boolean onItemClick(View view, int position) {
if (collapsedProgress == 0 && overscrollPrgoress == 0) {
onUserLongPressed(view, ((StoryCell) view).dialogId);
}
return false;
recyclerListView.setOnItemLongClickListener((view, position) -> {
if (collapsedProgress == 0 && overscrollPrgoress == 0) {
onUserLongPressed(view, ((StoryCell) view).dialogId);
}
return false;
});
recyclerListView.setAdapter(adapter);
@ -227,7 +222,6 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
titleView.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8));
titleView.setTextSize(AndroidUtilities.dp(!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? 18 : 20));
addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
ellipsizeSpanAnimator.addView(titleView);
titleView.setAlpha(0f);
@ -334,10 +328,10 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
}
return;
}
if (!storiesController.hasStories(cell.dialogId) && (!cell.isSelf || !storiesController.hasUploadingStories())) {
if (!storiesController.hasStories(cell.dialogId) && !storiesController.hasUploadingStories(cell.dialogId)) {
return;
}
TLRPC.TL_userStories userStories = storiesController.getStories(cell.dialogId);
TLRPC.PeerStories userStories = storiesController.getStories(cell.dialogId);
long startFromDialogId = cell.dialogId;
if (globalCancelable != null) {
globalCancelable.cancel();
@ -437,10 +431,11 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
items.add(new Item(UserConfig.getInstance(currentAccount).getClientUserId()));
}
ArrayList<TLRPC.TL_userStories> allStories = type == TYPE_ARCHIVE ? storiesController.getHiddenList() : storiesController.getDialogListStories();
ArrayList<TLRPC.PeerStories> allStories = type == TYPE_ARCHIVE ? storiesController.getHiddenList() : storiesController.getDialogListStories();
for (int i = 0; i < allStories.size(); i++) {
if (allStories.get(i).user_id != UserConfig.getInstance(currentAccount).getClientUserId()) {
items.add(new Item(allStories.get(i).user_id));
long dialogId = DialogObject.getPeerDialogId(allStories.get(i).peer);
if (dialogId != UserConfig.getInstance(currentAccount).getClientUserId()) {
items.add(new Item(dialogId));
}
}
int size = items.size();
@ -452,7 +447,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
totalCount = Math.max(1, Math.max(storiesController.getTotalStoriesCount(hidden), size));
if (storiesController.hasOnlySelfStories()) {
if (!storiesController.getUploadingStories().isEmpty()) {
if (storiesController.hasUploadingStories(UserConfig.getInstance(currentAccount).getClientUserId())) {
String str = LocaleController.getString("UploadingStory", R.string.UploadingStory);
int index = str.indexOf("");
if (index > 0) {
@ -877,7 +872,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
public void openStoryRecorder() {
final StoriesController.StoryLimit storyLimit = MessagesController.getInstance(currentAccount).getStoriesController().checkStoryLimit();
if (storyLimit != null) {
fragment.showDialog(new LimitReachedBottomSheet(fragment, getContext(), storyLimit.getLimitReachedType(), currentAccount, fragment.getResourceProvider()));
fragment.showDialog(new LimitReachedBottomSheet(fragment, getContext(), storyLimit.getLimitReachedType(), currentAccount, null));
return;
}
@ -899,6 +894,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
EllipsizeSpanAnimator ellipsizeSpanAnimator = new EllipsizeSpanAnimator(this);
public void setTitleOverlayText(String titleOverlayText, int textId) {
boolean hasEllipsizedText = false;
if (titleOverlayText != null) {
hasOverlayText = true;
if (overlayTextId != textId) {
@ -910,6 +906,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
if (index >= 0) {
SpannableString spannableString = SpannableString.valueOf(textToSet);
ellipsizeSpanAnimator.wrap(spannableString, index);
hasEllipsizedText = true;
textToSet = spannableString;
}
}
@ -920,6 +917,11 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
overlayTextId = 0;
titleView.setText(currentTitle, true);
}
if (hasEllipsizedText) {
ellipsizeSpanAnimator.addView(titleView);
} else {
ellipsizeSpanAnimator.removeView(titleView);
}
}
public void setClipTop(int clipTop) {
@ -944,7 +946,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
public void onResume() {
storiesController.checkExpiredStories();
for (int i = 0; i < items.size(); i++) {
TLRPC.TL_userStories stories = storiesController.getStories(items.get(i).dialogId);
TLRPC.PeerStories stories = storiesController.getStories(items.get(i).dialogId);
if (stories != null) {
storiesController.preloadUserStories(stories);
}
@ -956,6 +958,8 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
invalidate();
recyclerListView.invalidate();
if (overscrollPrgoress != 0) {
setClipChildren(false);
recyclerListView.setClipChildren(false);
((ViewGroup) getParent()).setClipChildren(false);
} else {
((ViewGroup) getParent()).setClipChildren(true);
@ -1040,7 +1044,8 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
}
}
public StoryCell findSelfStoryCell() {
public StoryCell findStoryCell(long dialogId) {
RecyclerListView parent = recyclerListView;
if (currentState == COLLAPSED_STATE) {
parent = listViewMini;
@ -1049,7 +1054,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
View child = parent.getChildAt(i);
if (child instanceof StoryCell) {
StoryCell storyCell = (StoryCell) child;
if (storyCell.isSelf) {
if (storyCell.dialogId == dialogId) {
return storyCell;
}
}
@ -1057,6 +1062,8 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
return null;
}
public class StoryCell extends FrameLayout {
public boolean drawInParent;
public int position;
@ -1093,6 +1100,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
private boolean isUploadingState;
private float overscrollProgress;
private boolean selectedForOverscroll;
boolean progressWasDrawn;
private final AnimatedFloat failT = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
@ -1141,7 +1149,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
this.dialogId = dialogId;
isSelf = dialogId == UserConfig.getInstance(currentAccount).getClientUserId();
isFail = isSelf && storiesController.isLastUploadingFailed();
isFail = storiesController.isLastUploadingFailed(dialogId);
TLObject object;
if (dialogId > 0) {
object = user = MessagesController.getInstance(currentAccount).getUser(dialogId);
@ -1161,18 +1169,18 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
if (mini) {
return;
}
if (dialogId == UserConfig.getInstance(currentAccount).getClientUserId()) {
textView.setRightDrawable(null);
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) {
StoriesUtilities.applyUploadingStr(textView, true, false);
isUploadingState = true;
} else {
textView.setRightDrawable(null);
if (storiesController.isLastUploadingFailed(dialogId)) {
textView.setText(LocaleController.getString("FailedStory", R.string.FailedStory));
isUploadingState = false;
} else if (!Utilities.isNullOrEmpty(storiesController.getUploadingStories(dialogId))) {
StoriesUtilities.applyUploadingStr(textView, true, false);
isUploadingState = true;
} else if (storiesController.getEditingStory(dialogId) != null) {
StoriesUtilities.applyUploadingStr(textView, true, false);
isUploadingState = true;
} else {
if (isSelf) {
if (animated && isUploadingState && !mini) {
View oldTextView = textView;
createTextView();
@ -1213,33 +1221,34 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
AndroidUtilities.runOnUIThread(animationRunnable, 500);
isUploadingState = false;
textView.setText(LocaleController.getString("MyStory", R.string.MyStory));//, animated);
}
} else if (user != null) {
String name = user.first_name == null ? "" : user.first_name.trim();
int index = name.indexOf(" ");
if (index > 0) {
name = name.substring(0, index);
}
if (user.verified) {
if (verifiedDrawable == null) {
verifiedDrawable = createVerifiedDrawable();
} else if (user != null) {
String name = user.first_name == null ? "" : user.first_name.trim();
int index = name.indexOf(" ");
if (index > 0) {
name = name.substring(0, index);
}
CharSequence text = name;
text = Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), false);
textView.setText(text);
textView.setRightDrawable(verifiedDrawable);
if (user.verified) {
if (verifiedDrawable == null) {
verifiedDrawable = createVerifiedDrawable();
}
CharSequence text = name;
text = Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), false);
textView.setText(text);
textView.setRightDrawable(verifiedDrawable);
} else {
CharSequence text = name;
text = Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), false);
textView.setText(text);
textView.setRightDrawable(null);
}//, false);
} else {
CharSequence text = name;
CharSequence text = chat.title;
text = Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), false);
textView.setText(text);
textView.setText(text);//, false);
textView.setRightDrawable(null);
}//, false);
} else {
CharSequence text = chat.title;
text = Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), false);
textView.setText(text);//, false);
textView.setRightDrawable(null);
}
}
}
@Override
@ -1294,125 +1303,122 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
if (progressToCollapsed != 0) {
canvas.drawCircle(cx, cy, radius + AndroidUtilities.dp(3), backgroundPaint);
}
if (isSelf) {
canvas.save();
canvas.scale(bounceScale, bounceScale, cx, cy);
if (radialProgress == null) {
radialProgress = DialogStoriesCell.this.radialProgress;
}
if (!storiesController.getUploadingAndEditingStories().isEmpty() || (progressWasDrawn && radialProgress != null && radialProgress.getAnimatedProgress() < 0.98f)) {
float uploadingProgress = 0;
boolean closeFriends = false;
if (storiesController.getUploadingAndEditingStories().isEmpty()) {
uploadingProgress = 1f;
closeFriends = lastUploadingCloseFriends;
} else {
for (int i = 0; i < storiesController.getUploadingAndEditingStories().size(); i++) {
uploadingProgress += storiesController.getUploadingAndEditingStories().get(i).progress;
}
uploadingProgress = uploadingProgress / storiesController.getUploadingAndEditingStories().size();
lastUploadingCloseFriends = closeFriends = storiesController.getUploadingAndEditingStories().get(storiesController.getUploadingAndEditingStories().size() - 1).isCloseFriends();
}
invalidate();
if (radialProgress == null) {
if (DialogStoriesCell.this.radialProgress != null) {
radialProgress = DialogStoriesCell.this.radialProgress;
} else {
DialogStoriesCell.this.radialProgress = radialProgress = new RadialProgress(this);
radialProgress.setBackground(null, true, false);
}
}
if (drawAvatar) {
canvas.save();
canvas.scale(params.getScale(), params.getScale(), params.originalAvatarRect.centerX(), params.originalAvatarRect.centerY());
avatarImage.setImageCoords(params.originalAvatarRect);
avatarImage.draw(canvas);
canvas.restore();
}
radialProgress.setDiff(0);
Paint paint = closeFriends ?
StoriesUtilities.getCloseFriendsPaint(avatarImage) :
StoriesUtilities.getActiveCirclePaint(avatarImage, true);
paint.setAlpha(255);
radialProgress.setPaint(paint);
radialProgress.setProgressRect(
(int) (avatarImage.getImageX() - AndroidUtilities.dp(3)), (int) (avatarImage.getImageY() - AndroidUtilities.dp(3)),
(int) (avatarImage.getImageX2() + AndroidUtilities.dp(3)), (int) (avatarImage.getImageY2() + AndroidUtilities.dp(3))
);
radialProgress.setProgress(Utilities.clamp(uploadingProgress, 1f, 0), progressWasDrawn);
if (avatarImage.getVisible()) {
radialProgress.draw(canvas);
}
progressWasDrawn = true;
drawCircleForce = true;
invalidate();
canvas.save();
canvas.scale(bounceScale, bounceScale, cx, cy);
if (radialProgress == null) {
radialProgress = DialogStoriesCell.this.radialProgress;
}
ArrayList<StoriesController.UploadingStory> uploadingOrEditingStories = storiesController.getUploadingAndEditingStories(dialogId);
boolean hasUploadingStories = (uploadingOrEditingStories != null && !uploadingOrEditingStories.isEmpty());
boolean drawProgress = hasUploadingStories || (progressWasDrawn && radialProgress != null && radialProgress.getAnimatedProgress() < 0.98f);
if (drawProgress) {
float uploadingProgress = 0;
boolean closeFriends;
if (!hasUploadingStories) {
uploadingProgress = 1f;
closeFriends = lastUploadingCloseFriends;
} else {
float failT = this.failT.set(isFail);
if (drawAvatar) {
if (progressWasDrawn) {
animateBounce();
params.forceAnimateProgressToSegments = true;
params.progressToSegments = 0f;
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f);
valueAnimator.addUpdateListener(animation -> {
params.progressToSegments = AndroidUtilities.lerp(0, 1f - collapsedProgress2, (float) animation.getAnimatedValue());
invalidate();
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
params.forceAnimateProgressToSegments = false;
}
});
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);
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);
}
for (int i = 0; i < uploadingOrEditingStories.size(); i++) {
uploadingProgress += uploadingOrEditingStories.get(i).progress;
}
progressWasDrawn = false;
if (drawAvatar) {
canvas.save();
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();
uploadingProgress = uploadingProgress / uploadingOrEditingStories.size();
lastUploadingCloseFriends = closeFriends = uploadingOrEditingStories.get(uploadingOrEditingStories.size() - 1).isCloseFriends();
}
invalidate();
if (radialProgress == null) {
if (DialogStoriesCell.this.radialProgress != null) {
radialProgress = DialogStoriesCell.this.radialProgress;
} else {
DialogStoriesCell.this.radialProgress = radialProgress = new RadialProgress(this);
radialProgress.setBackground(null, true, false);
}
}
canvas.restore();
} else {
if (drawAvatar) {
params.animate = true;
canvas.save();
canvas.scale(params.getScale(), params.getScale(), params.originalAvatarRect.centerX(), params.originalAvatarRect.centerY());
avatarImage.setImageCoords(params.originalAvatarRect);
avatarImage.draw(canvas);
canvas.restore();
}
radialProgress.setDiff(0);
Paint paint = closeFriends ?
StoriesUtilities.getCloseFriendsPaint(avatarImage) :
StoriesUtilities.getActiveCirclePaint(avatarImage, true);
paint.setAlpha(255);
radialProgress.setPaint(paint);
radialProgress.setProgressRect(
(int) (avatarImage.getImageX() - AndroidUtilities.dp(3)), (int) (avatarImage.getImageY() - AndroidUtilities.dp(3)),
(int) (avatarImage.getImageX2() + AndroidUtilities.dp(3)), (int) (avatarImage.getImageY2() + AndroidUtilities.dp(3))
);
radialProgress.setProgress(Utilities.clamp(uploadingProgress, 1f, 0), progressWasDrawn);
if (avatarImage.getVisible()) {
radialProgress.draw(canvas);
}
progressWasDrawn = true;
drawCircleForce = true;
invalidate();
} else {
float failT = this.failT.set(isFail);
if (drawAvatar) {
if (progressWasDrawn) {
animateBounce();
params.forceAnimateProgressToSegments = true;
params.progressToSegments = 0f;
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f);
valueAnimator.addUpdateListener(animation -> {
params.progressToSegments = AndroidUtilities.lerp(0, 1f - collapsedProgress2, (float) animation.getAnimatedValue());
invalidate();
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
params.forceAnimateProgressToSegments = false;
}
});
valueAnimator.setDuration(100);
valueAnimator.start();
}
failT *= params.progressToSegments;
params.animate = !progressWasDrawn;
params.progressToArc = getArcProgress(cx, radius);
params.isLast = isLast;
params.isFirst = isFirst;
if (crossfadeToDialog) {
params.alpha = 1f - failT;
if (!isSelf && crossfadeToDialog) {
params.crossfadeToDialog = crossfadeToDialogId;
params.crossfadeToDialogProgress = progressToCollapsed2;
} else {
params.crossfadeToDialog = 0;
}
StoriesUtilities.drawAvatarWithStory(dialogId, canvas, avatarImage, storiesController.hasStories(dialogId), params);
// avatarImage.draw(canvas);
if (isSelf) {
StoriesUtilities.drawAvatarWithStory(dialogId, canvas, avatarImage, storiesController.hasSelfStories(), params);
} else {
StoriesUtilities.drawAvatarWithStory(dialogId, canvas, avatarImage, storiesController.hasStories(dialogId), params);
}
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) {
canvas.save();
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();
}
}
canvas.restore();
if (crossfadeToDialog && progressToCollapsed2 > 0) {
crossfageToAvatarImage.setImageCoords(x, y, finalSize, finalSize);
@ -1532,7 +1538,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
}
public void drawPlus(Canvas canvas, float cx, float cy, float alpha) {
if (!isSelf || storiesController.hasStories(dialogId) || !storiesController.getUploadingStories().isEmpty()) {
if (!isSelf || storiesController.hasStories(dialogId) || !Utilities.isNullOrEmpty(storiesController.getUploadingStories(dialogId))) {
return;
}
float cx2 = cx + AndroidUtilities.dp(16);
@ -1561,7 +1567,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter
}
public void drawFail(Canvas canvas, float cx, float cy, float alpha) {
if (!isSelf || alpha <= 0) {
if (alpha <= 0) {
return;
}
float cx2 = cx + AndroidUtilities.dp(17);

View file

@ -15,6 +15,7 @@ public class MessageMediaStoryFull extends TLRPC.TL_messageMediaStory {
id = stream.readInt32(exception);
storyItem = TLRPC.StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception);
via_mention = stream.readBool(exception);
peer = MessagesController.getInstance(UserConfig.selectedAccount).getPeer(user_id);
}
public void serializeToStream(AbstractSerializedData stream) {

View file

@ -8,6 +8,7 @@ import static org.telegram.messenger.Utilities.clamp;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
@ -35,11 +36,13 @@ import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter;
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.Components.AnimatedFloat;
import org.telegram.ui.Components.AnimatedTextView;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.RadialProgress;
import org.telegram.ui.ProfileActivity;
import java.util.ArrayList;
@ -56,7 +59,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
private final Paint whitePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final int currentAccount;
private final long userId;
private final long dialogId;
private final View avatarContainer;
private final ProfileActivity.AvatarImageView avatarImage;
@ -70,6 +73,21 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
private final ArrayList<StoryCircle> circles = new ArrayList<>();
private boolean attached;
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private boolean lastDrawnStateIsFailed;
private RadialProgress radialProgress;
private boolean progressWasDrawn;
private boolean progressIsDone;
private float bounceScale = 1f;
private float progressToInsets = 1f;
public void setProgressToStoriesInsets(float progressToInsets) {
if (this.progressToInsets == progressToInsets) {
return;
}
this.progressToInsets = progressToInsets;
invalidate();
}
private class StoryCircle {
public StoryCircle(TLRPC.StoryItem storyItem) {
@ -112,13 +130,16 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
}
}
public ProfileStoriesView(Context context, int currentAccount, long userId, @NonNull View avatarContainer, ProfileActivity.AvatarImageView avatarImage, Theme.ResourcesProvider resourcesProvider) {
StoriesController storiesController;
public ProfileStoriesView(Context context, int currentAccount, long dialogId, @NonNull View avatarContainer, ProfileActivity.AvatarImageView avatarImage, Theme.ResourcesProvider resourcesProvider) {
super(context);
this.currentAccount = currentAccount;
this.userId = userId;
this.dialogId = dialogId;
this.avatarContainer = avatarContainer;
this.avatarImage = avatarImage;
storiesController = MessagesController.getInstance(currentAccount).getStoriesController();
storiesGradientTools = new StoriesGradientTools();
storiesGradientTools.paint.setStyle(Paint.Style.STROKE);
@ -140,7 +161,8 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
titleDrawable.setCallback(this);
clipOutAvatar.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
paint.setStrokeWidth(dpf2(2.33f));
paint.setStyle(Paint.Style.STROKE);
updateStories(false, false);
}
@ -149,18 +171,18 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
return who == titleDrawable || super.verifyDrawable(who);
}
private TLRPC.UserFull userFull;
public void setUserFull(TLRPC.UserFull userFull) {
this.userFull = userFull;
private TLRPC.PeerStories peerStories;
public void setStories(TLRPC.PeerStories peerStories) {
this.peerStories = peerStories;
updateStories(true, false);
}
private void updateStories(boolean animated, boolean asUpdate) {
final boolean me = userId == UserConfig.getInstance(currentAccount).getClientUserId();
TLRPC.TL_userStories userFullStories = userFull != null && !me ? userFull.stories : null;
TLRPC.TL_userStories stateStories = MessagesController.getInstance(currentAccount).getStoriesController().getStories(userId);
final TLRPC.TL_userStories userStories;
if (userId == 0) {
final boolean me = dialogId == UserConfig.getInstance(currentAccount).getClientUserId();
TLRPC.PeerStories userFullStories = peerStories;
TLRPC.PeerStories stateStories = MessagesController.getInstance(currentAccount).getStoriesController().getStories(dialogId);
final TLRPC.PeerStories userStories;
if (dialogId == 0) {
userStories = null;
// } else if (stateStories != null) {
// userStories = stateStories;
@ -309,7 +331,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
}
if (index == -1) {
storyItem.dialogId = userId;
storyItem.dialogId = dialogId;
StoryCircle circle = new StoryCircle(storyItem);
circle.index = i;
circle.scale = 1f;
@ -368,6 +390,8 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
private final AnimatedFloat segmentsCountAnimated = new AnimatedFloat(this, 0, 240 * 2, CubicBezierInterpolator.EASE_OUT_QUINT);
private final AnimatedFloat segmentsUnreadCountAnimated = new AnimatedFloat(this, 0, 240, CubicBezierInterpolator.EASE_OUT_QUINT);
private final AnimatedFloat progressToUploading = new AnimatedFloat(this, 0, 150, CubicBezierInterpolator.DEFAULT);
private final AnimatedFloat progressToFail = new AnimatedFloat(this, 0, 150, CubicBezierInterpolator.DEFAULT);
private float newStoryBounceT = 1;
private ValueAnimator newStoryBounce;
@ -425,7 +449,8 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
@Override
protected void dispatchDraw(Canvas canvas) {
float rright = rightAnimated.set(this.right);
float insetMain = 0;
float insetMain = AndroidUtilities.dpf2(3.5f);
insetMain *= progressToInsets;
float ax = avatarContainer.getX() + insetMain * avatarContainer.getScaleX();
float ay = avatarContainer.getY() + insetMain * avatarContainer.getScaleY();
float aw = (avatarContainer.getWidth() - insetMain * 2) * avatarContainer.getScaleX();
@ -454,13 +479,115 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
Collections.sort(circles, (a, b) -> (int) (b.cachedIndex - a.cachedIndex));
}
final float segmentsAlpha = clamp(1f - expandProgress / 0.2f, 1, 0);
final float segmentsCount = segmentsCountAnimated.set(count);
final float segmentsUnreadCount = segmentsUnreadCountAnimated.set(unreadCount);
float segmentsAlpha = clamp(1f - expandProgress / 0.2f, 1, 0);
boolean isFailed = storiesController.isLastUploadingFailed(dialogId);
boolean isUploading = (storiesController.hasUploadingStories(dialogId) && !isFailed) || progressWasDrawn && !progressIsDone;
float progressToUploading = this.progressToUploading.set(isUploading);
canvas.save();
canvas.scale(bounceScale, bounceScale, rect1.centerX(), rect1.centerY());
// float cy = lerp(rect1.centerY(), this.cy, expandProgress);
float cy = lerp(rect1.centerY(), this.expandY, expandProgress);
storiesGradientTools.setBounds(this.left, cy - dp(24), this.right, cy + dp(24));
if (progressToUploading > 0) {
rect2.set(rect1);
rect2.inset(-dpf2(2.66f + 2.23f / 2), -dpf2(2.66f + 2.23f / 2));
if (radialProgress == null) {
radialProgress = new RadialProgress(this);
radialProgress.setBackground(null, true, false);
}
float uploadingProgress = 0;
if (!storiesController.hasUploadingStories(dialogId) || storiesController.isLastUploadingFailed(dialogId)) {
uploadingProgress = 1f;
} else {
ArrayList<StoriesController.UploadingStory> uploadingOrEditingStories = storiesController.getUploadingStories(dialogId);
for (int i = 0; i < uploadingOrEditingStories.size(); i++) {
uploadingProgress += uploadingOrEditingStories.get(i).progress;
}
uploadingProgress = uploadingProgress / uploadingOrEditingStories.size();
}
radialProgress.setDiff(0);
storiesGradientTools.paint.setAlpha((int) (255 * segmentsAlpha * progressToUploading));
storiesGradientTools.paint.setStrokeWidth(dpf2(2.33f));
radialProgress.setPaint(storiesGradientTools.paint);
radialProgress.setProgressRect((int) rect2.left, (int) rect2.top, (int) rect2.right, (int) rect2.bottom);
radialProgress.setProgress(Utilities.clamp(uploadingProgress, 1f, 0.2f), true);
radialProgress.draw(canvas);
progressWasDrawn = true;
boolean oldIsDone = progressIsDone;
progressIsDone = radialProgress.getAnimatedProgress() >= 0.98f;
if (oldIsDone != progressIsDone) {
animateBounce();
}
} else {
progressWasDrawn = false;
}
if (progressToUploading < 1f) {
segmentsAlpha = clamp(1f - expandProgress / 0.2f, 1, 0) * (1f - progressToUploading);
final float segmentsCount = segmentsCountAnimated.set(count);
final float segmentsUnreadCount = segmentsUnreadCountAnimated.set(unreadCount);
storiesGradientTools.setBounds(this.left, cy - dp(24), this.right, cy + dp(24));
if (isFailed) {
rect2.set(rect1);
rect2.inset(-dpf2(2.66f + 2.23f / 2), -dpf2(2.66f + 2.23f / 2));
final Paint paint = StoriesUtilities.getErrorPaint(rect2);
paint.setStrokeWidth(AndroidUtilities.dp(2));
paint.setAlpha((int) (255 * segmentsAlpha));
canvas.drawCircle(rect2.centerX(), rect2.centerY(), rect2.width() / 2f, paint);
} else if (mainCircle != null && segmentsAlpha > 0) {
rect2.set(rect1);
rect2.inset(-dpf2(2.66f + 2.23f / 2), -dpf2(2.66f + 2.23f / 2));
rect3.set(rect1);
rect3.inset(-dpf2(2.66f + 1.5f / 2), -dpf2(2.66f + 1.5f / 2));
final float separatorAngle = lerp(0, (float) (dpf2(2 + 2.23f) / (rect1.width() * Math.PI) * 360f), clamp(segmentsCount - 1, 1, 0) * segmentsAlpha);
final float maxCount = 50; // (float) (AndroidUtilities.dp(60) * Math.PI / dpf2(4));
final int mcount = Math.min(count, (int) maxCount);
final float animcount = Math.min(segmentsCount, maxCount);
final float widthAngle = (360 - Math.max(0, animcount) * separatorAngle) / Math.max(1, animcount);
readPaint.setColor(ColorUtils.blendARGB(0x5affffff, 0x3a000000, actionBarProgress));
readPaintAlpha = readPaint.getAlpha();
float a = -90 - separatorAngle / 2f;
for (int i = 0; i < mcount; ++i) {
final float read = 1f - clamp(segmentsUnreadCount - i, 1, 0);
final float appear = 1f - clamp(mcount - animcount - i, 1, 0);
if (appear < 0) {
continue;
}
float bounceScale = i == 0 ? 1 + (newStoryBounceT - 1) / 2.5f : 1f;
if (bounceScale != 1) {
canvas.save();
canvas.scale(bounceScale, bounceScale, rect2.centerX(), rect2.centerY());
}
if (read < 1) {
storiesGradientTools.paint.setAlpha((int) (0xFF * (1f - read) * segmentsAlpha));
storiesGradientTools.paint.setStrokeWidth(dpf2(2.33f));
canvas.drawArc(rect2, a, -widthAngle * appear, false, storiesGradientTools.paint);
}
if (read > 0) {
readPaint.setAlpha((int) (readPaintAlpha * read * segmentsAlpha));
readPaint.setStrokeWidth(dpf2(1.5f));
canvas.drawArc(rect3, a, -widthAngle * appear, false, readPaint);
}
if (bounceScale != 1) {
canvas.restore();
}
a -= widthAngle * appear + separatorAngle * appear;
}
}
}
if (expandProgress > 0 && segmentsAlpha < 1) {
float ix = 0;
w = 0;
@ -500,15 +627,15 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
int wasAlpha = whitePaint.getAlpha();
whitePaint.setAlpha((int) (wasAlpha * expandProgress));
canvas.drawCircle(
circle.cachedRect.centerX(),
circle.cachedRect.centerY(),
Math.min(circle.cachedRect.width(), circle.cachedRect.height()) / 2f +
lerp(
dpf2(2.66f) + storiesGradientTools.paint.getStrokeWidth() / 2f,
dpf2(2.33f) - readPaint.getStrokeWidth() / 2f,
circle.cachedRead
) * expandProgress,
whitePaint
circle.cachedRect.centerX(),
circle.cachedRect.centerY(),
Math.min(circle.cachedRect.width(), circle.cachedRect.height()) / 2f +
lerp(
dpf2(2.66f) + storiesGradientTools.paint.getStrokeWidth() / 2f,
dpf2(2.33f) - readPaint.getStrokeWidth() / 2f,
circle.cachedRead
) * expandProgress,
whitePaint
);
whitePaint.setAlpha(wasAlpha);
}
@ -519,14 +646,14 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
StoryCircle C = nearest(i + 1 < circles.size() ? circles.get(i + 1) : null, i + 2 < circles.size() ? circles.get(i + 2) : null, B);
if (A != null && (
Math.abs(A.borderRect.centerX() - B.borderRect.centerX()) < Math.abs(B.borderRect.width() / 2f - A.borderRect.width() / 2f) ||
Math.abs(A.borderRect.centerX() - B.borderRect.centerX()) > A.borderRect.width() / 2f + B.borderRect.width() / 2f
Math.abs(A.borderRect.centerX() - B.borderRect.centerX()) < Math.abs(B.borderRect.width() / 2f - A.borderRect.width() / 2f) ||
Math.abs(A.borderRect.centerX() - B.borderRect.centerX()) > A.borderRect.width() / 2f + B.borderRect.width() / 2f
)) {
A = null;
}
if (C != null && (
Math.abs(C.borderRect.centerX() - B.borderRect.centerX()) < Math.abs(B.borderRect.width() / 2f - C.borderRect.width() / 2f) ||
Math.abs(C.borderRect.centerX() - B.borderRect.centerX()) > C.borderRect.width() / 2f + B.borderRect.width() / 2f
Math.abs(C.borderRect.centerX() - B.borderRect.centerX()) < Math.abs(B.borderRect.width() / 2f - C.borderRect.width() / 2f) ||
Math.abs(C.borderRect.centerX() - B.borderRect.centerX()) > C.borderRect.width() / 2f + B.borderRect.width() / 2f
)) {
C = null;
}
@ -555,55 +682,8 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
}
canvas.restore();
}
if (mainCircle != null && segmentsAlpha > 0) {
rect2.set(rect1);
rect2.inset(-dpf2(2.66f + 2.23f / 2), -dpf2(2.66f + 2.23f / 2));
rect3.set(rect1);
rect3.inset(-dpf2(2.66f + 1.5f / 2), -dpf2(2.66f + 1.5f / 2));
final float separatorAngle = lerp(0, (float) (dpf2(2 + 2.23f) / (rect1.width() * Math.PI) * 360f), clamp(segmentsCount - 1, 1, 0) * segmentsAlpha);
final float maxCount = 50; // (float) (AndroidUtilities.dp(60) * Math.PI / dpf2(4));
final int mcount = Math.min(count, (int) maxCount);
final float animcount = Math.min(segmentsCount, maxCount);
final float widthAngle = (360 - Math.max(0, animcount) * separatorAngle) / Math.max(1, animcount);
readPaint.setColor(ColorUtils.blendARGB(0x5affffff, 0x3a000000, actionBarProgress));
readPaintAlpha = readPaint.getAlpha();
float a = -90 - separatorAngle / 2f;
for (int i = 0; i < mcount; ++i) {
final float read = 1f - clamp(segmentsUnreadCount - i, 1, 0);
final float appear = 1f - clamp(mcount - animcount - i, 1, 0);
if (appear < 0) {
continue;
}
float bounceScale = i == 0 ? 1 + (newStoryBounceT - 1) / 2.5f : 1f;
if (bounceScale != 1) {
canvas.save();
canvas.scale(bounceScale, bounceScale, rect2.centerX(), rect2.centerY());
}
if (read < 1) {
storiesGradientTools.paint.setAlpha((int) (0xFF * (1f - read) * segmentsAlpha));
storiesGradientTools.paint.setStrokeWidth(dpf2(2.33f));
canvas.drawArc(rect2, a, -widthAngle * appear, false, storiesGradientTools.paint);
}
if (read > 0) {
readPaint.setAlpha((int) (readPaintAlpha * read * segmentsAlpha));
readPaint.setStrokeWidth(dpf2(1.5f));
canvas.drawArc(rect3, a, -widthAngle * appear, false, readPaint);
}
if (bounceScale != 1) {
canvas.restore();
}
a -= widthAngle * appear + separatorAngle * appear;
}
}
canvas.restore();
// float titleAlpha = Math.max(0, (expandProgress - .5f) * 2f);
// if (titleAlpha > 0) {
@ -616,6 +696,35 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
// }
}
private void animateBounce() {
AnimatorSet animatorSet = new AnimatorSet();
ValueAnimator inAnimator = ValueAnimator.ofFloat(1, 1.05f);
inAnimator.setDuration(100);
inAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT);
ValueAnimator outAnimator = ValueAnimator.ofFloat(1.05f, 1f);
outAnimator.setDuration(250);
outAnimator.setInterpolator(new OvershootInterpolator());
ValueAnimator.AnimatorUpdateListener updater = animation -> {
avatarImage.bounceScale = bounceScale = (float) animation.getAnimatedValue();
avatarImage.invalidate();
invalidate();
};
inAnimator.addUpdateListener(updater);
outAnimator.addUpdateListener(updater);
animatorSet.playSequentially(inAnimator, outAnimator);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
avatarImage.bounceScale = bounceScale = 1f;
avatarImage.invalidate();
invalidate();
}
});
animatorSet.start();
}
private void clipCircle(Canvas canvas, StoryCircle circle, StoryCircle nextCircle) {
if (nextCircle == null) {
return;
@ -895,7 +1004,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif
tapY = event.getY();
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if (hit && System.currentTimeMillis() - tapTime <= ViewConfiguration.getTapTimeout() && MathUtils.distance(tapX, tapY, event.getX(), event.getY()) <= AndroidUtilities.dp(12) && !circles.isEmpty()) {
if (hit && System.currentTimeMillis() - tapTime <= ViewConfiguration.getTapTimeout() && MathUtils.distance(tapX, tapY, event.getX(), event.getY()) <= AndroidUtilities.dp(12) && (storiesController.hasUploadingStories(dialogId) || storiesController.hasStories(dialogId) || !circles.isEmpty())) {
onTap(provider);
return true;
}

View file

@ -248,7 +248,6 @@ public abstract class SelfStoriesPreviewView extends View {
imageReceiversTmp.get(i).onDetach();
}
imageReceiversTmp.clear();
// canvas.drawLine(getMeasuredWidth() / 2f, 0, getMeasuredWidth() / 2f, getMeasuredHeight(), new Paint());
}
abstract void onDragging();

View file

@ -483,7 +483,8 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente
}
}
public void setStoryItem(SelfStoryViewsView.StoryItemInternal storyItem) {
public void setStoryItem(long dialogId, SelfStoryViewsView.StoryItemInternal storyItem) {
this.dialogId = dialogId;
this.storyItem = storyItem;
updateViewsVisibility();
updateViewState(false);
@ -507,7 +508,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente
if (defaultModel != null) {
defaultModel.release();
}
defaultModel = new ViewsModel(currentAccount, serverItem, true);
defaultModel = new ViewsModel(currentAccount, dialogId, serverItem, true);
defaultModel.reloadIfNeed(state, showContactsFilter, showReactionsSort);
defaultModel.loadNext();
MessagesController.getInstance(currentAccount).storiesController.selfViewsModel.put(serverItem.id, defaultModel);
@ -581,7 +582,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente
((MarginLayoutParams) shadowView2.getLayoutParams()).topMargin = AndroidUtilities.dp(TOP_PADDING - 17);
}
public static void preload(int currentAccount, TLRPC.StoryItem storyItem) {
public static void preload(int currentAccount, long dialogId, TLRPC.StoryItem storyItem) {
if (storyItem == null) {
return;
}
@ -591,7 +592,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente
if (model != null) {
model.release();
}
model = new ViewsModel(currentAccount, storyItem, true);
model = new ViewsModel(currentAccount, dialogId, storyItem, true);
model.loadNext();
MessagesController.getInstance(currentAccount).storiesController.selfViewsModel.put(storyItem.id, model);
}
@ -651,14 +652,14 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.storiesUpdated) {
if (storyItem.uploadingStory != null) {
TLRPC.TL_userStories stories = MessagesController.getInstance(currentAccount).storiesController.getStories(UserConfig.getInstance(currentAccount).clientUserId);
TLRPC.PeerStories stories = MessagesController.getInstance(currentAccount).storiesController.getStories(UserConfig.getInstance(currentAccount).clientUserId);
if (stories != null) {
for (int i = 0; i < stories.stories.size(); i++) {
TLRPC.StoryItem storyItem = stories.stories.get(i);
if (storyItem.attachPath != null && storyItem.attachPath.equals(this.storyItem.uploadingStory.path)) {
this.storyItem.uploadingStory = null;
this.storyItem.storyItem = storyItem;
setStoryItem(this.storyItem);
setStoryItem(dialogId, this.storyItem);
break;
}
}
@ -955,6 +956,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente
public int totalCount;
TLRPC.StoryItem storyItem;
private long dialogId;
int currentAccount;
boolean loading;
ArrayList<TLRPC.TL_storyView> views = new ArrayList<>();
@ -971,9 +973,10 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente
ArrayList<SelfStoryViewsPage> listeners = new ArrayList<>();
FiltersState state = new FiltersState();
public ViewsModel(int currentAccount, TLRPC.StoryItem storyItem, boolean isDefault) {
public ViewsModel(int currentAccount, long dialogId, TLRPC.StoryItem storyItem, boolean isDefault) {
this.currentAccount = currentAccount;
this.storyItem = storyItem;
this.dialogId = dialogId;
this.totalCount = storyItem.views == null ? 0 : storyItem.views.views_count;
if (totalCount < 200) {
useLocalFilters = true;
@ -1006,6 +1009,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente
}
TLRPC.TL_stories_getStoryViewsList req = new TLRPC.TL_stories_getStoryViewsList();
req.id = storyItem.id;
req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId);
if (useLocalFilters) {
req.q = "";
req.just_contacts = false;

View file

@ -22,6 +22,7 @@ import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.AdjustPanLayoutHelper;
@ -48,6 +49,7 @@ public class SelfStoryViewsView extends FrameLayout {
int keyboardHeight;
int animatedKeyboardHeight;
private long dialogId;
ViewPagerInner viewPager;
ArrayList<StoryItemInternal> storyItems = new ArrayList<>();
@ -197,7 +199,7 @@ public class SelfStoryViewsView extends FrameLayout {
item.setTag(position);
item.setShadowDrawable(shadowDrawable);
item.setPadding(0, AndroidUtilities.dp(16), 0 , 0);
item.setStoryItem(storyItems.get(position));
item.setStoryItem(dialogId,storyItems.get(position));
// bottomPadding = (selfStoriesPreviewView.getTop() + toHeight + AndroidUtilities.dp(24));
item.setListBottomPadding(bottomPadding);
@ -346,14 +348,18 @@ public class SelfStoryViewsView extends FrameLayout {
viewPagerContainer.setTranslationY(-bottomPadding + getMeasuredHeight() - selfStoriesViewsOffset);
}
public void setItems(ArrayList<TLRPC.StoryItem> storyItems, int selectedPosition) {
public void setItems(long dialogId, ArrayList<TLRPC.StoryItem> storyItems, int selectedPosition) {
this.storyItems.clear();
this.dialogId = dialogId;
for (int i = 0; i < storyItems.size(); i++) {
this.storyItems.add(new StoryItemInternal(storyItems.get(i)));
}
ArrayList<StoriesController.UploadingStory> uploadingStories = MessagesController.getInstance(storyViewer.currentAccount).storiesController.getUploadingStories();
for (int i = 0; i < uploadingStories.size(); i++) {
this.storyItems.add(new StoryItemInternal(uploadingStories.get(i)));
long clientUserId = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId();
ArrayList<StoriesController.UploadingStory> uploadingStories = MessagesController.getInstance(storyViewer.currentAccount).storiesController.getUploadingStories(clientUserId);
if (uploadingStories != null) {
for (int i = 0; i < uploadingStories.size(); i++) {
this.storyItems.add(new StoryItemInternal(uploadingStories.get(i)));
}
}
selfStoriesPreviewView.setItems(this.storyItems, selectedPosition);
viewPager.setAdapter(null);

View file

@ -107,11 +107,12 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider {
holder.clipParent = storiesCell;
holder.clipTop = holder.clipBottom = 0;
holder.alpha = 1;
if (cell.isFail) {
if (cell.isFail && storiesCell.isExpanded()) {
final Path path = new Path();
holder.drawClip = (canvas, bounds, alpha, opening) -> {
if (opening) return;
path.rewind();
final float t = opening ? 1f - (float) Math.pow(1f - alpha, 2) : (float) Math.pow(alpha, 2);
final float t = (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);
};

View file

@ -1,8 +1,6 @@
package org.telegram.ui.Stories;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import androidx.collection.LongSparseArray;
@ -14,24 +12,20 @@ import org.telegram.SQLite.SQLiteException;
import org.telegram.SQLite.SQLitePreparedStatement;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.DialogObject;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessageCustomParamsHelper;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.MessagesStorage;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.messenger.support.LongSparseIntArray;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.NativeByteBuffer;
import org.telegram.tgnet.RequestDelegate;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
@ -51,7 +45,7 @@ public class StoriesStorage {
storage.getStorageQueue().postRunnable(() -> {
SQLiteDatabase database = storage.getDatabase();
SQLiteCursor cursor = null;
ArrayList<TLRPC.TL_userStories> userStoriesArray = new ArrayList<>();
ArrayList<TLRPC.PeerStories> userStoriesArray = new ArrayList<>();
ArrayList<Long> usersToLoad = new ArrayList<>();
ArrayList<Long> chatsToLoad = new ArrayList<>();
boolean failed = false;
@ -93,11 +87,11 @@ public class StoriesStorage {
}
cursor.dispose();
cursor = null;
TLRPC.TL_userStories userStories;
userStories = new TLRPC.TL_userStories();
TLRPC.PeerStories userStories;
userStories = new TLRPC.TL_peerStories();
userStories.stories = storyItems;
userStories.max_read_id = maxReadId;
userStories.user_id = dialogId;
userStories.peer = MessagesController.getInstance(currentAccount).getPeer(dialogId);
userStoriesArray.add(userStories);
}
} catch (Throwable e) {
@ -113,19 +107,21 @@ public class StoriesStorage {
return;
}
TLRPC.TL_stories_allStories storiesResponse = new TLRPC.TL_stories_allStories();
storiesResponse.user_stories = userStoriesArray;
storiesResponse.peer_stories = userStoriesArray;
storiesResponse.users = storage.getUsers(usersToLoad);
for (int i = 0; i < storiesResponse.user_stories.size(); i++) {
TLRPC.TL_userStories userStories = storiesResponse.user_stories.get(i);
checkExpiredStories(userStories.user_id, userStories.stories);
storiesResponse.chats = storage.getChats(chatsToLoad);
for (int i = 0; i < storiesResponse.peer_stories.size(); i++) {
TLRPC.PeerStories userStories = storiesResponse.peer_stories.get(i);
long dialogId = DialogObject.getPeerDialogId(userStories.peer);
checkExpiredStories(dialogId, userStories.stories);
if (userStories.stories.isEmpty()) {
storiesResponse.user_stories.remove(i);
storiesResponse.peer_stories.remove(i);
i--;
}
Collections.sort(userStories.stories, StoriesController.storiesComparator);
}
Collections.sort(storiesResponse.user_stories, Comparator.comparingInt(o -> -o.stories.get(o.stories.size() - 1).date));
Collections.sort(storiesResponse.peer_stories, Comparator.comparingInt(o -> -o.stories.get(o.stories.size() - 1).date));
AndroidUtilities.runOnUIThread(() -> consumer.accept(storiesResponse));
});
@ -162,7 +158,7 @@ public class StoriesStorage {
}
public void putStoriesInternal(long dialogId, TLRPC.TL_userStories userStories) {
public void putStoriesInternal(long dialogId, TLRPC.PeerStories userStories) {
SQLiteDatabase database = storage.getDatabase();
try {
if (userStories != null) {
@ -232,12 +228,12 @@ public class StoriesStorage {
}
}
public void saveAllStories(ArrayList<TLRPC.TL_userStories> user_stories, boolean isNext, boolean hidden, Runnable callback) {
public void saveAllStories(ArrayList<TLRPC.PeerStories> user_stories, boolean isNext, boolean hidden, Runnable callback) {
storage.getStorageQueue().postRunnable(() -> {
SQLiteDatabase database = storage.getDatabase();
for (int i = 0; i < user_stories.size(); i++) {
TLRPC.TL_userStories stories = user_stories.get(i);
fillSkippedStories(stories.user_id, stories);
TLRPC.PeerStories stories = user_stories.get(i);
fillSkippedStories(DialogObject.getPeerDialogId(stories.peer), stories);
}
if (!isNext) {
try {
@ -246,12 +242,22 @@ public class StoriesStorage {
ArrayList<Long> dialogsToDelete = new ArrayList<>();
while (cursor.next()) {
long dialogId = cursor.longValue(0);
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId);
if (user == null) {
user = MessagesStorage.getInstance(currentAccount).getUser(dialogId);
}
if (user == null || user.stories_hidden == hidden && !dialogsToDelete.contains(dialogId)) {
dialogsToDelete.add(dialogId);
if (dialogId > 0) {
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId);
if (user == null) {
user = MessagesStorage.getInstance(currentAccount).getUser(dialogId);
}
if (user == null || user.stories_hidden == hidden && !dialogsToDelete.contains(dialogId)) {
dialogsToDelete.add(dialogId);
}
} else {
TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId);
if (chat == null) {
chat = MessagesStorage.getInstance(currentAccount).getChat(-dialogId);
}
if (chat == null || chat.stories_hidden == hidden && !dialogsToDelete.contains(dialogId)) {
dialogsToDelete.add(dialogId);
}
}
}
if (BuildVars.LOGS_ENABLED) {
@ -263,8 +269,8 @@ public class StoriesStorage {
}
}
for (int i = 0; i < user_stories.size(); i++) {
TLRPC.TL_userStories stories = user_stories.get(i);
putStoriesInternal(stories.user_id, stories);
TLRPC.PeerStories stories = user_stories.get(i);
putStoriesInternal(DialogObject.getPeerDialogId(stories.peer), stories);
}
if (callback != null) {
AndroidUtilities.runOnUIThread(callback);
@ -272,7 +278,7 @@ public class StoriesStorage {
});
}
private void fillSkippedStories(long user_id, TLRPC.TL_userStories userStories) {
private void fillSkippedStories(long user_id, TLRPC.PeerStories userStories) {
try {
if (userStories != null) {
ArrayList<TLRPC.StoryItem> storyItems = userStories.stories;
@ -321,17 +327,17 @@ public class StoriesStorage {
}
public void getStories(long dialogId, Consumer<TLRPC.TL_userStories> consumer) {
public void getStories(long dialogId, Consumer<TLRPC.PeerStories> consumer) {
storage.getStorageQueue().postRunnable(() -> {
TLRPC.TL_userStories finalUserStories = getStoriesInternal(dialogId);
TLRPC.PeerStories finalUserStories = getStoriesInternal(dialogId);
AndroidUtilities.runOnUIThread(() -> consumer.accept(finalUserStories));
});
}
private TLRPC.TL_userStories getStoriesInternal(long dialogId) {
private TLRPC.PeerStories getStoriesInternal(long dialogId) {
SQLiteDatabase database = storage.getDatabase();
SQLiteCursor cursor = null;
TLRPC.TL_userStories userStories = null;
TLRPC.PeerStories userStories = null;
try {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT count, max_read FROM stories_counter WHERE dialog_id = %d", dialogId));
int count = 0;
@ -360,10 +366,10 @@ public class StoriesStorage {
}
cursor.dispose();
cursor = null;
userStories = new TLRPC.TL_userStories();
userStories = new TLRPC.TL_peerStories();
userStories.max_read_id = maxReadId;
userStories.stories = storyItems;
userStories.user_id = dialogId;
userStories.peer = MessagesController.getInstance(currentAccount).getPeer(dialogId);
} catch (Exception e) {
FileLog.e(e);
@ -423,10 +429,18 @@ public class StoriesStorage {
}
public void updateMaxReadId(long dialogId, int max_read_id) {
TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(dialogId);
if (userFull != null && userFull.stories != null) {
userFull.stories.max_read_id = max_read_id;
storage.updateUserInfo(userFull, false);
if (dialogId > 0) {
TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(dialogId);
if (userFull != null && userFull.stories != null) {
userFull.stories.max_read_id = max_read_id;
storage.updateUserInfo(userFull, false);
}
} else {
TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(-dialogId);
if (chatFull != null && chatFull.stories != null) {
chatFull.stories.max_read_id = max_read_id;
storage.updateChatInfo(chatFull, false);
}
}
storage.getStorageQueue().postRunnable(() -> {
SQLiteDatabase database = storage.getDatabase();
@ -443,7 +457,7 @@ public class StoriesStorage {
SQLiteDatabase database = storage.getDatabase();
SQLiteCursor cursor = null;
try {
long dialogId = updateStory.user_id;
long dialogId = DialogObject.getPeerDialogId(updateStory.peer);
int count = 0;
int storyId = updateStory.story.id;
boolean storyExist = false;
@ -495,10 +509,10 @@ public class StoriesStorage {
});
}
public void updateStories(TLRPC.TL_userStories currentStories) {
public void updateStories(TLRPC.PeerStories currentStories) {
storage.getStorageQueue().postRunnable(() -> {
for (int i = 0; i < currentStories.stories.size(); i++) {
updateStoryItemInternal(currentStories.user_id, currentStories.stories.get(i));
updateStoryItemInternal(DialogObject.getPeerDialogId(currentStories.peer), currentStories.stories.get(i));
}
});
}
@ -565,7 +579,7 @@ public class StoriesStorage {
long dialogId = messagesWithUnknownStories.keyAt(i);
ArrayList<MessageObject> messageObjects = messagesWithUnknownStories.valueAt(i);
TLRPC.TL_stories_getStoriesByID request = new TLRPC.TL_stories_getStoriesByID();
request.user_id = MessagesController.getInstance(currentAccount).getInputUser(dialogId);
request.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId);
for (int j = 0; j < messageObjects.size(); j++) {
request.id.add(getStoryId(messageObjects.get(j)));
}
@ -612,7 +626,8 @@ public class StoriesStorage {
}
if (messageObject.type == MessageObject.TYPE_STORY || messageObject.type == MessageObject.TYPE_STORY_MENTION) {
MessageMediaStoryFull mediaStoryFull = new MessageMediaStoryFull();
mediaStoryFull.user_id = messageObject.messageOwner.media.user_id;
mediaStoryFull.user_id = DialogObject.getPeerDialogId(messageObject.messageOwner.media.peer);
mediaStoryFull.peer = messageObject.messageOwner.media.peer;
mediaStoryFull.id = messageObject.messageOwner.media.id;
mediaStoryFull.storyItem = checkExpiredStateLocal(currentAccount, dialogId, storyItem);
mediaStoryFull.via_mention = messageObject.messageOwner.media.via_mention;
@ -741,9 +756,9 @@ public class StoriesStorage {
});
}
public void putUserStories(TLRPC.TL_userStories userStories) {
public void putPeerStories(TLRPC.PeerStories userStories) {
storage.getStorageQueue().postRunnable(() -> {
putStoriesInternal(userStories.user_id, userStories);
putStoriesInternal(DialogObject.getPeerDialogId(userStories.peer), userStories);
});
}

Some files were not shown because too many files have changed in this diff Show more