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;